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