Relayouted all switch statements: case aligns with switch.
[mmh] / uip / conflict.c
1 /*
2 ** conflict.c -- check for conflicts in mail system
3 **
4 ** This code is Copyright (c) 2002, by the authors of nmh.  See the
5 ** COPYRIGHT file in the root directory of the nmh distribution for
6 ** complete copyright information.
7 */
8
9 #include <h/mh.h>
10 #include <fcntl.h>
11 #include <h/aliasbr.h>
12 #include <h/mts.h>
13 #include <h/utils.h>
14 #include <grp.h>
15 #include <pwd.h>
16
17 /*
18 ** maximum number of directories that can
19 ** be specified using -search switch.
20 */
21 #define NDIRS  100
22
23 /*
24 ** Add space for group names, 100 at a time
25 */
26 #define NGRPS  100
27
28 static struct swit switches[] = {
29 #define MAILSW  0
30         { "mail name", 0 },
31 #define SERCHSW  1
32         { "search directory", 0 },
33 #define VERSIONSW  2
34         { "version", 0 },
35 #define HELPSW  3
36         { "help", 0 },
37         { NULL, 0 }
38 };
39
40 static char *mail = NULL;
41 static char *dirs[NDIRS];
42 static FILE *out = NULL;
43
44 extern struct aka  *akahead;
45 extern struct home *homehead;
46
47 /*
48 ** prototypes
49 */
50 void alias_files(int, char **);
51 void pwd_names(void);
52 void grp_names(void);
53 void grp_members(void);
54 void grp_ids(void);
55 void maildrops(void);
56 void mdrop(char *);
57 int check(char *);
58 void setup(void);
59
60
61 int
62 main(int argc, char **argv)
63 {
64         int akp = 0, dp = 0;
65         char *cp, **argp, **arguments;
66         char buf[BUFSIZ], *akv[50];
67
68 #ifdef LOCALE
69         setlocale(LC_ALL, "");
70 #endif
71         invo_name = mhbasename(argv[0]);
72
73         /* foil search of user profile/context */
74         if (context_foil(NULL) == -1)
75                 done(1);
76
77         mts_init(invo_name);
78         arguments = getarguments(invo_name, argc, argv, 0);
79         argp = arguments;
80
81         while ((cp = *argp++)) {
82                 if (*cp == '-') {
83                         switch (smatch(++cp, switches)) {
84                         case AMBIGSW:
85                                 ambigsw(cp, switches);
86                                 done(1);
87                         case UNKWNSW:
88                                 adios(NULL, "-%s unknown", cp);
89
90                         case HELPSW:
91                                 snprintf(buf, sizeof(buf), "%s [switches] [aliasfiles ...]", invo_name);
92                                 print_help(buf, switches, 0);
93                                 done(1);
94                         case VERSIONSW:
95                                 print_version(invo_name);
96                                 done(1);
97
98                         case MAILSW:
99                                 if (!(cp = *argp++) || *cp == '-')
100                                         adios(NULL, "missing argument to %s",
101                                                         argp[-2]);
102                                 if (mail)
103                                         adios(NULL, "mail to one address only");
104                                 else
105                                         mail = cp;
106                                 continue;
107
108                         case SERCHSW:
109                                 if (!(cp = *argp++) || *cp == '-')
110                                         adios(NULL, "missing argument to %s",
111                                                         argp[-2]);
112                                 if (dp >= NDIRS)
113                                         adios(NULL, "more than %d directories",
114                                                         NDIRS);
115                                 dirs[dp++] = cp;
116                                 continue;
117                         }
118                 }
119                 akv[akp++] = cp;
120         }
121
122         if (!homehead)
123                 init_pw();
124         if (!mail)
125                 out = stdout;
126         dirs[dp] = NULL;
127
128         alias_files(akp, akv);
129         pwd_names();
130         grp_names();
131         grp_members();
132         grp_ids();
133 #ifdef UCI
134         ldr_names();
135         ldr_ship();
136 #endif /* UCI */
137         maildrops();
138
139         done(0);
140         return 1;
141 }
142
143
144 void
145 alias_files(int akp, char **akv)
146 {
147         register int i, err;
148
149         for (i = 0; i < akp; i++)
150                 if ((err = alias(akv[i])) != AK_OK) {
151                         setup();
152                         fprintf(out, "aliasing error in %s - %s\n", akv[i],
153                                         akerror(err));
154                 } else if (out && !mail)
155                         fprintf(out, "alias file %s is ok\n", akv[i]);
156 }
157
158
159 void
160 pwd_names(void)
161 {
162         int hit = 0;
163         register struct home *hm, *lm;
164
165         for (hm = homehead; hm; hm = hm->h_next)
166                 for (lm = hm->h_next; lm; lm = lm->h_next)
167                         if (strcmp(hm->h_name, lm->h_name) == 0) {
168                                 setup();
169                                 fprintf(out, "duplicate user %s(uid=%d)\n",
170                                                 lm->h_name, (int) lm->h_uid);
171                                 hit++;
172                         }
173
174         if (!hit && out && !mail)
175                 fprintf(out, "no duplicate users\n");
176 }
177
178
179 void
180 grp_names(void)
181 {
182         int numgroups, maxgroups;
183         int i, hit = 0;
184         char **grps;
185         struct group *gr;
186
187         /* allocate space NGRPS at a time */
188         numgroups = 0;
189         maxgroups = NGRPS;
190         grps = (char **) mh_xmalloc((size_t) (maxgroups * sizeof(*grps)));
191
192         setgrent();
193         while ((gr = getgrent())) {
194                 for (i = 0; i < numgroups; i++)
195                         if (!strcmp(grps[i], gr->gr_name)) {
196                                 setup();
197                                 fprintf(out, "duplicate group %s(gid=%d)\n",
198                                                 gr->gr_name, (int) gr->gr_gid);
199                                 hit++;
200                                 break;
201                         }
202                 if (i >= numgroups) {
203                         if (numgroups >= maxgroups) {
204                                 maxgroups += NGRPS;
205                                 grps = (char **) mh_xrealloc(grps,
206                                         (size_t) (maxgroups * sizeof(*grps)));
207                         }
208                         grps[numgroups++] = getcpy(gr->gr_name);
209                 }
210         }
211         endgrent();
212
213         for (i = 0; i < numgroups; i++)
214                 free(grps[i]);
215         free(grps);
216
217         if (!hit && out && !mail)
218                 fprintf(out, "no duplicate groups\n");
219 }
220
221
222 void
223 grp_members(void)
224 {
225         register int hit = 0;
226         register char **cp, **dp;
227         register struct group *gr;
228         register struct home  *hm;
229
230         setgrent();
231         while ((gr = getgrent())) {
232                 for (cp = gr->gr_mem; *cp; cp++) {
233                         for (hm = homehead; hm; hm = hm->h_next)
234                                 if (!strcmp(*cp, hm->h_name))
235                                         break;
236                         if (hm == NULL) {
237                                 setup();
238                                 fprintf(out, "group %s(gid=%d) has unknown member %s\n", gr->gr_name, (int) gr->gr_gid, *cp);
239                                 hit++;
240                         } else {
241                                 hm->h_ngrps++;
242                         }
243
244                         for (dp = cp + 1; *dp; dp++)
245                                 if (strcmp(*cp, *dp) == 0) {
246                                         setup();
247                                         fprintf(out, "group %s(gid=%d) has duplicate member %s\n", gr->gr_name, (int) gr->gr_gid, *cp);
248                                         hit++;
249                                 }
250                 }
251         }
252         endgrent();
253
254         for (hm = homehead; hm; hm = hm->h_next)
255                 if (hm->h_ngrps > NGROUPS_MAX) {
256                         setup();
257                         fprintf(out, "user %s is a member of %d groups (max %d)\n",
258                                         hm->h_name, hm->h_ngrps, NGROUPS_MAX);
259                         hit++;
260                 }
261
262         if (!hit && out && !mail)
263                 fprintf(out, "all group members accounted for\n");
264 }
265
266
267 void
268 grp_ids(void)
269 {  /* -DRAND not implemented at most places */
270         register int hit = 0;
271         register struct home *hm;
272
273         for (hm = homehead; hm; hm = hm->h_next)
274                 if (getgrgid(hm->h_gid) == NULL) {
275                         setup();
276                         fprintf(out, "user %s(uid=%d) has unknown group-id %d\n", hm->h_name, (int) hm->h_uid, (int) hm->h_gid);
277                         hit++;
278                 }
279
280         if (!hit && out && !mail)
281                 fprintf(out, "all group-id users accounted for\n");
282 }
283
284
285 void
286 maildrops(void)
287 {
288         register int i;
289
290         if (mmdfldir && *mmdfldir)
291                 mdrop(mmdfldir);
292         if (uucpldir && *uucpldir)
293                 mdrop(uucpldir);
294         for (i = 0; dirs[i]; i++)
295                 mdrop(dirs[i]);
296 }
297
298
299 void
300 mdrop(char *drop)
301 {
302         register int hit = 0;
303         register struct dirent *dp;
304         register DIR *dd = opendir(drop);
305
306         if (!dd) {
307                 setup();
308                 fprintf(out, "unable to open maildrop area %s\n", drop);
309                 return;
310         }
311
312         while ((dp = readdir(dd)))
313                 if (dp->d_name[0] != '.' && !check(dp->d_name)) {
314                         setup();
315                         fprintf(out, "there is a maildrop for the unknown user %s in %s\n", dp->d_name, drop);
316                         hit++;
317                 }
318
319         closedir(dd);
320         if (!hit && out && !mail)
321                 fprintf(out, "all maildrops accounted for in %s\n", drop);
322 }
323
324
325 int
326 check(char *s)
327 {
328         register struct home *hm;
329
330         for (hm = homehead; hm; hm = hm->h_next)
331                 if (!strcmp(s, hm->h_name))
332                         return 1;
333         return 0;
334 }
335
336 void
337 setup(void)
338 {
339         int fd, pd[2];
340
341         if (out)
342                 return;
343
344         if (mail) {
345                 if (pipe(pd) == NOTOK)
346                         adios("pipe", "unable to");
347
348                 switch (fork()) {
349                 case NOTOK:
350                         adios("fork", "unable to");
351
352                 case OK:
353                         close(pd[1]);
354                         if (pd[0] != 0) {
355                                 dup2(pd[0], 0);
356                                 close(pd[0]);
357                         }
358                         if ((fd = open("/dev/null", O_WRONLY))
359                                         != NOTOK)
360                                 if (fd != 1) {
361                                         dup2(fd, 1);
362                                         close(fd);
363                                 }
364                         execlp(mailproc, mhbasename(mailproc),
365                                         mail, "-subject", invo_name,
366                                         NULL);
367                         adios(mailproc, "unable to exec ");
368
369                 default:
370                         close(pd[0]);
371                         out = fdopen(pd[1], "w");
372                         fprintf(out, "%s: the following is suspicious\n\n", invo_name);
373                 }
374         }
375 }
376
377 #ifdef UCI
378 /*
379 ** UCI specific stuff for conflict
380 */
381
382 /* taken from <grpldr.h> */
383
384 #define GLDRS  "/admin/etc/GroupLeaders"
385
386 struct grpldr {
387         char *gl_name;
388         char **gl_ldr;
389 };
390
391 int setglent(), endglent();
392 struct grpldr *getglent(), *getglnam();
393
394
395 /* taken from the getglent() routines */
396
397 #define MAXGLS  100
398
399 static FILE *glp = NULL;
400 static char line[BUFSIZ+1];
401 static struct grpldr grpldr;
402 static char *gl_ldr[MAXGLS + 1];
403
404
405 setglent() {
406         if (glp == NULL)
407                 glp = fopen(GLDRS, "r");
408         else
409                 rewind(glp);
410
411         return (glp != NULL);
412 }
413
414
415 endglent() {
416         if (glp != NULL) {
417                 fclose(glp);
418                 glp = NULL;
419         }
420
421         return 1;
422 }
423
424 struct grpldr *getglent() {
425         register char  *cp, **q;
426
427         if (glp == NULL && !setglent())
428                 return NULL;
429         if ((cp = fgets(line, BUFSIZ, glp)) == NULL)
430                 return NULL;
431
432         grpldr.gl_name = cp;
433         grpldr.gl_ldr = q = gl_ldr;
434
435         while (*cp) {
436                 while (*cp && !isspace(*cp))
437                         cp++;
438                 while (*cp && isspace(*cp))
439                         *cp++ = '\0';
440                 if (*cp == '\0')
441                         break;
442                 if (q < gl_ldr + MAXGLS)
443                         *q++ = cp;
444                 else
445                         break;
446         }
447         *q = NULL;
448
449         return (&grpldr);
450 }
451
452 struct grpldr *getglnam(name)
453 char   *name;
454 {
455         register struct grpldr  *gl = NULL;
456
457         setglent();
458         while (gl = getglent())
459                 if (strcmp(name, gl->gl_name) == 0)
460                         break;
461         endglent();
462
463         return gl;
464 }
465
466 ldr_names() {
467         register int gp, hit = 0;
468         char *gldrs[NGRPS];
469         register struct grpldr  *gl;
470
471         gldrs[0] = NULL;
472         setglent();
473         while (gl = getglent()) {
474                 if (getgrnam(gl->gl_name) == NULL) {
475                         setup();
476                         fprintf(out, "unknown group %s in group leaders file\n",
477                                         gl->gl_name);
478                         hit++;
479                 }
480                 for (gp = 0; gldrs[gp]; gp++)
481                         if (strcmp(gldrs[gp], gl->gl_name) == 0) {
482                                 setup();
483                                 fprintf(out, "duplicate group %s in group leaders file\n", gl->gl_name);
484                                 hit++;
485                                 break;
486                         }
487                 if (gldrs[gp] == NULL)
488                         if (gp < NGRPS) {
489                                 gldrs[gp++] = getcpy(gl->gl_name);
490                                 gldrs[gp] = NULL;
491                         } else {
492                                 setup();
493                                 fprintf(out, "more than %d groups in group leaders file (time to recompile)\n", NGRPS - 1);
494                                 hit++;
495                         }
496         }
497         endglent();
498
499         for (gp = 0; gldrs[gp]; gp++)
500                 free(gldrs[gp]);
501
502         if (!hit && out && !mail)
503                 fprintf(out, "all groups in group leaders file accounted for\n");
504 }
505
506
507 ldr_ship() {
508         register int hit = 0;
509         register char **cp, **dp;
510         register struct grpldr  *gl;
511
512         setglent();
513         while (gl = getglent())
514                 for (cp = gl->gl_ldr; *cp; cp++) {
515                         if (!check(*cp)) {
516                                 setup();
517                                 fprintf(out, "group %s has unknown leader %s\n", gl->gl_name, *cp);
518                                 hit++;
519                         }
520
521                         for (dp = cp + 1; *dp; dp++)
522                                 if (strcmp(*cp, *dp) == 0) {
523                                         setup();
524                                         fprintf(out, "group %s had duplicate leader %s\n", gl->gl_name, *cp);
525                                         hit++;
526                                 }
527                 }
528         endglent();
529
530         if (!hit && out && !mail)
531                 fprintf(out, "all group leaders accounted for\n");
532 }
533 #endif /* UCI */