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