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: }