From c8f380432cf1eb45b364ed16d2e4c098cf45c3e4 Mon Sep 17 00:00:00 2001 From: Carlos Santos Date: Sat, 16 Nov 2019 22:40:46 -0300 Subject: [PATCH] Create a pid file if running in daemon mode - defs.h: #define PIDFILE (default /var/run/crond.pid). - subs.c: make fdprintf return a status, as required by the change in main.c. - main.c: create a pid file by default; add options to disable the pid file cration and to create it at a different path. - crond.8: document the new feature. Signed-off-by: Carlos Santos --- crond.8 | 12 ++++++++++- defs.h | 3 +++ main.c | 62 ++++++++++++++++++++++++++++++++++++++++++++++++++------- subs.c | 9 ++++++--- 4 files changed, 75 insertions(+), 11 deletions(-) diff --git a/crond.8 b/crond.8 index 1582235..a7e9d7c 100644 --- a/crond.8 +++ b/crond.8 @@ -4,7 +4,7 @@ crond - dillon's lightweight cron daemon .SH SYNOPSIS .PP -\f[B]crond [-s dir] [-c dir] [-t dir] [-m user\@host] [-M mailhandler] [-S|-L file] [-l loglevel] [-b|-f|-d]\f[] +\f[B]crond [-s dir] [-c dir] [-t dir] [-m user\@host] [-M mailhandler] [-S|-L file] [-P|-p file] [-l loglevel] [-b|-f|-d]\f[] .SH OPTIONS .PP \f[B]crond\f[] is a background daemon that parses individual @@ -69,6 +69,16 @@ log to specified file instead of syslog. .RS .RE .TP +.B -P +do not create a process-id file. +.RS +.RE +.TP +.B -L file +Write process-id to specified file instead of /var/run/crond.pid. +.RS +.RE +.TP .B -l loglevel log events at the specified, or more important, loglevels. The default is `notice'. diff --git a/defs.h b/defs.h index 5903e6e..819807e 100644 --- a/defs.h +++ b/defs.h @@ -51,6 +51,9 @@ #ifndef SCRONTABS #define SCRONTABS "/etc/cron.d" #endif +#ifndef PIDFILE +#define PIDFILE "/var/run/crond.pid" +#endif #ifndef CRONTABS #define CRONTABS "/var/spool/cron/crontabs" #endif diff --git a/main.c b/main.c index 1fc5cd6..ad9f60a 100644 --- a/main.c +++ b/main.c @@ -32,11 +32,13 @@ short DebugOpt = 0; short LogLevel = LOG_LEVEL; short ForegroundOpt = 0; short SyslogOpt = 1; +short PidFileOpt = 1; const char *CDir = CRONTABS; const char *SCDir = SCRONTABS; const char *TSDir = CRONSTAMPS; const char *LogFile = NULL; /* opened with mode 0600 */ const char *LogHeader = LOGHEADER; +const char *PidFile = PIDFILE; const char *SendMail = NULL; const char *Mailto = NULL; char *TempDir; @@ -72,7 +74,7 @@ main(int ac, char **av) opterr = 0; - while ((i = getopt(ac,av,"dl:L:fbSc:s:m:M:t:")) != -1) { + while ((i = getopt(ac,av,"dl:L:fbSc:s:m:M:t:Pp:")) != -1) { switch (i) { case 'l': { @@ -161,12 +163,19 @@ main(int ac, char **av) case 'm': if (*optarg != 0) Mailto = optarg; break; + case 'P': + PidFileOpt = 0; + break; + case 'p': + PidFileOpt = 1; + PidFile = optarg; + break; default: /* * check for parse error */ printf("dillon's cron daemon " VERSION "\n"); - printf("crond [-s dir] [-c dir] [-t dir] [-m user@host] [-M mailer] [-S|-L [file]] [-l level] [-b|-f|-d]\n"); + printf("crond [-s dir] [-c dir] [-t dir] [-m user@host] [-M mailer] [-S|-L [file]] [-P|-p [file]] [-l level] [-b|-f|-d]\n"); printf("-s directory of system crontabs (defaults to %s)\n", SCRONTABS); printf("-c directory of per-user crontabs (defaults to %s)\n", CRONTABS); printf("-t directory of timestamps (defaults to %s)\n", CRONSTAMPS); @@ -174,6 +183,8 @@ main(int ac, char **av) printf("-M mailer (defaults to %s)\n", SENDMAIL); printf("-S log to syslog using identity '%s' (default)\n", LOG_IDENT); printf("-L file log to specified file instead of syslog\n"); + printf("-P do not create process-id file\n"); + printf("-p file write pid to specified file instead of %s\n", PIDFILE); printf("-l loglevel log events <= this level (defaults to %s (level %d))\n", LevelAry[LOG_LEVEL], LOG_LEVEL); printf("-b run in background (default)\n"); printf("-f run in foreground\n"); @@ -219,16 +230,48 @@ main(int ac, char **av) int fd; int pid; + int pipe_fd[2]; + int status; + + if (pipe(pipe_fd) < 0) { + /* pipe failed */ + perror("pipe"); + exit(1); + } if ((pid = fork()) < 0) { /* fork failed */ perror("fork"); exit(1); } else if (pid > 0) { - /* parent */ - exit(0); + /* parent, reads from pipe */ + close(pipe_fd[1]); + if (read(pipe_fd[0], &status, sizeof(status)) > 0) { + exit(status); + } + /* error: got zero bytes, so child just closed the write end */ + exit(1); } + /* child continues */ + close(pipe_fd[0]); + status = 0; + + /* write pid file or exit */ + + if (PidFileOpt) { + if ((fd = open(PidFile, O_WRONLY|O_CREAT|O_TRUNC, 0644)) < 0) { + status = errno; + fprintf(stderr, "failed to open PID file '%s', reason: %s\n", PidFile, strerror(status)); + goto daemon_error; + } + if (fdprintf(fd, "%d\n", getpid()) < 0) { + status = errno; + fprintf(stderr, "failed to write PID file '%s', reason: %s\n", PidFile, strerror(status)); + goto daemon_error; + } + close(fd); + } /* become session leader, detach from terminal */ @@ -260,11 +303,16 @@ main(int ac, char **av) fclose(stderr); dup2(fd, 2); } else { - int n = errno; - fdprintf(2, "failed to open logfile '%s', reason: %s", LogFile, strerror(n)); - exit(n); + status = errno; + fdprintf(2, "failed to open logfile '%s', reason: %s\n", LogFile, strerror(status)); + goto daemon_error; } } +daemon_error: + write(pipe_fd[1], &status, sizeof(status)); + if (status != 0) { + exit(status); + } } else { /* daemon in foreground */ diff --git a/subs.c b/subs.c index 65cb564..9959fe4 100644 --- a/subs.c +++ b/subs.c @@ -11,7 +11,7 @@ Prototype void printlogf(int level, const char *ctl, ...); Prototype void fdprintlogf(int level, int fd, const char *ctl, ...); -Prototype void fdprintf(int fd, const char *ctl, ...); +Prototype int fdprintf(int fd, const char *ctl, ...); Prototype void initsignals(void); Prototype char Hostname[SMALL_BUFFER]; @@ -40,16 +40,19 @@ fdprintlogf(int level, int fd, const char *ctl, ...) va_end(va); } -void +int fdprintf(int fd, const char *ctl, ...) { va_list va; char buf[LOG_BUFFER]; + int n; va_start(va, ctl); vsnprintf(buf, sizeof(buf), ctl, va); - write(fd, buf, strlen(buf)); + n = write(fd, buf, strlen(buf)); va_end(va); + + return n; } void