2013-08-27 15:14:44 +04:00
|
|
|
#!/usr/bin/env compileAndGo
|
|
|
|
# -*- coding: utf-8 mode: c -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8
|
|
|
|
language=c
|
|
|
|
!#
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/file.h>
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
static void die(const char *format, ...) {
|
|
|
|
va_list ap;
|
2015-08-20 07:58:17 +04:00
|
|
|
|
2013-08-27 15:14:44 +04:00
|
|
|
va_start(ap, format);
|
|
|
|
vfprintf(stderr, format, ap);
|
|
|
|
va_end(ap);
|
2015-08-20 07:58:17 +04:00
|
|
|
|
2013-08-27 15:14:44 +04:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int dofork() {
|
|
|
|
switch(fork()) {
|
|
|
|
case 0: return 0;
|
|
|
|
case -1: return -1;
|
|
|
|
default:
|
|
|
|
_exit(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
int main(int argc, char **argv) {
|
|
|
|
if (argc == 2 && !strcmp(argv[1], "--help")) {
|
|
|
|
printf("udaemon.cgo: start a program as a daemon\n"
|
|
|
|
"\n"
|
|
|
|
"USAGE\n"
|
|
|
|
" udaemon.cgo /path/to/prog [args...]\n"
|
|
|
|
"\n"
|
|
|
|
"OPTIONS\n"
|
|
|
|
" -d DESTDIR\n"
|
|
|
|
" Change to DESTDIR instead of \"/\" before starting the program\n");
|
|
|
|
exit(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
char *destdir = "/";
|
|
|
|
int opt;
|
|
|
|
while((opt = getopt(argc, argv, "d:")) != -1) {
|
|
|
|
switch(opt) {
|
|
|
|
case 'd':
|
|
|
|
destdir = optarg;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (argc - optind < 1) die("The first argument is required\n");
|
|
|
|
char **cmd = &argv[optind];
|
|
|
|
|
|
|
|
if (cmd[0][0] != '/') die("%s: argument must be absolute\n", cmd[0]);
|
|
|
|
if (access(cmd[0], X_OK) == -1) die("%s: not executable\n", cmd[0]);
|
|
|
|
struct stat st;
|
|
|
|
if (stat(cmd[0], &st)) die("%s: does not exist\n", cmd[0]);
|
|
|
|
if(!S_ISREG(st.st_mode)) die("%s: not a regular file\n", cmd[0]);
|
|
|
|
if (chdir(destdir) != 0) die("%s: %s\n", destdir, strerror(errno));
|
2015-08-20 07:58:17 +04:00
|
|
|
|
2013-08-27 15:14:44 +04:00
|
|
|
int status = 0;
|
|
|
|
if ((status = dofork()) < 0) {
|
|
|
|
} else if (setsid() < 0) {
|
|
|
|
status = -1;
|
|
|
|
} else if ((status = dofork()) < 0) {
|
|
|
|
} else {
|
|
|
|
umask(0);
|
|
|
|
chdir(destdir);
|
|
|
|
close(0);
|
|
|
|
close(1);
|
|
|
|
close(2);
|
|
|
|
if (open("/dev/null", O_RDWR) != 0) exit(1);
|
|
|
|
dup(0);
|
|
|
|
dup(0);
|
|
|
|
}
|
|
|
|
if (status != 0) {
|
|
|
|
die("Can't daemonize: %s\n", strerror(errno));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (getenv("IFS") == NULL) setenv("IFS", " \t\n", 1);
|
|
|
|
if (getenv("PATH") == NULL) setenv("PATH", "/usr/local/sbin:/sbin:/bin:/usr/sbin:/usr/bin", 1);
|
|
|
|
|
|
|
|
execvp(cmd[0], cmd);
|
|
|
|
die("Can't exec \"%s\": %s\n", cmd[0], strerror(errno));
|
|
|
|
}
|