Add mysql database stuff
[mspang/pyceo.git] / src / ops.c
1 #include <errno.h>
2 #include <inttypes.h>
3 #include <unistd.h>
4 #include <fcntl.h>
5 #include <netdb.h>
6 #include <pwd.h>
7
8 #include "strbuf.h"
9 #include "ops.h"
10 #include "net.h"
11 #include "util.h"
12 #include "config.h"
13
14 static struct op *ops;
15
16 static const char *default_op_dir = "/usr/lib/ceod";
17 static const char *op_dir;
18
19 static void add_op(char *host, char *name, char *user, uint32_t id) {
20     struct op *new = xmalloc(sizeof(struct op));
21     errno = 0;
22     new->next = ops;
23     new->name = xstrdup(name);
24     new->id = id;
25     new->path = NULL;
26     new->user = xstrdup(user);
27
28     struct hostent *hostent = gethostbyname(host);
29     if (!hostent)
30         badconf("cannot add op %s: %s: %s", name, host, hstrerror(h_errno));
31     new->hostname = strdup(hostent->h_name);
32     new->local = !strcmp(fqdn.buf, hostent->h_name);
33     new->addr = *(struct in_addr *)hostent->h_addr_list[0];
34
35     if (new->local) {
36         new->path = xmalloc(strlen(op_dir) + strlen("/op-") + strlen(name) + 1);
37         sprintf(new->path, "%s/op-%s", op_dir, name);
38         if (access(new->path, X_OK))
39             fatalpe("cannot add op: %s: %s", name, new->path);
40
41         struct passwd *pw = getpwnam(user);
42         if (!pw)
43             fatalpe("cannot add op %s: getpwnam: %s", name, user);
44     }
45
46     ops = new;
47     debug("added op %s (%s%s) [%s]", new->name, new->local ? "" : "on ",
48             new->local ? "local" : host, new->user);
49 }
50
51 struct op *get_local_op(uint32_t id) {
52     for (struct op *op = ops; op; op = op->next) {
53         if (op->local && op->id == id)
54             return op;
55     }
56     return NULL;
57 }
58
59 struct op *find_op(const char *name) {
60     for (struct op *op = ops; op; op = op->next) {
61         if (!strcmp(name, op->name))
62             return op;
63     }
64     return NULL;
65 }
66
67 void setup_ops(void) {
68     char op_config_dir[1024];
69     DIR *dp;
70     struct dirent *de;
71     struct strbuf line = STRBUF_INIT;
72     unsigned lineno = 0;
73     unsigned op_count = 0;
74
75     op_dir = getenv("CEO_LIB_DIR") ?: default_op_dir;
76
77     if (snprintf(op_config_dir, sizeof(op_config_dir), "%s/%s", config_dir, "ops") >= sizeof(op_config_dir))
78         fatal("ops dir path too long");
79
80     dp = opendir(op_config_dir);
81     if (!dp)
82         fatalpe("opendir: %s", op_config_dir);
83
84     while ((de = readdir(dp))) {
85         FILE *fp = fopenat(dp, de->d_name, O_RDONLY);
86         if (!fp)
87             warnpe("open: %s/%s", op_config_dir, de->d_name);
88         while (strbuf_getline(&line, fp, '\n') != EOF) {
89             lineno++;
90             strbuf_trim(&line);
91
92             if (!line.len || line.buf[0] == '#')
93                 continue;
94
95             struct strbuf **words = strbuf_splitws(&line);
96
97             if (strbuf_list_len(words) != 4)
98                 badconf("%s/%s: expected four words on line %d", op_config_dir, de->d_name, lineno);
99
100             errno = 0;
101             char *end;
102             int id = strtol(words[3]->buf, &end, 0);
103             if (errno || *end)
104                 badconf("%s/%s: invalid id '%s' on line %d", op_config_dir, de->d_name, words[2]->buf, lineno);
105
106             add_op(words[0]->buf, words[1]->buf, words[2]->buf, id);
107             op_count++;
108
109             strbuf_list_free(words);
110         }
111         fclose(fp);
112     }
113
114     closedir(dp);
115     strbuf_release(&line);
116 }
117
118 void free_ops(void) {
119     while (ops) {
120         struct op *next = ops->next;
121         free(ops->name);
122         free(ops->hostname);
123         free(ops->path);
124         free(ops->user);
125         free(ops);
126         ops = next;
127     }
128 }