/* * ISA 563, Spring 2011 * Copyleft by Muhammad Abdulla */ #include #include #include #include #include #include #include #include #include #include #include #include #include /* * advanced_daemon.c -- demonstrates how to create daemons while taking more things into consideration */ #define LOCKFILE "/var/tmp/advanced_daemon.pid" #define LOCKMODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) void daemonize(const char *progname) { int i, fd, fd0, fd1, fd2; pid_t pid; struct rlimit rl; char buf[16]; // Clear file creation mask. umask(0); // Get maximum number of file descriptors. if (getrlimit(RLIMIT_NOFILE, &rl) < 0) { fprintf(stderr, "%s: can't get file limit", progname); exit(1); } if ((pid = fork()) < 0) { fprintf(stderr, "%s: can't fork", progname); exit(1); } else if (pid != 0) { // parent must quit exit(0); } // child continues from here // become a session leader setsid(); /* * Change the current working directory to the root so * we won't prevent file systems from being unmounted. */ if (chdir("/") < 0) { fprintf(stderr, "%s: can't change directory to /"); exit(1); } // Close all open file descriptors. if (rl.rlim_max == RLIM_INFINITY) { rl.rlim_max = 1024; } for (i = 0; i < rl.rlim_max; i++) { close(i); } /* * Attach file descriptors 0, 1, and 2 to /dev/null. * All terminal output to user should be printed before this. */ fd0 = open("/dev/null", O_RDWR); fd1 = dup(0); fd2 = dup(0); /* * Initialize the log file. */ openlog(progname, LOG_CONS, LOG_DAEMON); if (fd0 != 0 || fd1 != 1 || fd2 != 2) { syslog(LOG_ERR, "unexpected file descriptors %d %d %d", fd0, fd1, fd2); exit(1); } fd = open(LOCKFILE, O_RDWR|O_CREAT, LOCKMODE); if (fd < 0) { syslog(LOG_ERR, "%s: can't open %s: %s", progname, LOCKFILE, strerror(errno)); exit(1); } if (lockf(fd,F_TLOCK,0) < 0) { // try to lock without getting blocked if (errno == EACCES || errno == EAGAIN) { syslog(LOG_ERR, "%s: can't lock %s: %s", progname, LOCKFILE, strerror(errno)); close(fd); exit(1); } syslog(LOG_ERR, "%s: can't lock %s: %s", progname, LOCKFILE, strerror(errno)); exit(1); } // write pid to lock file ftruncate(fd, 0); sprintf(buf, "%ld", (long)getpid()); write(fd, buf, strlen(buf)+1); syslog(LOG_ERR, "Starting %s with pid %d", progname, getpid() ); } int main(int argc, char *argv[]) { daemonize(argv[0]); // do some hard work in the background while(1) { sleep(1); } }