Литмир - Электронная Библиотека
A
A

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

Строка

logstring
может включать элементы форматирования, такие же, как и в функции printf(3), с одним дополнительным выражением
%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);

60
{"b":"272553","o":1}