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