|
|
1.1 root 1: /* bbl.c - ease the tasks of a BBleader */
2:
3: #include "../h/mh.h"
4: #include "../zotnet/bboards.h"
5: #include <ctype.h>
6: #include <pwd.h>
7: #include <stdio.h>
8: #include <sys/types.h>
9: #ifndef BSD42
10: #ifndef SYS5
11: #include <ndir.h>
12: #else SYS5
13: #include <dir.h>
14: #endif SYS5
15: #else BSD42
16: #include <sys/dir.h>
17: #endif BSD42
18: #include <sys/stat.h>
19:
20: /* */
21:
22: static struct swit switches[] = {
23: #define SHELLSW 0
24: "shell program", 0,
25:
26: #define VERBSW 1
27: "verbose", 0,
28: #define NVERBSW 2
29: "noverbose", 0,
30:
31: #define HELPSW 3
32: "help", 4,
33:
34: NULL, NULL
35: };
36:
37: /* */
38:
39: static int verbosw = 0;
40:
41: static int sub_ok = 0;
42:
43: static char *bboards = BBOARDS;
44:
45: static char *cwd = NULL;
46:
47: static char *current_folder = NULL;
48:
49: static char *bbfolder = NULL;
50: static char subfolder[BUFSIZ];
51:
52: static struct stat bbstat;
53: static struct stat substat;
54:
55: static char *shell = "/bin/sh";
56:
57: static struct bboard *bb = NULL;
58:
59:
60: #ifdef SYS5
61: struct passwd *getpwnam (), *getpwuid ();
62: #endif SYS5
63:
64: /* */
65:
66: /* ARGSUSED */
67:
68: main (argc, argv)
69: int argc;
70: char **argv;
71: {
72: char *cp,
73: **ap,
74: **argp,
75: buffer[80],
76: *arguments[MAXARGS];
77: struct passwd *pw;
78:
79: invo_name = r1bindex (argv[0], '/');
80: if ((cp = m_find (invo_name)) != NULL) {
81: ap = brkstring (cp = getcpy (cp), " ", "\n");
82: ap = copyip (ap, arguments);
83: }
84: else
85: ap = arguments;
86: (void) copyip (argv + 1, ap);
87: argp = arguments;
88:
89: if ((shell = getenv ("SHELL")) == NULL)
90: if ((pw = getpwuid (getuid ())) != NULL
91: && pw -> pw_shell
92: && *pw -> pw_shell)
93: shell = getcpy (pw -> pw_shell);
94:
95: if ((pw = getpwnam (bboards)) == NULL)
96: adios (NULLCP, "no entry for ~%s", bboards);
97: if (pw -> pw_uid != geteuid ())
98: adios (NULLCP, "not running setuid to %s", bboards);
99:
100: current_folder = (cp = m_find (pfolder)) ? getcpy (cp) : defalt;
101:
102: /* */
103:
104: while (cp = *argp++) {
105: if (*cp == '-')
106: switch (smatch (++cp, switches)) {
107: case AMBIGSW:
108: ambigsw (cp, switches);
109: done (1);
110: case UNKWNSW:
111: adios (NULLCP, "-%s unknown", cp);
112: case HELPSW:
113: (void) sprintf (buffer, "%s [+folder] [switches] bboard",
114: invo_name);
115: help (buffer, switches);
116: done (1);
117:
118: case SHELLSW:
119: if (!(shell = *argp++) || *shell == '-')
120: adios (NULLCP, "missing argument to %s", argp[-2]);
121: continue;
122:
123: case VERBSW:
124: verbosw++;
125: continue;
126: case NVERBSW:
127: verbosw = 0;
128: continue;
129: }
130: if (*cp == '+')
131: if (bbfolder)
132: adios (NULLCP, "only one folder at a time!");
133: else
134: bbfolder = cp;
135: else
136: if (bb != NULL)
137: adios (NULLCP, "only one BBoard a time!");
138: else
139: if ((bb = getbbnam (cp)) == NULL
140: && (bb = getbbaka (cp)) == NULL)
141: adios (NULLCP, "no such BBoard as '%s'", cp);
142: }
143:
144: /* */
145:
146: if (!bb)
147: adios (NULLCP, "no BBoard specified");
148: if (!bbfolder)
149: bbfolder = "+bbl";
150: (void) sprintf (subfolder, "%s/arc", bbfolder);
151:
152: if (!m_find ("path"))
153: free (path ("./", TFOLDER));
154: cwd = getcpy (pwd ());
155:
156: process ();
157:
158: m_replace (pfolder, current_folder);
159: m_update ();
160:
161: done (0);
162: }
163:
164: /* */
165:
166: process () {
167: int child_id;
168: char buffer[BUFSIZ];
169:
170: if (!ldrbb (bb) && !ldrchk (bb))
171: return;
172:
173: if (stat (bb -> bb_file, &bbstat) == NOTOK)
174: adios (NULLCP, "no such file as %s", bb -> bb_file);
175:
176: if (stat (bb -> bb_archive, &substat) != NOTOK
177: && substat.st_size > 0)
178: sub_ok++;
179: /* else */
180: substat.st_mode = bbstat.st_mode;/* archive should always match */
181: substat.st_gid = bbstat.st_gid;/* actual bboard mode & gid */
182:
183: /* do subfolder first, since you will lose otherwise... */
184: (void) sprintf (buffer, "Remove messages currently in %s? ", subfolder);
185: if (check_folder (subfolder) && getanswer (buffer))
186: rmf (subfolder);
187:
188: (void) sprintf (buffer, "Remove messages currently in %s? ", bbfolder);
189: if (check_folder (bbfolder) && getanswer (buffer))
190: rmf (bbfolder);
191:
192: switch (child_id = fork ()) {
193: case NOTOK:
194: adios ("fork", "unable to");
195:
196: case OK:
197: do_child (); /* NOTREACHED */
198:
199: default:
200: do_parent (child_id);
201: break;
202: }
203: }
204:
205: /* */
206:
207: int check_folder (folder)
208: char *folder;
209: {
210: char *maildir;
211: struct stat st;
212: struct msgs *mp;
213:
214: maildir = m_maildir (folder + 1);
215:
216: if (stat (maildir, &st) == NOTOK)
217: return 0;
218:
219: if ((st.st_mode & S_IFMT) != S_IFDIR)
220: adios (NULLCP, "not a directory '%s'", maildir);
221: check_mode (maildir, (st.st_mode | 0555) & 0777);
222:
223: if (chdir (maildir) == NOTOK)
224: adios (maildir, "unable to change to");
225: if (!(mp = m_gmsg (folder + 1)))
226: adios (NULLCP, "unable to read %s", folder);
227:
228: if (chdir (cwd) == NOTOK)
229: admonish (cwd, "could not change back to");
230: return (mp -> hghmsg != 0);
231: }
232:
233: /* */
234:
235: do_parent (child_id)
236: int child_id;
237: {
238: int zap = 0;
239: char buffer[BUFSIZ];
240:
241: if (pidwait (child_id, NOTOK) == NOTOK)
242: done (1);
243:
244: (void) putchar ('\n');
245:
246: (void) check_folder (bbfolder);
247: if (getanswer ("Incorporate changes? "))
248: update (&bbstat, bb -> bb_file, bbfolder, bb -> bb_info, bb -> bb_map);
249: (void) sprintf (buffer, "Remove %s? ", bbfolder);
250: if (getanswer (buffer))
251: zap++;
252:
253: if (check_folder (subfolder)) {
254: if (getanswer ("Update archives? "))
255: update (&substat, bb -> bb_archive, subfolder, NULLCP, NULLCP);
256: (void) sprintf (buffer, "Remove %s? ", subfolder);
257: if (getanswer (buffer))
258: rmf (subfolder);
259: }
260: else
261: if (sub_ok
262: && getanswer ("Remove archives? ")
263: && getanswer ("Are you sure? "))
264: if (unlink (bb -> bb_archive) == NOTOK)
265: admonish (bb -> bb_archive, "unable to remove %s");
266: if (zap)
267: rmf (bbfolder);
268: }
269:
270: /* */
271:
272: check_mode (dir, mode)
273: char *dir;
274: unsigned int mode;
275: {
276: int child_id;
277: struct stat st;
278: struct direct *dp;
279: DIR * dd;
280:
281: if (verbosw)
282: fprintf (stderr, "chmod %o %s\n", mode, dir);
283:
284: switch (child_id = fork ()) {
285: case NOTOK:
286: adios ("fork", "unable to");
287:
288: case OK:
289: (void) setgid (getgid ());
290: (void) setuid (getuid ());
291:
292: if (chmod (dir, (int) mode) == NOTOK)
293: adios (dir, "unable to change mode of");
294: if (chdir (dir) == NOTOK)
295: adios (dir, "unable to change to");
296: if ((dd = opendir (dir)) == NULL)
297: adios (dir, "unable to read");
298: while (dp = readdir (dd))
299: if (dp -> d_name[0] != '.') {
300: if (stat (dp -> d_name, &st) == NOTOK) {
301: admonish (dp -> d_name, "unable to stat");
302: continue;
303: }
304: if (chmod (dp -> d_name, (int) ((st.st_mode | 0444) & 0777))
305: == NOTOK)
306: admonish (dp -> d_name, "unable to change mode of");
307: }
308: closedir (dd);
309: done (0);
310:
311: default:
312: if (pidwait (child_id, OK))
313: done (1);
314: break;
315: }
316: }
317:
318: /* */
319:
320: /* ARGSUSED */
321:
322: update (stp, file, folder, info, map)
323: struct stat *stp;
324: char *file,
325: *folder,
326: *info,
327: *map;
328: {
329: int fd;
330: struct stat st;
331:
332: if (stat (file, &st) != NOTOK
333: && st.st_mtime != stp -> st_mtime) {
334: printf ("File '%s' has changed...\n", file);
335: if (getanswer ("Append to it instead? "))
336: goto work;
337: else
338: if (!getanswer ("Still update it? "))
339: return;
340: }
341: if ((fd = creat (file, BBMODE)) == NOTOK)
342: adios (file, "unable to re-create");
343: else {
344: (void) close (fd);
345: if (map)
346: (void) unlink (map);
347: }
348: #ifdef notdef
349: if (info)
350: check_info (folder, info);
351: #endif notdef
352:
353: work: ;
354: pack (folder, file);
355: if (chmod (file, (int) (stp -> st_mode & 0777)) == NOTOK)
356: admonish (file, "unable to change mode of");
357: if (stat (file, &st) != NOTOK && st.st_gid != stp -> st_gid)
358: chgrp (file, stp -> st_gid);
359: }
360:
361: /* */
362:
363: #ifdef notdef
364: check_info (folder, info)
365: char *folder,
366: *info;
367: {
368: int id,
369: state;
370: char *hdrptr,
371: *maildir,
372: *msgnam,
373: posted[BUFSIZ],
374: name[NAMESZ],
375: buf[BUFSIZ];
376: struct msgs *mp;
377: FILE * fp;
378:
379: if (chdir (maildir = m_maildir (folder + 1)) == NOTOK)
380: adios (maildir, "unable to change to");
381:
382: if (!(mp = m_gmsg (folder + 1)))
383: adios (NULL, "unable to read %s", folder);
384: if (mp -> hghmsg) {
385: if ((fp = fopen (msgnam = m_name (mp -> hghmsg), "r")) == NULL)
386: adios (NULL, "unable to read message %s in %s",
387: msgnam, folder);
388: id = 0;
389: posted[0] = NULL;
390: for (state = FLD;;) {
391: switch (state = m_getfld (state, name, buf, sizeof buf, fp)) {
392: case FLD:
393: case FLDEOF:
394: case FLDPLUS:
395: hdrptr = add (buf, NULL);
396: while (state == FLDPLUS) {
397: state = m_getfld (state, name, buf, sizeof buf, fp);
398: hdrptr = add (buf, hdrptr);
399: }
400: if (uleq (name, "BBoard-ID")) {
401: id = atoi (buf);
402: if (id > 0 && posted[0])
403: break;
404: }
405: if (uleq (name, "BB-Posted")) {
406: strncpy (posted, buf, sizeof posted - 2);
407: if (posted[strlen (posted) - 1] == '\n')
408: posted[strlen (posted) - 1] = NULL;
409: if (id > 0 && posted[0])
410: break;
411: }
412: continue;
413:
414: default:
415: admonish (NULL, "unable to find BBoard-info in message %s",
416: msgnam);
417: (void) fclose (fp);
418: goto no_risk;
419: }
420: break;
421: }
422: (void) fclose (fp);
423:
424: if (verbosw)
425: fprintf (stderr,
426: "[ Highest message has %s%d and\n\t\t %s%s ]\n",
427: "BBoard-ID: ", id, "BB-Posted: ", posted);
428:
429: if ((fp = lkfopen (info, "w")) == NULL)
430: adios (info, "unable to lock and fopen");
431: fprintf (fp, "%d\n%s\n", id, posted);
432: (void) lkfclose (fp, info);
433: }
434:
435: no_risk: ;
436: if (chdir (cwd) == NOTOK)
437: admonish (cwd, "could not change back to");
438: }
439: #endif notdef
440:
441: /* */
442:
443: pack (folder, file)
444: char *folder,
445: *file;
446: {
447: int child_id;
448:
449: switch (child_id = fork ()) {
450: case NOTOK:
451: admonish ("fork", "unable to");
452: return;
453:
454: case OK:
455: if (verbosw)
456: fprintf (stderr, "pack %s -file %s\n", folder, file);
457:
458: execlp (packproc, r1bindex (packproc, '/'),
459: folder, "-file", file, NULLCP);
460: fprintf (stderr, "unable to exec ");
461: perror (packproc);
462: _exit (-1);
463:
464: default:
465: (void) pidXwait (child_id, packproc);
466: break;
467: }
468: }
469:
470: /* */
471:
472: chgrp (file, gid)
473: char *file;
474: short gid;
475: {
476: int child_id;
477: char group[BUFSIZ];
478:
479: switch (child_id = fork ()) {
480: case NOTOK:
481: admonish ("fork", "unable to");
482: return;
483:
484: case OK:
485: (void) setuid (geteuid ());/* make sure chgrp works */
486: (void) sprintf (group, "%d", gid);
487: if (verbosw)
488: fprintf (stderr, "chgrp %s %s\n", group, file);
489:
490: execlp ("/bin/chgrp", "chgrp", group, file, NULLCP);
491: fprintf (stderr, "unable to exec ");
492: perror ("/bin/chgrp");
493: _exit (-1);
494:
495: default:
496: (void) pidXwait (child_id, "chgrp");
497: break;
498: }
499: }
500:
501: /* */
502:
503: rmf (folder)
504: char *folder;
505: {
506: int child_id;
507:
508: switch (child_id = fork ()) {
509: case NOTOK:
510: admonish ("fork", "unable to");
511: return;
512:
513: case OK:
514: (void) setgid (getgid ());
515: (void) setuid (getuid ());
516: if (verbosw)
517: fprintf (stderr, "rmf %s\n", folder);
518:
519: execlp (rmfproc, r1bindex (rmfproc, '/'), folder, NULLCP);
520: fprintf (stderr, "unable to exec ");
521: perror (rmfproc);
522: _exit (-1);
523:
524: default:
525: (void) pidXwait (child_id, rmfproc);
526: break;
527: }
528: }
529:
530: /* */
531:
532: do_child () {
533: char buffer[BUFSIZ];
534:
535: (void) setgid (getgid ()); /* become the user, not bboards */
536: (void) setuid (getuid ());
537:
538: inc (bb -> bb_file, bbfolder);
539: if (sub_ok)
540: inc (bb -> bb_archive, subfolder);
541: /* else
542: create the folder */
543:
544: if (verbosw)
545: (void) putchar ('\n');
546: printf ("[ Working folder is %s, Archive folder is %s ]\n",
547: bbfolder, subfolder);
548: printf ("[ Type CTRL-D to finish ]\n");
549:
550: m_replace (pfolder, bbfolder + 1);
551: m_update ();
552:
553: (void) sprintf (buffer, "=> %s: %s", invo_name, bb -> bb_name);
554: execlp (shell, buffer, NULLCP);
555: fprintf (stderr, "unable to exec ");
556: perror (shell);
557: _exit (-1);
558: }
559:
560: /* */
561:
562: inc (file, folder)
563: char *file,
564: *folder;
565: {
566: int child_id;
567:
568: switch (child_id = fork ()) {
569: case NOTOK:
570: adios ("fork", "unable to");
571:
572: case OK:
573: if (verbosw)
574: fprintf (stderr, "inc %s -file %s -silent\n", folder, file);
575: execlp (incproc, r1bindex (incproc, '/'),
576: folder, "-file", file, "-silent", NULLCP);
577: fprintf (stderr, "unable to exec ");
578: perror (incproc);
579: _exit (-1);
580:
581: default:
582: if (pidXwait (child_id, incproc))
583: done (1);
584: break;
585: }
586: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.