summaryrefslogtreecommitdiff
path: root/daemonize.c
diff options
context:
space:
mode:
Diffstat (limited to 'daemonize.c')
-rw-r--r--daemonize.c104
1 files changed, 83 insertions, 21 deletions
diff --git a/daemonize.c b/daemonize.c
index 94662d6..c9c925f 100644
--- a/daemonize.c
+++ b/daemonize.c
@@ -1,16 +1,37 @@
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
+#include <getopt.h>
#include <ctype.h>
#include <string.h>
+#include <stdbool.h>
+
+const struct option longopts[] = {
+ {"chdir", no_argument, NULL, 'd'},
+ {"noclose", no_argument, NULL, 'n'},
+ {"log-stdout", required_argument, NULL, '1'},
+ {"log-stderr", required_argument, NULL, '2'},
+ {0, 0, 0, 0}
+};
+const char* optstring = "dn1:2:";
void q (char* m) {
fprintf(stderr, "%s\n", m);
exit(1);
}
+void qusage () {
+ q("[daemonize] Usage: daemonize [-d|--chdir] [-n|--noclose] [-1|--log-stdout /path/to/log] [-2|--log-stderr /path/to/log] <command>");
+}
+
void qtoofewargs () {
- q("[daemonize] Too few arguments.\nUsage: daemonize [--chdir] [--noclose] <command>");
+ fprintf(stderr, "[daemonize] Too few arguments.\n");
+ qusage();
+}
+
+void qinvalidarg (char* arg) {
+ fprintf(stderr, "[daemonize] Unrecognized argument: %s\n", arg);
+ qusage();
}
char* lowerdup (char* a) {
@@ -22,32 +43,73 @@ char* lowerdup (char* a) {
return b;
}
-int main (int argc, char** argv) {
+struct opts {
+ int nochdir;
+ int noclose;
+ FILE* stdlog;
+ FILE* errlog;
+};
+
+void parseargs(int argc, char** argv, struct opts* savedopts) {
if (argc < 2) qtoofewargs();
- int i, cmdlen = 0, buff_size = 256, nochdir = 1, noclose = 0;
+ int c;
+
+ while ((c = getopt_long(argc, argv, optstring, longopts, NULL)) != -1) {
+ switch (c) {
+ case 'd':
+ savedopts->nochdir = false;
+ break;
+ case 'n':
+ savedopts->noclose = true;
+ break;
+ case '1':
+ savedopts->stdlog = fopen(optarg, "a");
+ if (!savedopts->stdlog) q("[daemonize] Unable to open stdout log, quitting.");
+ break;
+ case '2':
+ savedopts->errlog = fopen(optarg, "a");
+ if (!savedopts->errlog) q("[daemonize] Unable to open stderr log, quitting.");
+ break;
+ default:
+ // just let getopt print the error
+ break;
+ }
+ }
+}
+
+int main (int argc, char** argv) {
+ struct opts options = {true, false, NULL, NULL};
+ parseargs(argc, argv, &options);
+
+ int cmdlen = 0, buff_size = 256;
char* buffer = malloc(buff_size);
-
- for (i = 1; i < argc; i++) {
- char* cmp = lowerdup(argv[i]);
- if (strcmp(cmp, "--chdir") == 0) nochdir = 0;
- else if (strcmp(cmp, "--noclose") == 0) noclose = 1;
- else {
- int arglen = strlen(argv[i]);
- if (cmdlen+arglen+1 > buff_size) {
- buff_size *= 2;
- buffer = realloc(buffer, buff_size);
- if (buffer == NULL) q("[daemonize] Out of memory parsing arguments.");
- }
- strncpy(&buffer[cmdlen], argv[i], arglen);
- cmdlen += arglen+1;
- buffer[cmdlen-1] = ' ';
+
+ while (optind < argc) {
+ int arglen = strlen(argv[optind]);
+ if (cmdlen+arglen+1 > buff_size) {
+ buff_size *= 2;
+ buffer = realloc(buffer, buff_size);
+ if (buffer == NULL) q("[daemonize] Out of memory parsing arguments.");
}
- free(cmp);
+ strncpy(&buffer[cmdlen], argv[optind++], arglen);
+ cmdlen += arglen+1;
+ buffer[cmdlen-1] = ' ';
}
buffer[cmdlen-1] = 0;
-
+
if (cmdlen < 1) qtoofewargs();
- daemon(nochdir, noclose);
+ // Set up logs as appropriate
+ int logs = options.stdlog || options.errlog;
+ if (options.stdlog) {
+ dup2(fileno(options.stdlog), fileno(stdout));
+ fclose(options.stdlog);
+ }
+ if (options.errlog) {
+ dup2(fileno(options.errlog), fileno(stderr));
+ fclose(options.errlog);
+ }
+ // TODO: close stdin, stderr, stdout and redirect to /dev/null if logging
+ daemon(options.nochdir, options.noclose | logs);
system(buffer);
}