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