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