]> diplodocus.org Git - nmh/blob - zotnet/bboards/getbbent.c
deal with SIGPIPE so mhl doesn't print "Broken pipe" if you quit out
[nmh] / zotnet / bboards / getbbent.c
1
2 /*
3 * getbbent.c -- subroutines for accessing the BBoards file
4 *
5 * $Id$
6 */
7
8 #include <h/nmh.h>
9
10 #ifdef MMDFONLY
11 # include <util.h>
12 # include <mmdf.h>
13 # include <strings.h>
14 #endif /* MMDFONLY */
15
16 #include <pwd.h>
17 #include <grp.h>
18 #include <bboards.h>
19
20 #ifdef HAVE_CRYPT_H
21 # include <crypt.h>
22 #endif
23
24 #ifdef HAVE_UNISTD_H
25 # include <unistd.h>
26 #endif
27
28 #ifndef MMDFONLY
29 # define NOTOK (-1)
30 # define OK 0
31 #endif
32
33 #define MaxBBAka 100
34 #define MaxBBLdr 100
35 #define MaxBBDist 100
36
37 #define NCOLON 9 /* currently 10 fields per entry */
38
39 #define COLON ':'
40 #define COMMA ','
41 #define NEWLINE '\n'
42
43 #define ARCHIVE "archive"
44 #define CNTFILE ".cnt"
45 #define DSTFILE ".dist"
46 #define MAPFILE ".map"
47
48 static int BBuid = -1;
49
50 static unsigned int BBflags = SB_NULL;
51
52 static char BBName[BUFSIZ] = BBOARDS;
53 static char BBDir[BUFSIZ] = "";
54 static char BBData[BUFSIZ] = "";
55
56 static FILE *BBfile = NULL;
57
58 static struct bboard BB;
59 static struct bboard *bb = &BB;
60
61 static int BBload = 1;
62
63 static char BBFile[BUFSIZ];
64 static char BBArchive[BUFSIZ];
65 static char BBInfo[BUFSIZ];
66 static char BBMap[BUFSIZ];
67 static char *BBAkas[MaxBBAka];
68 static char *BBLeaders[MaxBBLdr];
69 static char *BBDists[MaxBBDist];
70 static char BBAddr[BUFSIZ];
71 static char BBRequest[BUFSIZ];
72 static char BBDate[BUFSIZ];
73 static char BBErrors[BUFSIZ];
74
75 #ifdef MMDFONLY
76 extern LLog *logptr;
77 #endif
78
79 #ifdef UCL
80 int called_bbc = 0;
81 char *bbs[101];
82 #endif
83
84
85 /*
86 * static prototypes
87 */
88 static int setbbaux (char *, char *);
89 static int setpwaux (struct passwd *, char *);
90 static void BBread (void);
91 static int getbbitem (struct bboard *, char *, int (*)());
92 static int bblose (char *, ...);
93 static char *bbskip (char *, char);
94 static char *getcpy (char *);
95
96
97 int
98 setbbfile (char *file, int f)
99 {
100 if (BBuid == -1)
101 return setbbinfo (BBOARDS, file, f);
102
103 strncpy (BBData, file, sizeof(BBData));
104
105 BBflags = SB_NULL;
106 endbbent ();
107
108 return setbbent (f);
109 }
110
111
112 int
113 setbbinfo (char *user, char *file, int f)
114 {
115 register struct passwd *pw;
116
117 if ((pw = getpwnam (user)) == NULL) {
118 snprintf (BBErrors, sizeof(BBErrors), "unknown user: %s", user);
119 return 0;
120 }
121
122 return setpwinfo (pw, file, f);
123 }
124
125
126 int
127 setpwinfo (struct passwd *pw, char *file, int f)
128 {
129 if (!setpwaux (pw, file))
130 return 0;
131
132 BBflags = SB_NULL;
133 endbbent ();
134
135 return setbbent (f);
136 }
137
138
139 static int
140 setbbaux (char *name, char *file)
141 {
142 register struct passwd *pw;
143
144 if ((pw = getpwnam (name)) == NULL) {
145 snprintf (BBErrors, sizeof(BBErrors), "unknown user: %s", name);
146 return 0;
147 }
148
149 return setpwaux (pw, file);
150 }
151
152
153 static int
154 setpwaux (struct passwd *pw, char *file)
155 {
156 strncpy (BBName, pw->pw_name, sizeof(BBName));
157 BBuid = pw->pw_uid;
158 strncpy (BBDir, pw->pw_dir, sizeof(BBDir));
159 snprintf (BBData, sizeof(BBData), "%s/%s",
160 *file != '/' ? BBDir : "",
161 *file != '/' ? file : file + 1);
162
163 BBflags = SB_NULL;
164
165 return 1;
166 }
167
168
169 int
170 setbbent (int f)
171 {
172 if (BBfile == NULL) {
173 if (BBuid == -1 && !setbbaux (BBOARDS, BBDB))
174 return 0;
175
176 if ((BBfile = fopen (BBData, "r")) == NULL) {
177 snprintf (BBErrors, sizeof(BBErrors), "unable to open: %s", BBData);
178 return 0;
179 }
180 }
181 else
182 rewind (BBfile);
183
184 BBflags |= f;
185 return (BBfile != NULL);
186 }
187
188
189 int
190 endbbent (void)
191 {
192 if (BBfile != NULL && !(BBflags & SB_STAY)) {
193 fclose (BBfile);
194 BBfile = NULL;
195 }
196
197 return 1;
198 }
199
200
201 long
202 getbbtime (void)
203 {
204 struct stat st;
205
206 if (BBfile == NULL) {
207 if (BBuid == -1 && !setbbaux (BBOARDS, BBDB))
208 return 0;
209
210 if (stat (BBData, &st) == NOTOK) {
211 snprintf (BBErrors, sizeof(BBErrors), "unable to stat: %s", BBData);
212 return 0;
213 }
214 } else {
215 if (fstat (fileno (BBfile), &st) == NOTOK) {
216 snprintf (BBErrors, sizeof(BBErrors), "unable to fstat: %s", BBData);
217 return 0;
218 }
219 }
220
221 return ((long) st.st_mtime);
222 }
223
224
225 struct bboard *
226 getbbent (void)
227 {
228 register int count;
229 register char *p, *q, *r, *d, *f, **s;
230 static char line[BUFSIZ];
231
232 if (BBfile == NULL && !setbbent (SB_NULL))
233 return NULL;
234
235 retry: ;
236 if ((p = fgets (line, sizeof line, BBfile)) == NULL)
237 return NULL;
238
239 for (q = p, count = 0; *q != 0 && *q != NEWLINE; q++)
240 if (*q == COLON)
241 count++;
242
243 if (count != NCOLON) {
244 #ifdef MMDFONLY
245 if (q = strchr(p, NEWLINE))
246 *q = 0;
247 ll_log (logptr, LLOGTMP, "bad entry in %s: %s", BBData, p);
248 #endif /* MMDFONLY */
249 goto retry;
250 }
251
252 bb->bb_name = p;
253 p = q = bbskip (p, COLON);
254 p = bb->bb_file = bbskip (p, COLON);
255 bb->bb_archive = bb->bb_info = bb->bb_map = "";
256 p = bb->bb_passwd = bbskip (p, COLON);
257 p = r = bbskip (p, COLON);
258 p = bb->bb_addr = bbskip (p, COLON);
259 p = bb->bb_request = bbskip (p, COLON);
260 p = bb->bb_relay = bbskip (p, COLON);
261 p = d = bbskip (p, COLON);
262 p = f = bbskip (p, COLON);
263 bbskip (p, NEWLINE);
264
265 s = bb->bb_aka = BBAkas;
266 while (*q) {
267 *s++ = q;
268 q = bbskip (q, COMMA);
269 }
270 *s = 0;
271
272 s = bb->bb_leader = BBLeaders;
273 if (*r == 0) {
274 if (!(BBflags & SB_FAST)) {
275 *s++ = BBName;
276 *s = 0;
277 }
278 }
279 else {
280 while (*r) {
281 *s++ = r;
282 r = bbskip (r, COMMA);
283 }
284 *s = 0;
285 }
286
287 s = bb->bb_dist = BBDists;
288 while (*d) {
289 *s++ = d;
290 d = bbskip (d, COMMA);
291 }
292 *s = 0;
293
294 if (*f)
295 sscanf (f, "%o", &bb->bb_flags);
296 else
297 bb->bb_flags = BB_NULL;
298 bb->bb_count = bb->bb_maxima = 0;
299 bb->bb_date = NULL;
300 bb->bb_next = bb->bb_link = bb->bb_chain = NULL;
301
302 #ifdef UCL
303 /*
304 * Only do a BBread on bboards that the user has expressed an
305 * interest in, if we were called by bbc.
306 */
307 if (BBload) {
308 register char **ap, *cp;
309 register int bbp;
310
311 if (called_bbc == 0)
312 BBread();
313 else {
314 for (bbp = 0; cp = bbs[bbp]; bbp++) {
315 if (!strcmp(bb->bb_name, cp)) {
316 BBread();
317 break;
318 }
319 for (ap = bb->bb_aka; *ap; ap++)
320 if (!strcmp(*ap, cp)) {
321 BBread();
322 break;
323 }
324 }
325 }
326 }
327 #else
328 if (BBload)
329 BBread ();
330 #endif
331
332 return bb;
333 }
334
335
336 struct bboard *
337 getbbnam (char *name)
338 {
339 register struct bboard *b = NULL;
340
341 if (!setbbent (SB_NULL))
342 return NULL;
343 BBload = 0;
344 while ((b = getbbent ()) && strcmp (name, b->bb_name))
345 continue;
346 BBload = 1;
347 endbbent ();
348
349 if (b != NULL)
350 BBread ();
351
352 return b;
353 }
354
355
356 struct bboard *
357 getbbaka (char *aka)
358 {
359 register char **ap;
360 register struct bboard *b = NULL;
361
362 if (!setbbent (SB_NULL))
363 return NULL;
364 BBload = 0;
365 while ((b = getbbent ()) != NULL)
366 for (ap = b->bb_aka; *ap; ap++)
367 if (strcmp (aka, *ap) == 0)
368 goto hit;
369 hit: ;
370 BBload = 1;
371 endbbent ();
372
373 if (b != NULL)
374 BBread ();
375
376 return b;
377 }
378
379
380 static void
381 BBread (void)
382 {
383 register int i;
384 register char *cp, *dp, *p, *r;
385 char prf[BUFSIZ];
386 static char line[BUFSIZ];
387 register FILE * info;
388
389 if (BBflags & SB_FAST)
390 return;
391
392 p = strchr(bb->bb_request, '@');
393 r = strchr(bb->bb_addr, '@');
394 BBRequest[0] = 0;
395
396 if (*bb->bb_request == '-')
397 if (p == NULL && r && *r == '@')
398 snprintf (BBRequest, sizeof(BBRequest), "%s%s%s", bb->bb_name, bb->bb_request, r);
399 else
400 snprintf (BBRequest, sizeof(BBRequest), "%s%s", bb->bb_name, bb->bb_request);
401 else
402 if (p == NULL && r && *r == '@' && *bb->bb_request)
403 snprintf (BBRequest, sizeof(BBRequest), "%s%s", bb->bb_request, r);
404
405 if (BBRequest[0])
406 bb->bb_request = BBRequest;
407 else
408 if (*bb->bb_request == 0)
409 bb->bb_request = *bb->bb_addr ? bb->bb_addr
410 : bb->bb_leader[0];
411
412 if (*bb->bb_addr == '@') {
413 snprintf (BBAddr, sizeof(BBAddr), "%s%s", bb->bb_name, bb->bb_addr);
414 bb->bb_addr = BBAddr;
415 }
416 else
417 if (*bb->bb_addr == 0)
418 bb->bb_addr = bb->bb_name;
419
420 if (*bb->bb_file == 0)
421 return;
422 if (*bb->bb_file != '/') {
423 snprintf (BBFile, sizeof(BBFile), "%s/%s", BBDir, bb->bb_file);
424 bb->bb_file = BBFile;
425 }
426
427 if ((cp = strrchr(bb->bb_file, '/')) == NULL || *++cp == 0) {
428 strcpy (prf, "");
429 cp = bb->bb_file;
430 } else {
431 snprintf (prf, sizeof(prf), "%.*s", cp - bb->bb_file, bb->bb_file);
432 }
433 if ((dp = strchr(cp, '.')) == NULL)
434 dp = cp + strlen (cp);
435
436 snprintf (BBArchive, sizeof(BBArchive), "%s%s/%s", prf, ARCHIVE, cp);
437 bb->bb_archive = BBArchive;
438 snprintf (BBInfo, sizeof(BBInfo), "%s.%.*s%s", prf, dp - cp, cp, CNTFILE);
439 bb->bb_info = BBInfo;
440 snprintf (BBMap, sizeof(BBMap), "%s.%.*s%s", prf, dp - cp, cp, MAPFILE);
441 bb->bb_map = BBMap;
442
443 if ((info = fopen (bb->bb_info, "r")) == NULL)
444 return;
445
446 if (fgets (line, sizeof line, info) && (i = atoi (line)) > 0)
447 bb->bb_maxima = (unsigned) i;
448 if (!feof (info) && fgets (line, sizeof line, info)) {
449 strncpy (BBDate, line, sizeof(BBData));
450 if ((cp = strchr(BBDate, NEWLINE)))
451 *cp = 0;
452 bb->bb_date = BBDate;
453 }
454
455 fclose (info);
456 }
457
458
459 int
460 ldrbb (struct bboard *b)
461 {
462 register char *p, **q, **r;
463 static uid_t uid = 0;
464 static gid_t gid = 0;
465 static char username[10] = "";
466 register struct passwd *pw;
467 register struct group *gr;
468
469 if (b == NULL)
470 return 0;
471 if (BBuid == -1 && !setbbaux (BBOARDS, BBDB))
472 return 0;
473
474 if (username[0] == 0) {
475 if ((pw = getpwuid (uid = getuid ())) == NULL)
476 return 0;
477 gid = getgid ();
478 strncpy (username, pw->pw_name, sizeof(username));
479 }
480
481 if (uid == BBuid)
482 return 1;
483
484 q = b->bb_leader;
485 while ((p = *q++))
486 if (*p == '=') {
487 if ((gr = getgrnam (++p)) == NULL)
488 continue;
489 if (gid == gr->gr_gid)
490 return 1;
491 r = gr->gr_mem;
492 while ((p = *r++))
493 if (strcmp (username, p) == 0)
494 return 1;
495 }
496 else
497 if (strcmp (username, p) == 0)
498 return 1;
499
500 return 0;
501 }
502
503
504 int
505 ldrchk (struct bboard *b)
506 {
507 if (b == NULL)
508 return 0;
509
510 if (*b->bb_passwd == 0)
511 return 1;
512
513 if (strcmp (b->bb_passwd,
514 crypt (getpass ("Password: "), b->bb_passwd)) == 0)
515 return 1;
516
517 fprintf (stderr, "Sorry\n");
518 return 0;
519 }
520
521
522 struct bboard *
523 getbbcpy (struct bboard *bp)
524 {
525 register char **p, **q;
526 register struct bboard *b;
527
528 if (bp == NULL)
529 return NULL;
530
531 b = (struct bboard *) malloc ((unsigned) sizeof *b);
532 if (b == NULL)
533 return NULL;
534
535 b->bb_name = getcpy (bp->bb_name);
536 b->bb_file = getcpy (bp->bb_file);
537 b->bb_archive = getcpy (bp->bb_archive);
538 b->bb_info = getcpy (bp->bb_info);
539 b->bb_map = getcpy (bp->bb_map);
540 b->bb_passwd = getcpy (bp->bb_passwd);
541 b->bb_flags = bp->bb_flags;
542 b->bb_count = bp->bb_count;
543 b->bb_maxima = bp->bb_maxima;
544 b->bb_date = getcpy (bp->bb_date);
545 b->bb_addr = getcpy (bp->bb_addr);
546 b->bb_request = getcpy (bp->bb_request);
547 b->bb_relay = getcpy (bp->bb_relay);
548
549 for (p = bp->bb_aka; *p; p++)
550 continue;
551 b->bb_aka =
552 q = (char **) calloc ((unsigned) (p - bp->bb_aka + 1), sizeof *q);
553 if (q == NULL)
554 return NULL;
555 for (p = bp->bb_aka; *p; *q++ = getcpy (*p++))
556 continue;
557 *q = NULL;
558
559 for (p = bp->bb_leader; *p; p++)
560 continue;
561 b->bb_leader =
562 q = (char **) calloc ((unsigned) (p - bp->bb_leader + 1), sizeof *q);
563 if (q == NULL)
564 return NULL;
565 for (p = bp->bb_leader; *p; *q++ = getcpy (*p++))
566 continue;
567 *q = NULL;
568
569 for (p = bp->bb_dist; *p; p++)
570 continue;
571 b->bb_dist =
572 q = (char **) calloc ((unsigned) (p - bp->bb_dist + 1), sizeof *q);
573 if (q == NULL)
574 return NULL;
575 for (p = bp->bb_dist; *p; *q++ = getcpy (*p++))
576 continue;
577 *q = NULL;
578
579 b->bb_next = bp->bb_next;
580 b->bb_link = bp->bb_link;
581 b->bb_chain = bp->bb_chain;
582
583 return b;
584 }
585
586
587 int
588 getbbdist (struct bboard *bb, int (*action)())
589 {
590 register int result;
591 register char **dp;
592
593 BBErrors[0] = 0;
594 for (dp = bb->bb_dist; *dp; dp++)
595 if ((result = getbbitem (bb, *dp, action)))
596 return result;
597
598 return result;
599 }
600
601 char *
602 getbberr (void)
603 {
604 return (BBErrors[0] ? BBErrors : NULL);
605 }
606
607
608 static int
609 getbbitem (struct bboard *bb, char *item, int (*action)())
610 {
611 register int result;
612 register char *cp, *dp, *hp, *np;
613 char mbox[BUFSIZ],
614 buffer[BUFSIZ],
615 file[BUFSIZ],
616 host[BUFSIZ],
617 prf[BUFSIZ];
618 register FILE *fp;
619
620 switch (*item) {
621 case '*':
622 switch (*++item) {
623 case '/':
624 hp = item;
625 break;
626
627 case 0:
628 if ((cp = strrchr(bb->bb_file, '/')) == NULL || *++cp == 0) {
629 strcpy (prf, "");
630 cp = bb->bb_file;
631 } else {
632 snprintf (prf, sizeof(prf), "%.*s", cp - bb->bb_file, bb->bb_file);
633 }
634 if ((dp = strchr(cp, '.')) == NULL)
635 dp = cp + strlen (cp);
636 snprintf (file, sizeof(file), "%s.%.*s%s", prf, dp - cp, cp, DSTFILE);
637 hp = file;
638 break;
639
640 default:
641 snprintf (file, sizeof(file), "%s/%s", BBDir, item);
642 hp = file;
643 break;
644 }
645
646 if ((fp = fopen (hp, "r")) == NULL)
647 return bblose ("unable to read file %s", hp);
648 while (fgets (buffer, sizeof buffer, fp)) {
649 if ((np = strchr(buffer, '\n')))
650 *np = 0;
651 if ((result = getbbitem (bb, buffer, action))) {
652 fclose (fp);
653 bblose ("error with file %s, item %s", hp, buffer);
654 return result;
655 }
656 }
657 fclose (fp);
658 return OK;
659
660 default:
661 if ((hp = strrchr(item, '@'))) {
662 *hp++ = 0;
663 strncpy (mbox, item, sizeof(mbox));
664 strncpy (host, hp, sizeof(host));
665 *--hp = '@';
666 }
667 else {
668 snprintf (mbox, sizeof(mbox), "%s%s", DISTADR, bb->bb_name);
669 strncpy (host, item, sizeof(host));
670 }
671 if ((result = (*action) (mbox, host)))
672 bblose ("action (%s, %s) returned 0%o", mbox, host, result);
673 return result;
674 }
675 }
676
677
678 static int
679 bblose (char *fmt, ...)
680 {
681 va_list ap;
682
683 va_start(ap, fmt);
684 if (BBErrors[0] == 0)
685 vsnprintf (BBErrors, sizeof(BBErrors), fmt, ap);
686
687 va_end(ap);
688 return NOTOK;
689 }
690
691
692 void
693 make_lower (char *s1, char *s2)
694 {
695 if (!s1 || !s2)
696 return;
697
698 for (; *s2; s2++)
699 *s1++ = isupper (*s2) ? tolower (*s2) : *s2;
700 *s1 = 0;
701 }
702
703
704 static char *
705 bbskip (char *p, char c)
706 {
707 if (p == NULL)
708 return NULL;
709
710 while (*p && *p != c)
711 p++;
712 if (*p)
713 *p++ = 0;
714
715 return p;
716 }
717
718
719 static char *
720 getcpy (char *s)
721 {
722 register char *p;
723 size_t len;
724
725 if (s == NULL)
726 return NULL;
727
728 len = strlen (s) + 1;
729 if ((p = malloc (len)))
730 memcpy (p, s, len);
731 return p;
732 }
733