Операционная система UNIX
Последний тип сообщений подсказывает еще одну возможность использования системного журнала — для отладки программ, особенно неинтерактивных.
Строка
может включать элементы форматирования, такие же, как и в функции printf(3), с одним дополнительным выражениемlogstring, которое заменяется сообщением, соответствующим ошибке%m. При этом может осуществляться вывод значений дополнительных параметров.errnoФункция openlog(3) позволяет определить ряд опций ведения журнала. Она имеет следующее определение:
void openlog(char *ident, int logopt, int facility);Строка
будет предшествовать каждому сообщению программы. Аргументidentзадает дополнительные опции, в том числе:logopt
LOG_PIDПозволяет указывать идентификатор процесса в каждом сообщении. Эта опция полезна при журналировании нескольких демонов с одним и тем же значением ident, например, когда демоны порождаются вызовом fork(2). LOG_CONSПозволяет выводить сообщения на консоль при невозможности записи в журнал. Наконец, аргумент
позволяет определить источник сообщений:facility
LOG_KERNУказывает, что сообщения отправляются ядром. LOG_USERУказывает, что сообщения отправлены прикладным процессом (используется по умолчанию). LOG_MAILУказывает, что инициатором сообщений является система электронной почты. LOG_DAEMONУказывает, что инициатором сообщений является системный демон. LOG_NEWSУказывает, что инициатором сообщений является система телеконференций USENET. LOG_CRONУказывает, что инициатором сообщений является система cron(1). Закончив работу с журналом, следует аккуратно закрыть его с помощью функции closelog(3):
void closelog(void);Командный интерпретатор
Для примера интерактивного приложения, мы выбрали простейший командный интерпретатор. Данный пример позволяет продемонстрировать использование системных вызовов для порождения процесса, запуска программы и синхронизации выполнения процессов.
Функции приведенного командного интерпретатора сведены к минимуму: он распознает и выполняет несколько встроенных команд, остальной ввод он расценивает как внешние программы, которые и пытается запустить с помощью системного вызова exec(2).
#include <sys/types.h>#include <sys/wait.h>#include <unistd.h>extern char** environ;#define CMDSIZE 80/* Встроенные команды интерпретатора */#define CD 1#define ECHO 2#define EXEC 3 ...#define PROGRAM 1000/* Функция, которая производит анализ строки, введеннойпользователем, выполняет подстановки и определяет,встроенная ли это команда или программа. В качестве аргументафункция принимает строку cmdbuf, введенную пользователем,и возвращает имя команды/программы path и переданные ейпараметры arguments. Возвращаемое значение указывает навнутреннюю команду или внешнюю программу, которую необходимозапустить.*/int parse_command(char* cmdbuf, char* path, char** arguments);main {charcmd[CMDSIZE];int command;int stat_loc;char** args;char cmdpath[MAXPATH];while (1) {/* Выведем сообщение интерпретатора */write(1, "$ ", 2);/* Считаем ввод пользователя и проанализируем строку */cmdsize = read(0, cmd, CMDSIZE);cmd[cmdsize-1] ='\0';command = parse_command(cmd, cmdpath, args);switch(command) {/* Если это внутренняя команда, обработаем ее */case (CD):chdir(args[0]);break;case(ECHO):write(1, args[0], strlen(args[0]));break;case(EXEC):execve(path, args, environ);write(2, "shell: cannot execute", 21);break;.../* Если это внешняя программа, создадим дочерний процесс, которыйи запустит программу */case(PROGRAM):pid = fork();if (pid < 0)write(2, "shell: cannot fork", 18);else if (pid == 0) {/* Дочерний процесс */execve(path, args, environ);