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