supervise.c (3093B) download
1#include "common.h"
2#include "defs.h"
3#include "types.h"
4#include "util.h"
5
6#include <errno.h>
7#include <fcntl.h>
8#include <linux/limits.h>
9#include <signal.h>
10#include <stdio.h>
11#include <stdlib.h>
12#include <string.h>
13#include <sys/file.h>
14#include <sys/stat.h>
15#include <unistd.h>
16
17
18#define RUN_PATH "/run/fiss"
19
20service_t service;
21
22const char* current_prog(void) {
23 return "supervise";
24}
25
26int main(int argc, char** argv) {
27 static char path_buffer[PATH_MAX];
28 static char supervise_path[PATH_MAX];
29 struct stat sstruct;
30
31 if (argc >= 2 && chdir(argv[1]) == -1) {
32 fprint(1, "unable to change directory to '%s': %s\n", argv[1], strerror(errno));
33 exit(errno == ENOENT ? EXIT_USER : EXIT_PERM);
34 }
35
36 // reset service struct
37 memset(&service, 0, sizeof service);
38
39 THROW_NULL(getcwd(supervise_path, sizeof supervise_path), "unable to get current directory", EXIT_PERM);
40
41 // copy the last component of {PWD} to name
42 strcpy(service.name, strrchr(supervise_path, '/') + 1);
43
44 path_join(path_buffer, RUN_PATH, "supervise", NULL);
45
46 if (stat(RUN_PATH, &sstruct) == -1) {
47 THROW_MIN(mkdir(RUN_PATH, 0666), "unable to create %s", EXIT_TEMP, RUN_PATH);
48 } else if (!S_ISDIR(sstruct.st_mode)) {
49 fprint(1, "%s exists, but is not a directory", RUN_PATH);
50 exit(EXIT_TEMP);
51 }
52
53 if (stat(path_buffer, &sstruct) == -1) {
54 THROW_MIN(mkdir(path_buffer, 0666), "unable to create %s", EXIT_TEMP, path_buffer);
55 } else if (!S_ISDIR(sstruct.st_mode)) {
56 fprint(1, "%s exists, but is not a directory", RUN_PATH);
57 exit(EXIT_TEMP);
58 }
59
60 // symlink /run/fiss/supervise/<service> to ./supervise
61 THROW_MIN(symlink(path_buffer, "supervise"), "unable to link '%s' to 'supervise'", EXIT_TEMP, path_buffer);
62
63 // open ./supervise/lock
64 THROW_MIN(service.supervise.lock = open("supervise/lock", O_WRONLY | O_CREAT, 0600), "unable to open 'supervise/lock'", EXIT_PERM);
65
66 // lock ./supervise/lock, don't block! That means it will just throw if another instance is running
67 THROW_MIN(flock(service.supervise.lock, LOCK_EX | LOCK_NB), "unable to lock 'supervise/lock', probably an other 'supervise'-instance is running", EXIT_PERM);
68
69 // make fifo at ./supervise/ok, everyone should be able to check at least that
70 // the service is online, thus perm 666 instead of 600
71 THROW_MIN(mkfifo("supervise/ok", 0666), "unable to create 'supervise/control'", EXIT_TEMP);
72
73 // make fifo at ./supervise/control, only root should be able to control the service thus 0600
74 THROW_MIN(mkfifo("supervise/control", 0600), "unable to create 'supervise/control'", EXIT_TEMP);
75
76 // open ./supervise/ok and just leave it like that
77 THROW_MIN(service.supervise.ok = open("supervise/ok", O_RDONLY), "unable to open 'supervise/ok'", EXIT_PERM);
78
79 // open ./supervise/control
80 THROW_MIN(service.supervise.control = open("supervise/control", O_RDONLY), "unable to open 'supervise/control'", EXIT_PERM);
81
82 // open ./supervise/depends
83 THROW_MIN(service.supervise.dependent = open("supervise/depends", O_RDONLY | O_CREAT, 0666), "unable to open 'supervise/depends'", EXIT_PERM);
84
85 THROW_MIN(write_status(), "unable to write status", -1);
86}