]> andersk Git - moira.git/blob - clients/addusr/addusr.c
tcsh is dead. Long live bash.
[moira.git] / clients / addusr / addusr.c
1 /* $Id$
2  *
3  * Program to add users en masse to the moira database
4  *
5  * by Mark Rosenstein, July 1992.
6  *
7  * Copyright (C) 1992-1998 by the Massachusetts Institute of Technology.
8  * For copying and distribution information, please see the file
9  * <mit-copyright.h>.
10  */
11
12 #include <mit-copyright.h>
13 #include <moira.h>
14 #include <moira_site.h>
15 #include <mrclient.h>
16
17 #include <ctype.h>
18 #include <errno.h>
19 #include <stdio.h>
20 #include <string.h>
21
22 RCSID("$Header$");
23
24 struct owner_type {
25   int type;
26   char *name;
27 };
28
29 #define M_ANY           0
30 #define M_USER          1
31 #define M_LIST          2
32 #define M_KERBEROS      3
33 #define M_NONE          4
34
35 #ifdef ATHENA
36 #define DEFAULT_SHELL "/bin/athena/bash"
37 #else
38 #define DEFAULT_SHELL "/bin/bash"
39 #endif
40
41 #define DEFAULT_WINCONSOLESHELL "cmd"
42 #define DEFAULT_WINHOMEDIR "[DFS]"
43 #define DEFAULT_WINPROFILEDIR "[DFS]"
44
45 /* flags from command line */
46 char *class, *comment, *status_str, *shell, *winconsoleshell, *filename;
47 char *expiration;
48 int reg_only, reg, verbose, nodupcheck, securereg, nocaps;
49 struct owner_type *sponsor;
50
51 /* argument parsing macro */
52 #define argis(a, b) (!strcmp(*arg + 1, a) || !strcmp(*arg + 1, b))
53
54 char *whoami;
55 int duplicate, errors;
56
57 void usage(char **argv);
58 int usercheck(int argc, char **argv, void *qargv);
59 int get_uid(int argc, char **argv, void *qargv);
60 struct owner_type *parse_member(char *s);
61
62 int main(int argc, char **argv)
63 {
64   int status, lineno;
65   char **arg = argv, *qargv[U_END];
66   char *p, *first, *middle, *last, *id, *login, *server;
67   char buf[BUFSIZ];
68   FILE *input;
69
70   /* clear all flags & lists */
71   reg_only = reg = verbose = lineno = nodupcheck = errors = securereg = nocaps = 0;
72   sponsor = NULL;
73   server = NULL;
74   filename = "-";
75   shell = DEFAULT_SHELL;
76   winconsoleshell = DEFAULT_WINCONSOLESHELL;
77   class = "TEMP";
78   comment = "";
79   expiration = "";
80   status_str = "0";
81
82   whoami = argv[0];
83
84   /* parse args */
85   while (++arg - argv < argc)
86     {
87       if  (**arg == '-')
88         {
89           if (argis("c", "class"))
90             {
91               if (arg - argv < argc - 1)
92                 {
93                   ++arg;
94                   class = *arg;
95                 }
96               else
97                 usage(argv);
98             }
99           else if (argis("C", "comment"))
100             {
101               if (arg - argv < argc - 1)
102                 {
103                   ++arg;
104                   comment = *arg;
105                 }
106               else
107                 usage(argv);
108             }
109           else if (argis("s", "status"))
110             {
111               if (arg - argv < argc - 1)
112                 {
113                   ++arg;
114                   status_str = *arg;
115                 }
116               else
117                 usage(argv);
118             }
119           else if (argis("h", "shell"))
120             {
121               if (arg - argv < argc - 1)
122                 {
123                   ++arg;
124                   shell = *arg;
125                 }
126               else
127                 usage(argv);
128             }
129           else if (argis("w", "winshell"))
130             {
131               if (arg - argv < argc - 1)
132                 {
133                   ++arg;
134                   winconsoleshell = *arg;
135                 }
136               else 
137                 usage(argv);
138             }
139           else if (argis("sp", "sponsor"))
140             {
141               if (arg - argv < argc - 1)
142                 {
143                   ++arg;
144                   sponsor = parse_member(*arg);
145                 }
146               else
147                 usage(argv);
148             }
149           else if (argis("e", "expiration"))
150             {
151               if (arg - argv < argc - 1)
152                 {
153                   ++arg;
154                   expiration = *arg;
155                 }
156               else
157                 usage(argv);
158             }
159           else if (argis("6", "secure"))
160             securereg++;
161           else if (argis("r", "reg_only"))
162             reg_only++;
163           else if (argis("R", "register"))
164             reg++;
165           else if (argis("f", "file"))
166             {
167               if (arg - argv < argc - 1)
168                 {
169                   ++arg;
170                   filename = *arg;
171                 }
172               else
173                 usage(argv);
174             }
175           else if (argis("v", "verbose"))
176             verbose++;
177           else if (argis("d", "nodupcheck"))
178             nodupcheck++;
179           else if (argis("n", "nocaps"))
180             nocaps++;
181           else if (argis("S", "server") || argis("db", "database"))
182             {
183               if (arg - argv < argc - 1)
184                 {
185                   ++arg;
186                   server = *arg;
187                 }
188               else
189                 usage(argv);
190             }
191           else
192             usage(argv);
193         }
194       else
195         usage(argv);
196     }
197
198   if (!strcmp(filename, "-"))
199     input = stdin;
200   else
201     {
202       input = fopen(filename, "r");
203       if (!input)
204         {
205           com_err(whoami, errno, "opening input file %s", filename);
206           exit(2);
207         }
208     }
209
210   /* fire up Moira */
211   if (mrcl_connect(server, "addusr", 12, 1) != MRCL_SUCCESS)
212     exit(2);
213
214   qargv[U_NAME] = UNIQUE_LOGIN;
215   qargv[U_UID] = UNIQUE_UID;
216   qargv[U_SHELL] = shell;
217   qargv[U_WINCONSOLESHELL] = winconsoleshell;
218   qargv[U_WINHOMEDIR] = DEFAULT_WINHOMEDIR;
219   qargv[U_WINPROFILEDIR] = DEFAULT_WINPROFILEDIR;
220   qargv[U_EXPIRATION] = expiration;
221   qargv[U_STATE] = status_str;
222   qargv[U_CLASS] = class;
223   qargv[U_COMMENT] = comment;
224   qargv[U_SIGNATURE] = "";
225   qargv[U_SECURE] = securereg ? "1" : "0";
226   
227   while (fgets(buf, BUFSIZ, input))
228     {
229       /* throw away terminating newline */
230       p = &buf[strlen(buf) - 1];
231       if (*p == '\n')
232         *p = '\0';
233       lineno++;
234       if (strlen(buf) == 0)
235         continue;
236       /* Last name is first thing on line */
237       last = buf;
238       /* First name follows a comma */
239       p = strchr(last, ',');
240       if (!p)
241         {
242           com_err(whoami, MR_BAD_CHAR, "Missing comma on line %d", lineno);
243           errors++;
244           continue;
245         }
246       *p++ = '\0';
247       first = strtrim(p);
248       while (*p)                /* find end-of-line */
249         p++;
250       if (reg_only || reg)
251         {
252           while (!isspace(*p))
253             p--;
254           if (p <= first)
255             {
256               com_err(whoami, 0, "Missing login on line %d", lineno);
257               errors++;
258               continue;
259             }
260           login = strtrim(&p[1]);
261           *p-- = '\0';
262         }
263       else
264         {
265           /* ID is last thing on line */
266           p--;
267         }
268       while (isspace(*p))
269         p--;
270       while (!isspace(*p))
271         p--;
272       if (p <= first)
273         {
274           com_err(whoami, 0, "Missing ID on line %d", lineno);
275           errors++;
276           continue;
277         }
278       id = &p[1];
279       *p-- = '\0';
280       /* If something between first name & ID, it's middle name */
281       while (isspace(*p))
282         p--;
283       while (!isspace(*p))
284         p--;
285       if (p <= first)
286         middle = "";
287       else
288         {
289           middle = &p[1];
290           *p = '\0';
291         }
292       qargv[U_FIRST] = strtrim(first);
293       qargv[U_MIDDLE] = strtrim(middle);
294       qargv[U_LAST] = strtrim(last);
295       qargv[U_MITID] = strtrim(id);
296       if (!nocaps)
297         {
298           FixCase(qargv[U_FIRST]);
299           FixCase(qargv[U_MIDDLE]);
300           FixCase(qargv[U_LAST]);
301         }
302       RemoveHyphens(qargv[U_MITID]);
303       if (!reg_only)
304         {
305           if (!nodupcheck)
306             {
307               char *dargv[2];
308
309               dargv[0] = qargv[U_FIRST];
310               dargv[1] = qargv[U_LAST];
311               duplicate = 0;
312               status = mr_query("get_user_account_by_name", 2, dargv,
313                                 usercheck, qargv);
314               if (status && status != MR_NO_MATCH)
315                 {
316                   com_err(whoami, status,
317                           "checking to see if user %s %s already exists",
318                           qargv[U_FIRST], qargv[U_LAST]);
319                   com_err(whoami, 0, "NOT ADDING USER");
320                   errors++;
321                   continue;
322                 }
323               if (duplicate > 0)
324                 {
325                   com_err(whoami, MR_EXISTS, "user %s %s already exists",
326                           qargv[U_FIRST], qargv[U_LAST]);
327                   com_err(whoami, 0, "NOT ADDING USER");
328                   errors++;
329                   continue;
330                 }
331               else if (duplicate < 0)
332                 {
333                   com_err(whoami, MR_EXISTS,
334                           "user %s %s already exists with different ID number",
335                           qargv[U_FIRST], qargv[U_LAST]);
336                   com_err(whoami, 0, "ADDING user anyway");
337                 }
338             }
339
340           if (sponsor)
341             {
342               qargv[U_SPONSOR_NAME] = sponsor->name;
343               switch (sponsor->type)
344                 {
345                 case M_ANY:
346                 case M_USER:
347                   qargv[U_SPONSOR_TYPE] = "USER";
348                   status = mr_query("add_user_account", 18, qargv, NULL, NULL);
349                   if (sponsor->type != M_ANY || status != MR_USER)
350                     break;
351                   
352                 case M_LIST:
353                   qargv[U_SPONSOR_TYPE] = "LIST";
354                   status = mr_query("add_user_account", 18, qargv, NULL, NULL);
355                   break;
356                   
357                 case M_KERBEROS:
358                   qargv[U_SPONSOR_TYPE] = "KERBEROS";
359                   status = mrcl_validate_kerberos_member(qargv[U_SPONSOR_NAME],
360                                                          &qargv[U_SPONSOR_NAME]);
361                   if (mrcl_get_message())
362                     mrcl_com_err(whoami);
363                   if (status == MRCL_REJECT)
364                 exit(1);
365                   status = mr_query("add_user_account", 18, qargv, NULL, NULL);
366                   break;
367                   
368                 case M_NONE:
369                   qargv[U_SPONSOR_TYPE] = "NONE";
370                   status = mr_query("add_user_account", 18, qargv, NULL, NULL);
371                   break;
372                 }
373             }
374           else
375             {
376               qargv[U_SPONSOR_TYPE] = "NONE";
377               qargv[U_SPONSOR_NAME] = "NONE";
378           
379               status = mr_query("add_user_account", 18, qargv, NULL, NULL);
380             }
381           
382           if (status)
383             {
384               com_err(whoami, status, "adding user %s %s", first, last);
385               errors++;
386             }
387           else if (verbose)
388             {
389               printf("Added user %s %s %s (%s)\n", qargv[U_FIRST],
390                      qargv[U_MIDDLE], qargv[U_LAST], qargv[U_MITID]);
391             }
392         }
393       if (reg || reg_only)
394         {
395           char *gargv[2], *rargv[3], uid[10];
396
397           uid[0] = '\0';
398           gargv[0] = qargv[U_FIRST];
399           gargv[1] = qargv[U_LAST];
400           status = mr_query("get_user_account_by_name", 2, gargv,
401                             get_uid, &uid);
402           if (status)
403             {
404               com_err(whoami, status, "while looking up uid for %s %s",
405                       qargv[U_FIRST], qargv[U_LAST]);
406               errors++;
407               continue;
408             }
409
410           rargv[0] = uid;
411           rargv[1] = login;
412           rargv[2] = "IMAP";
413
414           status = mr_query("register_user", 3, rargv, NULL, NULL);
415           if (status)
416             {
417               com_err(whoami, status, "while registering (login) %s %s",
418                       qargv[U_FIRST], qargv[U_LAST]);
419               errors++;
420               continue;
421             }
422           else if (verbose)
423             {
424               printf("Registered user %s %s as %s\n", qargv[U_FIRST],
425                      qargv[U_LAST], login);
426             }
427         }
428     }
429
430   exit(errors);
431 }
432
433
434 void usage(char **argv)
435 {
436   fprintf(stderr, "Usage: %s [options]\n", argv[0]);
437   fprintf(stderr, "Options are\n");
438   fprintf(stderr, "   -f | -file filename (default STDIN)\n");
439   fprintf(stderr, "   -c | -class class (default TEMP)\n");
440   fprintf(stderr, "   -C | -comment \"comment\" (default \"\")\n");
441   fprintf(stderr, "   -s | -status status (default 0)\n");
442   fprintf(stderr, "   -h | -shell shell (default %s)\n", DEFAULT_SHELL);
443   fprintf(stderr, "   -w | -winshell windows console shell (default %s)\n",
444           DEFAULT_WINCONSOLESHELL);
445   fprintf(stderr, "   -sp | -sponsor sponsor (default NONE)\n");
446   fprintf(stderr, "   -e | -expiration \"expiration date\" (default \"\")\n");
447   fprintf(stderr, "   -r | -reg_only\n");
448   fprintf(stderr, "   -R | -register (and add to database)\n");
449   fprintf(stderr, "   -v | -verbose\n");
450   fprintf(stderr, "   -d | -nodupcheck (don't check for duplicates)\n");
451   fprintf(stderr, "   -n | -nocaps (don't fix capitalization of names)\n");
452   fprintf(stderr, "   -db | -database host:port\n");
453   exit(1);
454 }
455
456
457 /* query callback routine to check for duplicate users */
458
459 int usercheck(int argc, char **argv, void *qargv)
460 {
461   if (!strcmp(argv[U_MITID], ((char **)qargv)[U_MITID]))
462     duplicate++;
463   else
464     duplicate--;
465
466   return MR_CONT;
467 }
468
469 /* query callback to get uid of a just-added account */
470 int get_uid(int argc, char **argv, void *uidv)
471 {
472   char *uid = uidv;
473
474   if (uid[0] == '\0')
475     strcpy(uid, argv[U_UID]);
476   else
477     {
478       if (!strcmp(argv[U_MODWITH], "addusr"))
479         strcpy(uid, argv[U_UID]);
480     }
481
482   return MR_CONT;
483 }
484
485 /* Parse a line of input, fetching a member.  NULL is returned if a member
486  * is not found.  ';' is a comment character.
487  */
488 struct owner_type *parse_member(char *s)
489 {
490   struct owner_type *m;
491   char *p, *lastchar;
492
493   while (*s && isspace(*s))
494     s++;
495   lastchar = p = s;
496   while (*p && *p != '\n' && *p != ';')
497     {
498       if (isprint(*p) && !isspace(*p))
499         lastchar = p++;
500       else
501         p++;
502     }
503   lastchar++;
504   *lastchar = '\0';
505   if (p == s || strlen(s) == 0)
506     return NULL;
507
508   if (!(m = malloc(sizeof(struct owner_type))))
509     return NULL;
510
511   if ((p = strchr(s, ':')))
512     {
513       *p = '\0';
514       m->name = ++p;
515       if (!strcasecmp("user", s))
516         m->type = M_USER;
517       else if (!strcasecmp("list", s))
518         m->type = M_LIST;
519       else if (!strcasecmp("kerberos", s))
520         m->type = M_KERBEROS;
521       else if (!strcasecmp("none", s))
522         m->type = M_NONE;
523       else
524         {
525           m->type = M_ANY;
526           *(--p) = ':';
527           m->name = s;
528         }
529       m->name = strdup(m->name);
530     }
531   else
532     {
533       m->name = strdup(s);
534       m->type = strcasecmp(s, "none") ? M_ANY : M_NONE;
535     }
536   return m;
537 }
This page took 0.084069 seconds and 5 git commands to generate.