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