LINUX.ORG.RU

Как правильно выводить ошибки в консольке?


0

2

Все программы (по крайней мере, из coreutils) выводят ошибки в едином формате:

название_программы: ошибка: причина.

$ ls QWE
ls: cannot access QWE: No such file or directory

Для этого есть стандартные функции в системе или каждый пишет свою? Может тогда есть стандарты на эту тему?

И ещё вопрос: надо ли экранировать имена файлов в тексте ошибки? То есть заменять символы перевода строки на комбинацию «\n» и так далее?

Ответ на: комментарий от solovey

Не. Если верить ману, perror выводит ошибки в функциях стандартной библиотеки, предваряя их пользовательским текстом. Как это можно приспособить к своим текстам ошибок? А имя программы выводить вручную?

Masturbant
() автор топика
Ответ на: комментарий от Masturbant

argv[0] - имя программы. В твоём примере ошибка берётся из errno.

anonymous
()

скорее man strerror, хотя они с perror все равно в одном мане описаны

и до кучи /usr/include/sysexits.h - описание кодов завершения программы

Skolotovich ★★★
()
Ответ на: комментарий от Masturbant

Не пойму, чем мне может помочь функция, возвращающая указатель на стандартный текст?

тем что к стандартным кодам ошибок есть стандартный текст

Skolotovich ★★★
()
Ответ на: комментарий от Masturbant
#define warnc(c, format, args...)       \
        warnx(format ": %s", ## args, strerror(c))

Еще удобные define'ы, которыми пользуюсь:

#ifdef EBUG
        #define RED                     "\033[1;32;41m"
        #define GREEN           "\033[5;30;42m"
        #define OLDCOLOR        "\033[0;0;0m"
        #define FNAME() fprintf(stderr, "\n%s (%s, line %d)\n", __func__, __FILE__, __LINE__)
        #define DBG(...) do{fprintf(stderr, "%s (%s, line %d): ", __func__, __FILE__, __LINE__); \
                                        fprintf(stderr, __VA_ARGS__);                   \
                                        fprintf(stderr, "\n");} while(0)
        #define ERR(...) DBG(__VA_ARGS__)
#else
        #define FNAME()  do{}while(0)
        #define DBG(...) do{}while(0)
        #define ERR(...)        do{fprintf(stderr, __VA_ARGS__);                        \
                                                fprintf(stderr, "\n");} while(0)
#endif //EBUG

extern const char *__progname;
#define info(format, args...)   do{             \
        printf("%s: ", __progname);             \
        printf(format,  ## args);               \
        printf("\n");}while(0)

Eddy_Em ☆☆☆☆☆
()
Последнее исправление: Eddy_Em (всего исправлений: 1)
Ответ на: комментарий от Skolotovich

а ты уверен что все типы терминалов будут это поддерживать?

Можно у терминала предварительно спросить. Например, вызвав tput, или поколдовав с terminfo или ncurses.

Впрочем, вызов tput красивее, т.к. не требует тянуть в код лишнее.

anonymous
()
Ответ на: комментарий от anonymous

вызвав tput

Можно поподробней? Есть такая библиотека/функция? А то man 3 tput ничего не дает, по tput есть лишь man 1.

Или надо в ее исходниках ковыряться?

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Не все, конечно. Но по ssh работает. А вот при выводе в файл получается мусор.

ты лучше эту штуку в ifdef заверни или в рантайме определяй тип терминала

зы: мой вариант логирования https://github.com/skolot/c-logger/blob/master/log.h

Skolotovich ★★★
()

ls: cannot access QWE: No such file or directory

man 3 error:

CONFORMING TO
       These functions and variables are GNU extensions,  and  should  not  be used in programs intended to be portable.
quasimoto ★★★★
()
Ответ на: комментарий от anonymous

Для исходников нужно читать, более того — читать код. И, самое страшное, его понимать. Так что хватит издеваться над человеком, ты ещё ему консоль посоветуй.

anonymous
()
Ответ на: комментарий от Eddy_Em

А как тип терминала определять?

В принципе, когда надо будет, могу нагуглить.

дык анонимус уже ж рассказал

можно еще смотреть на переменную TERM в энвайроменте, но это менее надежно

Skolotovich ★★★
()
Ответ на: комментарий от Eddy_Em

Не факт.

конечно, но это самое простое и быстрое решение (:

Skolotovich ★★★
()
Ответ на: комментарий от Eddy_Em

tput по умолчанию читает переменную TERM. Потом по этой переменной парсит соотв. файл и выдаёт информацию о свойствах терминала. Так что смотреть TERM и выводить «\033[1;32;41m» и т.д. только для известных терминалов достаточно.

А чтобы в файл не выводился мусор, нужно определять файлом или терминалом является STDOUT (STDERR) с помощью isatty().

mky ★★★★★
()
Ответ на: комментарий от Eddy_Em

Можно поподробней? Есть такая библиотека/функция? А то man 3 tput ничего не дает, по tput есть лишь man 1.

Нет, tput надо вызывать как отдельное приложение же, например tput colors. Если хочется именно из си, то надо с terminfo или curses колдовать. Тут много подробностей: http://stackoverflow.com/questions/2465425/how-do-i-determine-if-a-terminal-i...

Просто не всем может быть приятно всовывать тот же curses в приложение, и вызов стороннего tput будет выглядеть лучше.

anonymous
()
Ответ на: комментарий от anonymous

и вызов стороннего tput будет выглядеть лучше.

нуну, с каких это пор system() код красит?

Skolotovich ★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.