Eliminated compilation warnings.
[mmh] / 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     }
402     else
403         if (p == NULL && r && *r == '@' && *bb->bb_request)
404             snprintf (BBRequest, sizeof(BBRequest), "%s%s", bb->bb_request, r);
405
406     if (BBRequest[0])
407         bb->bb_request = BBRequest;
408     else
409         if (*bb->bb_request == 0)
410             bb->bb_request = *bb->bb_addr ? bb->bb_addr
411                 : bb->bb_leader[0];
412
413     if (*bb->bb_addr == '@') {
414         snprintf (BBAddr, sizeof(BBAddr), "%s%s", bb->bb_name, bb->bb_addr);
415         bb->bb_addr = BBAddr;
416     }
417     else
418         if (*bb->bb_addr == 0)
419             bb->bb_addr = bb->bb_name;
420
421     if (*bb->bb_file == 0)
422         return;
423     if (*bb->bb_file != '/') {
424         snprintf (BBFile, sizeof(BBFile), "%s/%s", BBDir, bb->bb_file);
425         bb->bb_file = BBFile;
426     }
427
428     if ((cp = strrchr(bb->bb_file, '/')) == NULL || *++cp == 0) {
429         strcpy (prf, "");
430         cp = bb->bb_file;
431     } else {
432         snprintf (prf, sizeof(prf), "%.*s", cp - bb->bb_file, bb->bb_file);
433     }
434     if ((dp = strchr(cp, '.')) == NULL)
435         dp = cp + strlen (cp);
436
437     snprintf (BBArchive, sizeof(BBArchive), "%s%s/%s", prf, ARCHIVE, cp);
438     bb->bb_archive = BBArchive;
439     snprintf (BBInfo, sizeof(BBInfo), "%s.%.*s%s", prf, dp - cp, cp, CNTFILE);
440     bb->bb_info = BBInfo;
441     snprintf (BBMap, sizeof(BBMap), "%s.%.*s%s", prf, dp - cp, cp, MAPFILE);
442     bb->bb_map = BBMap;
443
444     if ((info = fopen (bb->bb_info, "r")) == NULL)
445         return;
446
447     if (fgets (line, sizeof line, info) && (i = atoi (line)) > 0)
448         bb->bb_maxima = (unsigned) i;
449     if (!feof (info) && fgets (line, sizeof line, info)) {
450         strncpy (BBDate, line, sizeof(BBData));
451         if ((cp = strchr(BBDate, NEWLINE)))
452             *cp = 0;
453         bb->bb_date = BBDate;
454     }
455
456     fclose (info);
457 }
458
459
460 int
461 ldrbb (struct bboard *b)
462 {
463     register char *p, **q, **r;
464     static uid_t uid = 0;
465     static gid_t gid = 0;
466     static char username[10] = "";
467     register struct passwd *pw;
468     register struct group  *gr;
469
470     if (b == NULL)
471         return 0;
472     if (BBuid == -1 && !setbbaux (BBOARDS, BBDB))
473         return 0;
474
475     if (username[0] == 0) {
476         if ((pw = getpwuid (uid = getuid ())) == NULL)
477             return 0;
478         gid = getgid ();
479         strncpy (username, pw->pw_name, sizeof(username));
480     }
481
482     if (uid == BBuid)
483         return 1;
484
485     q = b->bb_leader;
486     while ((p = *q++))
487         if (*p == '=') {
488             if ((gr = getgrnam (++p)) == NULL)
489                 continue;
490             if (gid == gr->gr_gid)
491                 return 1;
492             r = gr->gr_mem;
493             while ((p = *r++))
494                 if (strcmp (username, p) == 0)
495                     return 1;
496         }
497         else
498             if (strcmp (username, p) == 0)
499                 return 1;
500
501     return 0;
502 }
503
504
505 int
506 ldrchk (struct bboard *b)
507 {
508     if (b == NULL)
509         return 0;
510
511     if (*b->bb_passwd == 0)
512         return 1;
513
514     if (strcmp (b->bb_passwd,
515                 crypt (getpass ("Password: "), b->bb_passwd)) == 0)
516         return 1;
517
518     fprintf (stderr, "Sorry\n");
519     return 0;
520 }
521
522
523 struct bboard *
524 getbbcpy (struct bboard *bp)
525 {
526     register char **p, **q;
527     register struct bboard *b;
528
529     if (bp == NULL)
530         return NULL;
531
532     b = (struct bboard *) malloc ((unsigned) sizeof *b);
533     if (b == NULL)
534         return NULL;
535
536     b->bb_name = getcpy (bp->bb_name);
537     b->bb_file = getcpy (bp->bb_file);
538     b->bb_archive = getcpy (bp->bb_archive);
539     b->bb_info = getcpy (bp->bb_info);
540     b->bb_map = getcpy (bp->bb_map);
541     b->bb_passwd = getcpy (bp->bb_passwd);
542     b->bb_flags = bp->bb_flags;
543     b->bb_count = bp->bb_count;
544     b->bb_maxima = bp->bb_maxima;
545     b->bb_date = getcpy (bp->bb_date);
546     b->bb_addr = getcpy (bp->bb_addr);
547     b->bb_request = getcpy (bp->bb_request);
548     b->bb_relay = getcpy (bp->bb_relay);
549
550     for (p = bp->bb_aka; *p; p++)
551         continue;
552     b->bb_aka =
553         q = (char **) calloc ((unsigned) (p - bp->bb_aka + 1), sizeof *q);
554     if (q == NULL)
555         return NULL;
556     for (p = bp->bb_aka; *p; *q++ = getcpy (*p++))
557         continue;
558     *q = NULL;
559
560     for (p = bp->bb_leader; *p; p++)
561         continue;
562     b->bb_leader =
563         q = (char **) calloc ((unsigned) (p - bp->bb_leader + 1), sizeof *q);
564     if (q == NULL)
565         return NULL;
566     for (p = bp->bb_leader; *p; *q++ = getcpy (*p++))
567         continue;
568     *q = NULL;
569
570     for (p = bp->bb_dist; *p; p++)
571         continue;
572     b->bb_dist = 
573         q = (char **) calloc ((unsigned) (p - bp->bb_dist + 1), sizeof *q);
574     if (q == NULL)
575         return NULL;
576     for (p = bp->bb_dist; *p; *q++ = getcpy (*p++))
577         continue;
578     *q = NULL;
579
580     b->bb_next = bp->bb_next;
581     b->bb_link = bp->bb_link;
582     b->bb_chain = bp->bb_chain;
583
584     return b;
585 }
586
587
588 int
589 getbbdist (struct bboard  *bb, int (*action)())
590 {
591     register int result;
592     register char **dp;
593
594     BBErrors[0] = 0;
595     for (dp = bb->bb_dist; *dp; dp++)
596         if ((result = getbbitem (bb, *dp, action)))
597             return result;
598
599     return result;
600 }
601
602 char *
603 getbberr (void)
604 {
605     return (BBErrors[0] ? BBErrors : NULL);
606 }
607
608
609 static int
610 getbbitem (struct bboard *bb, char *item, int (*action)())
611 {
612     register int result;
613     register char *cp, *dp, *hp, *np;
614     char mbox[BUFSIZ],
615          buffer[BUFSIZ],
616          file[BUFSIZ],
617          host[BUFSIZ],
618          prf[BUFSIZ];
619     register FILE *fp;
620
621     switch (*item) {
622         case '*': 
623             switch (*++item) {
624                 case '/': 
625                     hp = item;
626                     break;
627
628                 case 0: 
629                     if ((cp = strrchr(bb->bb_file, '/')) == NULL || *++cp == 0) {
630                         strcpy (prf, "");
631                         cp = bb->bb_file;
632                     } else {
633                         snprintf (prf, sizeof(prf), "%.*s", cp - bb->bb_file, bb->bb_file);
634                     }
635                     if ((dp = strchr(cp, '.')) == NULL)
636                         dp = cp + strlen (cp);
637                     snprintf (file, sizeof(file), "%s.%.*s%s", prf, dp - cp, cp, DSTFILE);
638                     hp = file;
639                     break;
640
641                 default: 
642                     snprintf (file, sizeof(file), "%s/%s", BBDir, item);
643                     hp = file;
644                     break;
645             }
646
647             if ((fp = fopen (hp, "r")) == NULL)
648                 return bblose ("unable to read file %s", hp);
649             while (fgets (buffer, sizeof buffer, fp)) {
650                 if ((np = strchr(buffer, '\n')))
651                     *np = 0;
652                 if ((result = getbbitem (bb, buffer, action))) {
653                     fclose (fp);
654                     bblose ("error with file %s, item %s", hp, buffer);
655                     return result;
656                 }
657             }
658             fclose (fp);
659             return OK;
660
661         default: 
662             if ((hp = strrchr(item, '@'))) {
663                 *hp++ = 0;
664                 strncpy (mbox, item, sizeof(mbox));
665                 strncpy (host, hp, sizeof(host));
666                 *--hp = '@';
667             }
668             else {
669                 snprintf (mbox, sizeof(mbox), "%s%s", DISTADR, bb->bb_name);
670                 strncpy (host, item, sizeof(host));
671             }
672             if ((result = (*action) (mbox, host)))
673                 bblose ("action (%s, %s) returned 0%o", mbox, host, result);
674             return result;
675     }
676 }
677
678
679 static int
680 bblose (char *fmt, ...)
681 {
682     va_list ap;
683
684     va_start(ap, fmt);
685     if (BBErrors[0] == 0)
686         vsnprintf (BBErrors, sizeof(BBErrors), fmt, ap);
687
688     va_end(ap);
689     return NOTOK;
690 }
691
692
693 void
694 make_lower (char *s1, char *s2)
695 {
696     if (!s1 || !s2)
697         return;
698
699     for (; *s2; s2++)
700         *s1++ = isupper (*s2) ? tolower (*s2) : *s2;
701     *s1 = 0;
702 }
703
704
705 static char *
706 bbskip (char *p, char c)
707 {
708     if (p == NULL)
709         return NULL;
710
711     while (*p && *p != c)
712         p++;
713     if (*p)
714         *p++ = 0;
715
716     return p;
717 }
718
719
720 static char *
721 getcpy (char *s)
722 {
723     register char *p;
724     size_t len;
725
726     if (s == NULL)
727         return NULL;
728
729     len = strlen (s) + 1;
730     if ((p = malloc (len)))
731         memcpy (p, s, len);
732     return p;
733 }
734