#ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #define SYSTEM_ERRMSG_SIZE 4096 void system_error( const char *fmt, ... ) { va_list arg_ptr; char buf[SYSTEM_ERRMSG_SIZE]; char msg[SYSTEM_ERRMSG_SIZE]; char *format = "%s: %s\n"; va_start( arg_ptr, fmt ); vsnprintf( msg, SYSTEM_ERRMSG_SIZE, (const void *)fmt, arg_ptr ); va_end( arg_ptr ); /* Reset variable arguments. */ snprintf( buf, SYSTEM_ERRMSG_SIZE, format, "system", msg ); (void)write( STDERR_FILENO, buf, strlen( buf ) ); exit( 1 ); } system_errfunc system_fatal = system_error; static void xexec( const char *cmd ) { char *argv[4]; const char *shell = getenv ("SHELL"); if( !shell ) shell = "/bin/sh"; argv[0] = (char *) shell; argv[1] = (char *) "-c"; argv[2] = (char *) cmd; argv[3] = NULL; execv( shell, argv ); /****************************************** xexec() is called by child process, and here child process faced to FATAL error: */ system_fatal( "Cannot exec '%s'\n", cmd ); } static pid_t xfork( void ) { pid_t p = fork(); if( p == (pid_t) -1 ) { system_fatal( "Cannot %s: %s\n", "fork()", strerror( errno ) ); } return p; } pid_t sys_exec_command( struct strbuf *sb, const char *cmd ) { int pipe_fh[2]; pid_t pid = -1; if( sb ) { if( pipe(pipe_fh ) == -1 ) { system_fatal( "Cannot create pipe: %s\n", strerror( errno ) ); } } pid = xfork(); if( pid != 0 ) { if( sb ) { ssize_t ret; close(pipe_fh[1]); ret = strbuf_read( sb, pipe_fh[0], 1024 ); if( ret < 0 ) system_fatal( "Cannot read pipe: %s\n", strerror( errno ) ); close(pipe_fh[0]); } return pid; } if( sb ) { dup2(pipe_fh[1], STDOUT_FILENO); close(pipe_fh[1]); close(pipe_fh[0]); } xexec( cmd ); return pid; /* only to avoid compilaton warning */ } /***************************************************************** sys_wait_command() - Wait for pid. Return values: ------------- 0 - SUCCESS >=1 - status returned by child process -1 - Child terminated on signal -2 - Child terminated on unknown reason -3 - Cannot waitpid: waitpid() retusrs -1 Error message with SIZE length saved into *ERRMSG buffer. *****************************************************************/ int sys_wait_command( pid_t pid, struct strbuf *errmsg ) { int status; if( pid < 0 ) return (pid_t) -1; while( waitpid( pid, &status, 0 ) == -1 ) if( errno != EINTR ) { if( errmsg ) { strbuf_addf( errmsg, "PID %lu: Cannot %s", (unsigned long)pid, "waitpid" ); } return (int) -3; } if( WIFEXITED( status ) ) { if( WEXITSTATUS (status) ) { if( errmsg ) { strbuf_addf( errmsg, "PID %lu: Child returned status %d", (unsigned long)pid, WEXITSTATUS( status ) ); } return (int) WEXITSTATUS( status ); } } else if( WIFSIGNALED( status ) ) { if( errmsg ) { strbuf_addf( errmsg, "PID %lu: Child terminated on signal %d", (unsigned long)pid, WTERMSIG( status ) ); } return (int) -1; } else { if( errmsg ) { strbuf_addf( errmsg, "PID %lu: Child terminated on unknown reason", (unsigned long)pid ); } return (int) -2; } return 0; }