Removed UCI-specific group leader code from conflict(8).
[mmh] / uip / conflict.c
1 /*
2 ** conflict.c -- check for conflicts in mail system
3 **
4 ** This code is Copyright (c) 2002, by the authors of nmh.  See the
5 ** COPYRIGHT file in the root directory of the nmh distribution for
6 ** complete copyright information.
7 */
8
9 #include <h/mh.h>
10 #include <fcntl.h>
11 #include <h/aliasbr.h>
12 #include <h/mts.h>
13 #include <h/utils.h>
14 #include <grp.h>
15 #include <pwd.h>
16
17 /*
18 ** maximum number of directories that can
19 ** be specified using -search switch.
20 */
21 #define NDIRS  100
22
23 /*
24 ** Add space for group names, 100 at a time
25 */
26 #define NGRPS  100
27
28 static struct swit switches[] = {
29 #define MAILSW  0
30         { "mail name", 0 },
31 #define SERCHSW  1
32         { "search directory", 0 },
33 #define VERSIONSW  2
34         { "version", 0 },
35 #define HELPSW  3
36         { "help", 0 },
37         { NULL, 0 }
38 };
39
40 static char *mail = NULL;
41 static char *dirs[NDIRS];
42 static FILE *out = NULL;
43
44 extern struct aka  *akahead;
45 extern struct home *homehead;
46
47 /*
48 ** prototypes
49 */
50 void alias_files(int, char **);
51 void pwd_names(void);
52 void grp_names(void);
53 void grp_members(void);
54 void grp_ids(void);
55 void maildrops(void);
56 void mdrop(char *);
57 int check(char *);
58 void setup(void);
59
60
61 int
62 main(int argc, char **argv)
63 {
64         int akp = 0, dp = 0;
65         char *cp, **argp, **arguments;
66         char buf[BUFSIZ], *akv[50];
67
68 #ifdef LOCALE
69         setlocale(LC_ALL, "");
70 #endif
71         invo_name = mhbasename(argv[0]);
72
73         /* foil search of user profile/context */
74         if (context_foil(NULL) == -1)
75                 done(1);
76
77         mts_init(invo_name);
78         arguments = getarguments(invo_name, argc, argv, 0);
79         argp = arguments;
80
81         while ((cp = *argp++)) {
82                 if (*cp == '-') {
83                         switch (smatch(++cp, switches)) {
84                         case AMBIGSW:
85                                 ambigsw(cp, switches);
86                                 done(1);
87                         case UNKWNSW:
88                                 adios(NULL, "-%s unknown", cp);
89
90                         case HELPSW:
91                                 snprintf(buf, sizeof(buf), "%s [switches] [aliasfiles ...]", invo_name);
92                                 print_help(buf, switches, 0);
93                                 done(1);
94                         case VERSIONSW:
95                                 print_version(invo_name);
96                                 done(1);
97
98                         case MAILSW:
99                                 if (!(cp = *argp++) || *cp == '-')
100                                         adios(NULL, "missing argument to %s",
101                                                         argp[-2]);
102                                 if (mail)
103                                         adios(NULL, "mail to one address only");
104                                 else
105                                         mail = cp;
106                                 continue;
107
108                         case SERCHSW:
109                                 if (!(cp = *argp++) || *cp == '-')
110                                         adios(NULL, "missing argument to %s",
111                                                         argp[-2]);
112                                 if (dp >= NDIRS)
113                                         adios(NULL, "more than %d directories",
114                                                         NDIRS);
115                                 dirs[dp++] = cp;
116                                 continue;
117                         }
118                 }
119                 akv[akp++] = cp;
120         }
121
122         if (!homehead)
123                 init_pw();
124         if (!mail)
125                 out = stdout;
126         dirs[dp] = NULL;
127
128         alias_files(akp, akv);
129         pwd_names();
130         grp_names();
131         grp_members();
132         grp_ids();
133         maildrops();
134
135         done(0);
136         return 1;
137 }
138
139
140 void
141 alias_files(int akp, char **akv)
142 {
143         register int i, err;
144
145         for (i = 0; i < akp; i++)
146                 if ((err = alias(akv[i])) != AK_OK) {
147                         setup();
148                         fprintf(out, "aliasing error in %s - %s\n", akv[i],
149                                         akerror(err));
150                 } else if (out && !mail)
151                         fprintf(out, "alias file %s is ok\n", akv[i]);
152 }
153
154
155 void
156 pwd_names(void)
157 {
158         int hit = 0;
159         register struct home *hm, *lm;
160
161         for (hm = homehead; hm; hm = hm->h_next)
162                 for (lm = hm->h_next; lm; lm = lm->h_next)
163                         if (strcmp(hm->h_name, lm->h_name) == 0) {
164                                 setup();
165                                 fprintf(out, "duplicate user %s(uid=%d)\n",
166                                                 lm->h_name, (int) lm->h_uid);
167                                 hit++;
168                         }
169
170         if (!hit && out && !mail)
171                 fprintf(out, "no duplicate users\n");
172 }
173
174
175 void
176 grp_names(void)
177 {
178         int numgroups, maxgroups;
179         int i, hit = 0;
180         char **grps;
181         struct group *gr;
182
183         /* allocate space NGRPS at a time */
184         numgroups = 0;
185         maxgroups = NGRPS;
186         grps = (char **) mh_xmalloc((size_t) (maxgroups * sizeof(*grps)));
187
188         setgrent();
189         while ((gr = getgrent())) {
190                 for (i = 0; i < numgroups; i++)
191                         if (strcmp(grps[i], gr->gr_name)==0) {
192                                 setup();
193                                 fprintf(out, "duplicate group %s(gid=%d)\n",
194                                                 gr->gr_name, (int) gr->gr_gid);
195                                 hit++;
196                                 break;
197                         }
198                 if (i >= numgroups) {
199                         if (numgroups >= maxgroups) {
200                                 maxgroups += NGRPS;
201                                 grps = (char **) mh_xrealloc(grps,
202                                         (size_t) (maxgroups * sizeof(*grps)));
203                         }
204                         grps[numgroups++] = getcpy(gr->gr_name);
205                 }
206         }
207         endgrent();
208
209         for (i = 0; i < numgroups; i++)
210                 free(grps[i]);
211         free(grps);
212
213         if (!hit && out && !mail)
214                 fprintf(out, "no duplicate groups\n");
215 }
216
217
218 void
219 grp_members(void)
220 {
221         register int hit = 0;
222         register char **cp, **dp;
223         register struct group *gr;
224         register struct home  *hm;
225
226         setgrent();
227         while ((gr = getgrent())) {
228                 for (cp = gr->gr_mem; *cp; cp++) {
229                         for (hm = homehead; hm; hm = hm->h_next)
230                                 if (strcmp(*cp, hm->h_name)==0)
231                                         break;
232                         if (hm == NULL) {
233                                 setup();
234                                 fprintf(out, "group %s(gid=%d) has unknown member %s\n", gr->gr_name, (int) gr->gr_gid, *cp);
235                                 hit++;
236                         } else {
237                                 hm->h_ngrps++;
238                         }
239
240                         for (dp = cp + 1; *dp; dp++)
241                                 if (strcmp(*cp, *dp) == 0) {
242                                         setup();
243                                         fprintf(out, "group %s(gid=%d) has duplicate member %s\n", gr->gr_name, (int) gr->gr_gid, *cp);
244                                         hit++;
245                                 }
246                 }
247         }
248         endgrent();
249
250         for (hm = homehead; hm; hm = hm->h_next)
251                 if (hm->h_ngrps > NGROUPS_MAX) {
252                         setup();
253                         fprintf(out, "user %s is a member of %d groups (max %d)\n",
254                                         hm->h_name, hm->h_ngrps, NGROUPS_MAX);
255                         hit++;
256                 }
257
258         if (!hit && out && !mail)
259                 fprintf(out, "all group members accounted for\n");
260 }
261
262
263 void
264 grp_ids(void)
265 {  /* -DRAND not implemented at most places */
266         register int hit = 0;
267         register struct home *hm;
268
269         for (hm = homehead; hm; hm = hm->h_next)
270                 if (getgrgid(hm->h_gid) == NULL) {
271                         setup();
272                         fprintf(out, "user %s(uid=%d) has unknown group-id %d\n", hm->h_name, (int) hm->h_uid, (int) hm->h_gid);
273                         hit++;
274                 }
275
276         if (!hit && out && !mail)
277                 fprintf(out, "all group-id users accounted for\n");
278 }
279
280
281 void
282 maildrops(void)
283 {
284         register int i;
285
286         if (mmdfldir && *mmdfldir)
287                 mdrop(mmdfldir);
288         if (uucpldir && *uucpldir)
289                 mdrop(uucpldir);
290         for (i = 0; dirs[i]; i++)
291                 mdrop(dirs[i]);
292 }
293
294
295 void
296 mdrop(char *drop)
297 {
298         register int hit = 0;
299         register struct dirent *dp;
300         register DIR *dd = opendir(drop);
301
302         if (!dd) {
303                 setup();
304                 fprintf(out, "unable to open maildrop area %s\n", drop);
305                 return;
306         }
307
308         while ((dp = readdir(dd)))
309                 if (dp->d_name[0] != '.' && !check(dp->d_name)) {
310                         setup();
311                         fprintf(out, "there is a maildrop for the unknown user %s in %s\n", dp->d_name, drop);
312                         hit++;
313                 }
314
315         closedir(dd);
316         if (!hit && out && !mail)
317                 fprintf(out, "all maildrops accounted for in %s\n", drop);
318 }
319
320
321 int
322 check(char *s)
323 {
324         register struct home *hm;
325
326         for (hm = homehead; hm; hm = hm->h_next)
327                 if (strcmp(s, hm->h_name)==0)
328                         return 1;
329         return 0;
330 }
331
332 void
333 setup(void)
334 {
335         int fd, pd[2];
336
337         if (out)
338                 return;
339
340         if (mail) {
341                 if (pipe(pd) == NOTOK)
342                         adios("pipe", "unable to");
343
344                 switch (fork()) {
345                 case NOTOK:
346                         adios("fork", "unable to");
347
348                 case OK:
349                         close(pd[1]);
350                         if (pd[0] != 0) {
351                                 dup2(pd[0], 0);
352                                 close(pd[0]);
353                         }
354                         if ((fd = open("/dev/null", O_WRONLY))
355                                         != NOTOK)
356                                 if (fd != 1) {
357                                         dup2(fd, 1);
358                                         close(fd);
359                                 }
360                         execlp(mailproc, mhbasename(mailproc),
361                                         mail, "-subject", invo_name,
362                                         NULL);
363                         adios(mailproc, "unable to exec ");
364
365                 default:
366                         close(pd[0]);
367                         out = fdopen(pd[1], "w");
368                         fprintf(out, "%s: the following is suspicious\n\n", invo_name);
369                 }
370         }
371 }