1: /* mhconfig.c - configure MH */ 2: 3: #include "../h/strings.h" 4: #include <ctype.h> 5: #include <stdio.h> 6: 7: 8: #define BANNER "This is %s, for generic UNIX (MH.6 configuration program)\n\n" 9: 10: 11: #define SED "config.sed" 12: #define SEDOC "doc/config.sed" 13: #define MFIL(f) "makefiles/f", "f" 14: #define MMFIL(f,g) "makefiles/f", "g" 15: #define MAKE "../%s/Makefile" 16: 17: #define WARNING "This file is automatically generated. Do not edit!" 18: 19: #define NOTOK (-1) 20: 21: #define NULLCP ((char *) 0) 22: 23: #define SVAL(s) (s ? s : "") 24: 25: #define QUOTE '\\' 26: 27: /* */ 28: 29: static int smtp = 0; 30: 31: static int sedP = 1; 32: static int filesP = 1; 33: static int docP = 1; 34: static int makeP = 1; 35: 36: static char *myname = "mhconfig"; 37: 38: static char *myopts = NULL; 39: 40: static char *binpath = "/usr/local"; 41: static char *bbhome = "/usr/spool/bboards"; 42: static char *bboards = "off"; 43: static char *ccoptions = NULL; 44: static char *chownpath = "/etc/chown"; 45: static char *curses = "-lcurses -ltermlib"; 46: static char *debug = "off"; 47: static char *editor = "prompter"; 48: static char *etcpath = "/usr/local/lib/mh"; 49: static char *ldoptions = NULL; 50: static char *ldoptlibs = NULL; 51: static char *mailpath = "/usr/spool/mail"; 52: static char *maildir = NULL; 53: static char *mailfile = NULL; 54: static char *mandir = "/usr/man"; 55: static char *manuals = "standard"; 56: static char *mf = "off"; 57: static char *mts = "sendmail"; 58: static char *remove = "mv -f"; 59: static char *oldload = "off"; 60: static char *options = NULL; 61: static char *pop = "off"; 62: static char *popbboards = "off"; 63: static char *ranlib = "on"; 64: static char *tma = "off"; 65: 66: #define unknown 0 67: #define mmdf 1 68: #define mmdf2 2 69: #define mh 3 70: #define sendmail 4 71: static int mtsnum = unknown; 72: 73: static struct mtsopt { 74: char *mtskey; 75: char *optval; 76: int code; 77: int mtsflags; 78: #define NOFLAGS 0x00 79: #define DOSMTP 0x01 80: #define NOMF 0x02 81: } mtsopts[] = { 82: "mmdf", "MMDFMTS MMDFI", mmdf, NOFLAGS, 83: "mmdf/smtp", "SENDMTS SMTP", mmdf, DOSMTP, 84: "mmdf2", "MMDFMTS MMDFII", mmdf2, NOFLAGS, 85: "mmdf2/smtp", "SENDMTS MMDFII SMTP", mmdf2, DOSMTP, 86: "mh", "MHMTS", mh, NOFLAGS, 87: "sendmail", "SENDMTS", sendmail, NOMF, 88: "sendmail/smtp", "SENDMTS SMTP", sendmail, NOMF, 89: NULL, NULL, unknown, NOFLAGS 90: }; 91: 92: static struct bind { 93: char *keyword; 94: 95: char **value; 96: 97: int flags; 98: #define BD_NIL 0x00 99: #define BD_ADD 0x01 100: } binds[] = { 101: "bin", &binpath, BD_NIL, 102: "bbhome", &bbhome, BD_NIL, 103: "bboards", &bboards, BD_NIL, 104: "ccoptions", &ccoptions, BD_ADD, 105: "chown", &chownpath, BD_NIL, 106: "curses", &curses, BD_NIL, 107: "debug", &debug, BD_NIL, 108: "editor", &editor, BD_NIL, 109: "etc", &etcpath, BD_NIL, 110: "ldoptions", &ldoptions, BD_ADD, 111: "ldoptlibs", &ldoptlibs, BD_ADD, 112: "mail", &mailpath, BD_NIL, 113: "mandir", &mandir, BD_NIL, 114: "manuals", &manuals, BD_NIL, 115: "mf", &mf, BD_NIL, 116: "mts", &mts, BD_NIL, 117: "oldload", &oldload, BD_NIL, 118: "options", &options, BD_ADD, 119: "pop", &pop, BD_NIL, 120: "popbboards", &popbboards, BD_NIL, 121: "ranlib", &ranlib, BD_NIL, 122: "remove", &remove, BD_NIL, 123: "tma", &tma, BD_NIL, 124: NULL 125: }; 126: 127: 128: char *files[] = { 129: "../support/bboards/bboards.daily", 130: "../support/bboards/bboards.weekly", 131: "../support/bboards/crontab", 132: "../support/bboards/MakeBBoards", 133: "../config/config.c", 134: "../zotnet/mts/mts.c", 135: "../zotnet/mts/mtstailor", 136: "../support/general/MailAliases", 137: "../mts/sendmail/bboardsMH.m4", 138: "../mts/sendmail/popMH.m4", 139: NULL 140: }; 141: 142: static struct pair { 143: char *infile; 144: char *outfile; 145: } makefiles[] = { 146: MFIL (config), 147: MFIL (dist), 148: MFIL (doc), 149: MMFIL (mtsM,mts), 150: MFIL (mts/mh), 151: MFIL (mts/mmdf), 152: MFIL (mts/sendmail), 153: MFIL (papers), 154: MFIL (sbr), 155: MMFIL (supportM,support), 156: MFIL (support/bboards), 157: MFIL (support/general), 158: MFIL (support/pop), 159: MFIL (uip), 160: MMFIL (zotnetM,zotnet), 161: MFIL (zotnet/bboards), 162: MFIL (zotnet/mf), 163: MFIL (zotnet/mts), 164: MFIL (zotnet/tws), 165: NULL 166: }; 167: 168: 169: char *stradd (), *strdup (), *tail (); 170: 171: long time (); 172: 173: /* */ 174: 175: /* ARGSUSED */ 176: 177: main (argc, argv, envp) 178: int argc; 179: char **argv, 180: **envp; 181: { 182: arginit (argv); 183: 184: if (sedP) 185: do_sed (); 186: if (filesP) 187: do_files (); 188: if (docP) 189: do_doc (); 190: if (makeP) 191: do_make (); 192: 193: if (filesP || makeP) 194: printf ("Don't forget to run \"make clean\" before proceeding\n"); 195: 196: exit (0); 197: } 198: 199: /* */ 200: 201: static do_sed () { 202: do_sedfile (SED, 0); 203: do_sedfile (SEDOC, smtp); 204: } 205: 206: 207: static do_sedfile (sed, flag) 208: char *sed; 209: int flag; 210: { 211: int i; 212: FILE * fp; 213: 214: if ((fp = fopen (sed, "w")) == NULL) 215: adios (sed, "unable to write"); 216: printf ("generating %s\n", sed); 217: 218: fprintf (fp, "s%%@(MHWARNING)%%%s%%g\n", WARNING); 219: fprintf (fp, "s%%@(MHBINPATH)%%%s%%g\n", SVAL (binpath)); 220: fprintf (fp, "s%%@(MHETCPATH)%%%s%%g\n", SVAL (etcpath)); 221: fprintf (fp, "s%%@(MHCHOWNPATH)%%%s%%g\n", SVAL (chownpath)); 222: fprintf (fp, "s%%@(MHDROPATH)%%%s%%g\n", SVAL (maildir)); 223: fprintf (fp, "s%%@(MHDROPFIL)%%%s%%g\n", SVAL (mailfile)); 224: if (maildir) 225: fprintf (fp, "s%%@(MHDROPLOC)%%%s/$USER%%g\n", SVAL (maildir)); 226: else 227: fprintf (fp, "s%%@(MHDROPLOC)%%$HOME/%s%%g\n", SVAL (mailfile)); 228: fprintf (fp, "s%%@(MHDROPHAK)%%%s%%g\n",/* HACK */ 229: maildir ? maildir : "/usr/spool/mail"); 230: 231: fprintf (fp, "s%%@(MHMANDIR)%%%s%%g\n", mandir); 232: if (strcmp (manuals, "standard") == 0 || strcmp (manuals, "gen") == 0) 233: for (i = 1; i <= 8; i++) { 234: fprintf (fp, "s%%@(MHMANDIR%d)%%man%d%%g\n", i, i); 235: fprintf (fp, "s%%@(MHMANEXT%d)%%%d%%g\n", i, i); 236: } 237: else 238: for (i = 1; i <= 8; i++) { 239: fprintf (fp, "s%%@(MHMANDIR%d)%%man%c%%g\n", i, 240: strcmp (manuals, "new") == 0 ? 'n' 241: : strcmp (manuals, "old") == 0 ? 'o' 242: : 'l'); 243: fprintf (fp, "s%%@(MHMANEXT%d)%%%c%%g\n", i, 244: strcmp (manuals, "new") == 0 ? 'n' 245: : strcmp (manuals, "old") == 0 ? 'o' 246: : 'l'); 247: } 248: if (strcmp (manuals, "gen") == 0) 249: fprintf (fp, "s%%@(MHMANGEN)%%%s%%g\n", "#"); /* comment char */ 250: else 251: fprintf (fp, "s%%@(MHMANGEN)%%%s%%g\n", ""); 252: 253: fprintf (fp, "s%%@(MHEDITOR)%%%s%%g\n", SVAL (editor)); 254: fprintf (fp, "s%%@(MHCONFIG)%%%s%%g\n", SVAL (myopts)); 255: if (ccoptions) 256: fprintf (fp, "s%%@(MHOPTIONS)%%%s %s%%g\n", 257: SVAL (options), SVAL (ccoptions)); 258: else 259: fprintf (fp, "s%%@(MHOPTIONS)%%%s%%g\n", SVAL (options)); 260: fprintf (fp, "s%%@(LDOPTIONS)%%%s%%g\n", SVAL (ldoptions)); 261: fprintf (fp, "s%%@(LDOPTLIB)%%%s%%g\n", SVAL (ldoptlibs)); 262: fprintf (fp, "s%%@(LDCURSES)%%%s%%g\n", SVAL (curses)); 263: 264: if (strcmp (bboards, "on") == 0) 265: fprintf (fp, "/^@BEGIN: BBOARDS$/d\n/^@END: BBOARDS$/d\n"); 266: else 267: fprintf (fp, "/^@BEGIN: BBOARDS$/,/^@END: BBOARDS$/d\n"); 268: fprintf (fp, "s%%@(BBHOME)%%%s%%g\n", SVAL (bbhome)); 269: 270: if (strcmp (debug, "on") == 0) { 271: fprintf (fp, "/^@BEGIN: DEBUG$/d\n/^@END: DEBUG$/d\n"); 272: fprintf (fp, "/^@BEGIN: OPTIM$/,/^@END: OPTIM$/d\n"); 273: } 274: else { 275: fprintf (fp, "/^@BEGIN: DEBUG$/,/^@END: DEBUG$/d\n"); 276: fprintf (fp, "/^@BEGIN: OPTIM$/d\n/^@END: OPTIM$/d\n"); 277: } 278: 279: if (strcmp (oldload, "on") == 0) { 280: fprintf (fp, "/^@BEGIN: OLDLOAD$/d\n/^@END: OLDLOAD$/d\n"); 281: fprintf (fp, "/^@BEGIN: NEWLOAD$/,/^@END: NEWLOAD$/d\n"); 282: } 283: else { 284: fprintf (fp, "/^@BEGIN: NEWLOAD$/d\n/^@END: NEWLOAD$/d\n"); 285: fprintf (fp, "/^@BEGIN: OLDLOAD$/,/^@END: OLDLOAD$/d\n"); 286: } 287: 288: if (strcmp (ranlib, "on") == 0) { 289: fprintf (fp, "/^@BEGIN: RANLIB$/d\n/^@END: RANLIB$/d\n"); 290: fprintf (fp, "/^@BEGIN: LORDER$/,/^@END: LORDER$/d\n"); 291: } 292: else { 293: fprintf (fp, "/^@BEGIN: LORDER$/d\n/^@END: LORDER$/d\n"); 294: fprintf (fp, "/^@BEGIN: RANLIB$/,/^@END: RANLIB$/d\n"); 295: } 296: 297: if (strcmp (tma, "on") == 0) 298: fprintf (fp, "/^@BEGIN: TMA$/d\n/^@END: TMA$/d\n"); 299: else 300: fprintf (fp, "/^@BEGIN: TMA$/,/^@END: TMA$/d\n"); 301: if (flag || ((mtsnum == mmdf || mtsnum == mmdf2) && !smtp)) { 302: fprintf (fp, "/^@BEGIN: MMDFMTS$/d\n/^@END: MMDFMTS$/d\n"); 303: if (mtsnum == mmdf) 304: fprintf (fp, "/^@BEGIN: MMDFIMTS$/d\n/^@END: MMDFIMTS$/d\n"); 305: else 306: fprintf (fp, "/^@BEGIN: MMDFIMTS$/,/^@END: MMDFIMTS$/d\n"); 307: if (mtsnum == mmdf2) 308: fprintf (fp, "/^@BEGIN: MMDFIIMTS$/d\n/^@END: MMDFIIMTS$/d\n"); 309: else 310: fprintf (fp, "/^@BEGIN: MMDFIIMTS$/,/^@END: MMDFIIMTS$/d\n"); 311: } 312: else { 313: fprintf (fp, "/^@BEGIN: MMDFMTS$/,/^@END: MMDFMTS$/d\n"); 314: fprintf (fp, "/^@BEGIN: MMDFIMTS$/,/^@END: MMDFIMTS$/d\n"); 315: fprintf (fp, "/^@BEGIN: MMDFIIMTS$/,/^@END: MMDFIIMTS$/d\n"); 316: } 317: 318: if (mtsnum == mh) 319: fprintf (fp, "/^@BEGIN: MHMTS$/d\n/^@END: MHMTS$/d\n"); 320: else 321: fprintf (fp, "/^@BEGIN: MHMTS$/,/^@END: MHMTS$/d\n"); 322: 323: if (!flag && (mtsnum == sendmail || smtp)) 324: fprintf (fp, "/^@BEGIN: SENDMTS$/d\n/^@END: SENDMTS$/d\n"); 325: else 326: fprintf (fp, "/^@BEGIN: SENDMTS$/,/^@END: SENDMTS$/d\n"); 327: 328: switch (mtsnum) { 329: case mh: 330: case sendmail: 331: case mmdf: 332: fprintf (fp, "/^@BEGIN: SENDMTSHACK$/d\n/^@END: SENDMTSHACK$/d\n"); 333: break; 334: 335: default: 336: fprintf (fp, "/^@BEGIN: SENDMTSHACK$/,/^@END: SENDMTSHACK$/d\n"); 337: break; 338: } 339: 340: if (smtp) 341: fprintf (fp, "/^@BEGIN: SMTP$/d\n/^@END: SMTP$/d\n"); 342: else 343: fprintf (fp, "/^@BEGIN: SMTP$/,/^@END: SMTP$/d\n"); 344: 345: if (strcmp (pop, "on") == 0) 346: fprintf (fp, "/^@BEGIN: POP$/d\n/^@END: POP$/d\n"); 347: else 348: fprintf (fp, "/^@BEGIN: POP$/,/^@END: POP$/d\n"); 349: 350: if (strcmp (popbboards, "on") == 0) 351: fprintf (fp, "/^@BEGIN: BPOP$/d\n/^@END: BPOP$/d\n"); 352: else 353: fprintf (fp, "/^@BEGIN: BPOP$/,/^@END: BPOP$/d\n"); 354: 355: if (strcmp (mf, "on") == 0) 356: fprintf (fp, "/^@BEGIN: MF$/d\n/^@END: MF$/d\n"); 357: else 358: fprintf (fp, "/^@BEGIN: MF$/,/^@END: MF$/d\n"); 359: 360: fprintf (fp, "s%%@(MHREMOVE)%%%s%%g\n", SVAL (remove)); 361: 362: (void) fclose (fp); 363: } 364: 365: /* */ 366: 367: static do_files () { 368: char **pp; 369: 370: for (pp = files; *pp; pp++) 371: shell ("rm -f %s; sed -f %s < config/%s > %s", 372: *pp, SED, tail (*pp), *pp); 373: } 374: 375: 376: static do_doc () { 377: shell ("mhdoc"); 378: } 379: 380: 381: static do_make () { 382: char buffer[BUFSIZ]; 383: struct pair *pp; 384: 385: for (pp = makefiles; pp -> infile; pp++) { 386: (void) sprintf (buffer, MAKE, pp -> outfile); 387: shell ("rm -f %s; sed -f %s < %s > %s", 388: buffer, SED, pp -> infile, buffer); 389: } 390: } 391: 392: /* */ 393: 394: /* VARARGS */ 395: 396: static shell (fmt, a, b, c, d) 397: char *fmt, 398: *a, 399: *b, 400: *c, 401: *d; 402: { 403: char buffer[BUFSIZ]; 404: 405: (void) sprintf (buffer, fmt, a, b, c, d); 406: printf ("%s\n", buffer); 407: (void) fflush (stdout); 408: 409: if (system (buffer)) 410: adios (NULLCP, "failed"); 411: } 412: 413: /* */ 414: 415: static arginit (vec) 416: char **vec; 417: { 418: int i; 419: char *ap, 420: *cp, 421: *dp, 422: *config, 423: buffer[BUFSIZ]; 424: struct bind *bp; 425: FILE * fp; 426: 427: myname = tail (*vec); 428: printf (BANNER, myname); 429: (void) fflush (stdout); 430: 431: for (vec++;; vec++) { 432: if (strcmp (*vec, "-s") == 0) { 433: sedP = !sedP; 434: continue; 435: } 436: if (strcmp (*vec, "-f") == 0) { 437: filesP = !filesP; 438: continue; 439: } 440: if (strcmp (*vec, "-d") == 0) { 441: docP = !docP; 442: continue; 443: } 444: if (strcmp (*vec, "-m") == 0) { 445: makeP = !makeP; 446: continue; 447: } 448: break; 449: } 450: if ((config = *vec++) == NULL || *vec != NULL) 451: adios (NULLCP, "usage: %s file", myname); 452: 453: if ((fp = fopen (config, "r")) == NULL) 454: adios (config, "unable to read"); 455: 456: while (fgets (buffer, sizeof buffer, fp)) { 457: if (ap = index (buffer, '\n')) 458: *ap-- = NULL; 459: else 460: ap = &buffer[strlen (buffer) - 1]; 461: while (ap >= buffer) 462: if (isspace (*ap)) 463: *ap = NULL; 464: else 465: break; 466: for (cp = buffer; isspace (*cp); cp++) 467: continue; 468: if (*cp == NULL || *cp == '#') 469: continue; 470: for (ap = cp; *ap; ap++) 471: if (isspace (*ap)) { 472: *ap++ = NULL; 473: while (isspace (*ap)) 474: ap++; 475: break; 476: } 477: for (bp = binds; bp -> keyword; bp++) 478: if (strcmp (bp -> keyword, cp) == 0) 479: break; 480: if (bp -> keyword == NULL) 481: adios (NULLCP, "unknown option %s in %s", cp, config); 482: else 483: if (*(bp -> value) == NULL || !(bp -> flags & BD_ADD)) 484: *(bp -> value) = strdup (ap); 485: else 486: *(bp -> value) = stradd (ap, stradd (" ", *(bp -> value))); 487: } 488: 489: (void) fclose (fp); 490: 491: /* */ 492: 493: if (binpath == NULL) 494: adios (NULLCP, "bin must be specified in %s", config); 495: trim (binpath); 496: 497: if (strcmp (bboards, "on") && strcmp (bboards, "off")) 498: adios (NULLCP, "bboards should be either \"on\" or \"off\", not %s", 499: bboards); 500: if (bbhome == NULL) 501: adios (NULLCP, "bbhome must be specified in %s", config); 502: trim (bbhome); 503: 504: if (strcmp (debug, "on") && strcmp (debug, "off")) 505: adios (NULLCP, "debug should be either \"on\" or \"off\", not %s", 506: debug); 507: 508: if (etcpath == NULL) 509: adios (NULLCP, "etc must be specified in %s", config); 510: trim (etcpath); 511: 512: if (mailpath == NULL) 513: adios (NULLCP, "mail must be specified in %s", config); 514: trim (mailpath); 515: if (*mailpath == '/') 516: maildir = mailpath; 517: else 518: mailfile = mailpath; 519: 520: if (strcmp (manuals, "standard") 521: && strcmp (manuals, "local") 522: && strcmp (manuals, "new") 523: && strcmp (manuals, "old") 524: && strcmp (manuals, "gen") 525: && strcmp (manuals, "none")) 526: adios (NULLCP,"invalid manuals setting: %s",manuals); 527: 528: if (mts == NULL) 529: adios (NULLCP, "mts must be specified in %s", config); 530: for (i = 0; mtsopts[i].mtskey; i++) 531: if (strcmp (mts, mtsopts[i].mtskey) == 0) 532: break; 533: if ((mtsnum = mtsopts[i].code) == unknown) 534: adios (NULLCP, "invalid mts setting: %s", mts); 535: add_option (mtsopts[i].optval); 536: smtp = mtsopts[i].mtsflags & DOSMTP; 537: if (mtsopts[i].mtsflags & NOMF) 538: mf = "off"; /* hack... */ 539: 540: if (strcmp (pop, "on") && strcmp (pop, "off")) 541: adios (NULLCP, "pop should be either \"on\" or \"off\", not %s", pop); 542: if (strcmp (pop, "on") == 0) 543: add_option ("POP"); 544: 545: if (strcmp (popbboards, "on") && strcmp (popbboards, "off")) 546: adios (NULLCP, "popbboards should be either \"on\" or \"off\", not %s", 547: popbboards); 548: if (strcmp (popbboards, "on") == 0) { 549: add_option ("BPOP"); 550: if (strcmp (bboards, "on") || strcmp (pop, "on")) 551: adios (NULLCP, 552: "popbboards \"on\" requires both bboards and pop \"on\""); 553: } 554: 555: if (strcmp (mf, "on") && strcmp (mf, "off")) 556: adios (NULLCP, "mf should be either \"on\" or \"off\", not %s", mf); 557: if (strcmp (mf, "on") == 0) 558: add_option ("MF"); 559: 560: if (strcmp (tma, "on") && strcmp (tma, "off")) 561: adios (NULLCP, "tma should be either \"on\" or \"off\", not %s", tma); 562: if (strcmp (tma, "on") == 0) 563: add_option ("TMA"); 564: 565: begin_myopt (); 566: if (cp = options) { 567: for (ap = cp; *ap; ap++) 568: if (isspace (*ap)) 569: *ap = ' '; 570: options = NULL; 571: for (ap = cp; dp = index (ap, ' '); ap = dp) { 572: *dp++ = NULL; 573: add_myopt (ap); 574: (void) sprintf (buffer, "%s-D%s", options ? " " : "", ap); 575: ap = buffer; 576: options = stradd (ap, options); 577: while (isspace (*dp)) 578: dp++; 579: } 580: if (*ap) { 581: add_myopt (ap); 582: (void) sprintf (buffer, "%s-D%s", options ? " " : "", ap); 583: ap = buffer; 584: options = stradd (ap, options); 585: } 586: free (cp); 587: } 588: end_myopt (); 589: } 590: 591: /* */ 592: 593: static add_option (s) 594: char *s; 595: { 596: options = options ? stradd (s, stradd (" ", options)) : strdup (s); 597: } 598: 599: 600: begin_myopt () { 601: myopts = strdup ("char *options[] = {"); 602: } 603: 604: 605: add_myopt (s) 606: char *s; 607: { 608: int len; 609: char *bp, 610: buffer[BUFSIZ]; 611: static int nameoutput = 0; 612: static int linepos = 0; 613: static int outputlinelen = 72; 614: 615: if (!nameoutput) { 616: printf ("%s: ", bp = "options"); 617: linepos += (nameoutput = strlen (bp) + 2); 618: } 619: len = strlen (s); 620: if (linepos != nameoutput) 621: if (len + linepos + 3 > outputlinelen) 622: printf ("\n%*s", linepos = nameoutput, ""); 623: else 624: printf (" "), linepos++; 625: printf ("[%s]", s); 626: linepos += len + 2; 627: (void) fflush (stdout); 628: 629: bp = buffer; 630: *bp++ = '"'; 631: while (*s) { 632: if (*s == '"') 633: *bp++ = QUOTE, *bp++ = QUOTE; 634: *bp++ = *s++; 635: } 636: (void) strcpy (bp, "\", "); 637: myopts = stradd (buffer, myopts); 638: } 639: 640: 641: end_myopt () { 642: printf ("\n"); 643: (void) fflush (stdout); 644: 645: myopts = stradd ("NULL};", myopts); 646: } 647: 648: /* */ 649: 650: static trim (s) 651: char *s; 652: { 653: char *p; 654: 655: if (s == NULL || (p = rindex (s, '/')) == NULL) 656: return; 657: if (*++p == NULL) 658: *--p = NULL; 659: } 660: 661: 662: static char *tail (s) 663: char *s; 664: { 665: char *p; 666: 667: if (p = rindex (s, '/')) 668: p++; 669: return ((p == NULL || *p == NULL) ? s : p); 670: } 671: 672: /* */ 673: 674: static char *stradd (s1, s2) 675: char *s1, 676: *s2; 677: { 678: char *p; 679: 680: if (s1 == NULL || *s1 == NULL) 681: return s2; 682: if (s2 == NULL) 683: return strdup (s1); 684: if ((p = malloc ((unsigned) (strlen (s1) + strlen (s2) + 2))) == NULL) 685: adios (NULLCP, "insufficient memory"); 686: 687: (void) sprintf (p, "%s%s", s2, s1); 688: if (s2) 689: free (s2); 690: return p; 691: } 692: 693: 694: static char *strdup (s) 695: char *s; 696: { 697: char *p; 698: 699: if ((p = malloc ((unsigned) (strlen (s) + 1))) == NULL) 700: adios (NULLCP, "insufficient memory"); 701: 702: (void) strcpy (p, s); 703: return p; 704: } 705: 706: /* */ 707: 708: static char *index (s, c) 709: char *s, 710: c; 711: { 712: char i; 713: 714: while (i = *s++) 715: if (i == c) 716: return (s - 1); 717: 718: return NULL; 719: } 720: 721: 722: static char *rindex (s, c) 723: char *s, 724: c; 725: { 726: char i, 727: *t; 728: 729: t = NULL; 730: while (i = *s++) 731: if (i == c) 732: t = s - 1; 733: 734: return t; 735: } 736: 737: /* */ 738: 739: /* VARARGS */ 740: 741: adios (what, fmt, a, b, c) 742: char *what, 743: *fmt, 744: *a, 745: *b, 746: *c; 747: { 748: (void) fflush (stdout); 749: 750: fprintf (stderr, "%s: ", myname); 751: fprintf (stderr, fmt, a, b, c); 752: if (what) { 753: (void) fputc (' ', stderr); 754: perror (what); 755: } 756: else 757: (void) fputc ('\n', stderr); 758: 759: exit (1); 760: }