12
extern char **environ;
14
static inline void hardsleep(int sec)
21
static inline void redirect_output(const char *run_log)
23
freopen(run_log, "a+", stdout);
25
freopen(run_log, "a+", stderr);
27
freopen("/dev/null", "r", stdin);
31
int Action_exec(Action *action, Profile *prof)
35
debug("ACTION: command=%s, pid_file=%s, restart=%d, depends=%s",
36
bdata(prof->command), bdata(prof->pid_file), prof->restart,
37
bdata(action->depends));
40
check(pid >= 0, "Fork failed, WTF. How can fork fail?");
43
rc = Unixy_drop_priv(action->profile_dir);
46
log_err("Not fatal, but we couldn't drop priv for %s",
50
redirect_output("run.log");
52
rc = execle(bdata(prof->command), bdata(prof->command), NULL, environ);
53
check(rc != -1, "Failed to exec command: %s", bdata(prof->command));
56
debug("WAITING FOR CHILD.");
57
pid = waitpid(pid, &status, 0);
60
debug("Command ran and exited successfully, now looking for the PID file.");
67
void Action_task(void *v)
69
Action *action = (Action *)v;
72
Profile *prof = Profile_load(action->profile_dir);
74
taskname(bdata(action->name));
77
rc = Rampart_wait(action->before);
78
check(rc != -1, "A dependency failed to start, we can't start.");
80
Rampart_running(&action->after);
83
debug("STARTED %s", bdata(action->name));
86
taskstate("starting");
88
if(Unixy_still_running(prof->pid_file, &child)) {
89
debug("Looks like %s is already running, we'll just leave it alone.", bdata(action->name));
91
Unixy_remove_dead_pidfile(prof->pid_file);
92
Action_exec(action, prof);
95
check(access(bdata(prof->pid_file), R_OK) == 0, "%s didn't make pidfile %s.",
96
bdata(action->name), bdata(prof->pid_file));
99
while(Unixy_still_running(prof->pid_file, &child)) {
107
taskstate("restarting");
111
debug("ACTION %s exited.", bdata(action->name));
114
Rampart_failed(&action->after);
119
Action *Action_create(const char *profile)
121
Action *action = calloc(sizeof(Action), 1);
124
action->profile_dir = bfromcstr(profile);
125
action->name = bTail(action->profile_dir,
126
blength(action->profile_dir) -
127
bstrrchr(action->profile_dir, '/') - 1);
129
action->depends = Profile_read_setting(action->profile_dir, "depends");
138
int Action_depends(Action *this_one, Action *needs)
140
check(this_one->waiting_count < MAX_DEPENDS,
141
"Too many dependencies for %s, max is %d",
142
bdata(this_one->name), MAX_DEPENDS);
144
this_one->before[this_one->waiting_count] = &needs->after;
145
this_one->waiting_count++;
153
void Action_start(Action *action)
155
taskcreate(Action_task, action, 32 * 1024);
158
void Action_dependency_assign(void *value, void *data)
160
Action *action = (Action *)value;
161
Action *target = NULL;
162
tst_t *targets = (tst_t *)data;
165
if(!action->depends) return;
167
debug("Processed %s action depending on: %s", bdata(action->name), bdata(action->depends));
169
if(action->depends) {
170
struct bstrList *dep_list = bsplit(action->depends, ' ');
172
for(i = 0; i < dep_list->qty; i++) {
173
bstring dep = dep_list->entry[i];
175
target = (Action *)tst_search(targets, bdata(dep), blength(dep));
178
Action_depends(action, target);
180
log_err("Could not find dependency %s has on %s.",
181
bdata(action->name), bdata(dep));
185
bstrListDestroy(dep_list);
189
void Action_start_all(void *value, void *data)
191
Action *action = (Action *)value;
192
Action_start(action);
196
void taskmain(int argc, char *argv[])
202
Action *action = NULL;
203
tst_t *targets = NULL;
204
bstring pid_file = NULL;
206
check(argc == 3, "USAGE: procer <profile_dir> <procer_pid_file>");
207
pid_file = bfromcstr(argv[2]);
209
rc = Unixy_remove_dead_pidfile(pid_file);
210
check(rc == 0, "Failed to remove %s, procer is probably already running.", bdata(pid_file));
212
rc = Unixy_daemonize();
213
check(rc == 0, "Couldn't daemonize, that's not good.");
216
check(rc == 0, "Couldn't change to %s profile dir.", argv[1]);
218
rc = Unixy_pid_file(pid_file);
219
check(rc == 0, "Failed to make the PID file: %s", bdata(pid_file));
221
FILE *log = fopen("error.log", "a+");
222
check(log, "Couldn't open error.log");
226
bstring dir_glob = bformat("%s/[A-Za-z0-9]*", argv[1]);
227
check(dir_glob, "Couldn't make the directory glob.");
229
rc = glob(bdata(dir_glob), GLOB_ERR, NULL, &profile_glob);
230
check(rc == 0, "Failed to find directories in the profiles.");
233
debug("Loading %zu actions.", profile_glob.gl_pathc);
234
for(i = 0; i < profile_glob.gl_pathc; i++) {
235
rc = lstat(profile_glob.gl_pathv[i], &sb);
236
check(rc == 0, "Failed to stat file or directory: %s", profile_glob.gl_pathv[i]);
238
if (sb.st_mode & S_IFDIR) {
239
action = Action_create(profile_glob.gl_pathv[i]);
240
targets = tst_insert(targets, bdata(action->name), blength(action->name), action);
244
// now we setup the dependencies from the settings they've got
245
tst_traverse(targets, Action_dependency_assign, targets);
246
tst_traverse(targets, Action_start_all, NULL);