nutools/udaemon.cgo

92 lines
2.1 KiB
Plaintext
Raw Normal View History

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));
}