Реализация функции «system» в Unix

А. Вылиток

Функция int system (charcmd) из библиотеки передает свой аргумент-строку cmd на выполнение стандартному командному интерпретатору системы. В Unix стандартный интерпретатор shell (sh) хранится в файле «/bin/sh». Команда cmd может представлять собой простую команду shell или состоять из серии команд, разделенных точкой с запятой или символами канала, можно также задавать переназначение ввода/вывода. Вызвавший функцию system() процесс ожидает исполнения команды. После выполнения cmd порожденный процесс sh завершается, и его статус завершения передается в родительский процесс как результат функции system().

Программу-интерпретатор sh можно вызывать с двумя параметрами: флагом «–c» и параметром-командой, которую нужно выполнить, например:

$ sh –c "ls | cat –n"

В результате будет запущен процесс sh, он выполнит переданную ему как параметр команду «ls | cat –n» и завершится. Используем возможность опции «–с» для реализации system().

#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>
 
/* эмуляция функции system () */
 
int MySystem ( const char* cmd )
{
  pid_t  pid;
  int    status;
 
  switch ( pid=fork() )
  {
    case (pid_t) -1:
      /* fork не удался */
      return -1;
    case (pid_t)  0:
      execl  ( "/bin/sh", "sh", "-c", cmd, 0 );
      perror ( "execl" );
      exit   ( errno );
    default:
      /* nothing */;  
  }
  if ( pid == waitpid ( pid, &status, 0 ) && WIFEXITED ( status ) )
    return ( WEXITSTATUS ( status ) );
  return -1;
}
 
int main ()
{
  int    return_code=0;
  char   buf[1024];
 
  do
  { 
    printf ( "sh> " );
    fflush ( stdout );
    if ( !fgets ( buf, 1024, stdin ) )
      break;
    return_code = MySystem(buf);
  }
  while ( !return_code );
 
  return (return_code);
}

В настоящей system() игнорируются сигналы SIGINT и SIGQUIT и блокируется SIGCHLD.