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