From c5c5ff166e1d46726458533f5238e4323b23a8df Mon Sep 17 00:00:00 2001 From: short <> Date: Tue, 9 Aug 2005 05:13:04 +0000 Subject: [PATCH] First final but buggy code. --- inetdmx.c | 287 ++++++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 214 insertions(+), 73 deletions(-) diff --git a/inetdmx.c b/inetdmx.c index 4029438..d1e49c1 100644 --- a/inetdmx.c +++ b/inetdmx.c @@ -18,15 +18,17 @@ #include #include #include +#include +#include +#include +#include #define CONNECT_RETRY_MSEC 100 - -static long opt_start_timeout=60; -static int opt_port; -static int opt_syslog; -static int opt_stderr; -static const char *opt_lock; +#define DEFAULT_START_COMMAND_TIMEOUT 60 +#define DEFAULT_IDLE_SERVER_TIMEOUT (90*60) +#define FLOCK_TIMEOUT_OVER_START_TIMEOUT 2 +#define SESSION_BUFFER_SIZE 0x1000 /* /usr/include/glib-2.0/glib/gmacros.h */ @@ -59,6 +61,16 @@ static const char *opt_lock; static const char *program_name; +static int opt_start; +static int opt_stop; +static long opt_start_command_timeout=DEFAULT_START_COMMAND_TIMEOUT; +static long opt_idle_server_timeout=DEFAULT_IDLE_SERVER_TIMEOUT; +static int opt_port; +static int opt_syslog; +static int opt_stderr; +static const char *opt_lock; +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,...) { @@ -89,25 +101,96 @@ const char *const error_error="Error printing error message"; static void usage(void) { fprintf(stderr,"\ -Syntax: %s [{-T|--start-timeout} ]\n\ - {-p|--port} \n\ +Syntax: %s {-1|--start} [{-T|--start-command-timeout} ]\n\ + \t[{-l|--lock} ] [-S|--syslog] [-e|--stderr]\n\ + \t{-p|--port} \n\ + or %s {-0|--stop} [{-i|--idle-server-timeout} ]\n\ + \t[{-l|--lock} ] [-S|--syslog] [-e|--stderr]\n\ + \t\n\ \n\ -Error messages out to stderr by default, -S|--syslog omits stderr output,\n\ -both -S|--syslog and -e|--stderr output the errors by both methods.\n\ -\n",program_name); +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\ +\n",program_name,program_name); exit(EXIT_FAILURE); } static const struct option longopts[]={ - {"start-timeout",1,0,'T'}, - {"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'}, + {NULL ,0,0,0 }, }; +static int lock_fd=-1; + +static int sighandler_flock_timeout_hit; +static void sighandler_flock_timeout(int signo) +{ + sighandler_flock_timeout_hit=1; +} + +static int lock_create(int lock_mode) +{ +int retries=3; +sighandler_t sighandler_alrm_orig; +int flock_rc; + + if (!opt_lock) + return 1; + /* Never drop the lock if the lock is already being held. */ + if (lock_fd!=-1) + retries=-1; +retry: + if (lock_fd==-1) { + if (-1==(lock_fd=open(opt_lock,O_CREAT|O_RDWR,0600))) + fatal("Error creating lock file \"%s\": %m",opt_lock); + } + sighandler_alrm_orig=signal(SIGALRM,sighandler_flock_timeout); + alarm(opt_start_command_timeout+FLOCK_TIMEOUT_OVER_START_TIMEOUT); + flock_rc=flock(lock_fd,lock_mode); + alarm(0); + signal(SIGALRM,sighandler_alrm_orig); + if (sighandler_flock_timeout_hit) + fatal("Timeout locking lock file \"%s\": %m",opt_lock); + if (flock_rc) { + if (lock_mode&LOCK_NB && errno==EWOULDBLOCK) + return 0; + fatal("Error locking lock file \"%s\": %m",opt_lock); + } + 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)) + fatal("Error closing lock file \"%s\": %m",opt_lock); + lock_fd=-1; + goto retry; + } + return 1; +} + +static void lock_touch(void) +{ + if (!opt_lock || lock_fd==-1) + return; + if (utime(opt_lock,NULL)) + fatal("Error updating lock file \"%s\" timestamp: %m",opt_lock); +} + +static void lock_close(void) +{ + if (lock_fd==-1) + return; + if (close(lock_fd)) + fatal("Error closing lock file \"%s\": %m",opt_lock); + lock_fd=-1; +} + static int connect_try(void) { int fdtcp; @@ -152,8 +235,10 @@ int fdi,fdo; for (fdi=0;fdi=G_N_ELEMENTS(pollfdi)) + if (fdi>=G_N_ELEMENTS(pollfdi)) { + lock_close(); exit(EXIT_SUCCESS); + } if (0>=poll(pollfdi,G_N_ELEMENTS(pollfdi),-1)) fatal("poll(%s socket,%s socket): %m",pollfdi_name[0],pollfdi_name[1]); for (fdi=0;fdi=time(NULL)-opt_idle_server_timeout; } -static void lock_close(void) +static void lock_delete_and_close(void) { - if (lock_fd==-1) + /* Should not happen. */ + if (!opt_lock || lock_fd==-1) return; - if (close(lock_fd)) - fatal("Error closing lock file \"%s\": %m",opt_lock); - lock_fd=-1; + if (unlink(opt_lock)) + fatal("Error deleting no longer used lock file \"%s\": %m",opt_lock); + lock_close(); +} + +static void stop(void) G_GNUC_NORETURN; +static void stop(void) +{ +int is_fresh; + + /* Lock still being held! */ + if (opt_port) + fatal("-p|--port is a forbidden argument for -0|--stop"); + if (opt_start_command_timeout!=DEFAULT_START_COMMAND_TIMEOUT) + fatal("-T|--start-command-timeout is a forbidden argument for -0|--stop"); + if (opt_idle_server_timeout!=DEFAULT_IDLE_SERVER_TIMEOUT && !opt_lock) + fatal("-l|--lock is a required argument for -i|--idle-server-timeout of -1|--start"); + + is_fresh=lock_create_and_time_check(LOCK_SH); + lock_close(); + if (is_fresh) + exit(EXIT_SUCCESS); + + lock_create_and_time_check(LOCK_EX); + system_checked(opt_command); + lock_delete_and_close(); + + exit(EXIT_SUCCESS); } +int main(int argc,char **argv) G_GNUC_NORETURN; int main(int argc,char **argv) { -int retry; -const char *command; char optc; if ((program_name=strrchr(argv[0],'/'))) @@ -285,11 +414,26 @@ char optc; long l; char *endptr; - case 'T': /* -T|--start-timeout */ + case '1': /* -1|--start */ + opt_start=1; + break; + + case '0': /* -0|--stop */ + opt_stop=1; + break; + + case 'T': /* -T|--start-command-timeout */ + l=strtol(optarg,&endptr,0); + if (l<=0 || l>=LONG_MAX-FLOCK_TIMEOUT_OVER_START_TIMEOUT || (endptr && *endptr)) + fatal("Invalid -T|--start-command-timeout value: %s",optarg); + opt_start_command_timeout=l; + break; + + case 'i': /* -i|--idle-server-timeout */ l=strtol(optarg,&endptr,0); if (l<=0 || l>=LONG_MAX || (endptr && *endptr)) - fatal("Invalid -T|--start-timeout values: %s",optarg); - opt_start_timeout=l; + fatal("Invalid -i|--idle-server-timeout value: %s",optarg); + opt_idle_server_timeout=l; break; case 'S': /* -S|--syslog */ @@ -312,28 +456,25 @@ char *endptr; default: if (optc!='h') - fatal("Error parsing commandline!"); + fatal("Error parsing commandline"); usage(); break; } - if (!opt_port) - fatal("-p|--port is a required argument!"); + if (!opt_start && !opt_stop) + fatal("At least one of -1|--opt-start or -0|--opt-stop is required"); + if ( opt_start && opt_stop) + fatal("Both modes -1|--opt-start and -0|--opt-stop can never be specified simultaneously"); + if (optind>=argc) - fatal(" is a required argument!"); + fatal(" is a required argument"); if (optind+1 needs quoting?"); - command=argv[optind]; - - lock_create(); - session_try(); - system_checked(command); - - for (retry=0;retry*CONNECT_RETRY_MSEC/1000 may need quoting"); + opt_command=argv[optind]; + + if (opt_start) + start(); + if (opt_stop) + stop(); + assert(0); } -- 1.8.3.1