hang on exit bug under Linux
"Petersen, Jörg"
j.petersen at msh.de
Thu Dec 13 02:15:30 EST 2001
If you like a C-Version; you might be inspired by my "daemon.c":
I use it to run Shell-Scripts as "clean" daemons:
/* daemon.c
* $Id: daemon.c,v 1.4 2001/10/10 07:14:59 jp Exp $
* $Source: /home/u/jp/RCS/daemon.c,v $
*
* 1.1 19.09.2001 jp- RCS-Checkin der ersten Version
* 1.2 19.09.2001 jp- Einbau Option -l logfile, -c, -q
* 1.3 19.09.2001 jp- ID als extern-String
* 1.4 10.10.2001 jp- Usage auch auf stderr
*/
/*
cc daemon.c -o daemon; strip daemon
*/
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <sys/syslog.h>
#include <sys/types.h>
extern char version[]="$Id: daemon.c,v 1.4 2001/10/10 07:14:59 jp Exp $";
char * progname;
int chdirRoot=0;
int quiet=0;
void usage(char * txt) {
fprintf (stderr,"%s\n",txt);
fprintf (stderr,"Usage: %s [-c] [-l /log/file] /path/to/exe arg1
arg2\n",
progname);
fprintf (stderr," -l /log/file does '>/log/file 2>&1'\n");
fprintf (stderr," -c does cd / (use whenever
possible!)\n");
syslog (LOG_INFO | LOG_DAEMON,"%s\n",txt);
syslog (LOG_INFO | LOG_DAEMON,"Usage: %s [-c] [-l /log/file]
/path/to/exe arg1 arg2\n",
progname);
syslog (LOG_INFO | LOG_DAEMON," -l /log/file does '>/log/file
2>&1'\n");
syslog (LOG_INFO | LOG_DAEMON," -c does cd / (use
whenever possible!)\n");
exit(-1);
}
char * timetext(void) {
time_t current;
struct tm * local;
static char str[22];
time(¤t); /* momentane Zeit */
local = localtime(¤t);
sprintf(str,"%02i.%02i.%04i,%02i:%02i:%02i",
local->tm_mday,
local->tm_mon+1,
local->tm_year+1900,
local->tm_hour,
local->tm_min,
local->tm_sec);
return str;
}
void MSHdaemon(char * logfile, char * infotxt) {
int rc;
rc=fork();
if (-1==rc) {
syslog (LOG_INFO | LOG_DAEMON,"daemon - Unable to fork()\n");
exit(-1);
}
if (rc>0) exit(0); /* parent should exit and return control,
it's OK. */
rc=setsid();
if (-1==rc) {
syslog (LOG_INFO | LOG_DAEMON,"daemon - Unable to setsid()\n");
exit(-1);
}
rc=fork();
if (-1==rc) {
syslog (LOG_INFO | LOG_DAEMON,"daemon - Unable to fork()\n");
exit(-1);
}
if (rc>0) exit(0); /* parent should exit and return control,
it's OK. */
if (chdirRoot == 1) {
rc=chdir("/");
if (-1==rc) {
syslog (LOG_INFO | LOG_DAEMON,"daemon - Unable to chdir()\n");
exit(-1);
}
/* umask(0); */
}
if (!freopen("/dev/null", "r", stdin)) {
syslog (LOG_INFO | LOG_DAEMON,"daemon - Unable to freopen(%s,...,%s):
%s\n",
"/dev/null","stdin",strerror (errno));
fflush(stderr);
exit(-1);
}
if (!freopen(logfile, "a", stdout)) {
syslog (LOG_INFO | LOG_DAEMON,"daemon - Unable to freopen(%s,...,%s):
%s\n",
logfile,"stdout",strerror (errno));
fflush(stderr);
exit(-1);
}
if (! quiet)
fprintf(stdout,"Test stdout\n");
fflush(stdout);
if (!freopen(logfile, "a", stderr)) {
syslog (LOG_INFO | LOG_DAEMON,"daemon - Unable to freopen(%s,...,%s):
%s\n",
logfile,"stderr",strerror (errno));
fflush(stderr);
exit(-1);
}
if (! quiet)
fprintf(stderr,"Test stderr\n");
if (! quiet)
fprintf(stderr,"%s\n",infotxt);
fprintf(stderr,"%s\n__O_u_t_p_u_t_:____\n",timetext());
fflush(stderr);
if (! quiet)
syslog (LOG_INFO | LOG_DAEMON, infotxt);
return; /* a grandchild returns... free as a bird.. */
}
int main (int argc, char * const * argv) {
char prog[1024];
char infotxt[1024];
char errmsg[1024];
FILE * ftest;
extern char *optarg;
extern int optind;
int fd;
int ch; /* global int chdirRoot: cd / ? */
char logfile[256] = "/dev/null"; /* logfile:
where stdout&stderr are sent to */
progname = argv[0];
while ((ch = getopt(argc, argv, "qcl:")) != -1)
switch (ch) {
case 'q':
quiet = 1;
break;
case 'c':
chdirRoot = 1;
break;
case 'l':
if (argc < 2) {
syslog (LOG_INFO | LOG_DAEMON,"Logfilename too long! (max 255 char.!)\n");
exit(-1);
}
strcpy(logfile,optarg);
break;
case '?':
default:
usage("Unbekanntes Argument");
}
argc -= optind;
argv += optind;
if (strlen(progname)+strlen(argv[1]) > 750) {
syslog (LOG_INFO | LOG_DAEMON,"ArgV too long.... Tschuess\n");
exit(-1);
}
if (argc < 1) {
usage("Zu wenig Argumente!");
}
/* Testen ob Logfile geschrieben werden kann */
ftest=fopen(logfile, "w");
if (!ftest) {
syslog (LOG_INFO | LOG_DAEMON,"daemon - Unable to fopen(%s): %s\n",
logfile,strerror (errno));
fflush(stderr);
exit(-1);
}
fclose(ftest);
sprintf(prog,"uid=%i prog='%s'",(int)geteuid(),argv[0]);
sprintf(infotxt,"run as daemon: %s log='%s'",prog,logfile);
if (! quiet)
fprintf(stdout,"%s\n",infotxt);
MSHdaemon(logfile,infotxt);
execvp(argv[0],argv);
/* Wenn wir hier ankommen, hat exec nicht funktioniert... */
sprintf(errmsg,"%s ERROR: %s",prog,strerror (errno));
syslog (LOG_ERR | LOG_DAEMON, errmsg);
/* Write to log too ... */
syslog (LOG_INFO | LOG_DAEMON,"\nERROR\n%s\n",errmsg);
fflush(stderr);
fclose(stderr);
exit(0);
return 0;
}
More information about the openssh-unix-dev
mailing list