summaryrefslogtreecommitdiff
path: root/cgitcgi/system.c
diff options
context:
space:
mode:
authorkx <kx@radix.pro>2023-03-24 03:51:10 +0300
committerkx <kx@radix.pro>2023-03-24 03:51:10 +0300
commit05d292b208dfe01324826b4c87bbc4da3389a0d5 (patch)
treeb10a2269e9320785f3b61189e75f6778fa167986 /cgitcgi/system.c
parent40ab18a661ff6ada40e73969be293918d346a2f5 (diff)
downloadcgit-ui-05d292b208dfe01324826b4c87bbc4da3389a0d5.tar.xz
Version 0.1.7
Diffstat (limited to 'cgitcgi/system.c')
-rw-r--r--cgitcgi/system.c177
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;
+}