]> diplodocus.org Git - nmh/blob - uip/aliasbr.c
Added notes about the configure change.
[nmh] / uip / aliasbr.c
1
2 /*
3 * aliasbr.c -- new aliasing mechanism
4 *
5 * $Id$
6 */
7
8 #include <h/mh.h>
9 #include <h/aliasbr.h>
10 #include <grp.h>
11 #include <pwd.h>
12
13 static int akvis;
14 static char *akerrst;
15
16 struct aka *akahead = NULL;
17 struct aka *akatail = NULL;
18
19 struct home *homehead = NULL;
20 struct home *hometail = NULL;
21
22 /*
23 * prototypes
24 */
25 int alias (char *);
26 int akvisible (void);
27 void init_pw (void);
28 char *akresult (struct aka *);
29 char *akvalue (char *);
30 char *akerror (int);
31
32 static char *akval (struct aka *, char *);
33 static int aleq (char *, char *);
34 static char *scanp (char *);
35 static char *getp (char *);
36 static char *seekp (char *, char *, char **);
37 static int addfile (struct aka *, char *);
38 static int addgroup (struct aka *, char *);
39 static int addmember (struct aka *, char *);
40 static int addall (struct aka *);
41 static char *getalias (char *);
42 static void add_aka (struct aka *, char *);
43 static struct aka *akalloc (char *);
44 static struct home *hmalloc (struct passwd *);
45 #ifndef MMDFMTS
46 struct home *seek_home (char *);
47 #endif
48
49
50 char *
51 akvalue (char *s)
52 {
53 register char *v;
54
55 if (akahead == NULL)
56 alias (AliasFile);
57
58 akvis = -1;
59 v = akval (akahead, s);
60 if (akvis == -1)
61 akvis = 0;
62 return v;
63 }
64
65
66 int
67 akvisible (void)
68 {
69 return akvis;
70 }
71
72
73 char *
74 akresult (struct aka *ak)
75 {
76 register char *cp = NULL, *dp, *pp;
77 register struct adr *ad;
78
79 for (ad = ak->ak_addr; ad; ad = ad->ad_next) {
80 pp = ad->ad_local ? akval (ak->ak_next, ad->ad_text)
81 : getcpy (ad->ad_text);
82
83 if (cp) {
84 dp = cp;
85 cp = concat (cp, ",", pp, NULL);
86 free (dp);
87 free (pp);
88 }
89 else
90 cp = pp;
91 }
92
93 if (akvis == -1)
94 akvis = ak->ak_visible;
95 return cp;
96 }
97
98
99 static char *
100 akval (struct aka *ak, char *s)
101 {
102 if (!s)
103 return s; /* XXX */
104
105 for (; ak; ak = ak->ak_next)
106 if (aleq (s, ak->ak_name))
107 return akresult (ak);
108
109 return getcpy (s);
110 }
111
112
113 static int
114 aleq (char *string, char *aliasent)
115 {
116 register char c;
117
118 while ((c = *string++))
119 if (*aliasent == '*')
120 return 1;
121 else
122 if ((c | 040) != (*aliasent | 040))
123 return 0;
124 else
125 aliasent++;
126
127 return (*aliasent == 0 || *aliasent == '*');
128 }
129
130
131 int
132 alias (char *file)
133 {
134 int i;
135 register char *bp, *cp, *pp;
136 char lc, *ap;
137 register struct aka *ak = NULL;
138 register FILE *fp;
139
140 if (*file != '/'
141 && (strncmp (file, "./", 2) && strncmp (file, "../", 3)))
142 file = etcpath (file);
143 if ((fp = fopen (file, "r")) == NULL) {
144 akerrst = file;
145 return AK_NOFILE;
146 }
147
148 while (vfgets (fp, &ap) == OK) {
149 bp = ap;
150 switch (*(pp = scanp (bp))) {
151 case '<': /* recurse a level */
152 if (!*(cp = getp (pp + 1))) {
153 akerrst = "'<' without alias-file";
154 fclose (fp);
155 return AK_ERROR;
156 }
157 if ((i = alias (cp)) != AK_OK) {
158 fclose (fp);
159 return i;
160 }
161
162 case ':': /* comment */
163 case ';':
164 case '#':
165 case 0:
166 continue;
167 }
168
169 akerrst = bp;
170 if (!*(cp = seekp (pp, &lc, &ap))) {
171 fclose (fp);
172 return AK_ERROR;
173 }
174 if (!(ak = akalloc (cp))) {
175 fclose (fp);
176 return AK_LIMIT;
177 }
178 switch (lc) {
179 case ':':
180 ak->ak_visible = 0;
181 break;
182
183 case ';':
184 ak->ak_visible = 1;
185 break;
186
187 default:
188 fclose (fp);
189 return AK_ERROR;
190 }
191
192 switch (*(pp = scanp (ap))) {
193 case 0: /* EOL */
194 fclose (fp);
195 return AK_ERROR;
196
197 case '<': /* read values from file */
198 if (!*(cp = getp (pp + 1))) {
199 fclose (fp);
200 return AK_ERROR;
201 }
202 if (!addfile (ak, cp)) {
203 fclose (fp);
204 return AK_NOFILE;
205 }
206 break;
207
208 case '=': /* UNIX group */
209 if (!*(cp = getp (pp + 1))) {
210 fclose (fp);
211 return AK_ERROR;
212 }
213 if (!addgroup (ak, cp)) {
214 fclose (fp);
215 return AK_NOGROUP;
216 }
217 break;
218
219 case '+': /* UNIX group members */
220 if (!*(cp = getp (pp + 1))) {
221 fclose (fp);
222 return AK_ERROR;
223 }
224 if (!addmember (ak, cp)) {
225 fclose (fp);
226 return AK_NOGROUP;
227 }
228 break;
229
230 case '*': /* Everyone */
231 addall (ak);
232 break;
233
234 default: /* list */
235 while ((cp = getalias (pp)))
236 add_aka (ak, cp);
237 break;
238 }
239 }
240
241 fclose (fp);
242 return AK_OK;
243 }
244
245
246 char *
247 akerror (int i)
248 {
249 static char buffer[BUFSIZ];
250
251 switch (i) {
252 case AK_NOFILE:
253 snprintf (buffer, sizeof(buffer), "unable to read '%s'", akerrst);
254 break;
255
256 case AK_ERROR:
257 snprintf (buffer, sizeof(buffer), "error in line '%s'", akerrst);
258 break;
259
260 case AK_LIMIT:
261 snprintf (buffer, sizeof(buffer), "out of memory while on '%s'", akerrst);
262 break;
263
264 case AK_NOGROUP:
265 snprintf (buffer, sizeof(buffer), "no such group as '%s'", akerrst);
266 break;
267
268 default:
269 snprintf (buffer, sizeof(buffer), "unknown error (%d)", i);
270 break;
271 }
272
273 return buffer;
274 }
275
276
277 static char *
278 scanp (char *p)
279 {
280 while (isspace (*p))
281 p++;
282 return p;
283 }
284
285
286 static char *
287 getp (char *p)
288 {
289 register char *cp = scanp (p);
290
291 p = cp;
292 while (!isspace (*cp) && *cp)
293 cp++;
294 *cp = 0;
295
296 return p;
297 }
298
299
300 static char *
301 seekp (char *p, char *c, char **a)
302 {
303 register char *cp;
304
305 p = cp = scanp (p);
306 while (!isspace (*cp) && *cp && *cp != ':' && *cp != ';')
307 cp++;
308 *c = *cp;
309 *cp++ = 0;
310 *a = cp;
311
312 return p;
313 }
314
315
316 static int
317 addfile (struct aka *ak, char *file)
318 {
319 register char *cp;
320 char buffer[BUFSIZ];
321 register FILE *fp;
322
323 if (!(fp = fopen (etcpath (file), "r"))) {
324 akerrst = file;
325 return 0;
326 }
327
328 while (fgets (buffer, sizeof buffer, fp))
329 while ((cp = getalias (buffer)))
330 add_aka (ak, cp);
331
332 fclose (fp);
333 return 1;
334 }
335
336
337 static int
338 addgroup (struct aka *ak, char *grp)
339 {
340 register char *gp;
341 register struct group *gr = getgrnam (grp);
342 register struct home *hm = NULL;
343
344 if (!gr)
345 gr = getgrgid (atoi (grp));
346 if (!gr) {
347 akerrst = grp;
348 return 0;
349 }
350
351 #ifndef DBMPWD
352 if (homehead == NULL)
353 init_pw ();
354 #endif /* DBMPWD */
355
356 while ((gp = *gr->gr_mem++))
357 #ifdef DBMPWD
358 {
359 struct passwd *pw;
360 #endif /* DBMPWD */
361 for (hm = homehead; hm; hm = hm->h_next)
362 if (!strcmp (hm->h_name, gp)) {
363 add_aka (ak, hm->h_name);
364 break;
365 }
366 #ifdef DBMPWD
367 if ((pw = getpwnam(gp)))
368 {
369 hmalloc(pw);
370 add_aka (ak, gp);
371 }
372 }
373 #endif /* DBMPWD */
374
375 return 1;
376 }
377
378
379 static int
380 addmember (struct aka *ak, char *grp)
381 {
382 gid_t gid;
383 register struct group *gr = getgrnam (grp);
384 register struct home *hm = NULL;
385
386 if (gr)
387 gid = gr->gr_gid;
388 else {
389 gid = atoi (grp);
390 gr = getgrgid (gid);
391 }
392 if (!gr) {
393 akerrst = grp;
394 return 0;
395 }
396
397 #ifndef DBMPWD
398 if (homehead == NULL)
399 #endif /* DBMPWD */
400 init_pw ();
401
402 for (hm = homehead; hm; hm = hm->h_next)
403 if (hm->h_gid == gid)
404 add_aka (ak, hm->h_name);
405
406 return 1;
407 }
408
409
410 static int
411 addall (struct aka *ak)
412 {
413 int noshell = NoShell == NULL || *NoShell == 0;
414 register struct home *hm;
415
416 #ifndef DBMPWD
417 if (homehead == NULL)
418 #endif /* DBMPWD */
419 init_pw ();
420 if (Everyone < 0)
421 Everyone = EVERYONE;
422
423 for (hm = homehead; hm; hm = hm->h_next)
424 if (hm->h_uid > Everyone
425 && (noshell || strcmp (hm->h_shell, NoShell)))
426 add_aka (ak, hm->h_name);
427
428 return homehead != NULL;
429 }
430
431
432 static char *
433 getalias (char *addrs)
434 {
435 register char *pp, *qp;
436 static char *cp = NULL;
437
438 if (cp == NULL)
439 cp = addrs;
440 else
441 if (*cp == 0)
442 return (cp = NULL);
443
444 for (pp = cp; isspace (*pp); pp++)
445 continue;
446 if (*pp == 0)
447 return (cp = NULL);
448 for (qp = pp; *qp != 0 && *qp != ','; qp++)
449 continue;
450 if (*qp == ',')
451 *qp++ = 0;
452 for (cp = qp, qp--; qp > pp; qp--)
453 if (*qp != 0)
454 if (isspace (*qp))
455 *qp = 0;
456 else
457 break;
458
459 return pp;
460 }
461
462
463 static void
464 add_aka (struct aka *ak, char *pp)
465 {
466 register struct adr *ad, *ld;
467
468 for (ad = ak->ak_addr, ld = NULL; ad; ld = ad, ad = ad->ad_next)
469 if (!strcmp (pp, ad->ad_text))
470 return;
471
472 ad = (struct adr *) malloc (sizeof(*ad));
473 if (ad == NULL)
474 return;
475 ad->ad_text = getcpy (pp);
476 ad->ad_local = strchr(pp, '@') == NULL && strchr(pp, '!') == NULL;
477 ad->ad_next = NULL;
478 if (ak->ak_addr)
479 ld->ad_next = ad;
480 else
481 ak->ak_addr = ad;
482 }
483
484
485 void
486 init_pw (void)
487 {
488 register struct passwd *pw;
489 #ifdef DBMPWD
490 static int init;
491
492 if (!init)
493 {
494 /* if the list has yet to be initialized */
495 /* zap the list, and rebuild from scratch */
496 homehead=NULL;
497 hometail=NULL;
498 init++;
499 #endif /* DBMPWD */
500
501 setpwent ();
502
503 while ((pw = getpwent ()))
504 if (!hmalloc (pw))
505 break;
506
507 endpwent ();
508 #ifdef DBMPWD
509 }
510 #endif /* DBMPWD */
511 }
512
513
514 static struct aka *
515 akalloc (char *id)
516 {
517 register struct aka *p;
518
519 if (!(p = (struct aka *) malloc (sizeof(*p))))
520 return NULL;
521
522 p->ak_name = getcpy (id);
523 p->ak_visible = 0;
524 p->ak_addr = NULL;
525 p->ak_next = NULL;
526 if (akatail != NULL)
527 akatail->ak_next = p;
528 if (akahead == NULL)
529 akahead = p;
530 akatail = p;
531
532 return p;
533 }
534
535
536 static struct home *
537 hmalloc (struct passwd *pw)
538 {
539 register struct home *p;
540
541 if (!(p = (struct home *) malloc (sizeof(*p))))
542 return NULL;
543
544 p->h_name = getcpy (pw->pw_name);
545 p->h_uid = pw->pw_uid;
546 p->h_gid = pw->pw_gid;
547 p->h_home = getcpy (pw->pw_dir);
548 p->h_shell = getcpy (pw->pw_shell);
549 p->h_ngrps = 0;
550 p->h_next = NULL;
551 if (hometail != NULL)
552 hometail->h_next = p;
553 if (homehead == NULL)
554 homehead = p;
555 hometail = p;
556
557 return p;
558 }
559
560
561 #ifndef MMDFMTS
562 struct home *
563 seek_home (char *name)
564 {
565 register struct home *hp;
566 #ifdef DBMPWD
567 struct passwd *pw;
568 char lname[32];
569 char *c,*c1;
570 #else /* DBMPWD */
571
572 if (homehead == NULL)
573 init_pw ();
574 #endif /* DBMPWD */
575
576 for (hp = homehead; hp; hp = hp->h_next)
577 if (!strcasecmp (name, hp->h_name))
578 return hp;
579
580 #ifdef DBMPWD
581 /*
582 * The only place where there might be problems.
583 * This assumes that ALL usernames are kept in lowercase.
584 */
585 for (c = name, c1 = lname; *c && (c1 - lname < sizeof(lname) - 1); c++, c1++) {
586 if (isalpha(*c) && isupper(*c))
587 *c1 = tolower (*c);
588 else
589 *c1 = *c;
590 }
591 *c1 = '\0';
592 if ((pw = getpwnam(lname)))
593 return(hmalloc(pw));
594 #endif /* DBMPWD */
595
596 return NULL;
597 }
598 #endif /* MMDFMTS */