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