2026-04-01 19:12:55 +01:00
|
|
|
#include "log.h"
|
|
|
|
|
#include "queue.h"
|
|
|
|
|
#include "service.h"
|
2026-05-30 10:20:21 +01:00
|
|
|
#include "spawn.h"
|
2026-05-30 19:47:49 +01:00
|
|
|
#include "target.h"
|
2026-04-01 19:12:55 +01:00
|
|
|
|
|
|
|
|
#include <dirent.h>
|
2026-03-23 18:15:38 +00:00
|
|
|
#include <errno.h>
|
2026-04-01 19:12:55 +01:00
|
|
|
#include <fcntl.h>
|
2026-05-30 10:19:33 +01:00
|
|
|
#include <fx/string.h>
|
|
|
|
|
#include <magenta/log.h>
|
|
|
|
|
#include <magenta/task.h>
|
2026-03-23 18:15:38 +00:00
|
|
|
#include <pthread.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <string.h>
|
2026-03-24 20:25:49 +00:00
|
|
|
#include <sys/remote.h>
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include <unistd.h>
|
2026-03-23 18:15:38 +00:00
|
|
|
|
2026-04-01 19:12:55 +01:00
|
|
|
#ifdef TRACE
|
|
|
|
|
#define tracef(...) printf(__VA_ARGS__)
|
|
|
|
|
#else
|
|
|
|
|
#define tracef(...)
|
|
|
|
|
#endif
|
|
|
|
|
|
2026-03-23 18:15:38 +00:00
|
|
|
static void *thread_func(void *arg)
|
|
|
|
|
{
|
2026-04-01 19:12:55 +01:00
|
|
|
tracef("started thread with arg %p\n", arg);
|
2026-03-23 18:15:38 +00:00
|
|
|
errno = 100;
|
2026-04-01 19:12:55 +01:00
|
|
|
tracef("thread done");
|
2026-03-23 18:15:38 +00:00
|
|
|
return (void *)0xdeadbeef;
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-01 19:12:55 +01:00
|
|
|
static int load_services(const char *dir, struct queue *out)
|
2026-03-23 18:15:38 +00:00
|
|
|
{
|
2026-04-01 19:12:55 +01:00
|
|
|
DIR *d = opendir(dir);
|
|
|
|
|
if (!d) {
|
|
|
|
|
printf("cannot open '%s': %s\n", dir, strerror(errno));
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
2026-03-24 20:25:49 +00:00
|
|
|
|
2026-04-01 19:12:55 +01:00
|
|
|
struct dirent *dent = NULL;
|
|
|
|
|
|
|
|
|
|
while ((dent = readdir(d))) {
|
|
|
|
|
char filepath[4096];
|
|
|
|
|
snprintf(filepath, sizeof filepath, "%s/%s", dir, dent->d_name);
|
|
|
|
|
tracef(" - %s\n", dent->d_name);
|
|
|
|
|
struct service *s = NULL;
|
2026-05-30 19:47:49 +01:00
|
|
|
int err = service_load(dent->d_name, filepath, &s);
|
2026-04-01 19:12:55 +01:00
|
|
|
if (err != SUCCESS) {
|
|
|
|
|
printf("failed to load %s (%s)\n",
|
|
|
|
|
filepath,
|
|
|
|
|
strerror(errno));
|
2026-04-20 22:18:03 +01:00
|
|
|
} else {
|
|
|
|
|
queue_push_back(out, &s->s_entry);
|
2026-04-01 19:12:55 +01:00
|
|
|
}
|
2026-03-23 18:15:38 +00:00
|
|
|
}
|
|
|
|
|
|
2026-04-01 19:12:55 +01:00
|
|
|
closedir(d);
|
|
|
|
|
return SUCCESS;
|
|
|
|
|
}
|
2026-03-23 18:15:38 +00:00
|
|
|
|
2026-05-30 19:47:49 +01:00
|
|
|
static int load_targets(const char *dir, struct queue *out)
|
2026-04-01 19:12:55 +01:00
|
|
|
{
|
|
|
|
|
DIR *d = opendir(dir);
|
|
|
|
|
if (!d) {
|
|
|
|
|
printf("cannot open '%s': %s\n", dir, strerror(errno));
|
|
|
|
|
return -1;
|
2026-03-23 18:15:38 +00:00
|
|
|
}
|
|
|
|
|
|
2026-04-01 19:12:55 +01:00
|
|
|
struct dirent *dent = NULL;
|
|
|
|
|
|
|
|
|
|
while ((dent = readdir(d))) {
|
|
|
|
|
char filepath[4096];
|
|
|
|
|
snprintf(filepath, sizeof filepath, "%s/%s", dir, dent->d_name);
|
|
|
|
|
tracef(" - %s\n", dent->d_name);
|
2026-05-30 19:47:49 +01:00
|
|
|
struct target *rl = NULL;
|
|
|
|
|
int err = target_load(dent->d_name, filepath, &rl);
|
2026-04-01 19:12:55 +01:00
|
|
|
if (err != SUCCESS) {
|
|
|
|
|
printf("failed to load %s (%s)\n",
|
|
|
|
|
filepath,
|
|
|
|
|
strerror(errno));
|
|
|
|
|
continue;
|
2026-03-24 20:25:49 +00:00
|
|
|
}
|
2026-04-01 19:12:55 +01:00
|
|
|
|
2026-05-30 19:47:49 +01:00
|
|
|
tracef("target: %s\n", rl->rl_description);
|
2026-04-01 19:12:55 +01:00
|
|
|
for (size_t i = 0; i < rl->rl_requires_count; i++) {
|
|
|
|
|
tracef(" requires: %s\n", rl->rl_requires[i]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
queue_push_back(out, &rl->rl_entry);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
closedir(d);
|
|
|
|
|
return SUCCESS;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int main(int argc, const char *argv[], const char *envp[])
|
|
|
|
|
{
|
|
|
|
|
sys_remote_set(SYS_REMOTE_NSD, 0, 0);
|
|
|
|
|
|
2026-05-30 19:47:49 +01:00
|
|
|
struct queue *targets = global_targets();
|
2026-04-01 19:12:55 +01:00
|
|
|
struct queue *services = global_services();
|
|
|
|
|
|
2026-05-30 19:47:49 +01:00
|
|
|
int err = load_targets("/etc/herdd/targets", targets);
|
2026-04-01 19:12:55 +01:00
|
|
|
err = load_services("/etc/herdd/services", services);
|
|
|
|
|
|
2026-05-30 19:47:49 +01:00
|
|
|
struct target *rl = target_find("single-user.target");
|
2026-04-01 19:12:55 +01:00
|
|
|
if (!rl) {
|
2026-05-30 19:47:49 +01:00
|
|
|
log_fail("Cannot find target single-user.");
|
2026-04-01 19:12:55 +01:00
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
2026-05-30 19:47:49 +01:00
|
|
|
target_activate(rl);
|
2026-05-30 10:20:21 +01:00
|
|
|
#if 1
|
|
|
|
|
pid_t child = fork();
|
|
|
|
|
kern_logf(" fork returned %d", child);
|
2026-04-01 19:12:55 +01:00
|
|
|
|
2026-05-30 10:20:21 +01:00
|
|
|
if (child == 0) {
|
2026-04-01 19:12:55 +01:00
|
|
|
kern_log("this is the child");
|
2026-04-20 22:17:28 +01:00
|
|
|
long r = printf("hello\n");
|
|
|
|
|
kern_logf("printf returned %ld (%d)", r, (errno));
|
2026-05-30 10:20:21 +01:00
|
|
|
execlp(NULL, NULL);
|
2026-03-24 20:25:49 +00:00
|
|
|
} else {
|
2026-04-01 19:12:55 +01:00
|
|
|
kern_log("this is the parent");
|
2026-04-20 22:17:28 +01:00
|
|
|
long r = printf("goodbye\n");
|
|
|
|
|
kern_logf("printf returned %ld (%d)", r, (errno));
|
2026-03-24 20:25:49 +00:00
|
|
|
}
|
|
|
|
|
|
2026-04-20 22:17:28 +01:00
|
|
|
kern_logf("exiting (%s)", strerror(EFTYPE));
|
2026-05-30 10:20:21 +01:00
|
|
|
#endif
|
2026-03-23 18:15:38 +00:00
|
|
|
return 0;
|
|
|
|
|
}
|