home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume8 / unaxcess2 / part02 < prev    next >
Encoding:
Internet Message Format  |  1987-02-04  |  57.9 KB

  1. Subject:  v08i038:  UNaXcess Conferencing, version 1.00.02, Part02/04
  2. Newsgroups: mod.sources
  3. Approved: mirror!rs
  4.  
  5. Submitted by: abic!cwruecmp!allbery%ncoast.UUCP
  6. Mod.sources: Volume 8, Issue 38
  7. Archive-name: unaxcess2/Part02
  8.  
  9. #--------------------------------CUT HERE-------------------------------------
  10. #! /bin/sh
  11. #
  12. # This is a shell archive.  Save this into a file, edit it
  13. # and delete all lines above this comment.  Then give this
  14. # file to sh by executing the command "sh file".  The files
  15. # will be extracted into the current directory owned by
  16. # you with default permissions.
  17. #
  18. # The files contained herein are:
  19. #
  20. # -rw-rw-rw-   1 allbery  System     17362 Feb  3 21:10 message.c
  21. # -rw-rw-rw-   1 allbery  System      1052 Feb  3 21:11 mkconf.c
  22. # -rw-rw-rw-   1 allbery  System      4762 Feb  3 21:29 mvmsg.c
  23. # -rw-rw-rw-   1 allbery  System     18613 Feb  3 21:30 system.c
  24. # -rw-rw-rw-   1 allbery  System      1357 Feb  3 21:31 system.h
  25. # -rw-rw-rw-   1 allbery  System      8484 Feb  3 21:48 ua.c
  26. # -rw-rw-rw-   1 allbery  System      2555 Feb  3 21:32 ua.h
  27. # -rw-rw-rw-   1 allbery  System       419 Feb  3 21:33 udate.c
  28. #
  29. echo 'x - message.c'
  30. sed 's/^X//' << '________This_Is_The_END________' > message.c
  31. X/*
  32. X *    @(#)message.c    1.1 (TDI) 2/3/87
  33. X *    @(#)Copyright (C) 1984, 85, 86, 87 by Brandon S. Allbery.
  34. X *    @(#)This file is part of UNaXcess version 1.0.2.
  35. X *
  36. X *    Permission is hereby granted to copy and distribute this program
  37. X *    freely.  Permission is NOT given to modify this program or distribute
  38. X *    it at cost, except for charging a reasonable media/copying fee.
  39. X */
  40. X
  41. X#ifndef lint
  42. Xstatic char _FileID_[] = "@(#)message.c    1.1 (TDI) 2/3/87";
  43. Xstatic char _UAID_[]   = "@(#)UNaXcess version 1.0.2";
  44. X#endif lint
  45. X
  46. X#include "ua.h"
  47. X
  48. Xextern struct cmd maincmd[];
  49. X
  50. Xselmsg(fn)
  51. Xint (*fn)(); {
  52. X    char line[256], *p;
  53. X    short lomsg, himsg;
  54. X    FILE *f;
  55. X
  56. X    sprintf(line, "%s/%s/himsg", MSGBASE, conference);
  57. X    if ((f = fopen(line, "r")) == NULL) {
  58. X        log("Error %d opening %s", errno, line);
  59. X        if (strcmp(conference, "general") == 0)
  60. X            panic("conf");
  61. X        writes("I can't find the high message file.  Moving back to general...");
  62. X        strcpy(conference, "general");
  63. X        return 1;
  64. X    }
  65. X    fgets(line, 32, f);
  66. X    fclose(f);
  67. X    himsg = atoi(line);
  68. X    writef("Forward, Reverse, Individual, or New (RETURN to abort): ");
  69. X    line[0] = readc();
  70. X    log("Mode: %c", line[0]);
  71. X    switch (line[0]) {
  72. X    case 'F':
  73. X        lomsg = 1;
  74. X        break;
  75. X    case 'R':
  76. X        lomsg = himsg;
  77. X        himsg = 1;
  78. X        break;
  79. X    case 'I':
  80. X        writef("Enter message number: ");
  81. X        reads(line);
  82. X        log("Message: %s", line);
  83. X        if ((lomsg = atoi(line)) < 1 || lomsg > himsg) {
  84. X            writes("No such message.");
  85. X            log("No such message.");
  86. X            return 1;
  87. X        }
  88. X        domsg(conference, lomsg, lomsg, fn);
  89. X        return 1;
  90. X    case 'N':
  91. X        lomsg = 0;
  92. X        break;
  93. X    case ' ':
  94. X        return 1;
  95. X    default:
  96. X        writes("What?  Valid commands are F, R, I, N, or ENTER.");
  97. X        log("Illegal search mode.");
  98. X        return 1;
  99. X    }
  100. X    if (lomsg != 0) {
  101. X        writef("Starting message (%d): ", lomsg);
  102. X        reads(line);
  103. X        log("Start: %s", line);
  104. X        if (line[0] != 0)
  105. X            if (atoi(line) < 1 || (lomsg > 1 && atoi(line) > lomsg)) {
  106. X                writes("Bad message number.");
  107. X                log("Bad message number.");
  108. X                return 1;
  109. X            }
  110. X            else
  111. X                lomsg = atoi(line);
  112. X        writef("Ending message (%d): ", himsg);
  113. X        reads(line);
  114. X        log("End: %s", line);
  115. X        if (line[0] != 0)
  116. X            if (atoi(line) < 1 || (himsg > 1 && atoi(line) > himsg)) {
  117. X                writes("Bad message number.");
  118. X                log("Bad message number.");
  119. X                return 1;
  120. X            }
  121. X            else
  122. X                himsg = atoi(line);
  123. X    }
  124. X    domsg(conference, lomsg, himsg, fn);
  125. X    return 1;
  126. X}
  127. X
  128. Xreadmsg() {
  129. X    return selmsg(doread);
  130. X}
  131. X
  132. Xscanmsg() {
  133. X    return selmsg(doscan);
  134. X}
  135. X
  136. Xdoread(msg, conf, mnum)
  137. Xchar *msg, *conf;
  138. Xshort mnum; {
  139. X    char ch;
  140. X
  141. X    writef("\nMessage %d of %s:\n", mnum, conf);
  142. X    if (isprivate(msg)) {
  143. X        writes("This message is private.");
  144. X        return 1;
  145. X    }
  146. X    cat(msg);
  147. X
  148. XDR_Loop:
  149. X    writef("\nContinue, Stop, %sEnter a message, Unsubscribe, Xecute, or Reply? C\b", (user.u_access == A_WITNESS || s_cmp(getowner(msg), user.u_name) == 0? "Kill, ": ""));
  150. X    if (!isatty(0)) {
  151. X        ch = ' ';
  152. X        writes("C");
  153. X    }
  154. X    else
  155. X        ch = readc();
  156. X    log("C/S/K/E/U/R/X: %c", ch);
  157. X    switch (ch) {
  158. X    case 'c':
  159. X    case 'C':
  160. X    case '\n':
  161. X    case '\r':
  162. X    case ' ':
  163. X        return 1;
  164. X    case 'U':
  165. X    case 'u':
  166. X        unsubscribe(conf);
  167. X        return 0;
  168. X    case 's':
  169. X    case 'S':
  170. X        return 0;
  171. X    case 'r':
  172. X    case 'R':
  173. X        reply(msg, conf);
  174. X        goto DR_Loop;
  175. X    case 'k':
  176. X    case 'K':
  177. X        if (unlink(msg) < 0) {
  178. X            writef("Can't kill message: %d", mnum);
  179. X            log("Error %d unlinking %s", errno, msg);
  180. X            goto DR_Loop;
  181. X        }
  182. X        log("Deleted %s:%d", conference, mnum);
  183. X        return 1;
  184. X    case 'E':
  185. X    case 'e':
  186. X        enter("");
  187. X        goto DR_Loop;
  188. X    case 'x':
  189. X    case 'X':
  190. X        __recurse++;
  191. X        pcmd("Command (? for help, G to return): ", maincmd, (char *) 0);
  192. X        goto DR_Loop;
  193. X    default:
  194. X        writef("What?  Please enter one of C, S, %sE, U, X, or R.", (user.u_access == A_WITNESS || s_cmp(getowner(msg), user.u_name) == 0? "K, ": ""));
  195. X        goto DR_Loop;
  196. X    }
  197. X}
  198. X
  199. Xmsgok(file)
  200. Xchar *file; {
  201. X    FILE *fp;
  202. X
  203. X    if ((fp = fopen(file, "r")) == NULL)
  204. X    return 0;
  205. X    fclose(fp);
  206. X    return 1;
  207. X}
  208. X
  209. Xdoscan(msg, conf, mnum)
  210. Xchar *msg, *conf;
  211. Xshort mnum; {
  212. X    char line[1024];
  213. X    FILE *f;
  214. X    short dflag, fflag, tflag, sflag;
  215. X
  216. X    if ((f = fopen(msg, "r")) == NULL) {
  217. X        writes("Cannot open file.");
  218. X        log("Error %d opening %s", errno, msg);
  219. X        return 1;
  220. X    }
  221. X    writef("\nMessage %d of %s: \n", mnum, conf);
  222. X    dflag = fflag = tflag = sflag = 0;
  223. X    if (isprivate(msg))
  224. X        writes("Message is private.");
  225. X    else {
  226. X        while (fgets(line, 1024, f) != NULL) {
  227. X            if (line[0] == '\n')
  228. X                break;
  229. X            if (!dflag && strncmp(line, "Date: ", 6) == 0) {
  230. X                writef("%s", line);
  231. X                dflag++;
  232. X                continue;
  233. X            }
  234. X            if (!fflag && strncmp(line, "From: ", 6) == 0) {
  235. X                writef("%s", line);
  236. X                fflag++;
  237. X                continue;
  238. X            }
  239. X            if (!tflag && strncmp(line, "To: ", 4) == 0) {
  240. X                writef("%s", line);
  241. X                tflag++;
  242. X                continue;
  243. X            }
  244. X            if (!sflag && strncmp(line, "Subject: ", 9) == 0) {
  245. X                writef("%s", line);
  246. X                sflag++;
  247. X                continue;
  248. X            }
  249. X            if (!sflag && strncmp(line, "Subject (Private): ", 19) == 0) {
  250. X                writef("%s", line);
  251. X                sflag++;
  252. X                continue;
  253. X            }
  254. X        }
  255. X        if (!tflag)
  256. X        writes("To: All");
  257. X    }
  258. X    fclose(f);
  259. X    writes("--------------------------------");
  260. X    return 1;
  261. X}
  262. X
  263. Xdomsg(conf, lomsg, himsg, fn)
  264. Xchar *conf;
  265. Xshort lomsg, himsg;
  266. Xint (*fn)(); {
  267. X    short mcnt;
  268. X    char tmps[256];
  269. X    struct _himsg *ptr;
  270. X
  271. X    for (ptr = hicnts; ptr != NULL; ptr = ptr->hi_next)
  272. X        if (strcmp(conf, ptr->hi_conf) == 0)
  273. X            break;
  274. X    if (ptr == NULL) {
  275. X/*
  276. X * Query: how do you silence lint's complaints about calloc() casting?
  277. X */
  278. X        if ((ptr = (struct _himsg *) calloc((unsigned) 1, sizeof (struct _himsg))) == NULL) {
  279. X            log("Error %d allocating _himsg for %s", errno, conf);
  280. X            panic("alloc");
  281. X        }
  282. X        ptr->hi_next = hicnts;
  283. X        hicnts = ptr;
  284. X        ptr->hi_uns = HI_SUBSCR;
  285. X        strcpy(ptr->hi_conf, conf);
  286. X        ptr->hi_num = 0;
  287. X    }
  288. X    if (lomsg == 0)            /* read new messages */
  289. X        for (mcnt = ptr->hi_num + 1; mcnt <= himsg; mcnt++) {
  290. X            sprintf(tmps, "%s/%s/%d", MSGBASE, conf, mcnt);
  291. X            if (msgok(tmps) <= 0)
  292. X                continue;
  293. X            if (!(*fn)(tmps, conf, mcnt))
  294. X                break;
  295. X        }
  296. X    else if (lomsg <= himsg)        /* forward or individual read */
  297. X        for (mcnt = lomsg; mcnt <= himsg; mcnt++) {
  298. X            sprintf(tmps, "%s/%s/%d", MSGBASE, conf, mcnt);
  299. X            if (msgok(tmps) <= 0)
  300. X                continue;
  301. X            if (!(*fn)(tmps, conf, mcnt))
  302. X                break;
  303. X        }
  304. X    else
  305. X        for (mcnt = lomsg; mcnt >= himsg; mcnt--) {
  306. X            sprintf(tmps, "%s/%s/%d", MSGBASE, conf, mcnt);
  307. X            if (msgok(tmps) <= 0)
  308. X                continue;
  309. X            if (!(*fn)(tmps, conf, mcnt))
  310. X                break;
  311. X        }
  312. X    ptr->hi_num = himsg;
  313. X    writehigh(hicnts);
  314. X}
  315. X
  316. Xreadnew() {
  317. X    DIR *dp;
  318. X    struct direct *dirp;
  319. X    FILE *hp;
  320. X    short himsg;
  321. X    char line[256], ch;
  322. X
  323. X    if ((dp = opendir(MSGBASE)) == NULL) {
  324. X        log("Error %d reading dir %s/", errno, MSGBASE);
  325. X        panic("msgdir");
  326. X    }
  327. X    while ((dirp = readdir(dp)) != NULL) {
  328. X        if (dirp->d_name[0] == '.')
  329. X            continue;
  330. X        if (isunsub(dirp->d_name))
  331. X            continue;
  332. X        log("Reading %s.", dirp->d_name);
  333. X        if (user.u_access != A_WITNESS && parms.ua_xrc)
  334. X            if (!isrcmem(user.u_name, dirp->d_name)) {
  335. X                log("Skipping Restricted conference.");
  336. X                continue;
  337. X            }
  338. X        writef("\nExamining conference %s...\n", dirp->d_name);
  339. X        sprintf(line, "%s/%s/himsg", MSGBASE, dirp->d_name);
  340. X        if ((hp = fopen(line, "r")) == NULL) {
  341. X            log("Error %d opening %s", errno, line);
  342. X            writes("Can't open high message file.");
  343. X            continue;
  344. X        }
  345. X        fgets(line, 32, hp);
  346. X        fclose(hp);
  347. X        himsg = atoi(line);
  348. X        domsg(dirp->d_name, 0, himsg, doread);
  349. X    
  350. XRN_Loop:
  351. X        writef("\nNext conference, Unsubscribe, or Stop? N\b");
  352. X        if (!isatty(0)) {
  353. X            writes("N");
  354. X            ch = ' ';
  355. X        }
  356. X        else
  357. X            ch = readc();
  358. X        log("Next/Unsub/Stop: %c", ch);
  359. X        switch (ch) {
  360. X        case 'N':
  361. X        case 'n':
  362. X        case ' ':
  363. X        case '\r':
  364. X        case '\n':
  365. X            break;
  366. X        case 'U':
  367. X        case 'u':
  368. X            unsubscribe(dirp->d_name);
  369. X            break;
  370. X        case 'S':
  371. X        case 's':
  372. X            closedir(dp);
  373. X            return 1;
  374. X        default:
  375. X            writes("Please enter one of N, U, or S.");
  376. X            goto RN_Loop;
  377. X        }
  378. X    }
  379. X    closedir(dp);
  380. X    return 1;
  381. X}
  382. X
  383. Xenter() {
  384. X    char to[256], subj[256], *p, line[256];
  385. X    short pflag;
  386. X
  387. X    if (user.u_access == A_GUEST && strcmp(conference, "guest") != 0) {
  388. X        log("Security violation:  GUEST entering messages.");
  389. X        writes("You aren't allowed to enter messages in this conference.");
  390. X        return 1;
  391. X    }
  392. X    writef("Who is this message to (ENTER to abort)? ");
  393. X    reads(line);
  394. X    log("To: %s", line);
  395. X    if (line[0] == '\0')
  396. X        return 1;
  397. X    for (p = line; *p != '\0'; p++)
  398. X        *p = ToLower(*p);
  399. X    strcpy(to, line);
  400. X    writef("Subject: ");
  401. X    reads(line);
  402. X    if (line[0] == '\0')
  403. X        return 1;
  404. X    strcpy(subj, line);
  405. X    log("Subject: %s", line);
  406. X    mkmsg(to, subj, conference, 0);
  407. X    return 1;
  408. X}
  409. X
  410. Xreply(msg, conf)
  411. Xchar *msg, *conf; {
  412. X    char to[256], subj[256], line[1024];
  413. X    short fflag, sflag, pflag;
  414. X    FILE *f;
  415. X
  416. X    if (user.u_access == A_GUEST && strcmp(conf, "guest") != 0) {
  417. X        log("Security violation:  GUEST entering messages");
  418. X        writes("You aren't allowed to enter messages.");
  419. X        return;
  420. X    }
  421. X    if ((f = fopen(msg, "r")) == NULL) {
  422. X        log("Error %d opening %s", errno, msg);
  423. X        writes("Can't re-open message file.");
  424. X        return;
  425. X    }
  426. X    fflag = sflag = 0;
  427. X    strcpy(to, "All\n");
  428. X    strcpy(subj, "Re: Orphaned Response\n");    /* now you know... */
  429. X    while (fgets(line, 1024, f) != NULL) {
  430. X        if (line[0] == '\n')
  431. X            break;
  432. X        if (!fflag && strncmp(line, "From: ", 6) == 0) {
  433. X            strcpy(to, &line[6]);
  434. X            fflag++;
  435. X            continue;
  436. X        }
  437. X        if (!sflag && strncmp(line, "Subject: ", 9) == 0) {
  438. X            if (strncmp(&line[9], "Re: ", 4) == 0)
  439. X                strcpy(subj, &line[9]);
  440. X            else
  441. X                strcpy(&subj[4], &line[9]);
  442. X            sflag++;
  443. X            pflag = 0;
  444. X            continue;
  445. X        }
  446. X        if (!sflag && strncmp(line, "Subject (Private): ", 19) == 0) {
  447. X            if (strncmp(&line[19], "Re: ", 4) == 0)
  448. X                strcpy(subj, &line[19]);
  449. X            else
  450. X                strcpy(&subj[4], &line[19]);
  451. X            sflag++;
  452. X            pflag = 1;
  453. X            continue;
  454. X        }
  455. X    }
  456. X    fclose(f);
  457. X    to[strlen(to) - 1] = '\0';            /* get rid of trailing nl */
  458. X    subj[strlen(subj) - 1] = '\0';
  459. X    mkmsg(to, subj, conf, pflag);
  460. X}
  461. X
  462. Xdoqscan(msg, conf, mnum)
  463. Xchar *msg, *conf;
  464. Xshort mnum; {
  465. X    char line[1024];
  466. X    FILE *f;
  467. X
  468. X#ifdef lint
  469. X    puts(conf);    /* shut lint up about "arg not used" */
  470. X#endif lint
  471. X    if ((f = fopen(msg, "r")) == NULL) {
  472. X        writes("Cannot open file.");
  473. X        log("Error %d opening %s", errno, msg);
  474. X        return 1;
  475. X    }
  476. X    writef("%5d. ", mnum);
  477. X    if (isprivate(msg))
  478. X        writes("Private message.");
  479. X    else
  480. X        while (fgets(line, 1024, f) != NULL) {
  481. X            if (line[0] == '\n')
  482. X                break;
  483. X            if (strncmp(line, "Subject: ", 9) == 0) {
  484. X                writef("%s", &line[9]);
  485. X                break;
  486. X            }
  487. X            if (strncmp(line, "Subject (Private): ", 19) == 0) {
  488. X                writef("%s", &line[8]);        /* include privacy tag */
  489. X                break;
  490. X            }
  491. X        }
  492. X    fclose(f);
  493. X    return 1;
  494. X}
  495. X
  496. Xqscan() {
  497. X    return selmsg(doqscan);
  498. X}
  499. X
  500. Xmkmsg(to, subj, conf, dpflag)
  501. Xchar *to, *subj, *conf; {
  502. X    static char lockfile[] = "msgbase.lock";
  503. X    char *tempfile = mktemp("/tmp/UAmXXXXXX");
  504. X    FILE *mfp, *sfp;
  505. X    char line[1024], *p, ch, rconf[256];
  506. X    short mcnt;
  507. X    struct user ubuf;
  508. X
  509. X    for (;;) {
  510. X        writef("To which conference do you wish this message to go (%s)? ", conf);
  511. X        reads(rconf);
  512. X        if (rconf[0] == '\0')
  513. X            strcpy(rconf, conf);
  514. X        if (!isconf(rconf)) {
  515. X            writes("That conference doesn't exist.");
  516. X            continue;
  517. X        }
  518. X        if (!isrcmem(user.u_name, rconf)) {
  519. X            writes("You aren't a member of that conference.");
  520. X            continue;
  521. X        }
  522. X        if (user.u_access != A_WITNESS && parms.ua_roc && conf[0] == 'r' && conf[1] == '-') {
  523. X            writes("That conference is read-only.  Try dropping the R- prefix.");
  524. X            continue;
  525. X        }
  526. X        break;
  527. X    }
  528. X    if (parms.ua_pm) {
  529. X        writef("Is this message to be private? %c\b", (dpflag? 'Y': 'N'));
  530. X        line[0] = readc();
  531. X        log("Private? %c", line[0]);
  532. X        if (line[0] == 'Y')
  533. X            dpflag = 1;
  534. X        else if (line[0] == 'N')
  535. X            dpflag = 0;
  536. X    }
  537. X    if (dpflag && !getuser(to, &ubuf)) {
  538. X        writef("You can't send a private message to %s; he's unregistered.\n", upstr(to));
  539. X        log("Attempted private message to unregistered user.");
  540. X        return 0;
  541. X    }
  542. X    if ((mfp = fopen(tempfile, "w")) == NULL) {
  543. X        log("Error %d opening %s", errno, tempfile);
  544. X        panic("tmp");
  545. X    }
  546. X    for (p = to; *p != '\0'; p++)
  547. X        *p = ToUpper(*p);
  548. X    fprintf(mfp, "To: %s\nSubject%s: %s\n\n", to, (dpflag? " (Private)": ""), subj);
  549. X    fclose(mfp);
  550. X    input(tempfile);
  551. X    for (;;) {
  552. X        writef("\nList, Continue entry, Edit, Save, or Abort? ");
  553. X        ch = readc();
  554. X        log("Edit command: %c", ch);
  555. X        switch (ch) {
  556. X        case 'L':
  557. X            writes("\n--------------------");
  558. X            cat(tempfile);
  559. X            writes("--------------------");
  560. X            break;
  561. X        case 'C':
  562. X            input(tempfile);
  563. X            break;
  564. X        case 'E':
  565. X            edit(tempfile);
  566. X            break;
  567. X        case 'A':
  568. X            writef("Do you really want to abort this edit? N\b");
  569. X            line[0] = readc();
  570. X            log("Abort? %c", line[0]);
  571. X            if (line[0] == 'Y') {
  572. X                unlink(tempfile);
  573. X                return 0;
  574. X            }
  575. X            break;
  576. X        case '?':
  577. X            writes("Message entry commands:\n\nL - List message\nC - Continue message entry\nE - Edit message\nS - Save message\nA - Abort message\n");
  578. X            break;
  579. X        case 'S':
  580. X            writes("Saving message...");
  581. X            mklock(lockfile);
  582. X            sprintf(line, "%s/%s/himsg", MSGBASE, rconf);
  583. X            if ((sfp = fopen(line, "r")) == NULL) {
  584. X                log("Error %d opening %s", errno, line);
  585. X                rmlock(lockfile);
  586. X                unlink(tempfile);
  587. X                panic("himsg");
  588. X            }
  589. X            fgets(line, 32, sfp);
  590. X            fclose(sfp);
  591. X            mcnt = atoi(line) + 1;
  592. X            sprintf(line, "%s/%s/%d", MSGBASE, rconf, mcnt);
  593. X            if ((sfp = fopen(line, "w")) == NULL) {
  594. X                log("Error %d opening %s", errno, line);
  595. X                unlink(tempfile);
  596. X                rmlock(lockfile);
  597. X                panic("msg");
  598. X            }
  599. X            fprintf(sfp, "Date: %s\nFrom: %s\n", longdate(), upstr(user.u_name));
  600. X            if ((mfp = fopen(tempfile, "r")) == NULL) {
  601. X                fclose(sfp);
  602. X                log("Error %d opening %s", errno, tempfile);
  603. X                unlink(tempfile);
  604. X                unlink(line);
  605. X                rmlock(lockfile);
  606. X                panic("tmp");
  607. X            }
  608. X            while (fgets(line, 1024, mfp) != NULL)
  609. X                fputs(line, sfp);
  610. X            fclose(sfp);
  611. X            fclose(mfp);
  612. X            unlink(tempfile);
  613. X            sprintf(line, "%s/%s/himsg", MSGBASE, rconf);
  614. X            if ((sfp = fopen(line, "w")) == NULL) {
  615. X                log("Error %d opening %s", errno, line);
  616. X                panic("himsg_w");
  617. X            }
  618. X            fprintf(sfp, "%d\n", mcnt);
  619. X            fclose(sfp);
  620. X            rmlock(lockfile);
  621. X            return 1;
  622. X        default:
  623. X            writes("Please enter L, C, E, S, or A; or ? for help.");
  624. X        }
  625. X    }
  626. X}
  627. X
  628. Xedit(file)
  629. Xchar *file; {
  630. X    char find[256], replace[256], buf[1024], tempfile[80];
  631. X    char *bufp, *strp;
  632. X    long offset;
  633. X    FILE *src, *tmp;
  634. X    short ch, fch;
  635. X    
  636. X    sprintf(tempfile, "/tmp/UaEd%05d", getpid());
  637. X    writef("At the \"Find:\" prompt, enter the string to locate; pressing ENTER / RETURN alone exits the editor.  At each occurrence of the string you will be ");
  638. X    writef("shown that part of the message and prompted to Replace, Skip to the next occurence, or Quit the search.  If you Replace, you will be asked ");
  639. X    writef("for the replacement string; pressing ENTER or RETURN alone indicates that you wish to ");
  640. X    writef("to delete the string.\n\n");
  641. X    for (;;) {
  642. X        writef("Find: ");
  643. X        reads(find);
  644. X        if (find[0] == '\0')
  645. X            return;
  646. X        if ((tmp = fopen(tempfile, "w")) == (FILE *) 0) {
  647. X            log("Error %d opening %s", tempfile);
  648. X            panic("msged_tmpf");
  649. X        }
  650. X        if ((src = fopen(file, "r")) == (FILE *) 0) {
  651. X            log("Error %d opening %s", file);
  652. X            panic("msged_srcf");
  653. X        }
  654. X        offset = 0L;
  655. X        strp = find;
  656. X        writes("---------------");
  657. X        for (;;) {
  658. X            while ((ch = getc(src)) != EOF) {
  659. X                offset++;
  660. X                writec(ch);
  661. X                fch = ch;
  662. X                if (ToUpper(ch) == ToUpper(*strp))
  663. X                    break;
  664. X                putc(ch, tmp);
  665. X            }
  666. X            if (ch == EOF)
  667. X                break;
  668. X            strp++;
  669. X            while (*strp != '\0' && (ch = getc(src)) != EOF) {
  670. X                if (ToUpper(ch) != ToUpper(*strp))
  671. X                    break;
  672. X                strp++;
  673. X            }
  674. X            if (ch == EOF && *strp != '\0') {
  675. X                for (bufp = find; bufp != strp; bufp++) {
  676. X                    putc(*bufp, tmp);
  677. X                    writec(*bufp);
  678. X                }
  679. X                break;
  680. X            }
  681. X            if (*strp != '\0') {
  682. X                fseek(src, offset, 0L);
  683. X                strp = find;
  684. X                putc(fch, tmp);
  685. X                continue;
  686. X            }
  687. X            writef("\b \b[%s]\n---------------\n", find);
  688. X
  689. Xaskrepl:
  690. X            writef("Replace, Skip this one, Quit?  S\b");
  691. X            ch = readc();
  692. X            switch (ch) {
  693. X            case ' ':
  694. X            case 'S':
  695. X                fseek(src, offset, 0L);
  696. X                strp = find;
  697. X                writes("---------------");
  698. X                continue;
  699. X            case 'R':
  700. X                writef("Replacement: ");
  701. X                reads(replace);
  702. X                fputs(replace, tmp);
  703. X                offset += strlen(find);
  704. X                writes("---------------");
  705. X                continue;
  706. X            case 'Q':
  707. X                while ((ch = getc(src)) != EOF)
  708. X                    putc(ch, tmp);
  709. X                break;
  710. X            default:
  711. X                putchar('\7');
  712. X                goto askrepl;
  713. X            }
  714. X            break;
  715. X        }
  716. X        writes("---------------");
  717. X        fclose(src);
  718. X        fclose(tmp);
  719. X        if (unlink(file) < 0) {
  720. X            log("Error %d unlinking %s", errno, file);
  721. X            panic("msged_unlk");
  722. X        }
  723. X        if (copylink(tempfile, file) < 0) {
  724. X            log("Error %d copylinking %s to %s", errno, tempfile, file);
  725. X            panic("msged_cplk");
  726. X        }
  727. X    }
  728. X}
  729. X
  730. Xinput(file)
  731. Xchar *file; {
  732. X    FILE *fp;
  733. X    char line[256];
  734. X    char *cp;
  735. X    char ch;
  736. X    int lastwasnl;
  737. X
  738. X    if ((fp = fopen(file, "a")) == NULL) {
  739. X        log("Error %d opening %s", errno, file);
  740. X        unlink(file);
  741. X        panic("tmp");
  742. X    }
  743. X    writes("\nEnter your text now.  End it by typing any of ESCAPE, CONTROL-Z or CONTROL-D on a line by itself.  Your text will be word-wrapped automatically.\n");
  744. X    log("Entering text...");
  745. X    cp = line;
  746. X    interact();
  747. X    while (((ch = getchar() & 0x7f) != '\033' && ch != '\032' && ch != '\004') || !lastwasnl) {
  748. X        if (ch == '\b' || ch == '\177')
  749. X            if (cp == line) {
  750. X                putchar('\7');
  751. X                fflush(stdout);
  752. X            }
  753. X            else {
  754. X                writec('\b');
  755. X                writec(' ');
  756. X                writec('\b');
  757. X                cp--;
  758. X            }
  759. X        else if (ch == '\n' || ch == '\r') {
  760. X            *cp++ = '\n';
  761. X            *cp++ = '\0';
  762. X            fputs(line, fp);
  763. X            cp = line;
  764. X            writec('\n');
  765. X            lastwasnl = 1;
  766. X        }
  767. X        else if (ch < ' ') {
  768. X            putchar('\7');
  769. X            fflush(stdout);
  770. X        }
  771. X        else {
  772. X            lastwasnl = 0;
  773. X            *cp++ = ch;
  774. X            writec(ch == '\t'? ' ': ch);
  775. X            if (wrapped() != 0) {
  776. X                cp -= wrapped() + 1;
  777. X                ch = *cp;
  778. X                *cp = '\0';
  779. X                fputs(line, fp);
  780. X                cp = line + strlen(line);
  781. X                *cp = ch;
  782. X                strcpy(line, cp);
  783. X                cp = line + wrapped() + 1;
  784. X            }
  785. X        }
  786. X    }
  787. X    buffer();
  788. X    fclose(fp);
  789. X}
  790. ________This_Is_The_END________
  791. echo 'x - mkconf.c'
  792. sed 's/^X//' << '________This_Is_The_END________' > mkconf.c
  793. X/*
  794. X *    @(#)mkconf.c    1.1 (TDI) 2/3/87
  795. X *
  796. X *    Permission is hereby granted to copy and distribute this program
  797. X *    freely.  Permission is NOT given to modify this program or distribute
  798. X *    it at cost, except for charging a reasonable media/copying fee.
  799. X */
  800. X
  801. X#ifndef lint
  802. Xstatic char _FileID_[] = "@(#)mkconf.c    1.1 (TDI) 2/3/87";
  803. Xstatic char _UAID_[]   = "@(#)UNaXcess version 1.0.2";
  804. X#endif lint
  805. X
  806. X#include <sys/types.h>
  807. X#include <sys/stat.h>
  808. X#include <sys/dir.h>
  809. X
  810. Xchar line[256];
  811. X
  812. X#ifdef SYS5
  813. X#  define SYS3
  814. X#endif SYS5
  815. X
  816. X#ifdef SYS3
  817. X#  define RIndex    strrchr
  818. X#else
  819. X#  ifdef XENIX3
  820. X#    define RIndex    strrchr
  821. X#  else
  822. X#    ifdef XENIX5
  823. X#      define RIndex    strrchr
  824. X#    else
  825. X#      define RIndex    rindex
  826. X#    endif XENIX5
  827. X#  endif XENIX3
  828. X#endif SYS3
  829. X
  830. Xchar *RIndex();
  831. X
  832. Xmain(argc, argv)
  833. X    char **argv;
  834. X    {
  835. X    if (argc != 3)
  836. X    exit(1);
  837. X    mknod(argv[1], S_IFDIR|0755, 0);
  838. X    chown(argv[1], atoi(argv[2]), 50);
  839. X    sprintf(line, "%s/.", argv[1]);
  840. X    link(argv[1], line);
  841. X    *RIndex(argv[1], '/') = '\0';
  842. X    strcat(line, ".");
  843. X    link(argv[1], line);
  844. X    }
  845. ________This_Is_The_END________
  846. echo 'x - mvmsg.c'
  847. sed 's/^X//' << '________This_Is_The_END________' > mvmsg.c
  848. X/*
  849. X *    @(#)mvmsg.c    1.1 (TDI) 2/3/87
  850. X *    @(#)Copyright (C) 1984, 85, 86, 87 by Brandon S. Allbery.
  851. X *
  852. X *    @(#)This file is part of UNaXcess version 1.0.2.
  853. X *
  854. X *    Permission is hereby granted to copy and distribute this program
  855. X *    freely.  Permission is NOT given to modify this program or distribute
  856. X *    it at cost, except for charging a reasonable media/copying fee.
  857. X */
  858. X
  859. X#ifndef lint
  860. Xstatic char _FileID_[] = "@(#)mvmsg.c    1.1 (TDI) 2/3/87";
  861. Xstatic char _UAID_[]   = "@(#)UNaXcess version 1.0.2";
  862. X#endif lint
  863. X
  864. X#include <stdio.h>
  865. X#include <pwd.h>
  866. X#include <sys/types.h>
  867. X#include <sys/stat.h>
  868. X
  869. X#ifndef SYS3
  870. X#  ifdef XENIX3
  871. X#    define RIndex(s,c) strrchr(s, c)
  872. X#    define Index(s,c) strchr(s, c)
  873. Xextern char *strrchr(), *strchr();
  874. X#  else  XENIX3
  875. X#    ifdef XENIX5
  876. X#      define RIndex(s,c) strrchr(s, c)
  877. X#      define Index(s,c) strchr(s, c)
  878. Xextern char *strrchr(), *strchr();
  879. X#    else  XENIX5
  880. X#      define RIndex(s,c) rindex(s,c)
  881. X#      define Index(s,c) index(s,c)
  882. Xextern char *rindex(), *index();
  883. X#    endif XENIX5
  884. X#  endif XENIX3
  885. X#else
  886. X#  define RIndex(s,c) strrchr(s, c)
  887. X#  define Index(s,c) strchr(s, c)
  888. Xextern char *strrchr(), *strchr();
  889. X#endif
  890. X
  891. Xextern long atol();
  892. Xextern struct passwd *getpwuid();
  893. X
  894. Xmain(argc, argv)
  895. Xchar **argv; {
  896. X    char msgdir[256], conf[33];
  897. X    long msg;
  898. X    char *cp, *dp;
  899. X    int status;
  900. X
  901. X    if (argc != 3) {
  902. X        fprintf(stderr, "Usage: mvmsg conf[/n] conf\n");
  903. X        exit(1);
  904. X    }
  905. X    strcpy(msgdir, getpwuid(geteuid())->pw_dir);
  906. X    strcat(msgdir, "/msgdir");
  907. X    for (cp = argv[1], dp = conf; *cp != '/' && *cp != '\0'; cp++, dp++)
  908. X        *dp = *cp;
  909. X    *dp = '\0';
  910. X    if (*cp == '\0') {
  911. X        FILE *fp;
  912. X        char tmp[512];
  913. X        long limit, cnt;
  914. X        
  915. X        sprintf(tmp, "%s/%s/himsg", msgdir, conf);
  916. X        if ((fp = fopen(tmp, "r")) == (FILE *) 0) {
  917. X            fprintf(stderr, "Conference %s: missing himsg...\n", conf);
  918. X            exit(7);
  919. X        }
  920. X        fgets(tmp, sizeof tmp, fp);
  921. X        fclose(fp);
  922. X        if ((limit = atol(tmp)) <= 0) {
  923. X            fprintf(stderr, "Conference %s: invalid himsg...\n", conf);
  924. X            exit(8);
  925. X        }
  926. X        for (cnt = 0, msg = 1; msg <= limit; msg++)
  927. X            if ((status = mvmsg(msgdir, conf, msg, argv[2])) > 0)
  928. X                exit(status);
  929. X            else if (status == 0)
  930. X                cnt++;
  931. X        printf("%ld messages moved from %s to %s.\n", cnt, conf, argv[2]);
  932. X        sprintf(tmp, "%s/%s/himsg", msgdir, conf);
  933. X        if (unlink(tmp) != 0)
  934. X            exit(12);
  935. X        sprintf(tmp, "%s/%s", msgdir, conf);
  936. X        if (rmdir(tmp) != 0)
  937. X            exit(13);
  938. X        exit(cnt == 0? 9: 0);
  939. X    }
  940. X    msg = atol(++cp);
  941. X    if (Index(argv[2], '/') != (char *) 0) {
  942. X        fprintf(stderr, "Usage: mvmsg conf[/n] conf\n");
  943. X        exit(1);
  944. X    }
  945. X    if ((status = mvmsg(msgdir, conf, msg, argv[2])) == -1)
  946. X        fprintf(stderr, "Couldn't read %s/%ld\n", conf, msg);
  947. X    exit(status);
  948. X}
  949. X
  950. Xmvmsg(base, conf, msg, dest)
  951. Xchar *base, *conf, *dest;
  952. Xlong msg; {
  953. X    char path[512], temp[512];
  954. X    long newmsg;
  955. X    FILE *ifp, *ofp;
  956. X    struct stat sbuf;
  957. X    
  958. X    sprintf(path, "%s/%s/%ld", base, conf, msg);
  959. X    if (stat(path, &sbuf) < 0)
  960. X        return -1;    /* likely to be common... */
  961. X    sprintf(path, "%s/%s/himsg", base, dest);
  962. X    if ((ifp = fopen(path, "r")) == (FILE *) 0) {
  963. X        fprintf(stderr, "Conference %s: missing himsg...\n", dest);
  964. X        return 2;
  965. X    }
  966. X    fgets(temp, sizeof temp, ifp);
  967. X    fclose(ifp);
  968. X    if ((newmsg = atol(temp)) <= 0) {
  969. X        fprintf(stderr, "Conference %s: invalid himsg...\n", dest);
  970. X        return 2;
  971. X    }
  972. X    newmsg++;
  973. X    sprintf(path, "%s/%s/%ld", base, conf, msg);
  974. X    if ((ifp = fopen(path, "r")) == (FILE *) 0) {
  975. X        fprintf(stderr, "Conference %s: check permissions on message %ld\n", conf, msg);
  976. X        return 3;
  977. X    }
  978. X    sprintf(path, "%s/%s/%ld", base, dest, newmsg);
  979. X    if (stat(path, &sbuf) == 0) {
  980. X        fprintf(stderr, "Conference %s: corrupted (himsg incorrect)\n", dest);
  981. X        fclose(ifp);
  982. X        return 4;
  983. X    }
  984. X    if ((ofp = fopen(path, "w")) == (FILE *) 0) {
  985. X        fprintf(stderr, "Conference %s: check permissions (can't create message)\n", dest);
  986. X        fclose(ifp);
  987. X        return 5;
  988. X    }
  989. X    while (fgets(temp, sizeof temp, ifp) != (char *) 0) {
  990. X        fputs(temp, ofp);
  991. X        if (ferror(ofp)) {
  992. X            fprintf(stderr, "Write error on %s/%ld\n", dest, newmsg);
  993. X            exit(5);    /* fatal! */
  994. X        }
  995. X    }
  996. X    if (ferror(ifp)) {
  997. X        fprintf(stderr, "Read error on %s/%ld\n", conf, msg);
  998. X        fclose(ifp);
  999. X        fclose(ofp);
  1000. X        return 6;
  1001. X    }
  1002. X    fclose(ifp);
  1003. X    fclose(ofp);
  1004. X    sprintf(path, "%s/%s/himsg", base, dest);
  1005. X    if ((ifp = fopen(path, "w")) == (FILE *) 0) {
  1006. X        fprintf(stderr, "Conference %s: check permissions on himsg...\n", dest);
  1007. X        return 2;
  1008. X    }
  1009. X    fprintf(ifp, "%ld\n", newmsg);
  1010. X    fclose(ifp);
  1011. X    sprintf(path, "%s/%s/%ld", base, conf, msg);
  1012. X    if (unlink(path) < 0)
  1013. X        return 10;
  1014. X    return 0;
  1015. X}
  1016. X
  1017. X#ifndef BSD
  1018. X
  1019. X/* Berkeley has a rmdir() system call!  Heaven!  But I'm on sys3 (boo hiss) */
  1020. X
  1021. Xrmdir(path)
  1022. Xchar *path; {
  1023. X    int pid, status;
  1024. X    
  1025. X    switch (pid = fork()) {
  1026. X        case -1:
  1027. X            return -1;
  1028. X        case 0:
  1029. X            execl("/bin/rmdir", "rmdir", path, 0);
  1030. X            exit(-100);
  1031. X        default:
  1032. X            while (wait(&status) != pid)
  1033. X                ;
  1034. X            return status;
  1035. X    }
  1036. X}
  1037. X
  1038. X#endif BSD
  1039. ________This_Is_The_END________
  1040. echo 'x - system.c'
  1041. sed 's/^X//' << '________This_Is_The_END________' > system.c
  1042. X/*
  1043. X *    @(#)system.c    1.2 (TDI) 2/3/87
  1044. X *    @(#)Copyright (C) 1984, 85, 86, 87 by Brandon S. Allbery.
  1045. X *    @(#)This file is part of UNaXcess version 1.0.2.
  1046. X *
  1047. X *    Permission is hereby granted to copy and distribute this program
  1048. X *    freely.  Permission is NOT given to modify this program or distribute
  1049. X *    it at cost, except for charging a reasonable media/copying fee.
  1050. X */
  1051. X
  1052. X#ifndef lint
  1053. Xstatic char _FileID_[] = "@(#)system.c    1.2 (TDI) 2/3/87";
  1054. Xstatic char _UAID_[]   = "@(#)UNaXcess version 1.0.2";
  1055. X#endif lint
  1056. X
  1057. X#include "ua.h"
  1058. X
  1059. Xstruct sys parms = {
  1060. X#ifdef NOAUTOPATH
  1061. X    NOAUTOPATH,
  1062. X#else
  1063. X    "/usr/unaxcess",
  1064. X#endif NOAUTOPATH
  1065. X    1,
  1066. X    0,
  1067. X    "/bin/sh",
  1068. X    1,
  1069. X    "unaxcess",
  1070. X    30,
  1071. X    "sysop",
  1072. X    1,
  1073. X    0,
  1074. X    "",
  1075. X    "",
  1076. X    3,
  1077. X    "trap '' 2; stty -echo; echo 'Begin sending your file.  End with a CONTROL-D.'; cat - > %s; stty echo",
  1078. X    "trap '' 2; cat %s",
  1079. X    "umodem -rbld",
  1080. X    "umodem -sbld",
  1081. X    "kermit -iwr ;:",
  1082. X    "kermit -iws",
  1083. X    A_GUEST,
  1084. X};
  1085. X
  1086. X#define NUM        0
  1087. X#define STR        1
  1088. X#define BOOL        2
  1089. X
  1090. Xstruct rparm {
  1091. X    char *parmname;
  1092. X    char parmtype;
  1093. X    char *parmval;
  1094. X} sysparms[] = {
  1095. X    "bbs-directory",STR,    parms.ua_home,
  1096. X    "readonly",    BOOL,    &parms.ua_roc,
  1097. X    "restricted",    BOOL,    &parms.ua_xrc,
  1098. X    "shell",    STR,    parms.ua_shell,
  1099. X    "read-env",    BOOL,    &parms.ua_env,
  1100. X    "bbs-user",    STR,    parms.ua_bbs,
  1101. X    "time-limit",    NUM,    &parms.ua_tlimit,
  1102. X    "sysop",    STR,    parms.ua_sysop,
  1103. X     "private-msgs",    BOOL,    &parms.ua_pm,
  1104. X    "logging",    BOOL,    &parms.ua_log,
  1105. X    "banner",    STR,    parms.ua_bnr,
  1106. X    "login-msg",    STR,    parms.ua_login,
  1107. X    "login-tries",    NUM,    &parms.ua_nla,
  1108. X    "ascii-upload",    STR,    parms.ua_auc,
  1109. X    "ascii-download",STR,    parms.ua_adc,
  1110. X    "xmodem-upload",STR,    parms.ua_xuc,
  1111. X    "xmodem-download",STR,    parms.ua_xdc,
  1112. X    "kermit-upload",STR,    parms.ua_kuc,
  1113. X    "kermit-download",STR,    parms.ua_kdc,
  1114. X    "validation-level",NUM,    &parms.ua_vaxs,
  1115. X    0,        0,    0,
  1116. X};
  1117. X
  1118. Xstatic FILE *lfp;
  1119. Xstatic int __tlog = 0;
  1120. Xshort critical = 0;
  1121. Xshort quitc = 0;
  1122. Xshort intr = 0;
  1123. Xshort alrm = 0;
  1124. Xshort warned = 0;
  1125. X
  1126. Xlogon() {
  1127. X    struct stat sb;
  1128. X    char *cp;
  1129. X
  1130. X    if (!parms.ua_log || stat(LOG, &sb) < 0) {        /* no logfile => no logging */
  1131. X        lfp = NULL;
  1132. X        return;
  1133. X    }
  1134. X    if ((lfp = fopen(LOG, "a")) == NULL) {
  1135. X        io_off();
  1136. X        perror(LOG);
  1137. X        fprintf(stderr, "panic: log\n");
  1138. X        exit(2);
  1139. X    }
  1140. X}
  1141. X
  1142. Xlog(fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9)
  1143. Xchar *fmt, *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8, *a9; {
  1144. X    char buf[1024];
  1145. X    static char lockfile[] = "logfile.lock";
  1146. X
  1147. X    if (lfp == NULL)            /* logging not enabled */
  1148. X        return;
  1149. X    CRIT();
  1150. X    sprintf(buf, fmt, a1, a2, a3, a4, a5, a6, a7, a8, a9);
  1151. X    mklock(lockfile);
  1152. X    fprintf(lfp, "%s (%05d)  %s\n", date(), getpid(), visible(buf));
  1153. X    fflush(lfp);
  1154. X    rmlock(lockfile);
  1155. X    NOCRIT();
  1156. X}
  1157. X
  1158. Xlogsig(sig)
  1159. Xint sig; {
  1160. X    static int dbl = 0;    /* OOPS!  9 lines added 2/3/87 ++bsa */
  1161. X    
  1162. X    if (dbl++) {
  1163. X        fprintf(stderr, "\r\n\r\nDOUBLE PANIC: SIG %d\r\n\r\n", sig);
  1164. X        setuid(getuid());
  1165. X        chdir("/tmp");
  1166. X        signal(SIGIOT, SIG_DFL);
  1167. X        kill(getpid(), SIGIOT);
  1168. X    }
  1169. X    dolog();
  1170. X    log("Received signal %d.", sig);
  1171. X    fprintf(stderr, "\r\n\r\nUNaXcess internal error: %d.\r\n\r\n", sig);
  1172. X    unlink(RIndex(ttyname(fileno(stdin)), '/') + 1);
  1173. X    io_off();
  1174. X    signal(SIGIOT, SIG_DFL);
  1175. X    setuid(getuid());            /* OOPS!  2 lines added */
  1176. X    chdir(getpwuid(getuid())->pw_dir);    /*   2/3/87 ++bsa */
  1177. X    kill(getpid(), SIGIOT);
  1178. X}
  1179. X
  1180. Xpanic(s)
  1181. Xchar *s; {
  1182. X    static int dbl = 0;    /* OOPS!  9 lines added 2/3/87 ++bsa */
  1183. X
  1184. X    if (dbl++) {
  1185. X        fprintf(stderr, "\r\n\r\nDOUBLE PANIC: %s\r\n\r\n", s);
  1186. X        setuid(getuid());
  1187. X        chdir("/tmp");
  1188. X        signal(SIGIOT, SIG_DFL);
  1189. X        kill(getpid(), SIGIOT);
  1190. X    }
  1191. X    dolog();
  1192. X    log("panic: %s", s);
  1193. X    fprintf(stderr, "\r\n\r\nUNaXcess internal error: %s\r\n\r\n", s);
  1194. X    io_off();
  1195. X    unlink(RIndex(ttyname(2), '/') + 1);
  1196. X    setuid(getuid());
  1197. X    chdir(getpwuid(getuid())->pw_dir);
  1198. X    signal(SIGIOT, SIG_DFL);
  1199. X    kill(getpid(), SIGIOT);
  1200. X}
  1201. X
  1202. Xquit() {
  1203. X    char line[256];
  1204. X
  1205. X    if (critical) {
  1206. X        quitc++;
  1207. X        return;
  1208. X    }
  1209. X    writes("\n\nFast logout\n");
  1210. X    signal(SIGQUIT, quit);
  1211. X    log("Signalled QUIT.");
  1212. X    writef("\nDo you really want to leave UNaXcess? N\b");
  1213. X    line[0] = readc();
  1214. X    if (line[0] == 'Y') {
  1215. X        writef("OK");
  1216. X        if (user.u_name[0] != '\0')
  1217. X            writef(", %s", upstr(user.u_name));
  1218. X        writef(".  See you later!\n\n\n");
  1219. X        cleanup();
  1220. X    }
  1221. X}
  1222. X
  1223. Xintrp() {
  1224. X    if (critical) {
  1225. X        intr++;
  1226. X        return;
  1227. X    }
  1228. X    writes("\n\nAborted.");
  1229. X    log("Command aborted.");
  1230. X    signal(SIGINT, intrp);
  1231. X    longjmp(cmdloop, 1);
  1232. X}
  1233. X
  1234. Xchar *visible(s)
  1235. Xchar *s; {
  1236. X    static char vs[256];
  1237. X    char *sp, *vp;
  1238. X
  1239. X    vp = vs;
  1240. X    for (sp = s; *sp != '\0'; sp++)
  1241. X    if (!iscntrl(*sp))
  1242. X        *vp++ = *sp;
  1243. X    else {
  1244. X        *vp++ = '^';
  1245. X        *vp++ = uncntrl(*sp);
  1246. X    }
  1247. X    *vp = '\0';
  1248. X    return vs;
  1249. X}
  1250. X
  1251. Xshell() {
  1252. X    short sig;
  1253. X
  1254. X    if (user.u_access == A_GUEST || user.u_access == A_USER || parms.ua_shell[0] == '\0') {
  1255. X        writes("You don't have shell access privileges.");
  1256. X        log("Security violation:  Unauthorized SHELL");
  1257. X        return 1;
  1258. X    }
  1259. X    switch (fork()) {
  1260. X    case -1:
  1261. X        log("Error %d forking shell", errno);
  1262. X        writes("Sorry, the system's full.  Try again later.");
  1263. X        return 1;
  1264. X    case 0:
  1265. X        for (sig = SIGINT; sig <= SIGTERM; sig++)
  1266. X            signal(sig, SIG_DFL);
  1267. X        setuid(getuid());
  1268. X        chdir(getpwuid(getuid())->pw_dir);
  1269. X        run(parms.ua_shell, 0);
  1270. X        log("Error %d exec'ing %s", errno, parms.ua_shell);
  1271. X        writes("Couldn't run the shell.");
  1272. X        exit(1);
  1273. X    default:
  1274. X        CRIT();
  1275. X        io_off();
  1276. X        for (sig = SIGINT; sig <= SIGTERM; sig++)
  1277. X            signal(sig, SIG_IGN);
  1278. X        signal(SIGALRM, thatsall);    /* trapped by the CRIT() */
  1279. X        wait(NULL);
  1280. X        signal(SIGINT, intrp);
  1281. X        signal(SIGQUIT, quit);
  1282. X        for (sig = SIGIOT; sig < SIGTERM; sig++)
  1283. X            signal(sig, logsig);
  1284. X        signal(SIGALRM, thatsall);
  1285. X        io_on(0);
  1286. X        NOCRIT();
  1287. X    }
  1288. X    return 1;
  1289. X}
  1290. X
  1291. Xthatsall() {
  1292. X    if (critical) {
  1293. X        alrm++;
  1294. X        return;
  1295. X    }
  1296. X    if (warned) {
  1297. X        log("Timeout.");
  1298. X        writes("\nI'm sorry, but you're out of time.\n\n");
  1299. X        cleanup();
  1300. X    }
  1301. X    else {
  1302. X        log("5-minute warning.");
  1303. X        writes("\nYou have only five minutes left in this session.\n\n");
  1304. X        warned = 1;
  1305. X        alarm(5 * 60);
  1306. X    }
  1307. X}
  1308. X
  1309. Xmklock(lockfile)
  1310. Xchar *lockfile; {
  1311. X    char lockpath[50];
  1312. X    int lock_fd;
  1313. X    struct stat statbuf;
  1314. X    long now;
  1315. X    
  1316. X    strcpy(lockpath, "lock/");
  1317. X    strcat(lockpath, lockfile);
  1318. X    while (stat(lockpath, &statbuf) == 0) {
  1319. X        time(&now);
  1320. X        if (now - statbuf.st_mtime > 90) {    /* OOPS!  2/3/87 ++bsa */
  1321. X            unlink(lockpath);
  1322. X            break;
  1323. X        }
  1324. X        sleep(5);    /* OOPS!  1 line added 2/3/87 ++bsa */
  1325. X    }
  1326. X    if ((lock_fd = creat(lockpath, 0600)) < 0) {
  1327. X        fprintf(stderr, "Errno = %d creating lockfile %s\n", errno, lockpath);
  1328. X        /* OOPS!  1 line deleted 2/3/87 ++bsa */
  1329. X        panic(lockpath);
  1330. X    }
  1331. X    close(lock_fd);
  1332. X    sync();    /* insure disk files are updated! */
  1333. X}
  1334. X
  1335. Xrmlock(lockfile)
  1336. Xchar *lockfile; {
  1337. X    char lockpath[50];
  1338. X    struct stat statbuf;
  1339. X    
  1340. X    sync();
  1341. X    strcpy(lockpath, "lock/");
  1342. X    strcat(lockpath, lockfile);
  1343. X    if (stat(lockpath, &statbuf) < 0) {
  1344. X        log("Lockfile %s deleted???", lockpath);
  1345. X        writef("\n\nSomeone futzed with the lockfile.  Please tell %s IMMEDIATELY!!!\nSorry, but this means I have to log you out now.\n\n", parms.ua_sysop);
  1346. X        panic("LOCKFILE DELETED");
  1347. X    }
  1348. X    if (unlink(lockpath) < 0) {
  1349. X        log("Errno = %d, can't unlink lockfile %s", errno, lockpath);
  1350. X        writes("\nI've got a lockfile problem.  You won't be able to do some\nthings until it's fixed.  Sorry...\n");
  1351. X    }
  1352. X}
  1353. X
  1354. XCRIT() {
  1355. X    alrm = 0;
  1356. X    quitc = 0;
  1357. X    intr = 0;
  1358. X    if (critical)
  1359. X        return;    /* clears pending signals */
  1360. X    critical = 1;
  1361. X}
  1362. X
  1363. XNOCRIT() {
  1364. X    if (!critical)
  1365. X        return;
  1366. X    critical = 0;
  1367. X    if (alrm)
  1368. X        thatsall(14);
  1369. X    if (quitc)
  1370. X        quit(3);
  1371. X    if (intr)
  1372. X        intrp(2);
  1373. X    alrm = 0;
  1374. X    quitc = 0;
  1375. X    intr = 0;
  1376. X}
  1377. X
  1378. Xrun(cmd, arg)
  1379. Xchar *cmd, *arg; {
  1380. X    char cmdbuf[5120];
  1381. X    
  1382. X    sprintf(cmdbuf, "%s %s", cmd, (arg? arg: ""));
  1383. X    execl("/bin/sh", "sh", "-c", cmdbuf, 0);
  1384. X    return -1;
  1385. X}
  1386. X
  1387. Xcopylink(src, dest)
  1388. Xchar *src, *dest; {
  1389. X    int srcp, destp, cnt;
  1390. X    char buf[1024];
  1391. X    
  1392. X    if (link(src, dest) == 0) {
  1393. X        unlink(src);
  1394. X        return 0;
  1395. X    }
  1396. X    if ((srcp = open(src, 0)) < 0) {
  1397. X        perror(src);
  1398. X        return -1;
  1399. X    }
  1400. X    unlink(dest);
  1401. X    if ((destp = creat(dest, 0600)) < 0) {
  1402. X        perror(dest);
  1403. X        return -1;
  1404. X    }
  1405. X    while ((cnt = read(srcp, buf, sizeof buf)) > 0)
  1406. X        write(destp, buf, cnt);
  1407. X    close(destp);
  1408. X    close(srcp);
  1409. X    return 0;
  1410. X}
  1411. X
  1412. Xs_cmp(s1, s2)
  1413. Xchar *s1, *s2; {
  1414. X    for (; *s1 != '\0' && ToLower(*s1) == ToLower(*s2); s1++, s2++)
  1415. X        ;
  1416. X    return (!(*s1 == '\0' && *s2 == '\0'));
  1417. X}
  1418. X
  1419. Xchar *upstr(s)
  1420. Xchar *s; {
  1421. X    static char sbuf[512];
  1422. X    register char *cp, *dp;
  1423. X    
  1424. X    for (cp = s, dp = sbuf; *cp != '\0'; cp++, dp++)
  1425. X        *dp = ToUpper(*cp);
  1426. X    *dp = '\0';
  1427. X    return sbuf;
  1428. X}
  1429. X
  1430. Xismember(word, list)
  1431. Xchar *word, *list; {
  1432. X    char *cp;
  1433. X    char oldch;
  1434. X    
  1435. X    while (*list != '\0') {
  1436. X        while (*list == ' ' || *list == '\t')
  1437. X            list++;
  1438. X        for (cp = list; *cp != '\0' && *cp != ',' && *cp != ' ' && *cp != '\t'; cp++)
  1439. X            ;
  1440. X        oldch = '\0';
  1441. X        if (*cp != '\0') {
  1442. X            oldch = *cp;
  1443. X            *cp++ = '\0';
  1444. X        }
  1445. X        if (strcmp(word, list) == 0) {
  1446. X            *(cp - 1) = oldch;
  1447. X            return 1;
  1448. X        }
  1449. X        *(cp - 1) = oldch;
  1450. X        list = cp;
  1451. X    }
  1452. X    return 0;
  1453. X}
  1454. X
  1455. Xdolog() {
  1456. X    if (lfp != (FILE *) 0 || __tlog)
  1457. X        return;
  1458. X    logon();
  1459. X    __tlog = 1;
  1460. X}
  1461. X
  1462. Xnolog() {
  1463. X    if (!__tlog || lfp == (FILE *) 0)
  1464. X        return;
  1465. X    fclose(lfp);
  1466. X    __tlog = 0;
  1467. X}
  1468. X
  1469. Xalter() {
  1470. X    char line[256], uname[256];
  1471. X    char *p, *q, *okcmds;
  1472. X    struct user ubuf;
  1473. X    short crypted, not_FW;
  1474. X    char cmd;
  1475. X
  1476. X    if (user.u_access == A_MKUSER) {
  1477. X        log("An A_MKUSER got into alter()???");
  1478. X        panic("newalter");
  1479. X    }
  1480. X    if (user.u_access != A_WITNESS) {
  1481. X        not_FW = 1;
  1482. X        log("Alter by non-Witness; restricting control modes.");
  1483. X        strcpy(line, user.u_name);
  1484. X    }
  1485. X    else {
  1486. X        line[0] = '\0';
  1487. X        not_FW = 0;
  1488. X        writef("Examine which user: ");
  1489. X        reads(line);
  1490. X        log("User: %s", line);
  1491. X        if (line[0] == '\0')
  1492. X            return 1;
  1493. X        for (p = line; *p != '\0'; p++)
  1494. X            *p = ToLower(*p);
  1495. X        line[32] = '\0';
  1496. X    }
  1497. X    if (!getuser(line, &ubuf))
  1498. X        if (not_FW) {
  1499. X            log("Can't locate current user in the userfile.");
  1500. X            panic("user");
  1501. X        }
  1502. X        else {
  1503. X            writef("No such user.  Create him ? N\b");
  1504. X            strcpy(ubuf.u_name, line);
  1505. X            line[0] = readc();
  1506. X            log("New user? %c", line[0]);
  1507. X            if (line[0] != 'Y')
  1508. X                return 1;
  1509. X            ubuf.u_pass[0] = '\0';
  1510. X            ubuf.u_access = A_USER;
  1511. X            ubuf.u_llen = 80;
  1512. X            ubuf.u_nbull = 0;
  1513. X            strcpy(ubuf.u_lconf, "general");
  1514. X            ubuf.u_lines = 24;
  1515. X            crypted = 0;
  1516. X        }
  1517. X    else if (strlen(ubuf.u_pass) == 0)
  1518. X        crypted = 0;
  1519. X    else
  1520. X        crypted = 1;
  1521. X    strcpy(uname, ubuf.u_name);
  1522. X    for (;;) {
  1523. X        writec('\n');
  1524. X        writef("Name: %s\n", ubuf.u_name);
  1525. X        writef("Password: %s%s\n", ubuf.u_pass, (crypted? " (encrypted)": ""));
  1526. X        writef("Access level: %s\n", ua_acl(ubuf.u_access));
  1527. X        if (ubuf.u_access == A_MKUSER) {
  1528. X            writef("Default access level: %s\n", ua_acl(ubuf.u_llen));
  1529. X            okcmds = "NPADKQF";
  1530. X        }
  1531. X        else {
  1532. X            writef("UNIX(R) login name: %s\n", ubuf.u_login);
  1533. X            writef("Login conference: %s\n", ubuf.u_lconf);
  1534. X            writef("Line size: %d\n", ubuf.u_llen);
  1535. X            writef("Screen lines: %d\n", ubuf.u_lines);
  1536. X            if (ubuf.u_access == A_WITNESS && s_cmp(user.u_name, parms.ua_sysop) != 0 && s_cmp(user.u_name, uname) != 0)
  1537. X                okcmds = "Q";
  1538. X            else if (user.u_access < A_WITNESS)
  1539. X                okcmds = "PUCSLQF";
  1540. X            else if (s_cmp(user.u_name, uname) == 0)
  1541. X                okcmds = "NPUCSLQF";
  1542. X            else
  1543. X                okcmds = "NPAUCLSKQF";
  1544. X        }
  1545. X        writef("\nAlter command (");
  1546. X        for (p = okcmds; *p != '\0'; p++)
  1547. X            switch (*p) {
  1548. X            case 'N':
  1549. X                writef("Name, ");
  1550. X                break;
  1551. X            case 'P':
  1552. X                writef("Password, ");
  1553. X                break;
  1554. X            case 'A':
  1555. X                writef("Access, ");
  1556. X                break;
  1557. X            case 'U':
  1558. X                writef("UNIX(R) login, ");
  1559. X                break;
  1560. X            case 'C':
  1561. X                writef("Conference, ");
  1562. X                break;
  1563. X            case 'L':
  1564. X                writef("Lines, ");
  1565. X                break;
  1566. X            case 'S':
  1567. X                writef("Size, ");
  1568. X                break;
  1569. X            case 'D':
  1570. X                writef("Default access, ");
  1571. X                break;
  1572. X            case 'K':
  1573. X                writef("Kill, ");
  1574. X                break;
  1575. X            case 'Q':
  1576. X                writef("Quit, ");
  1577. X                break;
  1578. X            case 'F':
  1579. X                writef("Finished, ");
  1580. X                break;
  1581. X            default:
  1582. X                log("Invalid internal alter() command: '%c'", *p);
  1583. X                panic("altercmd");
  1584. X            }
  1585. X        writef("or ? for help): ");
  1586. X        cmd = readc();
  1587. X        log("Change: %c", cmd);
  1588. X        if (cmd != '?' && Index(okcmds, cmd) == (char *) 0)
  1589. X            cmd = ' ';
  1590. X        switch (cmd) {
  1591. X        case 'K':
  1592. X            writef("Kill user -- are you sure? N\b");
  1593. X            cmd = readc();
  1594. X            log("Kill user? %c", cmd);
  1595. X            if (cmd != 'Y')
  1596. X                break;
  1597. X            putuser(uname, (struct user *) 0);
  1598. X            writef("User %s killed.\n", upstr(uname));
  1599. X            return 1;
  1600. X        case 'N':
  1601. X            writef("Enter new name: ");
  1602. X            reads(line);
  1603. X            log("Name: %s", line);
  1604. X            if (line[0] == '\0')
  1605. X                break;
  1606. X            for (p = line; *p != '\0'; p++)
  1607. X                if (*p == ':') {
  1608. X                    log("Illegal colon in name.");
  1609. X                    writes("Can't put a colon in a user name.");
  1610. X                    break;
  1611. X                }
  1612. X            for (p = line, q = ubuf.u_name; *p != '\0'; p++, q++)
  1613. X                *q = ToLower(*p);
  1614. X            *q = '\0';
  1615. X            break;
  1616. X        case 'P':
  1617. X            strcpy(line, getpass("Enter new password: "));
  1618. X            if (line[0] == '\0')
  1619. X                break;
  1620. X            strcpy(ubuf.u_pass, line);
  1621. X            crypted = 0;        /* it's not encrypted now */
  1622. X            break;
  1623. X        case 'A':
  1624. X            writef("Access level: Deny access, Guest, Messages, Files, System, Witness, Newuser? ");
  1625. X            cmd = readc();
  1626. X            log("Access: %c", cmd);
  1627. X            if (cmd == 'A' && s_cmp(user.u_name, parms.ua_sysop) != 0) {
  1628. X                writes("Sorry, only the sysop can administer Witness privileges.");
  1629. X                log("Security violation: WITNESS administering WITNESS");
  1630. X                break;
  1631. X            }
  1632. X            switch (cmd) {
  1633. X            case 'G':
  1634. X                ubuf.u_access = A_GUEST;
  1635. X                break;
  1636. X            case 'D':
  1637. X                ubuf.u_access = A_NONE;
  1638. X                break;
  1639. X            case ' ':
  1640. X                break;
  1641. X            case 'M':
  1642. X                ubuf.u_access = A_USER;
  1643. X                break;
  1644. X            case 'S':
  1645. X                ubuf.u_access = A_SYSTEM;
  1646. X                break;
  1647. X            case 'W':
  1648. X                ubuf.u_access = A_WITNESS;
  1649. X                break;
  1650. X            case 'N':
  1651. X                ubuf.u_access = A_MKUSER;
  1652. X                break;
  1653. X            case 'F':
  1654. X                ubuf.u_access = A_FILES;
  1655. X                break;
  1656. X            default:
  1657. X                writes("What?  Valid commands are D, G, M, F, S, W, and N.  Access unchanged.");
  1658. X            }
  1659. X            break;
  1660. X        case 'C':
  1661. X            writef("Enter the default login conference: ");
  1662. X            reads(line);
  1663. X            log("Login conference: %s", line);
  1664. X            if (line[0] =='\0')
  1665. X                break;
  1666. X            if (!isconf(line))
  1667. X                writes("That conference doesn't exist.");
  1668. X            else if (uisunsub(ubuf.u_name, line))
  1669. X                writef("%s isn't subscribed to %s.\n", upstr(ubuf.u_name), line);
  1670. X            else if (!isrcmem(ubuf.u_name, line))
  1671. X                writef("%s isn't a member of that conference.\n", upstr(ubuf.u_name));
  1672. X            else
  1673. X                strcpy(ubuf.u_lconf, line);
  1674. X            break;
  1675. X        case 'S':
  1676. X            writef("Enter new line size, 32-132: ");
  1677. X            reads(line);
  1678. X            log("Line length: %s", line);
  1679. X            if (line[0] == '\0')
  1680. X                break;
  1681. X            ubuf.u_llen = atoi(line);
  1682. X            if (ubuf.u_llen < 32 || ubuf.u_llen > 132) {
  1683. X                ubuf.u_llen = 80;
  1684. X                writes("Garbage line size; using 80.");
  1685. X            }
  1686. X            break;
  1687. X        case 'U':
  1688. X            writef("UNIX(R) login name? ");
  1689. X            reads(line);
  1690. X            log("Login name: %s", line);
  1691. X            if (strlen(line) > 8) {
  1692. X                writes("That name is too long.");
  1693. X                break;
  1694. X            }
  1695. X            strcpy(ubuf.u_login, line);
  1696. X            break;
  1697. X        case 'D':
  1698. X            writef("Default Access: Deny access, Guest, Messages, Files, System? ");
  1699. X            cmd = readc();
  1700. X            log("Dft Access: %c", cmd);
  1701. X            switch (cmd) {
  1702. X            case 'G':
  1703. X                ubuf.u_llen = A_GUEST;
  1704. X                break;
  1705. X            case 'D':
  1706. X                ubuf.u_llen = A_NONE;
  1707. X                break;
  1708. X            case ' ':
  1709. X                break;
  1710. X            case 'M':
  1711. X                ubuf.u_llen = A_USER;
  1712. X                break;
  1713. X            case 'S':
  1714. X                ubuf.u_access = A_SYSTEM;
  1715. X                break;
  1716. X            case 'F':
  1717. X                ubuf.u_access = A_FILES;
  1718. X                break;
  1719. X            default:
  1720. X                writes("What?  Valid commands are D, G, M, F, or S.  Default access unchanged.");
  1721. X            }
  1722. X            break;
  1723. X        case 'Q':
  1724. X            if (okcmds[1] != '\0') {
  1725. X                writef("Abort user examine, are you sure? N\b");
  1726. X                cmd = readc();
  1727. X                log("Abort? %c", cmd);
  1728. X                if (cmd != 'Y')
  1729. X                    break;
  1730. X            }
  1731. X            return 1;
  1732. X        case 'F':
  1733. X            if (!crypted) {
  1734. X                writes("Encrypting password, please wait...");
  1735. X                strcpy(ubuf.u_pass, crypt(ubuf.u_pass, ubuf.u_pass) + 2);
  1736. X            }
  1737. X            putuser(uname, &ubuf);
  1738. X            if (s_cmp(uname, user.u_name) == 0)
  1739. X                user = ubuf;
  1740. X            return 1;
  1741. X        case 'L':
  1742. X            writef("Enter new lines/screen, 0-66: ");
  1743. X            reads(line);
  1744. X            log("Lines/screen: %s", line);
  1745. X            if (line[0] == '\0')
  1746. X                break;
  1747. X            ubuf.u_lines = atoi(line);
  1748. X            if (ubuf.u_lines < 0 || ubuf.u_lines > 66) {
  1749. X                ubuf.u_lines = 24;
  1750. X                writes("Garbage lines/screen; using 24.");
  1751. X            }
  1752. X            break;
  1753. X        case '?':
  1754. X            writef("\nThe commands are self-documenting.  If you don't see a command, it's because you can't perform that command on the current user.\n");
  1755. X            break;
  1756. X        default:
  1757. X            writef("What?  Please enter one of ");
  1758. X            for (p = okcmds; *p != '\0'; p++) {
  1759. X                writec(*p);
  1760. X                writec(',');
  1761. X                writec(' ');
  1762. X            }
  1763. X            writes("or ? for help.");
  1764. X        }
  1765. X    }
  1766. X}
  1767. X
  1768. Xgetparms() {
  1769. X     char home[512], line[512], var[20], sval[50];
  1770. X     FILE *cfp;
  1771. X     short cnt, pos, scnt, canon;
  1772. X     
  1773. X#ifdef NOAUTOPATH
  1774. X    strcpy(home, NOAUTOPATH);
  1775. X#else
  1776. X     strcpy(home, getpwuid(geteuid())->pw_dir);
  1777. X#endif NOAUTOPATH
  1778. X    strcpy(parms.ua_home, home);
  1779. X     strcpy(line, home);
  1780. X     strcat(line, "/");
  1781. X     strcat(line, CONFIG);
  1782. X     if ((cfp = fopen(line, "r")) == NULL) {
  1783. X         fprintf(stderr, "panic: param get, %s\n", line);
  1784. X         exit(1);
  1785. X     }
  1786. X     while (fgets(line, 512, cfp) != NULL) {
  1787. X         line[strlen(line) - 1] = '\0';
  1788. X         if (Index(line, '#') != NULL)
  1789. X             *(Index(line, '#')) = '\0';
  1790. X         scnt = 0;
  1791. X         pos = 0;
  1792. X         while (line[pos] != '\0' && line[pos] != ' ' && line[pos] != '\t')
  1793. X             var[scnt++] = line[pos++];
  1794. X         var[scnt] = '\0';
  1795. X         if (var[0] == '\0')
  1796. X             continue;
  1797. X         for (cnt = 0; sysparms[cnt].parmname != NULL; cnt++)
  1798. X             if (strcmp(sysparms[cnt].parmname, var) == 0)
  1799. X                 break;
  1800. X         if (sysparms[cnt].parmname == NULL) {
  1801. X             fprintf(stderr, "Please inform the sysop that there is an invalid parameter\n%s in the setup file.\n", var);
  1802. X             continue;
  1803. X         }
  1804. X        while (line[pos] == ' ' || line[pos] == '\t')
  1805. X            pos++;
  1806. X         switch (sysparms[cnt].parmtype) {
  1807. X             case NUM:
  1808. X                 *((char *) sysparms[cnt].parmval) = atoi(&line[pos]) & 0xff;
  1809. X                 break;
  1810. X             case BOOL:
  1811. X                 if (line[pos] == '\0' || ToLower(line[pos]) == 'y')
  1812. X                     *((char *) sysparms[cnt].parmval) = 1;
  1813. X                 else
  1814. X                     *((char *) sysparms[cnt].parmval) = 0;
  1815. X                 break;
  1816. X             case STR:
  1817. X                 canon = 0;
  1818. X                 if (line[pos] == '"') {
  1819. X                     canon = 1;
  1820. X                     pos++;
  1821. X                 }
  1822. X                 for (scnt = 0; (canon? line[pos] != '"': line[pos] != '\0' && line[pos] != ' ' && line[pos] != '\t'); pos++, scnt++) {    
  1823. X                     if (canon && line[pos] == '\\') {
  1824. X                         switch (line[++pos]) {    
  1825. X                             case 'n':
  1826. X                                 sval[scnt] = '\n';
  1827. X                                 break;
  1828. X                             case 't':
  1829. X                                 sval[scnt] = '\t';
  1830. X                                 break;
  1831. X                             case 'r':
  1832. X                                 sval[scnt] = '\r';
  1833. X                                 break;
  1834. X                             case 'b':
  1835. X                                 sval[scnt] = '\b';
  1836. X                                 break;
  1837. X                             case 'f':
  1838. X                                 sval[scnt] = '\f';
  1839. X                                 break;
  1840. X                             case 'e':
  1841. X                             case 'E':
  1842. X                                 sval[scnt] = '\033';
  1843. X                                 break;
  1844. X                             case 'a':
  1845. X                                 sval[scnt] = '\7';    /* proposed extension of C string metasyntax */
  1846. X                                 break;
  1847. X                             case '0':
  1848. X                             case '1':
  1849. X                             case '2':
  1850. X                             case '3':
  1851. X                             case '4':
  1852. X                             case '5':
  1853. X                             case '6':
  1854. X                             case '7':
  1855. X                                 sval[scnt] = 0;
  1856. X                                 while (Index("01234567", line[pos]) != NULL)
  1857. X                                     sval[scnt] = sval[scnt] * 8 + (line[pos++] - '0');
  1858. X                                pos--;
  1859. X                                break;
  1860. X                            default:
  1861. X                                sval[scnt] = line[pos];
  1862. X                         }
  1863. X                     }
  1864. X                     else
  1865. X                         sval[scnt] = line[pos];
  1866. X                 }
  1867. X                 sval[scnt] = '\0';
  1868. X                 strcpy(sysparms[cnt].parmval, sval);
  1869. X         }
  1870. X     }
  1871. X}
  1872. ________This_Is_The_END________
  1873. echo 'x - system.h'
  1874. sed 's/^X//' << '________This_Is_The_END________' > system.h
  1875. X/*
  1876. X *    @(#)system.h    1.1 (TDI) 2/3/87
  1877. X *    @(#)Copyright (C) 1984, 85, 86, 87 by Brandon S. Allbery.
  1878. X *    @(#)This file is part of UNaXcess version 1.0.2.
  1879. X *
  1880. X *    Permission is hereby granted to copy and distribute this program
  1881. X *    freely.  Permission is NOT given to modify this program or distribute
  1882. X *    it at cost, except for charging a reasonable media/copying fee.
  1883. X */
  1884. X
  1885. Xstruct sys {
  1886. X    char ua_home[50];    /* UNaXcess lives here */
  1887. X    char ua_roc;    /* read-only conference flag */
  1888. X    char ua_xrc;    /* x-rated conference flag */
  1889. X    char ua_shell[50];    /* the default shell */
  1890. X    char ua_env;    /* read environment for SHELL, EDITOR */
  1891. X    char ua_bbs[32];    /* name of BBS login */
  1892. X    char ua_tlimit;    /* minutes until logout */
  1893. X    char ua_sysop[32];    /* name of the sysop login */
  1894. X    char ua_pm;    /* allow private messages? */
  1895. X    char ua_log;    /* keep a log? */
  1896. X    char ua_bnr[50];    /* path of banner file, EOS = internal */
  1897. X    char ua_login[256];    /* login message, EOS = internal */
  1898. X    char ua_nla;    /* number of attempts to login allowed */
  1899. X    char ua_auc[256];    /* ascii upload command */
  1900. X    char ua_adc[256];    /* ascii download command */
  1901. X    char ua_xuc[256];    /* Xmodem upload command */
  1902. X    char ua_xdc[256];    /* Xmodem download command */
  1903. X    char ua_kuc[256];    /* Kermit upload command */
  1904. X    char ua_kdc[256];    /* Kermit download command */
  1905. X    char ua_vaxs;        /* validation access level */
  1906. X};
  1907. X
  1908. Xextern struct sys parms;
  1909. ________This_Is_The_END________
  1910. echo 'x - ua.c'
  1911. sed 's/^X//' << '________This_Is_The_END________' > ua.c
  1912. X/*
  1913. X *    @(#)ua.c    1.2 (TDI) 2/3/87
  1914. X *    @(#)Copyright (C) 1984, 85, 86, 87 by Brandon S. Allbery.
  1915. X *    @(#)This file is part of UNaXcess version 1.0.2.
  1916. X *
  1917. X *    Permission is hereby granted to copy and distribute this program
  1918. X *    freely.  Permission is NOT given to modify this program or distribute
  1919. X *    it at cost, except for charging a reasonable media/copying fee.
  1920. X */
  1921. X
  1922. X#ifndef lint
  1923. Xstatic char _FileID_[] = "@(#)ua.c    1.2 (TDI) 2/3/87";
  1924. Xstatic char _UAID_[]   = "@(#)UNaXcess version 1.0.2";
  1925. X#endif lint
  1926. X
  1927. X#include "ua.h"
  1928. X
  1929. X/* forward references for command executives */
  1930. X
  1931. Xextern int
  1932. X    readmsg(),    readnew(),    confidx(),    enter(),
  1933. X    join(),        killmsg(),    scanmsg(),    msgmenu(),
  1934. X    logout(),    bulletin(),    shell(),    edrest(),
  1935. X    alter(),    userlist(),    qscan(),    udl(),
  1936. X    unsub(),    setlconf(),    readmenu(),    mkbull(),
  1937. X    adminmenu(),    validate();
  1938. X
  1939. Xstruct cmd maincmd[] = {
  1940. X    'a', "Administration menu",        adminmenu,
  1941. X    'b', "Reprint login bulletins",        bulletin,
  1942. X    'c', "Shell command access",        shell,
  1943. X    'd', "Set default login conference",    setlconf,
  1944. X    'f', "File area (Downloading)",        udl,
  1945. X    'g', "Exit UNaXcess",            logout,
  1946. X    'm', "UNaXcess Message Base",        msgmenu,
  1947. X    'w', "List of UNaXcess users",        userlist,
  1948. X    '\0',"help/mainmenu",            NULL
  1949. X};
  1950. X
  1951. Xstruct cmd admincmd[] = {
  1952. X    'a', "Alter or examine a user",        alter,
  1953. X    'b', "Enter a bulletin",        mkbull,
  1954. X    'c', "Shell command access",        shell,
  1955. X    'e', "Edit conference membership",    edrest,
  1956. X    'g', "Exit UNaXcess",            logout,
  1957. X    'v', "Validate new users",        validate,
  1958. X    'w', "List of UNaXcess users",        userlist,
  1959. X    'x', "Return to the Main Menu",        (int (*)()) 0,
  1960. X    '\0',"help/adminmenu",            NULL
  1961. X};
  1962. X
  1963. Xstruct cmd msgcmd[] = {
  1964. X    'd', "Set default login conference",    setlconf,
  1965. X    'e', "Enter a message",            enter,
  1966. X    'g', "Exit UNaXcess",            logout,
  1967. X    'i', "Index of conferences",        confidx,
  1968. X    'j', "Join a new conference",        join,
  1969. X    'k', "Kill a message",            killmsg,
  1970. X    'n', "Read all new messages",        readnew,
  1971. X    'r', "Read commands menu",        readmenu,
  1972. X    'u', "Unsubscribe from a conference",    unsub,
  1973. X    'x', "Return to the Main Menu",        (int (*)()) 0,
  1974. X    '\0',"help/msgbase",            NULL
  1975. X};
  1976. X
  1977. Xstruct cmd readcmd[] = {
  1978. X    'g', "Exit UNaXcess",            logout,
  1979. X    'n', "Read all new messages",        readnew,
  1980. X    'q', "Quick scan of messages",        qscan,
  1981. X    'r', "Read messages in a conference",    readmsg,
  1982. X    's', "Scan messages",            scanmsg,
  1983. X    'x', "Return to the Message Base Menu",    (int (*)()) 0,
  1984. X    '\0',"help/readcmds",            NULL
  1985. X};
  1986. X
  1987. Xjmp_buf cmdloop;
  1988. Xint __recurse;
  1989. X
  1990. Xmain(argc, argv)
  1991. Xchar **argv; {
  1992. X    char line[256], *lp;
  1993. X    short lcnt;
  1994. X    FILE *tp;
  1995. X
  1996. X    getparms();
  1997. X    chdir(parms.ua_home);
  1998. X    if (parms.ua_env && (lp = getenv("SHELL")) != NULL)
  1999. X        strcpy(parms.ua_shell, lp);
  2000. X    __recurse = 0;
  2001. X    logon();
  2002. X    io_on(1);
  2003. X    signal(SIGINT, SIG_IGN);
  2004. X    signal(SIGQUIT, quit);
  2005. X    for (lcnt = SIGILL; lcnt <= SIGTERM; lcnt++)    /* we don't muck with others */
  2006. X        signal(lcnt, logsig);
  2007. X    signal(SIGALRM, thatsall);
  2008. X    /* OOPS!  1 lines deleted, 2 lines changed 2/3/87 ++bsa */
  2009. X    writes("\nWelcome to UNaXcess Conferencing, Version 1.00.02\nCopyright (C) 1984, 1985, 1986 by Brandon S. Allbery");
  2010. X    if (parms.ua_bnr[0] != 0)
  2011. X        cat(parms.ua_bnr);
  2012. X    if (argc > 2) {
  2013. X        writes("To run UNaXcess from the shell, type `ua' or `ua username'.\nIf username has spaces or shell metacharacters in it, quote it.\n");
  2014. X        log("Invoked with %d arguments.  Goodbye.", argc);
  2015. X        exit(1);
  2016. X    }
  2017. X    else
  2018. X        argc--;
  2019. X    if (ismember(getlogin(), parms.ua_bbs)) {
  2020. X
  2021. Xnouser:
  2022. X        for (lcnt = 0;; lcnt++) {
  2023. X             if (argc) {
  2024. X                strcpy(line, argv[1]);
  2025. X                argc--;
  2026. X                writec('\n');
  2027. X             }
  2028. X            else {
  2029. X                if (parms.ua_login[0] == 0)
  2030. X                    writef("\nEnter your user name, GUEST, OFF, or NEW: ");
  2031. X                else
  2032. X                    writef("%s", parms.ua_login);
  2033. X                reads(line);
  2034. X            }
  2035. X            log("Login: %s", line);
  2036. X            if (line[0] == '\0') {
  2037. X                lcnt--;
  2038. X                continue;
  2039. X            }
  2040. X            for (lp = line; *lp != '\0'; lp++)
  2041. X                *lp = ToLower(*lp);
  2042. X            if (strcmp(line, "off") == 0) {
  2043. X                writes("Goodbye...\n\n");
  2044. X                log("Logout.");
  2045. X                exit(0);
  2046. X            }
  2047. X            if (!getuser(line, &user)) {
  2048. X                writef("No such user.\n");
  2049. X                log("No such user.");
  2050. X            }
  2051. X            else if (user.u_pass[0] != '\0') {
  2052. X                xecho();
  2053. X                writef("Enter your password: ");
  2054. X                reads(line);
  2055. X                doecho();
  2056. X                log("Password: %s", line);
  2057. X                writes("\nChecking password...");
  2058. X                if (strcmp(crypt(line, line) + 2, user.u_pass) == 0)
  2059. X                    break;
  2060. X            }
  2061. X            else
  2062. X                break;
  2063. X        }
  2064. X        if (parms.ua_nla > 0 && lcnt == parms.ua_nla) {
  2065. X            writes("\nSorry, you blew it.");
  2066. X            log("Program aborted.");
  2067. X            exit(1);
  2068. X        }
  2069. X    }
  2070. X    else if (!getuser(getlogin(), &user))
  2071. X        goto nouser;
  2072. X    if (s_cmp(user.u_name, parms.ua_sysop) != 0)
  2073. X        alarm(parms.ua_tlimit * 60);        /* time limit */
  2074. X    log("%s, access = %d, sys = %s, line = %d", user.u_name, user.u_access, user.u_login, user.u_llen);
  2075. X    if (user.u_access == A_NONE) {
  2076. X        writes("Your access privileges have been revoked.  Goodbye...\n\n");
  2077. X        log("Security violation:  access revoked.");
  2078. X        exit(1);
  2079. X    }
  2080. X    if ((tp = fopen(RIndex(ttyname(fileno(stdin)), '/') + 1, "w")) == NULL) {
  2081. X        log("Error %d opening %s", errno, RIndex(ttyname(fileno(stdin)), '/') + 1);
  2082. X        log("Non-interactive session not logged to terminal.");
  2083. X    }
  2084. X    else {
  2085. X        fprintf(tp, "%s on as \"%s\" on %s\n", getlogin(), user.u_name, longdate());
  2086. X        fclose(tp);
  2087. X    }
  2088. X    writec('\n');
  2089. X    if (user.u_access != A_MKUSER)
  2090. X        bulletin();
  2091. X    if (user.u_lconf[0] != '\0')
  2092. X        if (isconf(user.u_lconf))
  2093. X            if (isrcmem(user.u_name, user.u_lconf))
  2094. X                strcpy(conference, user.u_lconf);
  2095. X            else {
  2096. X                writef("\nYour login conference, \"%s\",  has been restricted and you are not a member.  I'm moving you back to \"general\".\n", user.u_lconf);
  2097. X                strcpy(user.u_lconf, "general");
  2098. X                strcpy(conference, "general");
  2099. X            }
  2100. X        else {
  2101. X            writef("\n%s deleted \"%s\", your login conference.  I'm setting you back to the \"general\" conference.\n", upstr(parms.ua_sysop), user.u_lconf);
  2102. X            strcpy(user.u_lconf, "general");
  2103. X            strcpy(conference, "general");
  2104. X        }
  2105. X    else
  2106. X        strcpy(conference, "general");
  2107. X    if (user.u_access != A_GUEST && user.u_access != A_MKUSER) {
  2108. X        hicnts = readhigh(&user);
  2109. X        cleanhigh();    /* kill any lingering corpses */
  2110. X    }
  2111. X    if (!setjmp(cmdloop))
  2112. X        signal(SIGINT, intrp);
  2113. X    if (user.u_access == A_MKUSER) {
  2114. X        newuser();
  2115. X        if (user.u_access == A_NONE) {
  2116. X            writes("\nYou'll have to be validated before you can use UNaXcess.");
  2117. X            return 0;
  2118. X        }
  2119. X    }
  2120. X    pcmd("Command (? for help): ", maincmd, (char *) 0);
  2121. X    writef("Goodbye");
  2122. X    if (user.u_name[0] != '\0')
  2123. X        writef(", %s", upstr(user.u_name));
  2124. X    writef(".  Call again soon!\n\n\n");
  2125. X    log("Logout.");
  2126. X    cleanup();
  2127. X}
  2128. X
  2129. Xcleanup() {
  2130. X    char tmps[256];
  2131. X    FILE *fp;
  2132. X
  2133. X    sprintf(tmps, "%s/himotd", MOTD);
  2134. X    if ((fp = fopen(tmps, "r")) == NULL) {
  2135. X        log("Error %d opening %s", errno, tmps);
  2136. X        panic("himotd");
  2137. X    }
  2138. X    fgets(tmps, 32, fp);
  2139. X    fclose(fp);
  2140. X    user.u_nbull = atoi(tmps);
  2141. X    putuser(user.u_name, &user);
  2142. X    unlink(RIndex(ttyname(fileno(stdin)), '/') + 1);
  2143. X    io_off();
  2144. X    exit(0);
  2145. X}
  2146. X
  2147. Xlogout() {
  2148. X    char line[256];
  2149. X
  2150. X    if (__recurse > 0) {
  2151. X        __recurse--;
  2152. X        return 0;
  2153. X    }
  2154. X    writef("Are you sure you want to log out? N\b");
  2155. X    line[0] = readc();
  2156. X    log("Logout? %c", line[0]);
  2157. X    if (line[0] != 'Y')
  2158. X        return 1;
  2159. X    writef("Goodbye");
  2160. X    if (user.u_name[0] != '\0')
  2161. X        writef(", %s", upstr(user.u_name));
  2162. X    writef(".  Call again soon!\n\n\n");
  2163. X    log("Logout.");
  2164. X    cleanup();
  2165. X}
  2166. X
  2167. Xmsgmenu() {
  2168. X    pcmd("Message Base Command (? for help, X to exit): ", msgcmd, "Message Base");
  2169. X    return 1;
  2170. X}
  2171. X
  2172. Xreadmenu() {
  2173. X    pcmd("Read Command (? for help, X to exit): ", readcmd, "Read Commands");
  2174. X    return 1;
  2175. X}
  2176. X
  2177. Xadminmenu() {
  2178. X    pcmd("Admin Command (? for help, X to exit): ", admincmd, "Administration");
  2179. X    return 1;
  2180. X}
  2181. X
  2182. Xpcmd(prompt, cmdtab, previous)
  2183. Xchar *prompt, *previous;
  2184. Xstruct cmd cmdtab[]; {
  2185. X    char ch;
  2186. X    struct cmd *cmd;
  2187. X    short fullhelp;
  2188. X    unsigned int tleft;
  2189. X    
  2190. X    fullhelp = 0;
  2191. X    for (;;) {
  2192. X        if ((tleft = alarm((unsigned int) 0)) != 0) {
  2193. X            alarm(tleft);
  2194. X            writef("%d:%02d ", tleft / 60, tleft % 60);
  2195. X        }
  2196. X        writef("[%s] %s", conference, prompt);
  2197. X        ch = readc();
  2198. X        if (ch == '?') {
  2199. X            if (fullhelp) {
  2200. X                for (cmd = cmdtab; cmd->c_cmd != '\0'; cmd++)
  2201. X                    ;
  2202. X                writec('\n');
  2203. X                cat(cmd->c_desc);
  2204. X                writec('\n');
  2205. X                continue;
  2206. X            }
  2207. X            writef("\n%s Commands\n\n", (previous == (char *) 0? "Main": previous));
  2208. X            for (cmd = cmdtab; cmd->c_cmd != '\0'; cmd++)
  2209. X                writef("  %c - %s\n", ToUpper(cmd->c_cmd), cmd->c_desc);
  2210. X            fullhelp = 1;
  2211. X            writes("\nType ? for the full help file.\n");
  2212. X            continue;
  2213. X        }
  2214. X        for (cmd = cmdtab; cmd->c_cmd != '\0'; cmd++)
  2215. X            if (ToUpper(cmd->c_cmd) == ch)
  2216. X                break;
  2217. X        if (cmd->c_cmd == '\0') {
  2218. X            writes("Unrecognized command.  Type ? for help.");
  2219. X            continue;
  2220. X        }
  2221. X        if (cmd->c_func == (int (*)()) 0)
  2222. X            break;
  2223. X        if ((*cmd->c_func)() == 0)
  2224. X            break;
  2225. X        fullhelp = 0;
  2226. X    }
  2227. X}
  2228. ________This_Is_The_END________
  2229. echo 'x - ua.h'
  2230. sed 's/^X//' << '________This_Is_The_END________' > ua.h
  2231. X/*
  2232. X *    @(#)ua.h    1.1 (TDI) 2/3/87
  2233. X *    @(#)Copyright (C) 1984, 85, 86, 87 by Brandon S. Allbery.
  2234. X *    @(#)This file is part of UNaXcess version 1.0.2.
  2235. X *
  2236. X *    Permission is hereby granted to copy and distribute this program
  2237. X *    freely.  Permission is NOT given to modify this program or distribute
  2238. X *    it at cost, except for charging a reasonable media/copying fee.
  2239. X */
  2240. X
  2241. X#include <stdio.h>
  2242. X#include <ctype.h>
  2243. X#include <setjmp.h>
  2244. X#include <pwd.h>
  2245. X#include <signal.h>
  2246. X#include <sys/types.h>
  2247. X#include <sys/stat.h>
  2248. X#include <errno.h>
  2249. X#include "user.h"
  2250. X#include "dir.h"
  2251. X#include "system.h"
  2252. X#ifdef BSD
  2253. X#include <sys/time.h>
  2254. X#else
  2255. X#include <time.h>
  2256. X#endif
  2257. X
  2258. X#define SYSOP    parms.ua_sysop
  2259. X#define LOG    "Logfile"
  2260. X#define MOTD    "motd"
  2261. X#define PASSWD    "userfile"
  2262. X#define MSGBASE    "msgdir"
  2263. X#define NEWMSGS    "userind"
  2264. X#define NEWUSER    "NewMessage"
  2265. X#define CONFIG    "ua-config"
  2266. X#define MEMLIST    "members"
  2267. X
  2268. Xextern jmp_buf cmdloop;            /* so intrp() works */
  2269. Xextern int logsig(), quit(), intrp(), thatsall();
  2270. Xextern int doread(), doscan();
  2271. Xextern struct _himsg *readhigh();
  2272. Xextern struct tm *localtime();
  2273. Xextern struct passwd *getpwuid();
  2274. Xextern char *getowner(), *visible(), *mktemp(), *crypt(), *date(), *longdate(), *getenv(), *reads(), *fgets(), *today(), *calloc(), *ua_acl(), *upstr();
  2275. Xextern int errno, __recurse;
  2276. Xextern char conference[];
  2277. X
  2278. X#define ToLower(x) (isupper(x)?tolower(x):x)    /* not all tolower() work */
  2279. X#define ToUpper(x) (islower(x)?toupper(x):x)    /* not all toupper() work */
  2280. X#define uncntrl(x) (x+'@')    /* beware of non-ASCII character sets! */
  2281. X
  2282. X#ifdef SYS5
  2283. X#  define SYS3
  2284. X#endif SYS5
  2285. X
  2286. X#ifndef SYS3
  2287. X#  ifdef XENIX3
  2288. X#    define RIndex(s,c) strrchr(s, c)
  2289. X#    define Index(s,c) strchr(s, c)
  2290. Xextern char *strrchr(), *strchr();
  2291. X#  else  XENIX3
  2292. X#    ifdef XENIX5
  2293. X#      define RIndex(s,c) strrchr(s, c)
  2294. X#      define Index(s,c) strchr(s, c)
  2295. Xextern char *strrchr(), *strchr();
  2296. X#    else  XENIX5
  2297. X#      define RIndex(s,c) rindex(s,c)
  2298. X#      define Index(s,c) index(s,c)
  2299. Xextern char *rindex(), *index();
  2300. X#    endif XENIX5
  2301. X#  endif XENIX3
  2302. X#else
  2303. X#  define RIndex(s,c) strrchr(s, c)
  2304. X#  define Index(s,c) strchr(s, c)
  2305. Xextern char *strrchr(), *strchr();
  2306. X#endif
  2307. X
  2308. X#ifdef BSD
  2309. X#  define CONFSIZE    32
  2310. X#else
  2311. X#  define CONFSIZE    14
  2312. X#endif BSD
  2313. X
  2314. X#ifdef XENIX3
  2315. X#  define XENIX
  2316. X#  define SYS3
  2317. X#else  XENIX3
  2318. X#  ifdef XENIX5
  2319. X#    define XENIX
  2320. X#    define SYS3
  2321. X#    define SYS5    /* these only make a difference in uwho.c */
  2322. X#  endif XENIX5
  2323. X#endif XENIX3
  2324. X
  2325. Xstruct cmd {
  2326. X    char c_cmd;    /* command name */
  2327. X    char *c_desc;    /* short help message */
  2328. X    int (*c_func)();    /* function to run, passed rest of line */
  2329. X};
  2330. ________This_Is_The_END________
  2331. echo 'x - udate.c'
  2332. sed 's/^X//' << '________This_Is_The_END________' > udate.c
  2333. X/*
  2334. X *    @(#)udate.c    1.1 (TDI) 2/3/87
  2335. X *
  2336. X *    Permission is hereby granted to copy and distribute this program
  2337. X *    freely.  Permission is NOT given to modify this program or distribute
  2338. X *    it at cost, except for charging a reasonable media/copying fee.
  2339. X */
  2340. X
  2341. X#ifndef lint
  2342. Xstatic char _FileID_[] = "@(#)udate.c    1.1 (TDI) 2/3/87";
  2343. Xstatic char _UAID_[]   = "@(#)UNaXcess version 1.0.2";
  2344. X#endif lint
  2345. X
  2346. Xmain() {
  2347. X    puts(longdate());
  2348. X}
  2349. ________This_Is_The_END________
  2350. exit 0
  2351. --
  2352. ++Brandon (Resident Elf @ ncoast.UUCP)
  2353.  ____   ______________
  2354. /    \ / __   __   __ \   Brandon S. Allbery        <backbone>!ncoast!allbery
  2355.  ___  | /__> /  \ /  \    aXcess Co., Consulting    ncoast!allbery@Case.CSNET
  2356. /   \ | |    `--, `--,    6615 Center St. #A1-105        (...@relay.CS.NET)
  2357. |     | \__/ \__/ \__/    Mentor, OH 44060-4101     
  2358. \____/ \______________/   +1 216 781 6201
  2359.  
  2360.  
  2361.