Проверь код исходя из этих условий и выполни что надо
Программы должны быть разработаны на языке С стандарта C11 с использованием компилятора gcc.
Код программ cat и grep должен находиться в ветке develop в папках src/cat/ и src/grep/ соответственно.
Не используй устаревшие и выведенные из употребления конструкции языка и библиотечные функции. Обращай внимание на пометки legacy и obsolete в официальной документации по языку и используемым библиотекам. Ориентируйся на стандарт POSIX.1-2017.
При написании кода необходимо придерживаться Google Style.
Программы должны представлять собой исполняемый файл с аргументами командной строки
Сборка программ должна быть настроена с помощью Makefile с соответствующими целями: s21_cat, s21_grep.
Если используешь сторонние библиотеки, в Makefile должны быть заложены сценарии сборки, предусматривающие их подключение/загрузку.
Необходимо покрытие интеграционными тестами для всех вариантов флагов и входных значений, на базе сравнения с поведением реальных утилит Bash.
Программа должна быть разработана в соответствии с принципами структурного программирования.
Необходимо исключить дублирование кода, переиспользовать общие модули между утилитами. Общие модули можно вынести в отдельную папку src/common.
Можно использовать стандартные и нестандартные библиотеки языка С, а можно собственноручно разработанные библиотеки из других проектов.
Формулировка сообщения при возникновении ошибочной ситуации не имеет значения.
Ввод через stdin обрабатывать не обязательно.

#include <stdio.h>
#include <unistd.h>
#include <getopt.h>
#include <stdbool.h>

typedef struct flag {
    int b, e, n, s, t, v;
} flags;

int s21_parser(int argc, char *argv[], flags *flag);
int main(int argc, char *argv[]) {
    flags flag = {.b = 0, .e = 0, .n = 0, .s = 0, .t = 0, .v = 0};
    int parse_status = s21_parser(argc, argv, &flag);
    
    if (parse_status == -1) {
        return 1;
    }

    if (optind >= argc) {
        fprintf(stderr, "No files provided\n");
        return 1;
    }

    int err = 0;

    for (int i = optind; i < argc; i++) {
        FILE *file = fopen(argv[i], "r");
        if (!file) {
            fprintf(stderr, "Error opening file %s: ", argv[i]);
            perror("");
            err = 1;
            continue;
        }

        int c;
        size_t line_number = 1;
        size_t empty_line_flag = 0;
        bool is_new_line = true;

while ((c = fgetc(file)) != EOF) {
            if (flag.s) {
                if (c == '\n') {
                    empty_line_flag += 1;
                    if (empty_line_flag > 2) {
                        continue;
                    }
                } else {
                    empty_line_flag = 0;
                }
            }
            if (flag.n && is_new_line) {
                printf("%6ld\t", line_number);
                line_number += 1;
                is_new_line = false;
            }
            if (flag.b && is_new_line && c != '\n') {
                printf("%6ld\t", line_number);
                line_number += 1;
                is_new_line = false;
            }
            if (flag.t && c == '\t') {
                printf("^");
                c = 'I';
            }
            if (flag.v && c != '\n' && c != '\t') {
                if (c >= 0 && c <= 31) {
                    printf("^");
                    c += 64;
                } else if (c == 127) {
                    printf("^");
                    c -= 64;
                }
            }
            if (flag.e && c == '\n') {
                printf("$");
            }
            if (c == '\n') {
                is_new_line = true;
            }
            printf("%c", c);
        }

        fclose(file);
    }

    return err;
}

int s21_parser(int argc, char *argv[], flags *flag) {
    int option;
    int option_index = 0;
    const char *optstring = "+beEnsTvt";

    struct option long_options[] = {
        {"number-nonblank", no_argument, 0, 'b'},
        {"number", no_argument, 0, 'n'},
        {"squeeze-blank", no_argument, 0, 's'},
        {0, 0, 0, 0},
    };

    opterr = 0;
    while ((option = getopt_long(argc, argv, optstring, long_options, &option_index)) != -1) {
        switch (option) {
            case 'b':
                flag->b = 1;
                break;
            case 'e':
                flag->e = 1;
                flag->v = 1;
                break;
            case 'E':
                flag->e = 1;
                break;
            case 'n':
                flag->n = 1;
                break;
            case 's':
                flag->s = 1;
                break;
            case 't':
                flag->t = 1;
                flag->v = 1;
                break;
            case 'T':
                flag->t = 1;
                break;
            case 'v':
                flag->v = 1;
                break;
            case '?':
                fprintf(stderr, "Unknown option: %s\n", argv[optind - 1]);
                return -1;
        }
    }

    if (flag->b) {
        flag->n = 0;
    }

    return 0;
}