#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <syslog.h>
int main(int argc, char *argv[])
{
char c;
int _argc = 0;
char *_argv[3];
pid_t pid;
if ((pid = fork()) < 0) {
fprintf(stderr, "fork failed\n");
exit(1);
} else if (pid != 0) {
exit(0);
}
setsid();
chdir("/");
umask(0);
close(0);
close(1);
close(2);
for (;;) {
sleep(5);
syslog(LOG_INFO, "Still sleeping\n");
}
}
The trouble with the above is that it doesn't work under uClinux because there is no fork, only vfork. If we replace the fork call above with vfork, then the parent application never terminates. The child won't background until exec is called.
We can thus modify the classic daemonizing program to exec a program which can then be the background process while the parent process terminates. The trick is to exec the original program itself with an argument which indicates that it is the child process. The code below illustrates.
/*
* (c) Matthew Natalier, 2003
*
* If you want to use this, tell me that you love me :-)
*
*/
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <syslog.h>
#include <sys/types.h>
#include <unistd.h>
int execed = 0;
int main(int argc, char *argv[])
{
char c;
int _argc = 0;
char *_argv[3];
pid_t pid;
while ((c=getopt(argc, argv, "D")) > 0) {
switch(c) {
case 'D':
execed = 1;
break;
default:
fprintf(stderr, "You probably don't want to pass "
"options to this\n");
exit(1);
}
}
if (!execed) {
if ((pid = vfork()) < 0) {
fprintf(stderr, "vfork failed\n");
exit(1);
} else if (pid != 0) {
exit(0);
}
_argv[_argc++] = argv[0];
_argv[_argc++] = "-D";
_argv[_argc++] = NULL;
execv(_argv[0], _argv);
/* Not reached */
fprintf(stderr, "Couldn't exec\n");
_exit(1);
} else {
setsid();
chdir("/");
umask(0);
close(0);
close(1);
close(2);
}
for (;;) {
sleep(5);
syslog(LOG_INFO, "Still sleeping\n");
}
}
The best thing about the above code is that it will work on uClinux or standard Linux systems without modification.
angryman
|