2013-06-19 6 views
2

В базовом уровне программного обеспечения, которое я поддерживаю, имеется 150 заявлений, распространяемых среди различных приложений C, которые совершают вызов другой команды Linux (например, rm -rf ...) или настраиваемому приложению с использованием status = system(cmd)/256. Когда либо вызывается, код состояния, возвращаемый из команды Linux или пользовательского приложения, делится на . Так что, когда код состояния больше 0, мы знаем, что была проблема. Однако, как написано программное обеспечение, он не всегда регистрирует, какая команда или приложение вернули код состояния. Так что, если в коде состояния было указано 32768, при делении на 256, код состояния - .Определить код статуса выхода для выхода

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

Есть ли способ определить исходный код состояния в стандартном файле журнала Linux и приложении, которое его вернуло?

+1

Напишите обертку (функцию или макрос), которая вызывает исходную 'system()' и записывает полный результат перед возвратом. – alk

+1

Код состояния, возвращаемый 'system', помещается в один байт, если команда не получила сигнал (например, сбой с' SIGSEGV') –

+0

@BasileStarynkevitch: Тогда зачем делиться на 256? Я вижу коды ошибок, такие как 32768. –

ответ

4

Как написать обертку

После примера о том, как применить обертку вокруг LibC функции system().

Создать новый модуль (перевод единиц) называется system_wrapper.c так:

Заголовок system_wrapper.h:

#ifndef _SYSTEM_WRAPPER 
#define _SYSTEM_WRAPPER 

#define system(cmd) system_wrapper(cmd) 

int system_wrapper(const char *); 

#endif 

Модуль system_wrapper.c:

#include <stdlib.h> /* to prototype the original function, that is libc's system() */ 
#include "system_wrapper.h" 

#undef system 

int system_wrapper(const char * cmd) 
{ 
    int result = system(cmd); 

    /* Log result here. */ 

    return result; 
} 

Добавьте эту строку для всех модулей с использованием system():

#include "system_wrapper.h" 
+0

Хорошая идея .. это похоже на вызов system()/bin/sh -c. Есть ли способ заставить его позвонить/bin/sh -x -c вместо этого? http://linux.die.net/man/3/system –

+0

Что я имею в виду, так это то, что в программах на языке C он обращается к системе 'stdlib' ** и по ссылке, которую я опубликовал в комментарии выше, он вызывает/bin/sh -c. Я предполагаю, что это жестко закодировано в 'stdlib'. Не уверен, что это можно изменить без принудительной перекомпиляции –

+0

Я бы сказал, что recomopiling libc не должен быть вариантом. – alk

2

Как я заметил, system(3) библиотечная функция возвращает результат ожидания системного вызова, как waitpid(2). (Пожалуйста, перейдите по ссылкам на страницы руководства).

Таким образом, вы должны улучшить вашу программу использовать WIFEXITED, WIFSIGNALED, WEXITSTATUS, WTERMSIG стандартные (Posix) макросы в результате вызовов system (кроме случаев, когда этот результат -1, а затем использовать errno).

Кодирование

status = system(cmd)/256; 

неразборчивое (для человеческого разработчика) и непереносимым.

Я думаю, кодировщик, который закодированный, который хотел поймать прерванные команды ....

Вы должны заменить, что с

status = system(cmd); 
if (status < 0) /* e.g. fork failed */ 
    do_something_with_error_code (errno); 
else if (status == 0) /* cmd run without errors */ 
    do_something_to_tell_command_exited_ok(); 
else if (WIFEXITED(status)) /* cmd got an error */ 
    do_something_with_exit_code (WEXITSTATUS(status)); 
else if (WIFSIGNALED(status)) /* cmd or the shell got a signal */ 
    do_something_with_terminating_signal (WTERMSIG(status)); 

BTW, используя system("rm -rf /some/dir"); считается плохой практикой (что, если пользователь сделал свой собственный rm в своем $PATH) и не очень эффективен.(Можно использовать, например, nftw(3) с unlink(2)) или не менее /bin/rm -rf; но как насчет пробелов в имени каталога или dirty IFS tricks?)

+0

Базиле, не могли бы вы прояснить формулировку в своем последнем предложении? Для других: при использовании 'nftw (..., FTW_DEPTH)', 'unlink()' для файлов и 'rmdir()' для пустых каталогов (поэтому вы хотите выполнить поиск по глубине - для удаления файлов во-первых), все возможные имена файлов обрабатываются правильно (если вы не устанавливаете языковой стандарт или не устанавливаете языковой стандарт 'C' или' POSIX', поскольку последовательности, отличные от UTF-8 в локалях UTF-8, обычно прерывают C библиотечные функции). Проблемы с пробелами или грязными трюками IFS и так далее происходят только с 'system()'. –

Смежные вопросы