Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- // Размер статического буфера под вывод результата консольных команд
- #define BUFFER_SIZE 4096
- // Размер буфера под текстовое представление чисел
- // так как atoi и иже с ними в стандартной библиотеке принимают только сишные строки
- // заканчивающиеся на термининирующий ноль, поэтому будем копировать чтоб сделать сишные строки
- // можно конечно редактировать исходный буфер, но без необходимости лучше не заниматься преждевременной оптимизацией
- #define ATOI_BUFFER 256
- // Количество секунд между проверками
- #define SLEEP_TIME_SECONDS 30
- // Объявление функции, чтоб можно было их расположить в любом порядке, так я хочу их разместить после main функции
- int executeCommand(char *command, char *buffer, int bufferSize, size_t *dataSize);
- void checkNetLimit(char *buffer, size_t bufferSize);
- void checkLineLimit(char *buffer, size_t bufferSize);
- long int toNumber(char *buffer, size_t length);
- void getNextLine(char *buffer, size_t bufferSize, size_t *lineStart, size_t *lineLength);
- void skipNewLineSymbols(char *buffer, size_t bufferSize, size_t *pos);
- void findFirstNewLineSymbol(char *buffer, size_t bufferSize, size_t *pos);
- int isNewLine(char symbol);
- // Отсюда стартует программа
- int main()
- {
- // Наш буфер куда будем писать вывод консольных команд
- // выделяем на байт больше так как последний байт занулим
- // и не прийдется потом из размера буфера вычитать единицу чтоб не затереть этот терминирующий ноль
- char buf[BUFFER_SIZE + 1];
- // В конец на всякий случай пишем терминирующий ноль чтоб в худшем случае у нас получилась сишная строка
- buf[BUFFER_SIZE] = 0;
- // Переменная для размера текстовой строки
- // size_t это числовая переменная хранящая размер данных
- // это unsigned int но в 32 битных приложениях занимает 32 бита, на 64 битных соответственно 64 бита
- size_t dataSize = 0;
- // Переменная для результата выполнения функций, успех если 0 или номер ошибки
- int res = 0;
- system ("sh servMesg.sh");
- // Бесконечно крутимся в цикле
- // тут можно конечно добавить проверку на прерывание выполнения из консоли по ctrl+c и корректно завершиться
- // но это если уже весь код понятен, а так это лишнее для такого простого кода
- while (1) {
- // Выполняем командную строку и получаем вывод
- res = executeCommand("netstat |grep '7776 ESTABLISHED' | awk '{print $2}'", buf, BUFFER_SIZE, &dataSize);
- // Если есть вывод и он не пустой то проверяем лимиты
- if (res == 0 && dataSize) {
- checkNetLimit(buf, dataSize);
- }
- // Также получаем вывод и если не пустой то проверяем количество строк
- res = executeCommand("netstat |grep '7776 ESTABLISHED' | wc -l", buf, BUFFER_SIZE, &dataSize);
- if (res == 0 && dataSize) {
- checkLineLimit(buf, dataSize);
- }
- // Засыпаем на некоторое время
- sleep(SLEEP_TIME_SECONDS);
- }
- return 0;
- }
- // Выполнение консольной команды из переменной command, и запись текстового вывода в массив по указателю buffer
- // учитывая максимальный размер текстового буфера хранящего в переменной bufferSize
- // размер текста запишем в dataSize
- int executeCommand(char *command, char *buffer, int bufferSize, size_t *dataSize)
- {
- // Результат выполнения этой функции, ноль нет ошибок, остальное номер ошибки
- int result = 0;
- // Переменная содержащая указатель на пайп, иницилиазируем его нашей командой на выполнение
- FILE *pipe = popen(command, "r");
- // Обнуляем размер результата вывода на случай если будет ошибка
- *dataSize = 0;
- // Если не удалось открыть пайп то пишем ошибку и прерываем выполнение
- // в си не приветствуется множественное использование return
- // но в данном случае нам не надо очищать ресурсы
- if (pipe == NULL) {
- fprintf(stderr, "Error open pipe");
- return 1;
- }
- // Количество всех прочитанных байтов
- size_t bytesRead = 0;
- // Количество байтов прочитанных fread
- size_t bytes = 0;
- // Читаем из пайпа пока есть данные
- do {
- // Читаем данные в буфер
- // для того чтоб данные дописывались к предыдущим сдвигаем указатель buffer на количество уже записанных байт(bytesRead)
- // также не забываем уменьшить размер буфера на количество записанных байт
- bytes = fread(buffer + bytesRead, 1, bufferSize - bytesRead, pipe);
- // Если есть прочитанные байты то добавляем их к общему количеству прочитанных байт
- if (bytes) {
- bytesRead += bytes;
- // Если нет прочитанных байт то это либо конец данных либо ошибка
- } else {
- // Проверим есть ли ошибка и если есть напишем в вывод ошибок
- int errorCode = ferror(pipe);
- if (errorCode) {
- result = 1;
- fprintf(stderr, "Error read pipe: %d", errorCode);
- }
- }
- } while (bytes);
- // Записываем количество прочитанных данных в внешнюю переменную
- *dataSize = bytesRead;
- // Не забываем очистить ресурсы и закрываем пайп.
- pclose(pipe);
- return result;
- }
- // Функция проверки сетевых лимитов
- void checkNetLimit(char *buffer, size_t bufferSize)
- {
- // Начало строки, в данном случае это не указатель а смещение (offset) в байтах относительно начала текстового буфера
- size_t lineStart = 0;
- // Длина строки
- size_t lineLength = 0;
- // Числовой результат который попытаемся получить из строки
- long int number = 0;
- // Выполняем цикл пока есть непустые строки
- do {
- // Получаем начало и длину строки из текстового буфера
- getNextLine(buffer, bufferSize, &lineStart, &lineLength);
- // Если есть строка и она не пустая
- if (lineLength) {
- // Конвертим строку в число
- number = toNumber(buffer + lineStart, lineLength);
- if (number > 50000) {
- system ("sh alarm.sh");
- printf ("количество пакетов превышено\n");
- printf ("%ld\n", number);
- }
- }
- } while (lineLength);
- }
- // Функция проверки количества строк
- void checkLineLimit(char *buffer, size_t bufferSize)
- {
- // Начало строки, в данном случае это не указатель а смещение (offset) в байтах относительно начала текстового буфера
- size_t lineStart = 0;
- // Длина строки
- size_t lineLength = 0;
- // Числовой результат который попытаемся получить из строки
- long int number = 0;
- // Получаем начало и длину строки из текстового буфера
- getNextLine(buffer, bufferSize, &lineStart, &lineLength);
- // Если есть строка и она не пустая
- if (lineLength) {
- // Конвертим строку в число
- number = toNumber(buffer + lineStart, lineLength);
- if (number < 2) {
- system ("sh alarm1.sh");
- printf ("Строк меньше двух\n");
- }
- printf ("%ld\n", number);
- }
- }
- // Функция конвентирования строки в число
- long int toNumber(char *buffer, size_t length)
- {
- // Буфер где будем хранить строку с числом плюс байт на терминирующий ноль
- char atoibuf[ATOI_BUFFER + 1];
- // Обнуляем последний байт
- atoibuf[ATOI_BUFFER] = 0;
- // Если входная строка больше буфера то обрезаем длину и пишем в лог ошибок
- if (length > ATOI_BUFFER) {
- fprintf(stderr, "Error atoi buffer too small: %d, required size: %ld", ATOI_BUFFER, length);
- length = ATOI_BUFFER;
- }
- // Копируем строку из буфера вывода в наш временный буфер
- memcpy(atoibuf, buffer, length);
- // Не забываем в конец добавить терминирующий ноль для функции atol
- atoibuf[length] = 0;
- // Конвентируем строку в число и возращаем это число
- return atol(atoibuf);
- }
- // Функция для получения смещения в байтах следущей строки и её длину
- void getNextLine(char *buffer, size_t bufferSize, size_t *lineStart, size_t *lineLength)
- {
- // Получаем смещение новой строки, для этого к предыдущему смещению добавляем длину
- // в результате получим смещение сразу на следующий байт после предыдущей строки
- size_t newLineStart = *lineStart + *lineLength;
- // Длина новой строки пока что обнулим переменную
- size_t newLineLength = 0;
- // Переменная для указания получилось ли найти новую строку или нет, ноль значит больше нет строк, обнулим её
- int validString = 0;
- // Проверяем что смещение на новую строку меньше размера буфера, иное означает что буфер закончился и новых строк нет
- if (newLineStart < bufferSize) {
- // Для начала вызовем функцию которая сдвинет смещение к первому символу не являющемуся переводом строки
- // так мы пропустим байты означающие перевод строки и получим новое смещение указывающее на начало строки
- skipNewLineSymbols(buffer, bufferSize, &newLineStart);
- // Снова проверяем не закончился ли буфер и то что смещение указывает не на байт новой строки
- if ((newLineStart < bufferSize) && !isNewLine(buffer[newLineStart])) {
- // Создаем переменную смещения указывающую на конец строки, в данном случае это просто следующий байт
- size_t newLineEnd = newLineStart + 1;
- // Теперь вызываем функцию которая сдвинет смещения конца строки на первый попавшийся символ новой строки
- // Также если в конце буфера нет байта перевода строки то смещение будет указывать на первый байт за пределом буфера
- findFirstNewLineSymbol(buffer, bufferSize, &newLineEnd);
- // Получаем длину новой строки просто вычитая из смещения конца строки смещение начала строки
- newLineLength = newLineEnd - newLineStart;
- // В переменную успеха поиска строки записываем 1 как факт что мы нашли строку
- validString = 1;
- }
- }
- // Если мы нашли строку то устанавливаем новые значения смещения и длины строки
- // иначе просто обнуляем длину
- if (validString) {
- *lineStart = newLineStart;
- *lineLength = newLineLength;
- } else {
- *lineStart = 0;
- *lineLength = 0;
- }
- }
- // Функция которая сдвигает смещение пока оно не будет указывать на символ новой строки
- // либо будет указывать на следующий байт за пределами буфера
- // функцию просто сдвинет смещение пропуская все смещения указывающие на символ новой строки
- void skipNewLineSymbols(char *buffer, size_t bufferSize, size_t *pos)
- {
- // Крутим цикл пока не вылезем за пределы буфера
- while (*pos < bufferSize) {
- // Если смещение указывает на символ новой строки то пропускаем его увеличивая смещение на еденицу
- // иначе прерываем цикл так как нашли начало новой строки
- if (isNewLine(buffer[*pos])) {
- (*pos)++;
- } else {
- break;
- }
- }
- }
- // Функция которая сдвигает смещение пока оно будет указывать не на символ новой строки
- // либо будет указывать на следующий байт за пределами буфера
- // функция просто сдвинет указатель к символу новой строки
- void findFirstNewLineSymbol(char *buffer, size_t bufferSize, size_t *pos)
- {
- // Крутим цикл пока не вылезем за пределы буфера
- while (*pos < bufferSize) {
- // Если смещение не указывает на символ новой строки то увеличиваем смещение на еденицу
- // иначе прерываем цикл так как нашли конец строки
- if (!isNewLine(buffer[*pos])) {
- (*pos)++;
- } else {
- break;
- }
- }
- }
- // Функция проверки символа на символ новой строки
- // в качестве новой строки будет проверять как символ новой строки \n так и символ возарата каретки \r
- // так как типичная ситуация когда перевод строки это последовательность символов \r\n
- // учитываем что это работает только для ascii и utf-8 и то что оба символа в utf-8 занимают один байт
- // с кириллицей данное не будет работать в utf-8
- int isNewLine(char symbol)
- {
- return (symbol == '\r' || symbol == '\n');
- }
Advertisement
Add Comment
Please, Sign In to add comment