From 009beb6c39a09220131eed12a9d79a83e140e245 Mon Sep 17 00:00:00 2001 From: short <> Date: Tue, 9 Aug 2005 06:10:04 +0000 Subject: [PATCH] Looks as generally working now. --- inetdmx.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 120 insertions(+), 29 deletions(-) diff --git a/inetdmx.c b/inetdmx.c index d1e49c1..ebab3bf 100644 --- a/inetdmx.c +++ b/inetdmx.c @@ -29,6 +29,8 @@ #define DEFAULT_IDLE_SERVER_TIMEOUT (90*60) #define FLOCK_TIMEOUT_OVER_START_TIMEOUT 2 #define SESSION_BUFFER_SIZE 0x1000 +#define SYSTEM_CHECKED_BUFFER_SIZE_MIN 0x1000 +#define SYSTEM_CHECKED_BUFFER_SIZE (LINE_MAX > SYSTEM_CHECKED_BUFFER_SIZE_MIN ? LINE_MAX : SYSTEM_CHECKED_BUFFER_SIZE_MIN) /* /usr/include/glib-2.0/glib/gmacros.h */ @@ -69,62 +71,104 @@ static int opt_port; static int opt_syslog; static int opt_stderr; static const char *opt_lock; +static int opt_ignore_spawned_command_output; static const char *opt_command; + static void fatal(const char *fmt,...) G_GNUC_PRINTF(1,2) G_GNUC_NORETURN; -static void fatal(const char *fmt,...) + +static void verror(const char *fmt,va_list ap) G_GNUC_PRINTF(1,0); +static void verror(const char *fmt,va_list ap) { int use_syslog=opt_syslog,use_stderr=opt_stderr; -va_list ap; char *string; -const char *const error_error="Error printing error message"; +const char *const double_error="Error printing error message"; if (!use_syslog && !use_stderr) use_stderr=1; - va_start(ap,fmt); if (-1==vasprintf(&string,fmt,ap)) { - if (fmt==error_error) + if (fmt==double_error) exit(EXIT_FAILURE); - fatal(error_error); + fatal(double_error); } if (use_stderr) - fprintf(stderr,"%s: %s!\n",program_name,string); + fprintf(stderr,"%s: %s\n",program_name,string); if (use_syslog) { openlog(program_name,LOG_PID,LOG_DAEMON); - syslog(LOG_DAEMON|LOG_ERR,"%s!",string); + syslog(LOG_DAEMON|LOG_ERR,"%s",string); closelog(); } +} + +static void error(const char *fmt,...) G_GNUC_PRINTF(1,2); +static void error(const char *fmt,...) +{ +va_list ap; + + va_start(ap,fmt); + verror(fmt,ap); + va_end(ap); +} + +static void fatal(const char *fmt,...) +{ +va_list ap; + + va_start(ap,fmt); + verror(fmt,ap); va_end(ap); exit(EXIT_FAILURE); } +static char *asprintf_checked(const char *fmt,...) G_GNUC_PRINTF(1,2); +static char *asprintf_checked(const char *fmt,...) +{ +char *string; +va_list ap; +int rc; + + va_start(ap,fmt); + rc=vasprintf(&string,fmt,ap); + va_end(ap); + if (rc==-1) + fatal("Error formatting string using formatstring: %s",fmt); + return string; +} + static void usage(void) { fprintf(stderr,"\ Syntax: %s {-1|--start} [{-T|--start-command-timeout} ]\n\ \t[{-l|--lock} ] [-S|--syslog] [-e|--stderr]\n\ + \t\[-I|--ignore-spawned-command-output]\n\ \t{-p|--port} \n\ or %s {-0|--stop} [{-i|--idle-server-timeout} ]\n\ \t[{-l|--lock} ] [-S|--syslog] [-e|--stderr]\n\ + \t\[-I|--ignore-spawned-command-output]\n\ \t\n\ \n\ Error messages are printed to stderr by default,\n\ -S|--syslog omits stderr output, both -S|--syslog and -e|--stderr output\n\ the errors by both methods.\n\ +-I|--ignore-spawned-command-output will no longer warn of any stdout/stderr\n\ +output of <*-server-command>s but it will no longer stuck if they held their\n\ +output descriptors open.\n\ \n",program_name,program_name); exit(EXIT_FAILURE); } static const struct option longopts[]={ - {"start" ,0,0,'1'}, - {"stop" ,0,0,'0'}, - {"start-command-timeout",1,0,'T'}, - {"idle-server-timeout" ,1,0,'i'}, - {"syslog" ,0,0,'S'}, - {"stderr" ,0,0,'e'}, - {"lock" ,1,0,'l'}, - {"port" ,1,0,'p'}, - {NULL ,0,0,0 }, + {"start" ,0,0,'1'}, + {"stop" ,0,0,'0'}, + {"start-command-timeout" ,1,0,'T'}, + {"idle-server-timeout" ,1,0,'i'}, + {"syslog" ,0,0,'S'}, + {"stderr" ,0,0,'e'}, + {"lock" ,1,0,'l'}, + {"port" ,1,0,'p'}, + {"ignore-spawned-command-output",0,0,'I'}, + {"help" ,0,0,'h'}, + {NULL ,0,0,0 }, }; static int lock_fd=-1; @@ -163,7 +207,7 @@ retry: return 0; fatal("Error locking lock file \"%s\": %m",opt_lock); } - if (!access(opt_lock,R_OK|W_OK)) { + if (access(opt_lock,R_OK|W_OK)) { if (retries--<=0) fatal("Racing for the lock file \"%s\", giving up",opt_lock); if (close(lock_fd)) @@ -290,11 +334,52 @@ int fdtcp; session_transfer("remote",STDIN_FILENO,STDOUT_FILENO,"local",fdtcp,fdtcp); } +static int popen_pclose_checked(const char *command) +{ +FILE *f; +char buf[SYSTEM_CHECKED_BUFFER_SIZE]; +size_t got; + + if (!(f=popen(command,"r"))) + fatal("Error opening spawned command \"%s\": %m",command); + setlinebuf(f); + while ((got=fread(buf,1,sizeof(buf)-1,f))) { +char *s,*s_next; + + assert(got&1",command) + ); + else + rc=system(opt_stderr + ? asprintf_checked("(%s) >&2",command) + : asprintf_checked("(%s) &>/dev/null",command) + ); if (WIFEXITED(rc) && !WEXITSTATUS(rc)) return; if (WIFEXITED(rc)) @@ -355,22 +440,20 @@ static int lock_create_and_time_check(int lock_mode) struct stat statbuf; if (!opt_lock) - return 1; + return 0; if (!lock_create(lock_mode|LOCK_NB)) exit(EXIT_SUCCESS); - if (lock_fd==-1 || !fstat(lock_fd,&statbuf)) + if (lock_fd==-1 || fstat(lock_fd,&statbuf)) fatal("Error fstat(2)ting lock file \"%s\": %m",opt_lock); return statbuf.st_mtime>=time(NULL)-opt_idle_server_timeout; } static void lock_delete_and_close(void) { - /* Should not happen. */ - if (!opt_lock || lock_fd==-1) - return; - if (unlink(opt_lock)) - fatal("Error deleting no longer used lock file \"%s\": %m",opt_lock); + if (opt_lock && lock_fd!=-1) + if (unlink(opt_lock)) + fatal("Error deleting no longer used lock file \"%s\": %m",opt_lock); lock_close(); } @@ -410,7 +493,7 @@ char optc; program_name=argv[0]; optarg=NULL; optind=0; /* FIXME: Possible portability problem. */ - while ((optc=getopt_long(argc,argv,"c:d:L:l:b:xCM:P:s:m:r:t:T:w:fvhV",longopts,NULL))!=EOF) switch (optc) { + while ((optc=getopt_long(argc,argv,"01T:i:Sel:p:Ih",longopts,NULL))!=EOF) switch (optc) { long l; char *endptr; @@ -446,6 +529,11 @@ char *endptr; case 'l': /* -l|--lock */ opt_lock=optarg; + break; + + case 'I': /* -I|--ignore-spawned-command-output */ + opt_ignore_spawned_command_output=1; + break; case 'p': /* -p|--port */ l=strtol(optarg,&endptr,0); @@ -462,9 +550,9 @@ char *endptr; } if (!opt_start && !opt_stop) - fatal("At least one of -1|--opt-start or -0|--opt-stop is required"); + fatal("At least one of -1|--start or -0|--stop is required"); if ( opt_start && opt_stop) - fatal("Both modes -1|--opt-start and -0|--opt-stop can never be specified simultaneously"); + fatal("Both modes -1|--start and -0|--stop can never be specified simultaneously"); if (optind>=argc) fatal(" is a required argument"); @@ -472,6 +560,9 @@ char *endptr; fatal("Too many arguments, may need quoting"); opt_command=argv[optind]; + if (!opt_syslog && !opt_stderr) + opt_stderr=1; + if (opt_start) start(); if (opt_stop) -- 1.8.3.1