diff options
author | kx <kx@radix.pro> | 2023-03-24 03:51:10 +0300 |
---|---|---|
committer | kx <kx@radix.pro> | 2023-03-24 03:51:10 +0300 |
commit | 05d292b208dfe01324826b4c87bbc4da3389a0d5 (patch) | |
tree | b10a2269e9320785f3b61189e75f6778fa167986 /cgitcgi/system.c | |
parent | 40ab18a661ff6ada40e73969be293918d346a2f5 (diff) | |
download | cgit-ui-05d292b208dfe01324826b4c87bbc4da3389a0d5.tar.xz |
Version 0.1.7
Diffstat (limited to 'cgitcgi/system.c')
-rw-r--r-- | cgitcgi/system.c | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/cgitcgi/system.c b/cgitcgi/system.c new file mode 100644 index 0000000..afab9a7 --- /dev/null +++ b/cgitcgi/system.c @@ -0,0 +1,177 @@ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <error.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include <stdarg.h> +#include <unistd.h> + +#include <defs.h> + +#include <strbuf.h> +#include <system.h> + + +#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; +} |