/*
- * $Id$ */
+ * $Id$
* Latest:
- * http://cvs.jankratochvil.net/viewcvs/*checkout*/nethome/src/inetdmx.c?rev=HEAD
+ * http://cvs.jankratochvil.net/viewcvs/nethome/src/inetdmx.c?rev=HEAD
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
fprintf(stderr,"\
Syntax: %s {-1|--start} [{-T|--start-command-timeout} <start-command-timeout>]\n\
\t[{-l|--lock} <filename>] [-S|--syslog] [-e|--stderr]\n\
- \t\[-I|--ignore-spawned-command-output]\n\
+ \t[-I|--ignore-spawned-command-output]\n\
\t{-p|--port} <server-port> <start-server-command>\n\
or %s {-0|--stop} [{-i|--idle-server-timeout} <idle-server-timeout>]\n\
\t[{-l|--lock} <filename>] [-S|--syslog] [-e|--stderr]\n\
- \t\[-I|--ignore-spawned-command-output]\n\
+ \t[-I|--ignore-spawned-command-output]\n\
\t<stop-server-command>\n\
\n\
Error messages are printed to stderr by default,\n\
sighandler_flock_timeout_hit=1;
}
-static int lock_create(int lock_mode)
+enum lock_create_rc {
+ LOCK_CREATE_NO_LOCK_FILENAME,
+ LOCK_CREATE_FILE_NOT_FOUND, /* only if: lock_mode&LOCK_NB */
+ LOCK_CREATE_ALREADY_LOCKED, /* only if: lock_mode&LOCK_NB */
+ LOCK_CREATE_MYSELF_LOCKED, /* only for: lock_create() */
+ LOCK_CREATE_MYSELF_LOCKED_AND_FRESH, /* only for: lock_open_and_time_check() */
+ LOCK_CREATE_MYSELF_LOCKED_AND_STALE, /* only for: lock_open_and_time_check() */
+ };
+/* It will never create the lock file if: lock_mode&LOCK_NB */
+static enum lock_create_rc lock_create(int lock_mode)
{
int retries=3;
sighandler_t sighandler_alrm_orig;
int flock_rc;
if (!opt_lock)
- return 1;
+ return LOCK_CREATE_NO_LOCK_FILENAME;
/* 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)))
+ if (-1==(lock_fd=open(opt_lock,
+ O_RDWR | (lock_mode&LOCK_NB ? 0 : O_CREAT),
+ 0600))) {
+ if (errno==ENOENT && lock_mode&LOCK_NB)
+ return LOCK_CREATE_FILE_NOT_FOUND;
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);
fatal("Timeout locking lock file \"%s\": %m",opt_lock);
if (flock_rc) {
if (lock_mode&LOCK_NB && errno==EWOULDBLOCK)
- return 0;
+ return LOCK_CREATE_ALREADY_LOCKED;
fatal("Error locking lock file \"%s\": %m",opt_lock);
}
if (access(opt_lock,R_OK|W_OK)) {
lock_fd=-1;
goto retry;
}
- return 1;
+ return LOCK_CREATE_MYSELF_LOCKED;
}
static void lock_touch(void)
{
struct pollfd pollfdi[2];
int pollfdo[2];
-const char *pollfdi_name[2];
+const char *pollfd_name[2];
int fdi,fdo;
pollfdi[0].fd=conn0_fdin;
pollfdi[1].events=POLLIN;
pollfdo[0]=conn0_fdout;
pollfdo[1]=conn1_fdout;
- pollfdi_name[0]=conn0_name;
- pollfdi_name[1]=conn1_name;
+ pollfd_name[0]=conn0_name;
+ pollfd_name[1]=conn1_name;
for (;;) {
if (0>=poll(pollfdi,G_N_ELEMENTS(pollfdi),-1))
- fatal("poll(%s socket,%s socket): %m",pollfdi_name[0],pollfdi_name[1]);
+ fatal("poll(%s socket,%s socket): %m",pollfd_name[0],pollfd_name[1]);
for (fdi=0;fdi<G_N_ELEMENTS(pollfdi);fdi++)
if (0
|| pollfdi[fdi].revents & (POLLERR|POLLHUP|POLLNVAL)
|| ((pollfdi[fdi].revents & POLLIN) && !(pollfdi[fdi].events & POLLIN))
)
fatal("poll(%s socket): revents=0x%X (events=0x%X)",
- pollfdi_name[fdi],(unsigned)pollfdi[fdi].revents,
+ pollfd_name[fdi],(unsigned)pollfdi[fdi].revents,
(unsigned)pollfdi[fdi].events);
for (fdi=0;fdi<G_N_ELEMENTS(pollfdi);fdi++) {
for (;;) {
char buf[SESSION_BUFFER_SIZE];
if (fcntl(pollfdi[fdi].fd,F_SETFL,O_NONBLOCK))
- fatal("fcntl(%s socket,F_SETFL,O_NONBLOCK): %m",pollfdi_name[fdi]);
+ fatal("fcntl(%s socket,F_SETFL,O_NONBLOCK): %m",pollfd_name[fdi]);
got=read(pollfdi[fdi].fd,buf,sizeof(buf));
if (got<0) {
if (errno==EAGAIN)
break;
- fatal("read(%s socket): %m",pollfdi_name[fdi]);
+ fatal("read(%s socket): %m",pollfd_name[fdi]);
}
if (got==0) {
lock_close();
exit(EXIT_SUCCESS);
}
- for (fdo=0;fdo<G_N_ELEMENTS(pollfdi);fdo++) {
+ for (fdo=0;fdo<G_N_ELEMENTS(pollfdo);fdo++) {
if (fdi==fdo)
continue;
- if (fcntl(pollfdi[fdo].fd,F_SETFL,0 /* !O_NONBLOCK */))
+ if (fcntl(pollfdo[fdo],F_SETFL,0 /* !O_NONBLOCK */))
fatal("fcntl(%s socket,F_SETFL,0 /* !O_NONBLOCK */): %m",
- pollfdi_name[fdo]);
- if (got!=write(pollfdi[fdo].fd,buf,got))
+ pollfd_name[fdo]);
+ if (got!=write(pollfdo[fdo],buf,got))
fatal("write(%s socket,%ld): %m",
- pollfdi_name[fdo],(long)got);
+ pollfd_name[fdo],(long)got);
}
}
}
opt_start_command_timeout,opt_port,opt_command);
}
-/* Returns: Is fresh? */
-static int lock_create_and_time_check(int lock_mode)
+static enum lock_create_rc lock_open_and_time_check(int lock_mode)
{
+enum lock_create_rc rc;
struct stat statbuf;
- if (!opt_lock)
- return 0;
-
- if (!lock_create(lock_mode|LOCK_NB))
- exit(EXIT_SUCCESS);
+ if (LOCK_CREATE_MYSELF_LOCKED!=(rc=lock_create(lock_mode|LOCK_NB)))
+ return rc;
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;
+ return (statbuf.st_mtime>=time(NULL)-opt_idle_server_timeout
+ ? LOCK_CREATE_MYSELF_LOCKED_AND_FRESH : LOCK_CREATE_MYSELF_LOCKED_AND_STALE);
}
static void lock_delete_and_close(void)
lock_close();
}
+static void lock_open_and_return_if_stale(int lock_mode)
+{
+ switch (lock_open_and_time_check(lock_mode)) {
+ case LOCK_CREATE_NO_LOCK_FILENAME: return;
+ case LOCK_CREATE_FILE_NOT_FOUND: exit(EXIT_SUCCESS);
+ case LOCK_CREATE_ALREADY_LOCKED: exit(EXIT_SUCCESS);
+ case LOCK_CREATE_MYSELF_LOCKED: assert(0);
+ case LOCK_CREATE_MYSELF_LOCKED_AND_FRESH: exit(EXIT_SUCCESS);
+ case LOCK_CREATE_MYSELF_LOCKED_AND_STALE: return;
+ }
+ assert(0);
+}
+
static void stop(void) G_GNUC_NORETURN;
static void stop(void)
{
-int is_fresh;
/* Lock still being held! */
if (opt_port)
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_open_and_return_if_stale(LOCK_SH);
lock_close();
- if (is_fresh)
- exit(EXIT_SUCCESS);
- lock_create_and_time_check(LOCK_EX);
+ lock_open_and_return_if_stale(LOCK_EX);
system_checked(opt_command);
lock_delete_and_close();