]> diplodocus.org Git - nmh/blob - uip/conflict.c
Cope with sasl_decode64() returning SASL_CONTINUE as well as SASL_OK.
[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 done (0);
143 return 1;
144 }
145
146
147 void
148 alias_files (int akp, char **akv)
149 {
150 register int i, err;
151
152 for (i = 0; i < akp; i++)
153 if ((err = alias (akv[i])) != AK_OK) {
154 setup ();
155 fprintf (out, "aliasing error in %s - %s\n", akv[i], akerror (err));
156 }
157 else
158 if (out && !mail)
159 fprintf (out, "alias file %s is ok\n", akv[i]);
160 }
161
162
163 void
164 pwd_names (void)
165 {
166 int hit = 0;
167 register struct home *hm, *lm;
168
169 for (hm = homehead; hm; hm = hm->h_next)
170 for (lm = hm->h_next; lm; lm = lm->h_next)
171 if (strcmp (hm->h_name, lm->h_name) == 0) {
172 setup ();
173 fprintf (out, "duplicate user %s(uid=%d)\n",
174 lm->h_name, (int) lm->h_uid);
175 hit++;
176 }
177
178 if (!hit && out && !mail)
179 fprintf (out, "no duplicate users\n");
180 }
181
182
183 void
184 grp_names (void)
185 {
186 int numgroups, maxgroups;
187 int i, hit = 0;
188 char **grps;
189 struct group *gr;
190
191 /* allocate space NGRPS at a time */
192 numgroups = 0;
193 maxgroups = NGRPS;
194 grps = (char **) mh_xmalloc((size_t) (maxgroups * sizeof(*grps)));
195
196 setgrent ();
197 while ((gr = getgrent ())) {
198 for (i = 0; i < numgroups; i++)
199 if (!strcmp (grps[i], gr->gr_name)) {
200 setup ();
201 fprintf (out, "duplicate group %s(gid=%d)\n",
202 gr->gr_name, (int) gr->gr_gid);
203 hit++;
204 break;
205 }
206 if (i >= numgroups) {
207 if (numgroups >= maxgroups) {
208 maxgroups += NGRPS;
209 grps = (char **) mh_xrealloc(grps,
210 (size_t) (maxgroups * sizeof(*grps)));
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 */