Re-build so debian.csclub include library as a dependency
[public/pyceo-broken.git] / src / addmember.c
1 #include <unistd.h>
2 #include <sys/types.h>
3 #include <sys/wait.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <getopt.h>
7 #include <ctype.h>
8 #include <pwd.h>
9 #include <grp.h>
10 #include <errno.h>
11 #include <libgen.h>
12 #include <syslog.h>
13
14 #include "util.h"
15 #include "config.h"
16 #include "ldap.h"
17 #include "krb5.h"
18 #include "kadm.h"
19 #include "ceo.pb-c.h"
20
21 char *prog = NULL;
22
23 static int use_stdin = 0;
24
25 static char *name = NULL;
26 static char *userid = NULL;
27 static char *program = NULL;
28 static char password[1024];
29
30 static struct option opts[] = {
31     { "stdin", 0, NULL, 's' },
32     { NULL, 0, NULL, '\0' },
33 };
34
35 const char *default_lib_dir = "/usr/lib/ceod";
36 const char *lib_dir;
37
38 static void usage() {
39     fprintf(stderr, "Usage: %s userid realname [program]\n", prog);
40     exit(2);
41 }
42
43 int addmember(void) {
44     struct strbuf preq = STRBUF_INIT;
45     struct strbuf pret = STRBUF_INIT;
46     char cpath[1024];
47     char *cargv[] = { "ceoc", "adduser", NULL };
48     int ret = 0;
49
50     if (snprintf(cpath, sizeof(cpath), "%s/ceoc", lib_dir) >= sizeof(cpath))
51         fatal("path too long");
52
53     if (ceo_read_password(password, sizeof(password), use_stdin))
54         return 1;
55
56     Ceo__AddUser req;
57     ceo__add_user__init(&req);
58
59     req.username = userid;
60     req.password = password;
61     req.program  = program;
62     req.realname = name;
63     req.type = CEO__ADD_USER__TYPE__MEMBER;
64
65     strbuf_grow(&preq, ceo__add_user__get_packed_size(&req));
66     strbuf_setlen(&preq, ceo__add_user__pack(&req, (uint8_t *)preq.buf));
67
68     if (spawnvem(cpath, cargv, environ, &preq, &pret, 0))
69         return 1;
70
71     Ceo__AddUserResponse *resp = ceo__add_user_response__unpack(NULL,
72                                                                pret.len, (uint8_t *)pret.buf);
73     if (!resp)
74         fatal("failed to unpack response");
75
76     for (int i = 0; i < resp->n_messages; i++) {
77         if (resp->messages[i]->status) {
78             ret = -1;
79             error("%s", resp->messages[i]->message);
80         } else {
81             notice("%s", resp->messages[i]->message);
82         }
83     }
84
85     ceo__add_user_response__free_unpacked(resp, NULL);
86     strbuf_release(&preq);
87     strbuf_release(&pret);
88
89     return ret;
90 }
91
92 int main(int argc, char *argv[]) {
93     int opt;
94     int ret;
95
96     prog = xstrdup(basename(argv[0]));
97     init_log(prog, LOG_PID, LOG_AUTHPRIV, 1);
98
99     configure();
100
101     while ((opt = getopt_long(argc, argv, "", opts, NULL)) != -1) {
102         switch (opt) {
103             case 's':
104                 use_stdin = 1;
105                 break;
106             case '?':
107                 usage();
108                 break;
109             default:
110                 fatal("error parsing arguments");
111         }
112     }
113
114     if (argc - optind != 2 && argc - optind != 3)
115         usage();
116
117     userid = argv[optind++];
118     name = argv[optind++];
119
120     if (argc - optind)
121         program = argv[optind++];
122
123     lib_dir = getenv("CEO_LIB_DIR") ?: default_lib_dir;
124
125     ret = addmember();
126
127     free_config();
128     free(prog);
129
130     return ret;
131 }