]> diplodocus.org Git - nmh/blob - uip/conflict.c
add rmf(1) and folder(1) to one another's SEE ALSO sections
[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 #define CONFLICT_SWITCHES \
30 X("mail name", 0, MAILSW) \
31 X("search directory", 0, SERCHSW) \
32 X("version", 0, VERSIONSW) \
33 X("help", 0, HELPSW) \
34
35 #define X(sw, minchars, id) id,
36 DEFINE_SWITCH_ENUM(CONFLICT);
37 #undef X
38
39 #define X(sw, minchars, id) { sw, minchars, id },
40 DEFINE_SWITCH_ARRAY(CONFLICT, switches);
41 #undef X
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 if (nmh_init(argv[0], 0 /* use context_foil() */)) { return 1; }
72
73 mts_init (invo_name);
74 arguments = getarguments (invo_name, argc, argv, 0);
75 argp = arguments;
76
77 while ((cp = *argp++)) {
78 if (*cp == '-') {
79 switch (smatch (++cp, switches)) {
80 case AMBIGSW:
81 ambigsw (cp, switches);
82 done (1);
83 case UNKWNSW:
84 adios (NULL, "-%s unknown", cp);
85
86 case HELPSW:
87 snprintf (buf, sizeof(buf), "%s [switches] [aliasfiles ...]",
88 invo_name);
89 print_help (buf, switches, 0);
90 done (0);
91 case VERSIONSW:
92 print_version(invo_name);
93 done (0);
94
95 case MAILSW:
96 if (!(cp = *argp++) || *cp == '-')
97 adios (NULL, "missing argument to %s", argp[-2]);
98 if (mail)
99 adios (NULL, "mail to one address only");
100 else
101 mail = cp;
102 continue;
103
104 case SERCHSW:
105 if (!(cp = *argp++) || *cp == '-')
106 adios (NULL, "missing argument to %s", argp[-2]);
107 if (dp >= NDIRS)
108 adios (NULL, "more than %d directories", NDIRS);
109 dirs[dp++] = cp;
110 continue;
111 }
112 }
113 akv[akp++] = cp;
114 }
115
116 if (akp == 0)
117 akv[akp++] = AliasFile;
118 if (!homehead)
119 init_pw ();
120 if (!mail)
121 out = stdout;
122 dirs[dp] = NULL;
123
124 alias_files (akp, akv);
125 pwd_names ();
126 grp_names ();
127 grp_members ();
128 grp_ids ();
129 maildrops ();
130
131 done (0);
132 return 1;
133 }
134
135
136 void
137 alias_files (int akp, char **akv)
138 {
139 register int i, err;
140
141 for (i = 0; i < akp; i++)
142 if ((err = alias (akv[i])) != AK_OK) {
143 setup ();
144 fprintf (out, "aliasing error in %s - %s\n", akv[i], akerror (err));
145 }
146 else
147 if (out && !mail)
148 fprintf (out, "alias file %s is ok\n", akv[i]);
149 }
150
151
152 void
153 pwd_names (void)
154 {
155 int hit = 0;
156 register struct home *hm, *lm;
157
158 for (hm = homehead; hm; hm = hm->h_next)
159 for (lm = hm->h_next; lm; lm = lm->h_next)
160 if (strcmp (hm->h_name, lm->h_name) == 0) {
161 setup ();
162 fprintf (out, "duplicate user %s(uid=%d)\n",
163 lm->h_name, (int) lm->h_uid);
164 hit++;
165 }
166
167 if (!hit && out && !mail)
168 fprintf (out, "no duplicate users\n");
169 }
170
171
172 void
173 grp_names (void)
174 {
175 int numgroups, maxgroups;
176 int i, hit = 0;
177 char **grps;
178 struct group *gr;
179
180 /* allocate space NGRPS at a time */
181 numgroups = 0;
182 maxgroups = NGRPS;
183 grps = (char **) mh_xmalloc((size_t) (maxgroups * sizeof(*grps)));
184
185 setgrent ();
186 while ((gr = getgrent ())) {
187 for (i = 0; i < numgroups; i++)
188 if (!strcmp (grps[i], gr->gr_name)) {
189 setup ();
190 fprintf (out, "duplicate group %s(gid=%d)\n",
191 gr->gr_name, (int) gr->gr_gid);
192 hit++;
193 break;
194 }
195 if (i >= numgroups) {
196 if (numgroups >= maxgroups) {
197 maxgroups += NGRPS;
198 grps = (char **) mh_xrealloc(grps,
199 (size_t) (maxgroups * sizeof(*grps)));
200 }
201 grps[numgroups++] = getcpy (gr->gr_name);
202 }
203 }
204 endgrent ();
205
206 for (i = 0; i < numgroups; i++)
207 free (grps[i]);
208 free (grps);
209
210 if (!hit && out && !mail)
211 fprintf (out, "no duplicate groups\n");
212 }
213
214
215 void
216 grp_members (void)
217 {
218 register int hit = 0;
219 register char **cp, **dp;
220 register struct group *gr;
221 register struct home *hm;
222
223 setgrent ();
224 while ((gr = getgrent ())) {
225 for (cp = gr->gr_mem; *cp; cp++) {
226 for (hm = homehead; hm; hm = hm->h_next)
227 if (!strcmp (*cp, hm->h_name))
228 break;
229 if (hm == NULL) {
230 setup ();
231 fprintf (out, "group %s(gid=%d) has unknown member %s\n",
232 gr->gr_name, (int) gr->gr_gid, *cp);
233 hit++;
234 } else {
235 hm->h_ngrps++;
236 }
237
238 for (dp = cp + 1; *dp; dp++)
239 if (strcmp (*cp, *dp) == 0) {
240 setup ();
241 fprintf (out, "group %s(gid=%d) has duplicate member %s\n",
242 gr->gr_name, (int) gr->gr_gid, *cp);
243 hit++;
244 }
245 }
246 }
247 endgrent ();
248
249 for (hm = homehead; hm; hm = hm->h_next)
250 if (hm->h_ngrps > NGROUPS_MAX) {
251 setup ();
252 fprintf (out, "user %s is a member of %d groups (max %d)\n",
253 hm->h_name, hm->h_ngrps, NGROUPS_MAX);
254 hit++;
255 }
256
257 if (!hit && out && !mail)
258 fprintf (out, "all group members accounted for\n");
259 }
260
261
262 void
263 grp_ids (void)
264 { /* -DRAND not implemented at most places */
265 register int hit = 0;
266 register struct home *hm;
267
268 for (hm = homehead; hm; hm = hm->h_next)
269 if (getgrgid (hm->h_gid) == NULL) {
270 setup ();
271 fprintf (out, "user %s(uid=%d) has unknown group-id %d\n",
272 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,
312 "there is a maildrop for the unknown user %s in %s\n",
313 dp->d_name, drop);
314 hit++;
315 }
316
317 closedir (dd);
318 if (!hit && out && !mail)
319 fprintf (out, "all maildrops accounted for in %s\n", drop);
320 }
321
322
323 int
324 check (char *s)
325 {
326 register struct home *hm;
327
328 for (hm = homehead; hm; hm = hm->h_next)
329 if (!strcmp (s, hm->h_name))
330 return 1;
331 return 0;
332 }
333
334 void
335 setup (void)
336 {
337 int fd, pd[2];
338
339 if (out)
340 return;
341
342 if (mail) {
343 if (pipe (pd) == NOTOK)
344 adios ("pipe", "unable to");
345
346 switch (fork ()) {
347 case NOTOK:
348 adios ("fork", "unable to");
349
350 case OK:
351 close (pd[1]);
352 if (pd[0] != 0) {
353 dup2 (pd[0], 0);
354 close (pd[0]);
355 }
356 if ((fd = open ("/dev/null", O_WRONLY)) != NOTOK)
357 if (fd != 1) {
358 dup2 (fd, 1);
359 close (fd);
360 }
361 execlp (mailproc, r1bindex (mailproc, '/'),
362 mail, "-subject", invo_name, (void *) 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",
369 invo_name);
370 }
371 }
372 }