|
|
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: {
168: int child_id;
169: char buffer[BUFSIZ];
170:
171: if (!ldrbb (bb) && !ldrchk (bb))
172: return;
173:
174: if (stat (bb -> bb_file, &bbstat) == NOTOK)
175: adios (NULLCP, "no such file as %s", bb -> bb_file);
176:
177: if (stat (bb -> bb_archive, &substat) != NOTOK
178: && substat.st_size > 0)
179: sub_ok++;
180: /* else */
181: substat.st_mode = bbstat.st_mode;/* archive should always match */
182: substat.st_gid = bbstat.st_gid;/* actual bboard mode & gid */
183:
184: /* do subfolder first, since you will lose otherwise... */
185: (void) sprintf (buffer, "Remove messages currently in %s? ", subfolder);
186: if (check_folder (subfolder) && getanswer (buffer))
187: rmf (subfolder);
188:
189: (void) sprintf (buffer, "Remove messages currently in %s? ", bbfolder);
190: if (check_folder (bbfolder) && getanswer (buffer))
191: rmf (bbfolder);
192:
193: switch (child_id = fork ()) {
194: case NOTOK:
195: adios ("fork", "unable to");
196:
197: case OK:
198: do_child (); /* NOTREACHED */
199:
200: default:
201: do_parent (child_id);
202: break;
203: }
204: }
205:
206: /* */
207:
208: check_folder(folder)
209: char *folder;
210: {
211: char *maildir;
212: struct stat st;
213: struct msgs *mp;
214:
215: maildir = m_maildir (folder + 1);
216:
217: if (stat (maildir, &st) == NOTOK)
218: return 0;
219:
220: if ((st.st_mode & S_IFMT) != S_IFDIR)
221: adios (NULLCP, "not a directory '%s'", maildir);
222: check_mode (maildir, (st.st_mode | 0555) & 0777);
223:
224: if (chdir (maildir) == NOTOK)
225: adios (maildir, "unable to change to");
226: if (!(mp = m_gmsg (folder + 1)))
227: adios (NULLCP, "unable to read %s", folder);
228:
229: if (chdir (cwd) == NOTOK)
230: admonish (cwd, "could not change back to");
231: return (mp -> hghmsg != 0);
232: }
233:
234: /* */
235:
236: do_parent(child_id)
237: int child_id;
238: {
239: int zap = 0;
240: char buffer[BUFSIZ];
241:
242: if (pidwait (child_id, NOTOK) == NOTOK)
243: done (1);
244:
245: (void) putchar ('\n');
246:
247: (void) check_folder (bbfolder);
248: if (getanswer ("Incorporate changes? "))
249: update (&bbstat, bb -> bb_file, bbfolder, bb -> bb_info, bb -> bb_map);
250: (void) sprintf (buffer, "Remove %s? ", bbfolder);
251: if (getanswer (buffer))
252: zap++;
253:
254: if (check_folder (subfolder)) {
255: if (getanswer ("Update archives? "))
256: update (&substat, bb -> bb_archive, subfolder, NULLCP, NULLCP);
257: (void) sprintf (buffer, "Remove %s? ", subfolder);
258: if (getanswer (buffer))
259: rmf (subfolder);
260: }
261: else
262: if (sub_ok
263: && getanswer ("Remove archives? ")
264: && getanswer ("Are you sure? "))
265: if (unlink (bb -> bb_archive) == NOTOK)
266: admonish (bb -> bb_archive, "unable to remove %s");
267: if (zap)
268: rmf (bbfolder);
269: }
270:
271: /* */
272:
273: check_mode(dir, mode)
274: char *dir;
275: unsigned int mode;
276: {
277: int child_id;
278: struct stat st;
279: struct direct *dp;
280: DIR * dd;
281:
282: if (verbosw)
283: fprintf (stderr, "chmod %o %s\n", mode, dir);
284:
285: switch (child_id = fork ()) {
286: case NOTOK:
287: adios ("fork", "unable to");
288:
289: case OK:
290: (void) setgid (getgid ());
291: (void) setuid (getuid ());
292:
293: if (chmod (dir, (int) mode) == NOTOK)
294: adios (dir, "unable to change mode of");
295: if (chdir (dir) == NOTOK)
296: adios (dir, "unable to change to");
297: if ((dd = opendir (dir)) == NULL)
298: adios (dir, "unable to read");
299: while (dp = readdir (dd))
300: if (dp -> d_name[0] != '.') {
301: if (stat (dp -> d_name, &st) == NOTOK) {
302: admonish (dp -> d_name, "unable to stat");
303: continue;
304: }
305: if (chmod (dp -> d_name, (int) ((st.st_mode | 0444) & 0777))
306: == NOTOK)
307: admonish (dp -> d_name, "unable to change mode of");
308: }
309: closedir (dd);
310: done (0);
311:
312: default:
313: if (pidwait (child_id, OK))
314: done (1);
315: break;
316: }
317: }
318:
319: /* */
320:
321: /* ARGSUSED */
322:
323: update(stp, file, folder, info, map)
324: struct stat *stp;
325: char *file, *folder, *info, *map;
326: {
327: int fd;
328: struct stat st;
329:
330: if (stat (file, &st) != NOTOK
331: && st.st_mtime != stp -> st_mtime) {
332: printf ("File '%s' has changed...\n", file);
333: if (getanswer ("Append to it instead? "))
334: goto work;
335: else
336: if (!getanswer ("Still update it? "))
337: return;
338: }
339: if ((fd = creat (file, BBMODE)) == NOTOK)
340: adios (file, "unable to re-create");
341: else {
342: (void) close (fd);
343: if (map)
344: (void) unlink (map);
345: }
346: #ifdef notdef
347: if (info)
348: check_info (folder, info);
349: #endif notdef
350:
351: work: ;
352: pack (folder, file);
353: if (chmod (file, (int) (stp -> st_mode & 0777)) == NOTOK)
354: admonish (file, "unable to change mode of");
355: if (stat (file, &st) != NOTOK && st.st_gid != stp -> st_gid)
356: chgrp (file, stp -> st_gid);
357: }
358:
359: /* */
360:
361: #ifdef notdef
362: check_info(folder, info)
363: char *folder, *info;
364: {
365: int id,
366: state;
367: char *hdrptr,
368: *maildir,
369: *msgnam,
370: posted[BUFSIZ],
371: name[NAMESZ],
372: buf[BUFSIZ];
373: struct msgs *mp;
374: FILE * fp;
375:
376: if (chdir (maildir = m_maildir (folder + 1)) == NOTOK)
377: adios (maildir, "unable to change to");
378:
379: if (!(mp = m_gmsg (folder + 1)))
380: adios (NULL, "unable to read %s", folder);
381: if (mp -> hghmsg) {
382: if ((fp = fopen (msgnam = m_name (mp -> hghmsg), "r")) == NULL)
383: adios (NULL, "unable to read message %s in %s",
384: msgnam, folder);
385: id = 0;
386: posted[0] = NULL;
387: for (state = FLD;;) {
388: switch (state = m_getfld (state, name, buf, sizeof buf, fp)) {
389: case FLD:
390: case FLDEOF:
391: case FLDPLUS:
392: hdrptr = add (buf, NULL);
393: while (state == FLDPLUS) {
394: state = m_getfld (state, name, buf, sizeof buf, fp);
395: hdrptr = add (buf, hdrptr);
396: }
397: if (uleq (name, "BBoard-ID")) {
398: id = atoi (buf);
399: if (id > 0 && posted[0])
400: break;
401: }
402: if (uleq (name, "BB-Posted")) {
403: strncpy (posted, buf, sizeof posted - 2);
404: if (posted[strlen (posted) - 1] == '\n')
405: posted[strlen (posted) - 1] = NULL;
406: if (id > 0 && posted[0])
407: break;
408: }
409: continue;
410:
411: default:
412: admonish (NULL, "unable to find BBoard-info in message %s",
413: msgnam);
414: (void) fclose (fp);
415: goto no_risk;
416: }
417: break;
418: }
419: (void) fclose (fp);
420:
421: if (verbosw)
422: fprintf (stderr,
423: "[ Highest message has %s%d and\n\t\t %s%s ]\n",
424: "BBoard-ID: ", id, "BB-Posted: ", posted);
425:
426: if ((fp = lkfopen (info, "w")) == NULL)
427: adios (info, "unable to lock and fopen");
428: fprintf (fp, "%d\n%s\n", id, posted);
429: (void) lkfclose (fp, info);
430: }
431:
432: no_risk: ;
433: if (chdir (cwd) == NOTOK)
434: admonish (cwd, "could not change back to");
435: }
436: #endif notdef
437:
438: /* */
439:
440: pack(folder, file)
441: char *folder, *file;
442: {
443: int child_id;
444:
445: switch (child_id = fork ()) {
446: case NOTOK:
447: admonish ("fork", "unable to");
448: return;
449:
450: case OK:
451: if (verbosw)
452: fprintf (stderr, "pack %s -file %s\n", folder, file);
453:
454: execlp (packproc, r1bindex (packproc, '/'),
455: folder, "-file", file, NULLCP);
456: fprintf (stderr, "unable to exec ");
457: perror (packproc);
458: _exit (-1);
459:
460: default:
461: (void) pidXwait (child_id, packproc);
462: break;
463: }
464: }
465:
466: /* */
467:
468: chgrp(file, gid)
469: char *file;
470: short gid;
471: {
472: int child_id;
473: char group[BUFSIZ];
474:
475: switch (child_id = fork ()) {
476: case NOTOK:
477: admonish ("fork", "unable to");
478: return;
479:
480: case OK:
481: (void) setuid (geteuid ());/* make sure chgrp works */
482: (void) sprintf (group, "%d", gid);
483: if (verbosw)
484: fprintf (stderr, "chgrp %s %s\n", group, file);
485:
486: execlp ("/bin/chgrp", "chgrp", group, file, NULLCP);
487: fprintf (stderr, "unable to exec ");
488: perror ("/bin/chgrp");
489: _exit (-1);
490:
491: default:
492: (void) pidXwait (child_id, "chgrp");
493: break;
494: }
495: }
496:
497: /* */
498:
499: rmf(folder)
500: char *folder;
501: {
502: int child_id;
503:
504: switch (child_id = fork ()) {
505: case NOTOK:
506: admonish ("fork", "unable to");
507: return;
508:
509: case OK:
510: (void) setgid (getgid ());
511: (void) setuid (getuid ());
512: if (verbosw)
513: fprintf (stderr, "rmf %s\n", folder);
514:
515: execlp (rmfproc, r1bindex (rmfproc, '/'), folder, NULLCP);
516: fprintf (stderr, "unable to exec ");
517: perror (rmfproc);
518: _exit (-1);
519:
520: default:
521: (void) pidXwait (child_id, rmfproc);
522: break;
523: }
524: }
525:
526: /* */
527:
528: do_child()
529: {
530: char buffer[BUFSIZ];
531:
532: (void) setgid (getgid ()); /* become the user, not bboards */
533: (void) setuid (getuid ());
534:
535: inc (bb -> bb_file, bbfolder);
536: if (sub_ok)
537: inc (bb -> bb_archive, subfolder);
538: /* else
539: create the folder */
540:
541: if (verbosw)
542: (void) putchar ('\n');
543: printf ("[ Working folder is %s, Archive folder is %s ]\n",
544: bbfolder, subfolder);
545: printf ("[ Type CTRL-D to finish ]\n");
546:
547: m_replace (pfolder, bbfolder + 1);
548: m_update ();
549:
550: (void) sprintf (buffer, "=> %s: %s", invo_name, bb -> bb_name);
551: execlp (shell, buffer, NULLCP);
552: fprintf (stderr, "unable to exec ");
553: perror (shell);
554: _exit (-1);
555: }
556:
557: /* */
558:
559: inc(file, folder)
560: char *file, *folder;
561: {
562: int child_id;
563:
564: switch (child_id = fork ()) {
565: case NOTOK:
566: adios ("fork", "unable to");
567:
568: case OK:
569: if (verbosw)
570: fprintf (stderr, "inc %s -file %s -silent\n", folder, file);
571: execlp (incproc, r1bindex (incproc, '/'),
572: folder, "-file", file, "-silent", NULLCP);
573: fprintf (stderr, "unable to exec ");
574: perror (incproc);
575: _exit (-1);
576:
577: default:
578: if (pidXwait (child_id, incproc))
579: done (1);
580: break;
581: }
582: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.