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

  1. Subject:  v08i037:  UNaXcess Conferencing, version 1.00.02, Part01/04
  2. Newsgroups: mod.sources
  3. Approved: mirror!rs
  4.  
  5. Submitted by: abic!cwruecmp!allbery%ncoast.UUCP
  6. Mod.sources: Volume 8, Issue 37
  7. Archive-name: unaxcess2/Part01
  8.  
  9. [  Like with UUMAIL, I got this new release before I would have published
  10.    the old release.  --r$  ]
  11.  
  12. #--------------------------------CUT HERE-------------------------------------
  13. #! /bin/sh
  14. #
  15. # This is a shell archive.  Save this into a file, edit it
  16. # and delete all lines above this comment.  Then give this
  17. # file to sh by executing the command "sh file".  The files
  18. # will be extracted into the current directory owned by
  19. # you with default permissions.
  20. #
  21. # The files contained herein are:
  22. #
  23. # -rw-r--r--   1 allbery  System      4044 Feb  3 21:44 README
  24. # -rw-rw-rw-   1 allbery  System      3428 Feb  3 21:49 bulletin.c
  25. # -rw-rw-rw-   1 allbery  System     19341 Feb  3 21:07 conference.c
  26. # -rw-rw-rw-   1 allbery  System      1837 Feb  3 21:08 date.c
  27. # -rw-rw-rw-   1 allbery  System      2649 Nov 22 19:50 dir.c
  28. # -rw-rw-rw-   1 allbery  System      3164 Nov 22 19:50 dir.h
  29. # -rw-rw-rw-   1 allbery  System     13499 Feb  3 21:08 fileudl.c
  30. # -rw-r--r--   1 allbery  System     13080 Feb  3 21:09 io.c
  31. #
  32. echo 'x - README'
  33. sed 's/^X//' << '________This_Is_The_END________' > README
  34. X[The README files for 1.00.01 and 1.00.00 are included below.]
  35. X
  36. XThis is the UNaXcess Conferencing 1.00.02 distribution.  It provides bug
  37. Xfixes to the 1.00.01 distribution.
  38. X
  39. XThe installation instructions have not changed; see the included README files
  40. Xbelow.
  41. X
  42. XThere were six primary fixes:
  43. X
  44. X(1) Private messages were still broken.  Code was added in conference.c to
  45. X    fix this.
  46. X
  47. X(2) Conference membership had a bug; while I had known about it, I had thought
  48. X    it was an I/O bug.  Code was changed in conference.c to fix this.
  49. X
  50. X(3) Panics were not dumping core as they should have.  Code was added to
  51. X    system.c to correct this; also, a "double-panic" quick exit was provided
  52. X    to forestall infinite loops.
  53. X
  54. X(4) The format of the "directory" file was incorrect in install.sh and in
  55. X    admin.man.  Fixed, albeit via what can only be termed a hack in install.
  56. X    At least UA-Conf doesnt' do anything other than print dates.
  57. X
  58. X(5) The terminal handling code in io.c had some casts that were mangled by
  59. X    Ultrix cc (VAX 8600 and MicroVAX II); this resulted in a warning from
  60. X    the Ultrix assembler, and caused UA-Conf to go into convulsions on start-
  61. X    up.  The casts were removed; I hope DEC fixes its compiler soon.
  62. X
  63. X(6) Yet another locking fix.  If you still get "UNaXcess internal error:
  64. X    LOCKFILE DELETED" messages, let me know; I haven't had a lock work in
  65. X    this thing since I used Xenix semaphores back in V0.3.3.
  66. X
  67. X-------------------------------------------------------------------------------
  68. X
  69. X[The README file for 1.00.00 is included below.]
  70. X
  71. XThis is the UNaXcess 1.00.01 distribution.  It provides bug fixes and enhance-
  72. Xments to the 1.00.00 distribution; however, enough was changed that a new
  73. Xdistribution was a good idea.
  74. X
  75. XRead the various manuals and the Makefile, as well as the 1.00.00 README
  76. Xbelow, for information on installing this program.
  77. X
  78. XNOTE!!!  If you already have UNaXcess 1.00.00 or 0.4.x, you must run the
  79. Xscript reinstall.sh after you run install.sh, in order to upgrade your
  80. Xua-config and userfile to the new version.  To run it, become the owner of
  81. Xthe BBS system and issue the command "sh reinstall.sh /path/to/BBS".  It will
  82. Xfigure out whether you are using an alternate BBS directory.
  83. X
  84. XEnjoy.  ++Brandon
  85. X
  86. XP.S.  There is now a mailing list for UNaXcess; if you wish to subscribe, send
  87. Xmail to "cbatt!cwruecmp!ncoast!unaxcess-request" or to
  88. X"ncoast!unaxcess-request%Case.CSNET@relay.CS.NET", as your system (UUCP or
  89. XInternet) requires.  Submissions may be sent to the user "unaxcess" at the
  90. Xabove-named site.
  91. X
  92. X===============================================================================
  93. X
  94. XThis is the UNaXcess 1.00.00 distribution.  It is not in its "final" form yet;
  95. XI have to rewrite the UDL module, and I expect to add the UANet interface as
  96. Xsoon as possible; this, however, will require me to develop a replacement for
  97. X"sendmail" on those systems (e.g. V7, System III/V) which don't have it.  (And
  98. Xperhaps for those that do, given the horror stories...)  There will also be
  99. Xnew administration commands forthcoming.
  100. X
  101. XThere are three manuals included in this distribution:
  102. X
  103. X(1) The UNaXcess Installation Manual, which explains the installation
  104. X    procedure.  This replaces the old README file, and is much more readable.
  105. X
  106. X(2) The UNaXcess User's Manual, an nroff'ed version of which is automatically
  107. X    placed in the UDL area by the installation script.  This guides the user
  108. X    through UNaXces in more detail than the help messages and help files.
  109. X
  110. X(3) The UNaXcess Administrator's Manual, which guides the administrator
  111. X    through the process of maintaining UNaXcess.
  112. X
  113. XThe "noautopath" mode is still supported, but it may disappear in the future,
  114. Xsince it interferes strongly with UNaXcess security.
  115. X
  116. XThe author may be contacted at ..ihnp4!sun!cwruecmp!ncoast!allbery, or by
  117. Xless mundane means as:
  118. X
  119. X            Brandon S. Allbery
  120. X            6615 N. Center St., Apt. A1-105
  121. X            Mentor, OH 44060-4101
  122. X            
  123. X            Phone: +1 216 974 9210
  124. X
  125. XPlease read the Installation Manual before compiling UNaXcess.
  126. X
  127. X++Brandon
  128. ________This_Is_The_END________
  129. echo 'x - bulletin.c'
  130. sed 's/^X//' << '________This_Is_The_END________' > bulletin.c
  131. X/*
  132. X *    bulletin.c    1.2 (TDI) 2/3/87
  133. X *    Copyright (C) 1984, 85, 86, 87 by Brandon S. Allbery.
  134. X *    This file is part of UNaXcess version 1.0.2.
  135. X */
  136. X
  137. X#ifndef lint
  138. Xstatic char _FileID_[] = "@(#)bulletin.c    1.2 (TDI) 2/3/87";
  139. Xstatic char _UAID_[]   = "@(#)UNaXcess version 1.0.2";
  140. X#endif lint
  141. X
  142. X#include "ua.h"
  143. X
  144. Xbulletin() {
  145. X    short mcnt, himotd;
  146. X    char tmps[256];
  147. X    FILE *fp;
  148. X
  149. X    if (user.u_access == A_MKUSER)
  150. X        return 1;
  151. X    sprintf(tmps, "%s/himotd", MOTD);
  152. X    if ((fp = fopen(tmps, "r")) == NULL) {
  153. X        log("Error %d opening %s", errno, tmps);
  154. X        panic("himotd");
  155. X    }
  156. X    fgets(tmps, 32, fp);
  157. X    fclose(fp);
  158. X    himotd = atoi(tmps);
  159. X    if (s_cmp(user.u_name, "guest") == 0)
  160. X        mcnt = 1;
  161. X    else
  162. X        mcnt = user.u_nbull + 1;
  163. X    for (; mcnt <= himotd; mcnt++) {
  164. X        sprintf(tmps, "%s/%d", MOTD, mcnt);
  165. X        if (!readmotd(tmps, mcnt))
  166. X            break;
  167. X    }
  168. X    return 1;
  169. X}
  170. X
  171. Xreadmotd(motd, mnum)
  172. Xchar *motd;
  173. Xshort mnum; {
  174. X    char ch;
  175. X
  176. X    writef("Bulletin #%d:\n", mnum);
  177. X    cat(motd);
  178. X    writef("\nContinue or Stop? C\b");
  179. X    ch = readc();
  180. X    log("C/S? %c", ch);
  181. X    return ToLower(ch) != 's';
  182. X}
  183. X
  184. Xmkbull() {
  185. X    static char lockfile[] = "bulletin.lock";
  186. X    char *tempfile = mktemp("/tmp/UAbXXXXXX");
  187. X    FILE *mfp, *sfp;
  188. X    char line[1024], *p, ch;
  189. X    short mcnt;
  190. X
  191. X    if (user.u_access != A_WITNESS) {
  192. X        log("Attempted mkbull by non-FW.");
  193. X        writes("You aren't permitted to enter bulletins.");
  194. X        return 1;
  195. X    }
  196. X    if ((mfp = fopen(tempfile, "w")) == NULL) {
  197. X        log("Error %d opening %s", errno, tempfile);
  198. X        panic("tmp");
  199. X    }
  200. X    fclose(mfp);
  201. X    input(tempfile);
  202. X    for (;;) {
  203. X        writef("\nList, Continue entry, Edit, Save, or Abort? ");
  204. X        ch = readc();
  205. X        log("Edit command: %c", ch);
  206. X        switch (ch) {
  207. X        case 'L':
  208. X            writes("\n--------------------");
  209. X            cat(tempfile);
  210. X            writes("--------------------");
  211. X            break;
  212. X        case 'C':
  213. X            input(tempfile);
  214. X            break;
  215. X        case 'E':
  216. X            edit(tempfile);
  217. X            break;
  218. X        case 'A':
  219. X            writef("Do you really want to abort this edit? N\b");
  220. X            line[0] = readc();
  221. X            log("Abort? %c", line[0]);
  222. X            if (line[0] == 'Y') {
  223. X                unlink(tempfile);
  224. X                return 0;
  225. X            }
  226. X            break;
  227. X        case '?':
  228. X            writes("Bulletin create commands:\n\nL - List message\nC - Continue message entry\nE - Edit message\nS - Save message\nA - Abort message\n");
  229. X            break;
  230. X        case 'S':
  231. X            writes("Saving bulletin...");
  232. X            mklock(lockfile);
  233. X            sprintf(line, "%s/himotd", MOTD);
  234. X            if ((sfp = fopen(line, "r")) == NULL) {
  235. X                log("Error %d opening %s", errno, line);
  236. X                rmlock(lockfile);
  237. X                unlink(tempfile);
  238. X                panic("himotd");
  239. X            }
  240. X            fgets(line, 32, sfp);
  241. X            fclose(sfp);
  242. X            mcnt = atoi(line) + 1;
  243. X            sprintf(line, "%s/%d", MOTD, mcnt);
  244. X            if ((sfp = fopen(line, "w")) == NULL) {
  245. X                log("Error %d opening %s", errno, line);
  246. X                unlink(tempfile);
  247. X                rmlock(lockfile);
  248. X                panic("motd");
  249. X            }
  250. X            fprintf(mfp, "UNaXcess Conferencing, Version 1.00.02\nDate: %s\nFrom: %s\n\n", longdate(), upstr(user.u_name));
  251. X            if ((mfp = fopen(tempfile, "r")) == NULL) {
  252. X                fclose(sfp);
  253. X                log("Error %d opening %s", errno, tempfile);
  254. X                unlink(tempfile);
  255. X                unlink(line);
  256. X                rmlock(lockfile);
  257. X                panic("btmp");
  258. X            }
  259. X            while (fgets(line, 1024, mfp) != NULL)
  260. X                fputs(line, sfp);
  261. X            fclose(sfp);
  262. X            fclose(mfp);
  263. X            unlink(tempfile);
  264. X            sprintf(line, "%s/himotd", MOTD);
  265. X            if ((sfp = fopen(line, "w")) == NULL) {
  266. X                log("Error %d opening %s", errno, line);
  267. X                panic("himotd_w");
  268. X            }
  269. X            fprintf(sfp, "%d\n", mcnt);
  270. X            fclose(sfp);
  271. X            rmlock(lockfile);
  272. X            return 1;
  273. X        default:
  274. X            writes("Please enter L, C, E, S, or A; or ? for help.");
  275. X        }
  276. X    }
  277. X}
  278. ________This_Is_The_END________
  279. echo 'x - conference.c'
  280. sed 's/^X//' << '________This_Is_The_END________' > conference.c
  281. X/*
  282. X *    conference.c    1.2 (TDI) 2/3/87
  283. X *    Copyright (C) 1984, 85, 86, 87 by Brandon S. Allbery.
  284. X *    This file is part of UNaXcess version 1.0.2.
  285. X *
  286. X *    Permission is hereby granted to copy and distribute this program
  287. X *    freely.  Permission is NOT given to modify this program or distribute
  288. X *    it at cost, except for charging a reasonable media/copying fee.
  289. X */
  290. X
  291. X#ifndef lint
  292. Xstatic char _FileID_[] = "@(#)conference.c    1.2 (TDI) 2/3/87";
  293. Xstatic char _UAID_[]   = "@(#)UNaXcess version 1.0.2";
  294. X#endif lint
  295. X
  296. X#include "ua.h"
  297. X
  298. Xchar conference[33];
  299. X
  300. Xconfidx() {
  301. X    FILE *ifd;
  302. X    short himsg;
  303. X    char line[256];
  304. X    DIR *dp;
  305. X    struct direct *dfd;
  306. X
  307. X    writes("\nConference                      Subscribed?  Messages  # Read  Restricted?\n");
  308. X    if ((dp = opendir(MSGBASE)) == NULL) {
  309. X        log("Error %d opening dir %s/", errno, MSGBASE);
  310. X        panic("msgdir");
  311. X    }
  312. X    while ((dfd = readdir(dp)) != NULL) {
  313. X        if (dfd->d_name[0] == '.')
  314. X            continue;
  315. X        sprintf(line, "%s/%s/himsg", MSGBASE, dfd->d_name);
  316. X        if ((ifd = fopen(line, "r")) == NULL) {
  317. X            log("No himsg in conference %s", dfd->d_name);
  318. X            continue;
  319. X        }
  320. X        fgets(line, 32, ifd);
  321. X        himsg = atoi(line);
  322. X        writef("%-32.32s     %c        %5d    %5d        %c\n", dfd->d_name, (isunsub(dfd->d_name)? 'N': 'Y'), himsg, cnread(dfd->d_name), (isrconf(dfd->d_name)? 'Y': 'N'));
  323. X        fclose(ifd);
  324. X    }
  325. X    closedir(dp);
  326. X    return 1;
  327. X}
  328. X
  329. Xjoin() {
  330. X    char line[256], *p;
  331. X
  332. X    do {
  333. X        writef("Enter conference: ");
  334. X        reads(line);
  335. X        log("Enter conference: %s", line);
  336. X        if (line[0] == '\0')
  337. X            return 1;
  338. X    } while (!verify(line));
  339. X    strcpy(conference, line);
  340. X    log("Current conference is %s", conference);
  341. X    return 1;
  342. X}
  343. X
  344. Xverify(conf)
  345. Xchar *conf; {
  346. X    char *cp, line[256];
  347. X
  348. X    for (cp = conf; *cp != 0; cp++) {
  349. X        if (!isprint(*cp))
  350. X            return 0;
  351. X        else if (*cp == '/' || *cp == '!' || *cp == ':')
  352. X            *cp = '.';
  353. X        else
  354. X            *cp = ToLower(*cp);
  355. X    }
  356. X    if (cp - conf > CONFSIZE)
  357. X        conf[CONFSIZE] = '\0';
  358. X    sprintf(line, "%s/%s", MSGBASE, conf);
  359. X    if (chdir(line) == -1) {
  360. X        if (errno != ENOENT) {
  361. X            log("Error %d accessing dir %s/", errno, line);
  362. X            return 0;
  363. X        }
  364. X        else
  365. X            return newconf(conf);
  366. X    }
  367. X    if (chdir(parms.ua_home) == -1) {
  368. X        log("Can't chdir to HOME (errno=%d)", errno);
  369. X        system("pwd");
  370. X        panic("isconf_cd");
  371. X    }
  372. X    if (isunsub(conf)) {
  373. X        writef("You are unsubscribed from this conference.  Rejoin? N\b");
  374. X        line[0] = readc();
  375. X        log("Unsubscribed.  Resubscribe? %c", line[0]);
  376. X        if (line[0] == 'Y')
  377. X            resubscribe(conf);
  378. X        else
  379. X            return 0;
  380. X    }
  381. X    if (user.u_access != A_WITNESS && parms.ua_xrc && !isrcmem(user.u_name, conf)) {
  382. X        log("No access to restricted conference %s", conf);
  383. X        writes("I'm sorry, but that conference has restricted membership.");
  384. X        return 0;
  385. X    }
  386. X    return 1;
  387. X}
  388. X
  389. Xkillmsg() {
  390. X    short mnum;
  391. X    char line[256], *p;
  392. X
  393. X    if (user.u_access == A_GUEST) {
  394. X        writes("You aren't authorized for this function.");
  395. X        log("Security violation:  KILL by a GUEST");
  396. X        return 1;
  397. X    }
  398. X    writef("Enter message number to kill: ");
  399. X    reads(line);
  400. X    if (line[0] == '\0')
  401. X        return 1;
  402. X    if ((mnum = atoi(line)) < 1) {
  403. X        writes("Bad message number.");
  404. X        log("Bad message number: %s", line);
  405. X        return 1;
  406. X    }
  407. X    dokill(mnum);
  408. X    return 1;
  409. X}
  410. X
  411. Xdokill(msg)
  412. Xshort msg; {
  413. X    char mfile[256];
  414. X
  415. X    sprintf(mfile, "%s/%s/%d", MSGBASE, conference, msg);
  416. X    if (user.u_access != A_WITNESS && s_cmp(getowner(mfile), user.u_name) != 0) {
  417. X        writes("Sorry, you don't own that message.");
  418. X        log("Security violation:  KILL by non-owner");
  419. X        return;
  420. X    }
  421. X    if (unlink(mfile) < 0) {
  422. X        writef("No such message: %d", msg);
  423. X        log("Error %d unlinking %s", errno, mfile);
  424. X        return;
  425. X    }
  426. X    log("Deleted %s:%d", conference, msg);
  427. X}
  428. X
  429. Xchar *getowner(file)
  430. Xchar *file; {
  431. X    FILE *f;
  432. X    char line[1024], *p;
  433. X    static char owner[256];
  434. X
  435. X    strcpy(owner, parms.ua_sysop);
  436. X    if ((f = fopen(file, "r")) == NULL)
  437. X        return owner;
  438. X    while (fgets(line, 1024, f) != NULL)
  439. X        if (line[0] == '\n')
  440. X            break;
  441. X        else if (strncmp(line, "From: ", 6) == 0) {
  442. X            strcpy(owner, &line[6]);
  443. X            break;
  444. X        }
  445. X    fclose(f);
  446. X    for (p = owner; *p != '\0'; p++)
  447. X        *p = ToLower(*p);
  448. X    return owner;
  449. X}
  450. X
  451. Xnewconf(conf)
  452. Xchar *conf; {
  453. X    char line[256];
  454. X    FILE *f;
  455. X
  456. X    if (user.u_access == A_GUEST) {
  457. X        log("Security violation:  attempted MKCONF by guest");
  458. X        writes("Sorry, there is no such conference.");
  459. X        return 0;
  460. X    }
  461. X    writef("There is no conference by that name.  Do you want to create it? N\b");
  462. X    line[0] = readc();
  463. X    log("Nonexistent.  Create? %c", line[0]);
  464. X    if (line[0] != 'Y')
  465. X        return 0;
  466. X    if (parms.ua_roc && conf[0] == 'r' && conf[1] == '-')
  467. X        if (user.u_access != A_WITNESS) {
  468. X            writes("Only Fairwitnesses can make READ-ONLY conferences.  If you really want one, you will have to ask the Sysop to make you a Fairwitness.  Otherwise, try using a conference name not beginning with \"R-\".");
  469. X            log("Attempted mk of RO conf by non-FW");
  470. X            return 0;
  471. X        }
  472. X        else {
  473. X            writef("This conference will be READ-ONLY, except to Fairwitnesses.  If you want anyone to be able to add to it, answer NO and use a name not beginning with \"R-\".  Do you want to make this READ-ONLY conference? N\b");
  474. X            line[0] = readc();
  475. X            log("Read-only.  Create? %c", line[0]);
  476. X            if (line[0] != 'Y')
  477. X                return 0;
  478. X        }
  479. X#ifdef BSD
  480. X    sprintf(line, "%s/%s", MSGBASE, conf);
  481. X    if (mkdir(line, 0600) < 0) {
  482. X        log("Mkconf of %s failed", conf);
  483. X        writes("Hmmm... guess you aren't allowed.");
  484. X        return 0;
  485. X    }
  486. X    chown(line, geteuid(), getegid());
  487. X#else  !BSD
  488. X    sprintf(line, "exec mkconf %s/%s %d", MSGBASE, conf, geteuid());
  489. X    if (system(line) != 0) {
  490. X        log("Mkconf of %s failed.", conf);
  491. X        writes("Hmmm... guess you aren't allowed.");
  492. X        return 0;
  493. X    }
  494. X#endif BSD
  495. X    log("New conference: %s", conf);
  496. X    sprintf(line, "%s/%s/himsg", MSGBASE, conf);
  497. X    if ((f = fopen(line, "w")) == NULL) {
  498. X        log("Error %d opening %s", line);
  499. X        writes("Can't create high message file.  Strange...");
  500. X        return 0;
  501. X    }
  502. X    fputs("0\n", f);
  503. X    fclose(f);
  504. X    writes("You will now be placed in the message editor to make a message describing this conference.  It will be addressed to, and readable by, all users.");
  505. X    mkmsg("All", "This conference", conf, 0);
  506. X    return 1;
  507. X}
  508. X
  509. Xisprivate(msg)
  510. Xchar *msg; {
  511. X    FILE *fp;
  512. X    char line[1024], to[1024], from[1024];
  513. X    short pflag;
  514. X    register char *cp;
  515. X
  516. X    if (user.u_access == A_WITNESS)
  517. X        return 0;
  518. X    if ((fp = fopen(msg, "r")) == NULL)
  519. X        return 0;
  520. X    strcpy(to, "All");
  521. X    pflag = 0;
  522. X    while (fgets(line, 1024, fp) != NULL) {
  523. X        if (line[0] == '\n')
  524. X            break;
  525. X        else if (strncmp(line, "To: ", 4) == 0)
  526. X            strcpy(to, &line[4]);
  527. X        else if (strncmp(line, "From: ", 6) == 0)
  528. X            strcpy(from, &line[6]);
  529. X        else if (strncmp(line, "Subject (Private): ", 19) == 0)
  530. X            pflag = 1;
  531. X    }
  532. X    fclose(fp);
  533. X    for (cp = to; *cp != '\0'; cp++)    /* OOPS!  2/3/87 ++bsa */
  534. X        if (*cp == '\n') {
  535. X            *cp = '\0';
  536. X            break;
  537. X        }
  538. X    for (cp = from; *cp != '\0'; cp++)
  539. X        if (*cp == '\n') {
  540. X            *cp = '\0';
  541. X            break;
  542. X        }
  543. X    if (!pflag)
  544. X        return 0;
  545. X    if (s_cmp(user.u_name, to) == 0)
  546. X        return 0;
  547. X    else if (s_cmp(user.u_name, from) == 0)
  548. X        return 0;
  549. X    else {
  550. X        log("Message %s is private.", msg);
  551. X        return 1;
  552. X    }                        /* end mods 2/3/87 */
  553. X}
  554. X
  555. Xisunsub(conf)
  556. Xchar *conf; {
  557. X    struct _himsg *hip;
  558. X
  559. X    for (hip = hicnts; hip != NULL; hip = hip->hi_next)
  560. X        if (strcmp(hip->hi_conf, conf) == 0)
  561. X            break;
  562. X    return (hip != NULL && hip->hi_uns == HI_UNSUB);
  563. X}
  564. X
  565. Xunsubscribe(conf)
  566. Xchar *conf; {
  567. X    struct _himsg *hip, *workp;
  568. X    char line[512];
  569. X    
  570. X    if (s_cmp(conf, "general") == 0) {
  571. X        writes("Can't unsubscribe the general conference.");
  572. X        log("Attempted to unsubscribe to general.");
  573. X        return;
  574. X    }
  575. X    if (s_cmp(conf, user.u_lconf) == 0) {
  576. X        writef("Unsubscribe to login conference? N\b");
  577. X        line[0] = readc();
  578. X        log("Unsub login conf? %c", line[0]);
  579. X        if (line[0] != 'Y')
  580. X            return;
  581. X        strcpy(user.u_lconf, "general");
  582. X    }
  583. X    for (hip = hicnts; hip != NULL; hip = hip->hi_next)
  584. X        if (strcmp(hip->hi_conf, conf) == 0)
  585. X            break;
  586. X    if (hip != NULL)
  587. X        hip->hi_uns = HI_UNSUB;
  588. X    else {
  589. X        if ((workp = (struct _himsg *) calloc((unsigned) 1, sizeof (struct _himsg))) == NULL) {
  590. X            log("Error %d allocating _himsg for %s", errno, conf);
  591. X            panic("alloc");
  592. X        }
  593. X        strcpy(workp->hi_conf, conf);
  594. X        workp->hi_num = 0;
  595. X        workp->hi_next = hicnts;
  596. X        hicnts = workp;
  597. X        workp->hi_uns = HI_UNSUB;
  598. X    }
  599. X    writehigh(hicnts);
  600. X    log("Unsubscribed to %s", conf);
  601. X    writef("Unsubscribed to conference %s.\n", conf);
  602. X}
  603. X
  604. Xresubscribe(conf)
  605. Xchar *conf; {
  606. X    struct _himsg *hip, *workp;
  607. X    
  608. X    for (hip = hicnts; hip != NULL; hip = hip->hi_next)
  609. X        if (strcmp(hip->hi_conf, conf) == 0)
  610. X            break;
  611. X    if (hip != NULL)
  612. X        hip->hi_uns = HI_SUBSCR;
  613. X    else {
  614. X        if ((workp = (struct _himsg *) calloc((unsigned) 1, sizeof (struct _himsg))) == NULL) {
  615. X            log("Error %d allocating _himsg for %s", errno, conf);
  616. X            panic("alloc");
  617. X        }
  618. X        strcpy(workp->hi_conf, conf);
  619. X        workp->hi_num = 0;
  620. X        workp->hi_next = hicnts;
  621. X        hicnts = workp;
  622. X        workp->hi_uns = HI_SUBSCR;
  623. X    }
  624. X    writehigh(hicnts);
  625. X    log("Resubscribed to %s", conf);
  626. X    writef("Resubscribed to conference %s.\n", conf);
  627. X}
  628. X
  629. Xunsub() {
  630. X    char line[256], *p;
  631. X
  632. X    for (;;) {
  633. X        writef("Unsubscribe to which conference (ENTER to abort): ");
  634. X        reads(line);
  635. X        log("Unsub conference: %s", line);
  636. X        if (line[0] == '\0')
  637. X            return 1;
  638. X        if (isconf(line)) {
  639. X            unsubscribe(line);
  640. X            return 1;
  641. X        }
  642. X        writef("That's not a valid conference.  ");
  643. X    }
  644. X}
  645. X
  646. Xisconf(conf)
  647. Xchar *conf; {
  648. X    char *cp, line[256];
  649. X
  650. X    for (cp = conf; *cp != 0; cp++) {
  651. X        if (!isprint(*cp))
  652. X            return 0;
  653. X        else if (*cp == '/' || *cp == '!' || *cp == ':')
  654. X            *cp = '.';
  655. X        else
  656. X            *cp = ToLower(*cp);
  657. X    }
  658. X    if (cp - conf > CONFSIZE)
  659. X        conf[CONFSIZE] = '\0';
  660. X    sprintf(line, "%s/%s", MSGBASE, conf);
  661. X    if (chdir(line) == -1)
  662. X        return 0;
  663. X    if (chdir(parms.ua_home) == -1) {
  664. X        log("Can't chdir to HOME (errno=%d)", errno);
  665. X        system("pwd");
  666. X        panic("isconf_cd");
  667. X    }
  668. X    return 1;
  669. X}
  670. X
  671. Xsetlconf() {
  672. X    char line[256], *p;
  673. X
  674. X    if (s_cmp(user.u_name, "guest") == 0) {
  675. X        log("Guest SET LOGIN CONF denied.");
  676. X        writes("GUEST can't set a login conference.");
  677. X        return 1;
  678. X    }
  679. X    do {
  680. X        writef("Enter new login conference: ");
  681. X        reads(line);
  682. X        log("Login conference: %s", line);
  683. X        if (line[0] == '\0')
  684. X            return 1;
  685. X    } while (!isconf(line));
  686. X    if (isunsub(line)) {
  687. X        writes("You're unsubscribed from it.  <J>oin it and resubscribe.");
  688. X        log("Unsubscribed -- login conf set aborted.");
  689. X        return 1;
  690. X    }
  691. X    if (!isrcmem(user.u_name, line)) {
  692. X        writes("You aren't a member of that conference.");
  693. X        log("Not a member -- login conf set aborted.");
  694. X        return 1;
  695. X    }
  696. X    strcpy(user.u_lconf, line);
  697. X    log("New login conference: %s", user.u_lconf);
  698. X    putuser(user.u_name, &user);
  699. X    return 1;
  700. X}
  701. X
  702. Xuisunsub(uname, conf)
  703. Xchar *uname, *conf; {
  704. X    struct _himsg *hip, *uhi;
  705. X    char *cp;
  706. X
  707. X    for (cp = uname; *cp != '\0'; cp++)
  708. X        *cp = ToLower(*cp);
  709. X    if ((uhi = readhigh(uname)) < 0) {
  710. X        log("Couldn't read %s's userindex.", uname);
  711. X        return 0;
  712. X    }
  713. X    writef("Checking %s's user index...\n", uname);
  714. X    for (hip = uhi; hip != NULL; hip = hip->hi_next)
  715. X        if (strcmp(hip->hi_conf, conf) == 0)
  716. X            break;
  717. X    cp = (hip != NULL && hip->hi_uns == HI_UNSUB? "!": ":");
  718. X    for (hip = uhi; hip != NULL; hip = uhi) {
  719. X        uhi = hip->hi_next;
  720. X        free((char *) hip);
  721. X    }
  722. X    return (*cp == '!');
  723. X}
  724. X
  725. Xcleanhigh() {
  726. X    struct _himsg *hip, *lastp;
  727. X    DIR *confs;
  728. X    struct direct *conf;
  729. X    int nunread;
  730. X    char line[80];
  731. X    FILE *fp;
  732. X    
  733. X    lastp = NULL;
  734. X    writes("Checking for deleted conferences...");
  735. X    for (hip = hicnts; hip != NULL; lastp = hip, hip = hip->hi_next) {
  736. X        if (!isconf(hip->hi_conf)) {
  737. X            writef("Conference \"%s\" was deleted since your last session.\n", hip->hi_conf);
  738. X            if (lastp == NULL)
  739. X                hicnts = hip->hi_next;
  740. X            else
  741. X                lastp->hi_next = hip->hi_next;
  742. X            free((char *) hip);
  743. X        }
  744. X    }
  745. X    writes("\nChecking for new messages and conferences...");
  746. X    if ((confs = opendir(MSGBASE)) == NULL) {
  747. X        log("Error %d opening dir %s/", errno, MSGBASE);
  748. X        panic("msgdir");
  749. X    }
  750. X    while ((conf = readdir(confs)) != NULL) {
  751. X        if (strcmp(conf->d_name, ".") == 0)
  752. X            continue;
  753. X        if (strcmp(conf->d_name, "..") == 0)
  754. X            continue;
  755. X        for (hip = hicnts; hip != NULL; hip = hip->hi_next)
  756. X            if (strcmp(hip->hi_conf, conf->d_name) == 0) {
  757. X                sprintf(line, "%s/%s/himsg", MSGBASE, conf->d_name);
  758. X                if ((fp = fopen(line, "r")) == (FILE *) 0)
  759. X                    break;
  760. X                fgets(line, 32, fp);
  761. X                fclose(fp);
  762. X                nunread = atoi(line);
  763. X                if ((nunread -= hip->hi_num) <= 0)
  764. X                    break;
  765. X                writef("There are %d new messages in \"%s\".\n", nunread, conf->d_name);
  766. X                break;
  767. X            }
  768. X        if (hip == NULL) {
  769. X            writef("Conference \"%s\" has been created since your last session.\n", conf->d_name);
  770. X            if ((hip = (struct _himsg *) calloc((unsigned) 1, sizeof (struct _himsg))) == NULL) {
  771. X                log("Error %d allocating _himsg for %s", errno, conf);
  772. X                panic("alloc");
  773. X            }
  774. X            strcpy(hip->hi_conf, conf->d_name);
  775. X            hip->hi_num = 0;
  776. X            hip->hi_next = hicnts;
  777. X            hicnts = hip;
  778. X        }
  779. X    }
  780. X    writehigh(hicnts);
  781. X    closedir(confs);
  782. X}
  783. X
  784. Xcnread(conf)
  785. Xchar *conf; {
  786. X    struct _himsg *hi;
  787. X    
  788. X    for (hi = hicnts; hi != (struct _himsg *) 0; hi = hi->hi_next)
  789. X        if (s_cmp(conf, hi->hi_conf) == 0)
  790. X            return hi->hi_num;
  791. X    return -1;
  792. X}
  793. X
  794. Xedrest() {
  795. X    char rconf[256], line[256];
  796. X    char *p;
  797. X    FILE *fp;
  798. X
  799. X    if (user.u_access != A_WITNESS) {
  800. X        writes("You aren't permitted to edit Restricted conference membership lists.");
  801. X        log("Non-FW attempted to edit restricted conf membership lists");
  802. X        return 1;
  803. X    }
  804. X    if (!parms.ua_xrc) {
  805. X        writes("Restricted conferences are not permitted on this BBS.");
  806. X        log("redit: restricted conferences disabled");
  807. X        return 1;
  808. X    }
  809. X    writef("Enter conference (RETURN / ENTER to abort): ");
  810. X    reads(rconf);
  811. X    log("Rconf: %s", rconf);
  812. X    if (rconf[0] == '\0')
  813. X        return 1;
  814. X    if (!isconf(rconf)) {
  815. X        writef("Conference \"%s\" doesn't exist.", rconf);
  816. X        log("Bad conference: %s", rconf);
  817. X        return 1;
  818. X    }
  819. X    for (p = rconf; *p != '\0'; p++)
  820. X        *p = ToLower(*p);
  821. X    if (s_cmp(user.u_name, parms.ua_sysop) != 0 && !isrcmem(user.u_name, rconf)) {
  822. X        log("FW not a member; list only");
  823. X        rcmemlist(rconf);
  824. X        return 1;
  825. X    }
  826. X    if (!isrconf(rconf))
  827. X        if (s_cmp(user.u_name, parms.ua_sysop) != 0) {
  828. X            writes("Only the Sysop can restrict a conference's membership.");
  829. X            return 1;
  830. X        }
  831. X        else {
  832. X            writef("Conference \"%s\" isn't restricted.  Restrict? N\b", rconf);
  833. X            line[0] = readc();
  834. X            log("Restrict %s? %c", rconf, line[0]);
  835. X            if (line[0] != 'Y')
  836. X                return 1;
  837. X            sprintf(line, "%s/%s", MEMLIST, rconf);
  838. X            if ((fp = fopen(line, "w")) == (FILE *) 0) {
  839. X                log("Error %d creating %s", errno, line);
  840. X                panic("rest_mk");
  841. X            }
  842. X            fclose(fp);
  843. X        }
  844. X    for (;;) {
  845. X        writef("\nList members, Add a member, Delete a member, Clear membership list, or Quit: ");
  846. X        line[0] = readc();
  847. X        switch (line[0]) {
  848. X        case 'L':
  849. X            rcmemlist(rconf);
  850. X            break;
  851. X        case 'A':
  852. X            rcmemadd(rconf);
  853. X            break;
  854. X        case 'D':
  855. X            rcmemdel(rconf);
  856. X            break;
  857. X        case 'C':
  858. X            rcmemclr(rconf);
  859. X            break;
  860. X        case 'Q':
  861. X            return 1;
  862. X        default:
  863. X            writes("Please enter L, A, D, C, or Q.");
  864. X        }
  865. X    }
  866. X}
  867. X
  868. Xisrcmem(uname, conf)
  869. Xchar *uname, *conf; {
  870. X    FILE *fp;
  871. X    char line[256];
  872. X    char *cp;
  873. X
  874. X    if (!parms.ua_xrc || s_cmp(uname, parms.ua_sysop) == 0)
  875. X        return 1;
  876. X    sprintf(line, "%s/%s", MEMLIST, conf);
  877. X    if ((fp = fopen(line, "r")) == (FILE *) 0)
  878. X        return 1;    /* no mem list == no restrictions */
  879. X    while (fgets(line, sizeof line, fp) != (char *) 0) {
  880. X        if ((cp = RIndex(line, '\n')) != (char *) 0)
  881. X            *cp = '\0';
  882. X        if (s_cmp(line, uname) == 0) {
  883. X            fclose(fp);
  884. X            log("%s is a member of restricted conf %s", uname, conf);
  885. X            return 1;
  886. X        }
  887. X    }
  888. X    fclose(fp);
  889. X    log("%s isn't a member of restricted conf %s", uname, conf);
  890. X    return 0;
  891. X}
  892. X
  893. Xrcmemlist(conf)
  894. Xchar *conf; {
  895. X    FILE *fp;
  896. X    char line[256];
  897. X    short headf;
  898. X
  899. X    if (!parms.ua_xrc) {
  900. X        writef("Conference \"%s\" has no restrictions on membership.\n", conf);
  901. X        return;
  902. X    }
  903. X    sprintf(line, "%s/%s", MEMLIST, conf);
  904. X    if ((fp = fopen(line, "r")) == (FILE *) 0) {
  905. X        writef("Conference \"%s\" has no restrictions on membership.\n", conf);
  906. X        return;
  907. X    }
  908. X    headf = 0;
  909. X    while (fgets(line, sizeof line, fp) != (char *) 0) {
  910. X        if (!headf) {
  911. X            writef("Members of the \"%s\" conference:\n\n", conf);
  912. X            headf++;
  913. X        }
  914. X        writef("\t%s\n", upstr(line));
  915. X        /* OOPS!  1 line deleted 2/3/87 ++bsa */
  916. X    }
  917. X    if (!headf)
  918. X        writef("Conference \"%s\" is restricted to Fairwitnesses and the Sysop.\n", conf);
  919. X    fclose(fp);
  920. X}
  921. X
  922. Xrcmemadd(conf)
  923. Xchar *conf; {
  924. X    char line[256], uname[256];
  925. X    struct user ubuf;
  926. X    FILE *fp;
  927. X    
  928. X    writef("Name (RETURN to abort): ");
  929. X    reads(uname);
  930. X    log("Add user %s to %s's mem list", uname, conf);
  931. X    if (uname[0] == '\0')
  932. X        return;
  933. X    if (!getuser(uname, &ubuf)) {
  934. X        writef("User \"%s\" doesn't exist.\n", upstr(uname));
  935. X        log("No such user: %s", uname);
  936. X        return;
  937. X    }
  938. X    if (ubuf.u_access == A_WITNESS && s_cmp(user.u_name, "sysop") != 0) {
  939. X        log("FW attempted to change membership of %s in %s", ubuf.u_name, conf);
  940. X        writes("Sorry, only the Sysop can change a FairWitness's conference membership.");
  941. X        return;
  942. X    }
  943. X    if (isrcmem(uname, conf)) {
  944. X        log("Already a member.");
  945. X        writef("\"%s\" is already a member of this conference.\n", upstr(uname));
  946. X        return;
  947. X    }
  948. X    mklock("memlist.lock");
  949. X    sprintf(line, "%s/%s", MEMLIST, conf);
  950. X    if ((fp = fopen(line, "a")) == (FILE *) 0) {
  951. X        rmlock(conf);
  952. X        log("Error %d opening %s", errno, line);
  953. X        panic("memlist_app");
  954. X    }
  955. X    fprintf(fp, "%s\n", upstr(uname));    /* OOPS!  2/3/87 ++bsa */
  956. X    fclose(fp);
  957. X    rmlock("memlist.lock");
  958. X}
  959. X
  960. Xrcmemdel(conf)
  961. Xchar *conf; {
  962. X    char line[256], uname[256], tname[256];
  963. X    struct user ubuf;
  964. X    FILE *fp, *tp;
  965. X    
  966. X    writef("Name (RETURN to abort): ");
  967. X    reads(uname);
  968. X    log("Del user %s from %s's mem list", uname, conf);
  969. X    if (uname[0] == '\0')
  970. X        return;
  971. X    if (!getuser(uname, &ubuf)) {
  972. X        writef("User \"%s\" doesn't exist.\n", upstr(uname));
  973. X        log("No such user: %s", uname);
  974. X        return;
  975. X    }
  976. X    if (ubuf.u_access == A_WITNESS && s_cmp(user.u_name, "sysop") != 0) {
  977. X        log("FW attempted to change membership of %s in %s", ubuf.u_name, conf);
  978. X        writes("Sorry, only the Sysop can change a FairWitness's conference membership.");
  979. X        return;
  980. X    }
  981. X    if (!isrcmem(uname, conf)) {
  982. X        log("Not a member.");
  983. X        writef("\"%s\" isn't a member of this conference.\n", upstr(uname));
  984. X        return;
  985. X    }
  986. X    sprintf(tname, "/tmp/UAxD%05d", getpid());
  987. X    if ((tp = fopen(tname, "w")) == (FILE *) 0) {
  988. X        log("Error %d opening %s", errno, tname);
  989. X        panic("memlist_dtmp");
  990. X    }
  991. X    mklock("memlist.lock");
  992. X    sprintf(line, "%s/%s", MEMLIST, conf);
  993. X    if ((fp = fopen(line, "r")) == (FILE *) 0) {
  994. X        rmlock(conf);
  995. X        fclose(tp);
  996. X        unlink(tname);
  997. X        log("Error %d opening %s", errno, line);
  998. X        panic("memlist_app");
  999. X    }
  1000. X    while (fgets(line, sizeof line, fp) != (char *) 0)
  1001. X        if (s_cmp(line, uname) != 0)
  1002. X            fputs(line, tp);
  1003. X    fclose(fp);
  1004. X    fclose(tp);
  1005. X    sprintf(line, "%s/%s", MEMLIST, conf);
  1006. X    if (unlink(line) < 0) {
  1007. X        log("Error %d unlinking %s", errno, line);
  1008. X        rmlock("memlist.lock");
  1009. X        panic("memlist_drmv");
  1010. X    }
  1011. X    if (copylink(tname, line) < 0) {
  1012. X        log("Error %d copylinking %s to %s", errno, tname, line);
  1013. X        rmlock("memlist.lock");
  1014. X        panic("memlist_dclnk");
  1015. X    }
  1016. X    rmlock("memlist.lock");
  1017. X}
  1018. X
  1019. Xrcmemclr(conf)
  1020. Xchar *conf; {
  1021. X    char mlist[256];
  1022. X    
  1023. X    if (s_cmp(user.u_name, parms.ua_sysop) != 0) {
  1024. X        log("Attempt to clear %s's mem list by non-sysop", conf);
  1025. X        writes("Only the Sysop can clear a conference's membership list.");
  1026. X        return;
  1027. X    }
  1028. X    writef("Clear membership list for the \"%s\" conference? N\b", conf);
  1029. X    mlist[0] = readc();
  1030. X    log("Clear? %c", mlist[0]);
  1031. X    if (mlist[0] != 'Y') {
  1032. X        log("Aborted.");
  1033. X        writes("Aborted.");
  1034. X        return;
  1035. X    }
  1036. X    sprintf(mlist, "%s/%s", MEMLIST, conf);
  1037. X    if (unlink(mlist) < 0) {
  1038. X        log("Error %s unlinking %s", errno, mlist);
  1039. X        writes("Can't remove the membership list.");
  1040. X    }
  1041. X}
  1042. X
  1043. Xisrconf(rconf)
  1044. Xchar *rconf; {
  1045. X    char line[256];
  1046. X    FILE *fp;
  1047. X    
  1048. X    sprintf(line, "%s/%s", MEMLIST, rconf);
  1049. X    if ((fp = fopen(line, "r")) == (FILE *) 0)
  1050. X        return 0;
  1051. X    fclose(fp);
  1052. X    return 1;
  1053. X}
  1054. ________This_Is_The_END________
  1055. echo 'x - date.c'
  1056. sed 's/^X//' << '________This_Is_The_END________' > date.c
  1057. X/*
  1058. X *    @(#)date.c    1.1 (TDI) 2/3/87
  1059. X *    @(#)Copyright (C) 1984, 85, 86, 87 by Brandon S. Allbery.
  1060. X *    @(#)This file is part of UNaXcess version 1.0.2.
  1061. X *
  1062. X *    Permission is hereby granted to copy and distribute this program
  1063. X *    freely.  Permission is NOT given to modify this program or distribute
  1064. X *    it at cost, except for charging a reasonable media/copying fee.
  1065. X */
  1066. X
  1067. X#ifndef lint
  1068. Xstatic char _FileID_[] = "@(#)date.c    1.1 (TDI) 2/3/87";
  1069. Xstatic char _UAID_[]   = "@(#)UNaXcess version 1.0.2";
  1070. X#endif lint
  1071. X
  1072. X#include "ua.h"
  1073. X
  1074. Xstatic char *month[] = {
  1075. X    "January",    "February",    "March",    "April",
  1076. X    "May",        "June",        "July",        "August",
  1077. X    "September",    "October",    "November",    "December"
  1078. X};
  1079. X
  1080. Xstatic char *wkday[] = {
  1081. X    "Sunday",    "Monday",    "Tuesday",    "Wednesday",
  1082. X    "Thursday",    "Friday",    "Saturday"
  1083. X};
  1084. X
  1085. Xchar *date() {
  1086. X    long clock;
  1087. X    struct tm *ltbuf;
  1088. X    static char tbuf[18];
  1089. X
  1090. X    time(&clock);
  1091. X    ltbuf = localtime(&clock);
  1092. X    sprintf(tbuf, "%02d/%02d/%02d %02d:%02d:%02d", ltbuf->tm_mon + 1, ltbuf->tm_mday, ltbuf->tm_year, ltbuf->tm_hour, ltbuf->tm_min, ltbuf->tm_sec);
  1093. X    return tbuf;
  1094. X}
  1095. X
  1096. Xchar *longdate() {
  1097. X    long clock;
  1098. X    struct tm *ltbuf;
  1099. X    static char tbuf[80];
  1100. X    short hour;
  1101. X    char ampm;
  1102. X
  1103. X    time(&clock);
  1104. X    ltbuf = localtime(&clock);
  1105. X    if (ltbuf->tm_hour == 0) {
  1106. X        hour = 12;
  1107. X        ampm = 'A';
  1108. X    }
  1109. X    else if (ltbuf->tm_hour < 12) {
  1110. X        hour = ltbuf->tm_hour;
  1111. X        ampm = 'A';
  1112. X    }
  1113. X    else if (ltbuf->tm_hour == 12) {
  1114. X        hour = 12;
  1115. X        ampm = 'P';
  1116. X    }
  1117. X    else {
  1118. X        hour = ltbuf->tm_hour - 12;
  1119. X        ampm = 'P';
  1120. X    }
  1121. X    sprintf(tbuf, "%s, %s %d, 19%02d - %d:%02d %cM", wkday[ltbuf->tm_wday], month[ltbuf->tm_mon], ltbuf->tm_mday, ltbuf->tm_year, hour, ltbuf->tm_min, ampm);
  1122. X    return tbuf;
  1123. X}
  1124. X
  1125. Xchar *today() {
  1126. X    long now;
  1127. X    struct tm *datebuf;
  1128. X    static char buf[11];
  1129. X    
  1130. X    time(&now);
  1131. X    datebuf = localtime(&now);
  1132. X    sprintf(buf, "%d/%d/%d", datebuf->tm_mon + 1, datebuf->tm_mday, datebuf->tm_year);
  1133. X    return buf;
  1134. X}
  1135. ________This_Is_The_END________
  1136. echo 'x - dir.c'
  1137. sed 's/^X//' << '________This_Is_The_END________' > dir.c
  1138. X/*
  1139. X *
  1140. X *                N O T I C E
  1141. X *
  1142. X * This file is NOT a copyrighted part of the UNaXcess distribution.  These
  1143. X * are directory-reading routines which are compatible with the Berkeley Unix
  1144. X * (4.2BSD, 4.3BSD) directory routines.  They come from the Usenet news
  1145. X * distribution and are in the public domain.
  1146. X *
  1147. X * To get the best use of them:  install the file "dir.h" in /usr/include
  1148. X * -- standard usage calls it "ndir.h", and make a random archive of dir.o and
  1149. X * put it in /usr/lib/libndir.a .  It is then available with "-lndir".
  1150. X *
  1151. X * Bell System {III, V} sites, just make an archive -- it is only one file
  1152. X * anyway.  Other sites will have to run ranlib on the archive to keep ld
  1153. X * happy.
  1154. X */
  1155. X
  1156. X#include <sys/types.h>
  1157. X#include "dir.h"
  1158. X
  1159. X#ifndef BSD
  1160. X
  1161. Xextern char *malloc();
  1162. X
  1163. X/*
  1164. X * close a directory.
  1165. X */
  1166. Xclosedir(dirp)
  1167. X        register DIR *dirp;
  1168. X{
  1169. X        close(dirp->dd_fd);
  1170. X        dirp->dd_fd = -1;
  1171. X        dirp->dd_loc = 0;
  1172. X        free(dirp);
  1173. X}
  1174. X
  1175. X
  1176. X
  1177. X/*
  1178. X * open a directory.
  1179. X */
  1180. XDIR *
  1181. Xopendir(name)
  1182. X        char *name;
  1183. X{
  1184. X        register DIR *dirp;
  1185. X        register int fd;
  1186. X
  1187. X        if ((fd = open(name, 0)) == -1)
  1188. X                return NULL;
  1189. X        if ((dirp = (DIR *)malloc(sizeof(DIR))) == NULL) {
  1190. X                close (fd);
  1191. X                return NULL;
  1192. X        }
  1193. X        dirp->dd_fd = fd;
  1194. X        dirp->dd_loc = 0;
  1195. X        return dirp;
  1196. X}
  1197. X
  1198. X
  1199. X
  1200. X/*
  1201. X * read an old style directory entry and present it as a new one
  1202. X */
  1203. X#define ODIRSIZ 14
  1204. X
  1205. Xstruct  olddirect {
  1206. X        ino_t   od_ino;
  1207. X        char    od_name[ODIRSIZ];
  1208. X};
  1209. X
  1210. X/*
  1211. X * get next entry in a directory.
  1212. X */
  1213. Xstruct direct *
  1214. Xreaddir(dirp)
  1215. X        register DIR *dirp;
  1216. X{
  1217. X        register struct olddirect *dp;
  1218. X        static struct direct dir;
  1219. X
  1220. X        for (;;) {
  1221. X                if (dirp->dd_loc == 0) {
  1222. X                        dirp->dd_size = read(dirp->dd_fd, dirp->dd_buf, 
  1223. X                            DIRBLKSIZ);
  1224. X                        if (dirp->dd_size <= 0)
  1225. X                                return NULL;
  1226. X                }
  1227. X                if (dirp->dd_loc >= dirp->dd_size) {
  1228. X                        dirp->dd_loc = 0;
  1229. X                        continue;
  1230. X                }
  1231. X                dp = (struct olddirect *)(dirp->dd_buf + dirp->dd_loc);
  1232. X                dirp->dd_loc += sizeof(struct olddirect);
  1233. X                if (dp->od_ino == 0)
  1234. X                        continue;
  1235. X                dir.d_ino = dp->od_ino;
  1236. X                strncpy(dir.d_name, dp->od_name, ODIRSIZ);
  1237. X                dir.d_name[ODIRSIZ] = '\0'; /* insure null termination */
  1238. X                dir.d_namlen = strlen(dir.d_name);
  1239. X                dir.d_reclen = DIRBLKSIZ;
  1240. X                return (&dir);
  1241. X        }
  1242. X}
  1243. X
  1244. X#endif BSD
  1245. ________This_Is_The_END________
  1246. echo 'x - dir.h'
  1247. sed 's/^X//' << '________This_Is_The_END________' > dir.h
  1248. X/*
  1249. X *
  1250. X *                N O T I C E
  1251. X *
  1252. X * This file is NOT a copyrighted part of the UNaXcess distribution.  These
  1253. X * are directory-reading routines which are compatible with the Berkeley Unix
  1254. X * (4.2BSD, 4.3BSD) directory routines.  They come from the Usenet news
  1255. X * distribution and are in the public domain.
  1256. X *
  1257. X * To get the best use of them:  install the file "dir.h" in /usr/include
  1258. X * -- standard usage calls it "ndir.h", and make a random archive of dir.o and
  1259. X * put it in /usr/lib/libndir.a .  It is then available with "-lndir".
  1260. X *
  1261. X * Bell System {III, V} sites, just make an archive -- it is only one file
  1262. X * anyway.  Other sites will have to run ranlib on the archive to keep ld
  1263. X * happy.
  1264. X */
  1265. X
  1266. X/*    dir.h    4.4    82/07/25    */
  1267. X
  1268. X#ifdef BSD
  1269. X#include <sys/dir.h>
  1270. X#else
  1271. X
  1272. X/*
  1273. X * A directory consists of some number of blocks of DIRBLKSIZ
  1274. X * bytes, where DIRBLKSIZ is chosen such that it can be transferred
  1275. X * to disk in a single atomic operation (e.g. 512 bytes on most machines).
  1276. X *
  1277. X * Each DIRBLKSIZ byte block contains some number of directory entry
  1278. X * structures, which are of variable length.  Each directory entry has
  1279. X * a struct direct at the front of it, containing its inode number,
  1280. X * the length of the entry, and the length of the name contained in
  1281. X * the entry.  These are followed by the name padded to a 4 byte boundary
  1282. X * with null bytes.  All names are guaranteed null terminated.
  1283. X * The maximum length of a name in a directory is MAXNAMLEN.
  1284. X *
  1285. X * The macro DIRSIZ(dp) gives the amount of space required to represent
  1286. X * a directory entry.  Free space in a directory is represented by
  1287. X * entries which have dp->d_reclen >= DIRSIZ(dp).  All DIRBLKSIZ bytes
  1288. X * in a directory block are claimed by the directory entries.  This
  1289. X * usually results in the last entry in a directory having a large
  1290. X * dp->d_reclen.  When entries are deleted from a directory, the
  1291. X * space is returned to the previous entry in the same directory
  1292. X * block by increasing its dp->d_reclen.  If the first entry of
  1293. X * a directory block is free, then its dp->d_ino is set to 0.
  1294. X * Entries other than the first in a directory do not normally have
  1295. X * dp->d_ino set to 0.
  1296. X */
  1297. X#define DIRBLKSIZ    512
  1298. X#define    MAXNAMLEN    255
  1299. X
  1300. Xstruct    direct {
  1301. X    long    d_ino;            /* inode number of entry */
  1302. X    short    d_reclen;        /* length of this record */
  1303. X    short    d_namlen;        /* length of string in d_name */
  1304. X    char    d_name[MAXNAMLEN + 1];    /* name must be no longer than this */
  1305. X};
  1306. X
  1307. X/*
  1308. X * The DIRSIZ macro gives the minimum record length which will hold
  1309. X * the directory entry.  This requires the amount of space in struct direct
  1310. X * without the d_name field, plus enough space for the name with a terminating
  1311. X * null byte (dp->d_namlen+1), rounded up to a 4 byte boundary.
  1312. X */
  1313. X#ifdef DIRSIZ
  1314. X#undef DIRSIZ
  1315. X#endif
  1316. X#define DIRSIZ(dp) \
  1317. X    ((sizeof (struct direct) - (MAXNAMLEN+1)) + (((dp)->d_namlen+1 + 3) &~ 3))
  1318. X
  1319. X#ifndef KERNEL
  1320. X/*
  1321. X * Definitions for library routines operating on directories.
  1322. X */
  1323. Xtypedef struct _dirdesc {
  1324. X    int    dd_fd;
  1325. X    long    dd_loc;
  1326. X    long    dd_size;
  1327. X    char    dd_buf[DIRBLKSIZ];
  1328. X} DIR;
  1329. X#ifndef NULL
  1330. X#define NULL 0
  1331. X#endif
  1332. Xextern    DIR *opendir();
  1333. Xextern    struct direct *readdir();
  1334. Xextern    closedir();
  1335. X#endif KERNEL
  1336. X
  1337. X#endif BSD
  1338. ________This_Is_The_END________
  1339. echo 'x - fileudl.c'
  1340. sed 's/^X//' << '________This_Is_The_END________' > fileudl.c
  1341. X/*
  1342. X *    @(#)fileudl.c    1.1 (TDI) 2/3/87
  1343. X *    @(#)Copyright (C) 1984, 85, 86, 87 by Brandon S. Allbery.
  1344. X *    @(#)This file is part of UNaXcess version 1.0.2.
  1345. X *
  1346. X *    Permission is hereby granted to copy and distribute this program
  1347. X *    freely.  Permission is NOT given to modify this program or distribute
  1348. X *    it at cost, except for charging a reasonable media/copying fee.
  1349. X */
  1350. X
  1351. X#ifndef lint
  1352. Xstatic char _FileID_[] = "@(#)fileudl.c    1.1 (TDI) 2/3/87";
  1353. Xstatic char _UAID_[]   = "@(#)UNaXcess version 1.0.2";
  1354. X#endif lint
  1355. X
  1356. X#include "ua.h"
  1357. X#include <varargs.h>
  1358. X
  1359. X#define A_UPLOAD    parms.ua_auc
  1360. X#define A_DOWNLOAD    parms.ua_adc
  1361. X
  1362. X#define X_UPLOAD    parms.ua_xuc
  1363. X#define X_DOWNLOAD    parms.ua_xdc
  1364. X
  1365. X#define K_UPLOAD    parms.ua_kuc
  1366. X#define K_DOWNLOAD    parms.ua_kdc
  1367. X
  1368. X#define LIBRARY        "library"
  1369. X#define DIRECTORY    "directory"
  1370. X#define STORAGE        "uploads"
  1371. X#define UPLOG        "upload-log"
  1372. X
  1373. X#define DIRFORMAT    "%[^ ] %*1[Ff]%*1[Ii]%*1[Ll]%*1[Ee] %[^;]; %[^ ] %*1[Bb]%*1[Yy] %[^:]: %[^\n]"
  1374. X
  1375. Xjmp_buf brchloop, fileloop;
  1376. X
  1377. Xchar *whatis(), *cpmform(), *upstr(), *today();
  1378. X
  1379. Xextern struct tm *localtime();
  1380. X
  1381. Xudl() {
  1382. X    int again();
  1383. X    int (*oldint)();
  1384. X    char *cp;
  1385. X
  1386. X    if (user.u_access < A_FILES) {
  1387. X        writes("\nYou will not be able to upload or download files.  You may, however, download File Lists.");
  1388. X        log("File Section entered; access restricted");
  1389. X    }
  1390. X    oldint = signal(SIGINT, again);
  1391. X    setjmp(brchloop);
  1392. X    while (libmenu())
  1393. X        ;
  1394. X    writef("\n");
  1395. X    signal(SIGINT, oldint);
  1396. X}
  1397. X
  1398. Xagain() {
  1399. X    signal(SIGINT, again);
  1400. X    writef("\nInterrupt\n");
  1401. X    log("Interrupt");
  1402. X    longjmp(brchloop, 1);
  1403. X}
  1404. X
  1405. Xlibmenu() {
  1406. X    struct direct *branch;
  1407. X    DIR *library;
  1408. X    char cmd[512], bname[512];
  1409. X    int (*oldsig)();
  1410. X    int brch_cmd();
  1411. X    char *desc;
  1412. X    
  1413. X    if ((library = opendir(LIBRARY)) == NULL) {
  1414. X        writef("The Library is closed\n");
  1415. X        return 0;
  1416. X    }
  1417. X    writef("\nThe UNaXcess File Section.  Please select one of the following\nbranches, or EXIT to leave the Library.\n\n");
  1418. X    while ((branch = readdir(library)) != NULL) {
  1419. X        if ((desc = whatis(branch->d_name, NULL)) == NULL)
  1420. X            continue;
  1421. X        writef("    %-8.8s   %s\n", upstr(branch->d_name), desc);
  1422. X    }
  1423. X    closedir(library);
  1424. X    writef("\nBranch: ");
  1425. X    reads(cmd);
  1426. X    log("Branch: %s", cmd);
  1427. X    if (cmd[0] == '\0' || s_cmp(cmd, "EXIT") == 0)
  1428. X        return 0;
  1429. X    if (whatis(cmd, NULL) != NULL) {
  1430. X        library = opendir(LIBRARY);
  1431. X        while ((branch = readdir(library)) != NULL)
  1432. X            if (s_cmp(branch->d_name, cmd) == 0) {
  1433. X                closedir(library);
  1434. X                strcpy(bname, branch->d_name);
  1435. X                oldsig = signal(SIGINT, brch_cmd);
  1436. X                setjmp(fileloop);
  1437. X                while (visit(bname))
  1438. X                    ;
  1439. X                signal(SIGINT, oldsig);
  1440. X                return 1;
  1441. X            }
  1442. X    }
  1443. X    closedir(library);
  1444. X    writef("There is no such branch.  If you wish to open a new branch,\nleave a message to %s.\n", parms.ua_sysop);
  1445. X    return 1;
  1446. X}
  1447. X
  1448. Xvisit(branch)
  1449. Xchar *branch; {
  1450. X    char cmd[512];
  1451. X    DIR *directory;
  1452. X    
  1453. X    sprintf(cmd, "%s/%s", LIBRARY, branch);
  1454. X    if ((directory = opendir(cmd)) == NULL) {
  1455. X        writef("The %s branch is closed.\n", upstr(branch));
  1456. X        return 0;
  1457. X    }
  1458. X    closedir(directory);
  1459. X    writef("\n%s Branch\nUpload, Download, List of Files, Get File List, Exit: ", upstr(branch));
  1460. X    cmd[0] = readc();
  1461. X    log("Branch cmd: %c", cmd[0]);
  1462. X    switch (cmd[0]) {
  1463. X        case 'E':
  1464. X            return 0;
  1465. X        case 'U':
  1466. X            upload(branch);
  1467. X            break;
  1468. X        case 'D':
  1469. X            download(branch);
  1470. X            break;
  1471. X        case 'L':
  1472. X            filelist(branch);
  1473. X            break;
  1474. X        case 'G':
  1475. X            getlist(branch);
  1476. X            break;
  1477. X        default:
  1478. X            writef("Unrecognized command.\n");
  1479. X    }
  1480. X    return 1;
  1481. X}
  1482. X
  1483. Xbrch_cmd() {
  1484. X    writef("\nInterrupt\n");
  1485. X    log("Interrupt");
  1486. X    signal(SIGINT, brch_cmd);
  1487. X    longjmp(fileloop, 1);
  1488. X}
  1489. X
  1490. Xfilelist(branch)
  1491. Xchar *branch; {
  1492. X    char path[512];
  1493. X    DIR *directory;
  1494. X    struct direct *file;
  1495. X    char *desc;
  1496. X
  1497. X    sprintf(path, "%s/%s", LIBRARY, branch);
  1498. X    directory = opendir(path);
  1499. X    writef("\nFile Directory for the %s Branch:\n\n", upstr(branch));
  1500. X    while ((file = readdir(directory)) != NULL) {
  1501. X        if ((desc = whatis(branch, file->d_name)) == NULL)
  1502. X            continue;
  1503. X        writef("    %-12.12s   %s\n", cpmform(file->d_name), desc);
  1504. X    }
  1505. X    writef("\n");
  1506. X    closedir(directory);
  1507. X}
  1508. X
  1509. Xgetlist(branch)
  1510. Xchar *branch; {
  1511. X    char path[512], listfile[30], cmd[512];
  1512. X    DIR *directory;
  1513. X    struct direct *file;
  1514. X    int (*oldsig)();
  1515. X    char *desc;
  1516. X    FILE *list;
  1517. X
  1518. X    sprintf(listfile, "/tmp/cli%05d", getpid());
  1519. X    if ((list = fopen(listfile, "w")) == NULL) {
  1520. X        writef("Can't open temporary list file???\n");
  1521. X        log("Error %d opening %s", errno,listfile);
  1522. X        panic("gfl_temp");
  1523. X    }
  1524. X    writef("\nDownload file listing from the %s branch\n\nSupported transfer protocols are: Ascii, Xmodem, and Kermit.\n\nEnter File Transfer Protocol (XMODEM default): ", upstr(branch));
  1525. X    reads(cmd);
  1526. X    log("List dnld mode: %s", cmd);
  1527. X    switch (cmd[0]) {
  1528. X        case 'A':
  1529. X        case 'a':
  1530. X            if (!validudl(A_DOWNLOAD)) {
  1531. X                writef("\nAscii Download is not supported.\n");
  1532. X                log("No Ascii");
  1533. X                return;
  1534. X            }
  1535. X            sprintf(cmd, A_DOWNLOAD, listfile);
  1536. X            break;
  1537. X        case 'K':
  1538. X        case 'k':
  1539. X            if (!validudl(K_DOWNLOAD)) {
  1540. X                writef("\nKermit Download is not supported.\n");
  1541. X                log("No Kermit");
  1542. X                return;
  1543. X            }
  1544. X            sprintf(cmd, K_DOWNLOAD, listfile);
  1545. X            break;
  1546. X        case 'X':
  1547. X        case 'x':
  1548. X            if (!validudl(X_DOWNLOAD)) {
  1549. X                writef("\nXModem Download is not supported.\n");
  1550. X                log("No Xmodem");
  1551. X                return;
  1552. X            }
  1553. X            sprintf(cmd, X_DOWNLOAD, listfile);
  1554. X            break;
  1555. X        case '\0':
  1556. X            cmd[0] = 'X';
  1557. X            if (!validudl(X_DOWNLOAD)) {
  1558. X                writef("\nXModem Download is not supported.\n");
  1559. X                log("No Xmodem");
  1560. X                return;
  1561. X            }
  1562. X            sprintf(cmd, X_DOWNLOAD, listfile);
  1563. X            break;
  1564. X        default:
  1565. X            writef("Invalid protocol designation.\n");
  1566. X            return;
  1567. X    }
  1568. X    sprintf(path, "%s/%s", LIBRARY, branch);
  1569. X    directory = opendir(path);
  1570. X    fprintf(list, "File Directory for the %s Branch:\r\n\r\n", upstr(branch));
  1571. X    while ((file = readdir(directory)) != NULL) {
  1572. X        if ((desc = whatis(branch, file->d_name)) == NULL)
  1573. X            continue;
  1574. X        fprintf(list, "    %-12.12s   %s\r\n", cpmform(file->d_name), desc);
  1575. X    }
  1576. X    fclose(list);
  1577. X    closedir(directory);
  1578. X    writef("You have 30 seconds to prepare for file transmission.\nPress BREAK to abort transmission.\n\n");
  1579. X    sleep(30);
  1580. X    oldsig = signal(SIGINT, SIG_IGN);
  1581. X    udlrun(cmd, (char *) 0);
  1582. X#ifdef SYS3
  1583. X    udlrun("stty", "echoe");
  1584. X#endif SYS3
  1585. X    signal(SIGINT, oldsig);
  1586. X    unlink(listfile);
  1587. X}
  1588. X
  1589. Xdownload(branch)
  1590. Xchar *branch; {
  1591. X    char path[512], filename[512], cmd[512];
  1592. X    DIR *directory;
  1593. X    struct direct *file;
  1594. X    int (*oldsig)();
  1595. X    
  1596. X    if (user.u_access < A_FILES) {
  1597. X        log("Attempted download, access denied.");
  1598. X        writes("You may not download files.");
  1599. X        return;
  1600. X    }
  1601. X    writef("\nDownload from the %s branch\n\nEnter file to download: ", branch);
  1602. X    reads(filename);
  1603. X    log("Dnld file: %s", filename);
  1604. X    if (filename[0] == '.' || Index(filename, '/') != NULL) {
  1605. X        writef("No such file: \"%s\"\n", upstr(filename));
  1606. X        return;
  1607. X    }
  1608. X    if (whatis(branch, filename) != NULL) {
  1609. X        sprintf(path, "%s/%s", LIBRARY, branch);
  1610. X        directory = opendir(path);
  1611. X        while ((file = readdir(directory)) != NULL) {
  1612. X            if (s_cmp(file->d_name, filename) == 0) {
  1613. X                closedir(directory);
  1614. X                sprintf(path, "%s/%s/%s", LIBRARY, branch, file->d_name);
  1615. X                writef("Supported transfer protocols are: Ascii, Xmodem, and Kermit.\n\nEnter File Transfer Protocol (XMODEM default): ", upstr(branch));
  1616. X                reads(cmd);
  1617. X                switch (cmd[0]) {
  1618. X                    case 'A':
  1619. X                    case 'a':
  1620. X                        if (!validudl(A_DOWNLOAD)) {
  1621. X                            writef("\nAscii Download is not supported.\n");
  1622. X                            log("No Ascii");
  1623. X                            return;
  1624. X                        }
  1625. X                        sprintf(cmd, A_DOWNLOAD, path);
  1626. X                        break;
  1627. X                    case 'K':
  1628. X                    case 'k':
  1629. X                        if (!validudl(K_DOWNLOAD)) {
  1630. X                            writef("\nKermit Download is not supported.\n");
  1631. X                            log("No Kermit");
  1632. X                            return;
  1633. X                        }
  1634. X                        sprintf(cmd, K_DOWNLOAD, path);
  1635. X                        break;
  1636. X                    case 'X':
  1637. X                    case 'x':
  1638. X                        if (!validudl(X_DOWNLOAD)) {
  1639. X                            writef("\nXModem Download is not supported.\n");
  1640. X                            log("No Xmodem");
  1641. X                            return;
  1642. X                        }
  1643. X                        sprintf(cmd, X_DOWNLOAD, path);
  1644. X                        break;
  1645. X                    case '\0':
  1646. X                        cmd[0] = 'X';
  1647. X                        if (!validudl(X_DOWNLOAD)) {
  1648. X                            writef("\nXModem Download is not supported.\n");
  1649. X                            log("No Xmodem");
  1650. X                            return;
  1651. X                        }
  1652. X                        sprintf(cmd, X_DOWNLOAD, path);
  1653. X                        break;
  1654. X                    default:
  1655. X                        writef("Invalid protocol designation.\n");
  1656. X                        return;
  1657. X                }
  1658. X                writef("You have 30 seconds to prepare for file transmission.\nPress BREAK to abort transmission.\n\n");
  1659. X                sleep(30);
  1660. X                oldsig = signal(SIGINT, SIG_IGN);
  1661. X                udlrun(cmd, (char *) 0);
  1662. X#ifdef SYS3
  1663. X                udlrun("stty", "echoe");
  1664. X#endif SYS3
  1665. X                signal(SIGINT, oldsig);
  1666. X                return;
  1667. X            }
  1668. X        }
  1669. X        closedir(directory);
  1670. X    }
  1671. X    writef("No such file: \"%s\"\n", upstr(filename));
  1672. X    log("No such file");
  1673. X}
  1674. X
  1675. Xupload(branch)
  1676. Xchar *branch; {
  1677. X    char path[512], filename[512], cmd[512], desc[512];
  1678. X    DIR *directory;
  1679. X    struct direct *file;
  1680. X    int (*oldsig)();
  1681. X    FILE *logf;
  1682. X    
  1683. X    if (user.u_access < A_FILES) {
  1684. X        log("Attempted upload, access denied.");
  1685. X        writes("You may not upload files.");
  1686. X        return;
  1687. X    }
  1688. X    writef("\nUpload to the %s branch\n\nEnter the name to give the new file: ", branch);
  1689. X    reads(filename);
  1690. X    log("Upld file: %s", filename);
  1691. X    if (filename[0] == '.' || Index(filename, '/') != NULL || Index(filename, ';') != NULL) {
  1692. X        writef("Invalid filename: \"%s\"\n", upstr(filename));
  1693. X        log("Invalid filename");
  1694. X        return;
  1695. X    }
  1696. X    sprintf(path, "%s/%s", STORAGE, branch);
  1697. X    if ((directory = opendir(path)) == NULL) {
  1698. X        writef("The %s has denied upload ability for this branch.\n", parms.ua_sysop);
  1699. X        return;
  1700. X    }
  1701. X    while ((file = readdir(directory)) != NULL) {
  1702. X        if (s_cmp(file->d_name, filename) == 0) {
  1703. X            closedir(directory);
  1704. X            writef("That file name is used.  Please try again with a different filename.\n");
  1705. X            log("File exists");
  1706. X            return;
  1707. X        }
  1708. X    }
  1709. X    closedir(directory);
  1710. X    writef("Enter a description for the file: ");
  1711. X    reads(desc);
  1712. X    log("Description: %s", desc);
  1713. X    if ((logf = fopen(UPLOG, "a")) == NULL) {
  1714. X        log("Error %d opening %s", errno, UPLOG);
  1715. X        writef("Can't log the new file.\n");
  1716. X        return;
  1717. X    }
  1718. X    fprintf(logf, "%s file %s; %s by %s: %s\n", branch, filename, today(), upstr(user.u_name), desc);
  1719. X    fclose(logf);
  1720. X    sprintf(path, "%s/%s/%s", STORAGE, branch, filename);
  1721. X    writef("Supported transfer protocols are: Ascii, Xmodem, and Kermit.\nXmodem protocol uses checksums; CCITT CRC is not supported.\n\nEnter File Transfer Protocol (XMODEM default): ", upstr(branch));
  1722. X    reads(cmd);
  1723. X    log("Upld protocol: %s", cmd);
  1724. X    switch (cmd[0]) {
  1725. X        case 'A':
  1726. X        case 'a':
  1727. X            if (!validudl(A_UPLOAD)) {
  1728. X                writef("\nAscii Upload is not supported.\n");
  1729. X                log("No Ascii");
  1730. X                return;
  1731. X            }
  1732. X            sprintf(cmd, A_UPLOAD, path);
  1733. X            break;
  1734. X        case 'K':
  1735. X        case 'k':
  1736. X            if (!validudl(K_UPLOAD)) {
  1737. X                writef("\nKermit Upload is not supported.\n");
  1738. X                log("No Kermit");
  1739. X                return;
  1740. X            }
  1741. X            sprintf(cmd, K_UPLOAD, path);
  1742. X            break;
  1743. X        case 'X':
  1744. X        case 'x':
  1745. X            if (!validudl(X_UPLOAD)) {
  1746. X                writef("\nXModem Upload is not supported.\n");
  1747. X                log("No Xmodem");
  1748. X                return;
  1749. X            }
  1750. X            sprintf(cmd, X_UPLOAD, path);
  1751. X            break;
  1752. X        case '\0':
  1753. X            cmd[0] = 'X';
  1754. X            if (!validudl(X_UPLOAD)) {
  1755. X                writef("\nXModem Upload is not supported.\n");
  1756. X                log("No Xmodem");
  1757. X                return;
  1758. X            }
  1759. X            sprintf(cmd, X_UPLOAD, path);
  1760. X            break;
  1761. X        default:
  1762. X            writef("Invalid protocol designation.\n");
  1763. X            return;
  1764. X    }
  1765. X    writef("You have 30 seconds to prepare for file transmission.\nPress BREAK to abort transmission.\n\n");
  1766. X    sleep(30);
  1767. X    oldsig = signal(SIGINT, SIG_IGN);
  1768. X    udlrun(cmd, (char *) 0);
  1769. X#ifdef SYS3
  1770. X    udlrun("stty", "echoe");
  1771. X#endif SYS3
  1772. X    signal(SIGINT, oldsig);
  1773. X}
  1774. X
  1775. Xchar *whatis(branch, file)
  1776. Xchar *branch, *file; {
  1777. X    static FILE *directory = NULL;
  1778. X    static char dent[512];
  1779. X    char tbr[512], tfi[512], fdate[512], who[512], desc[512];
  1780. X    
  1781. X    if (directory != NULL || (directory = fopen(DIRECTORY, "r")) != NULL) {
  1782. X        fseek(directory, 0L, 0);
  1783. X        while (fgets(dent, sizeof dent, directory) != NULL) {
  1784. X            if (dent[0] == '%' || dent[0] == '\n')
  1785. X                continue;
  1786. X            tbr[0] = '\0';
  1787. X            tfi[0] = '\0';
  1788. X            fdate[0] = '\0';
  1789. X            who[0] = '\0';
  1790. X            desc[0] = '\0';
  1791. X            if (sscanf(dent, DIRFORMAT, tbr, tfi, fdate, who, desc) != 5)
  1792. X                continue;
  1793. X            if (s_cmp(tbr, branch) == 0) {
  1794. X                if (s_cmp(tfi, (file == NULL? "branch": file)) != 0)
  1795. X                    continue;
  1796. X                sprintf(dent, "%s [Created %s by %s]", desc, fdate, who);
  1797. X                return dent;
  1798. X            }
  1799. X        }
  1800. X    }
  1801. X    if (directory == NULL)
  1802. X        log("No download directory");
  1803. X    return NULL;
  1804. X}
  1805. X
  1806. Xchar *cpmform(fn)
  1807. Xchar *fn; {
  1808. X    static char buf[13];
  1809. X    register int cnt, scnt;
  1810. X    
  1811. X    for (scnt = 0, cnt = 0; cnt < 8 && fn[cnt] != '.' && fn[cnt] != '\0'; cnt++, scnt++)
  1812. X        buf[scnt] = ToUpper(fn[cnt]);
  1813. X    while (scnt < 8)
  1814. X        buf[scnt++] = ' ';
  1815. X    buf[scnt++] = '.';
  1816. X    while (fn[cnt] != '.' && fn[cnt] != '\0')
  1817. X        cnt++;
  1818. X    if (fn[cnt] == '.')
  1819. X        cnt++;
  1820. X    while (scnt < 12 && fn[cnt] != '\0') {
  1821. X        buf[scnt++] = ToUpper(fn[cnt]);
  1822. X        cnt++;
  1823. X    }
  1824. X    while (scnt < 12)
  1825. X        buf[scnt++] = ' ';
  1826. X    buf[scnt] = '\0';
  1827. X    return buf;
  1828. X}
  1829. X
  1830. Xvalidudl(cmd)
  1831. Xchar *cmd; {
  1832. X    if (cmd[0] == '\0')
  1833. X        return 0;
  1834. X    if (Index(cmd, '%') != RIndex(cmd, '%'))
  1835. X        return 0;
  1836. X    if (Index(cmd, '%') == (char *) 0) {
  1837. X        strcat(cmd, " %s");
  1838. X        return 1;
  1839. X    }
  1840. X    if (*(Index(cmd, '%') + 1) != 's')
  1841. X        return 0;
  1842. X    return 1;
  1843. X}
  1844. X
  1845. Xudlrun(cmd, arg)
  1846. Xchar *cmd, *arg; {
  1847. X    int pid, sig, status;
  1848. X
  1849. X    switch (pid = fork()) {
  1850. X    case -1:
  1851. X        log("Error %d on fork for udlrun", errno);
  1852. X        writes("The system is too busy; try again later.");
  1853. X        return -1;
  1854. X    case 0:
  1855. X        for (sig = SIGINT; sig <= SIGTERM; sig++)
  1856. X            signal(sig, SIG_DFL);
  1857. X        setuid(getuid());
  1858. X        run(cmd, arg);
  1859. X        exit(-1);
  1860. X    default:
  1861. X        CRIT();
  1862. X        io_off();
  1863. X        for (sig = SIGIOT; sig <= SIGTERM; sig++)
  1864. X            signal(sig, SIG_IGN);
  1865. X        while (wait(&status) != pid)
  1866. X            ;
  1867. X        if (status != 0) {
  1868. X            log("Status from \"%s %s\": %d", cmd, arg, status);
  1869. X            writes("Error executing UDL program");
  1870. X        }
  1871. X        for (sig = SIGIOT; sig <= SIGTERM; sig++)
  1872. X            signal(sig, logsig);
  1873. X        signal(SIGALRM, thatsall);
  1874. X        io_on(0);
  1875. X        NOCRIT();
  1876. X    }
  1877. X    return 1;
  1878. X}
  1879. ________This_Is_The_END________
  1880. echo 'x - io.c'
  1881. sed 's/^X//' << '________This_Is_The_END________' > io.c
  1882. X/*
  1883. X *    @(#)io.c    1.2 (TDI) 2/3/87
  1884. X *    @(#)Copyright (C) 1984, 85, 86, 87 by Brandon S. Allbery.
  1885. X *    @(#)This file is part of UNaXcess version 1.0.2.
  1886. X *
  1887. X *    Permission is hereby granted to copy and distribute this program
  1888. X *    freely.  Permission is NOT given to modify this program or distribute
  1889. X *    it at cost, except for charging a reasonable media/copying fee.
  1890. X */
  1891. X
  1892. X#ifndef lint
  1893. Xstatic char _FileID_[] = "@(#)io.c    1.1 (TDI) 2/3/87";
  1894. Xstatic char _UAID_[]   = "@(#)UNaXcess version 1.0.2";
  1895. X#endif lint
  1896. X
  1897. X#include "ua.h"
  1898. X#include <varargs.h>
  1899. X
  1900. X#define linelen    user.u_llen
  1901. X#define pagelen    user.u_lines
  1902. X
  1903. X#ifdef SYS3
  1904. X#  include <sys/ioctl.h>
  1905. X#  include <termio.h>
  1906. X#  define TERMPARAMS        struct termio
  1907. X#  define GETPARAMS(fd, buf)    ioctl(fd, TCGETA, buf)
  1908. X#  define SETPARAMS(fd, buf)    ioctl(fd, TCSETAW, buf)
  1909. X#  define TERM_CHARMODE(buf)    ((buf)->c_lflag &= ~(ICANON|ECHO), (buf)->c_cc[VMIN] = 1, (buf)->c_cc[VTIME] = 0)    /* OOPS!  2/3/87 ++bsa */
  1910. X#else
  1911. X#  include <sgtty.h>
  1912. X#  ifdef V7
  1913. X#    define SETPARAMS(fd, buf)    gtty(fd, buf)
  1914. X#    define SETPARAMS(fd, buf)    stty(fd, buf)
  1915. X#    define TERMPARAMS        struct sgttyb
  1916. X#    define TERM_CHARMODE(buf)    ((buf)->sg_flags &= ~ECHO, (buf)->sg_flags |= RAW)    /* OOPS!  2/3/87 ++bsa */
  1917. X#  else
  1918. X#    include <sys/ioctl.h>
  1919. X#    define GETPARAMS(fd, buf)    (ioctl(fd, TIOCGETP, &((*(buf)).__tp)), ioctl(fd, TIOCGETC, &((*(buf)).__tc)))
  1920. X#    define SETPARAMS(fd, buf)    (ioctl(fd, TIOCSETN, &((*(buf)).__tp)), ioctl(fd, TIOCSETC, &((*(buf)).__tc)))
  1921. X#    define TERMPARAMS        struct { struct sgttyb __tp; struct tchars __tc; }
  1922. X#    define TERM_CHARMODE(buf)    ((buf)->__tp.sg_flags &= ~ECHO, (buf)->__tp.sg_flags |= CBREAK, (buf)->__tc.t_intrc = '\003')    /* OOPS!  2/387 ++bsa */
  1923. X#  endif V7
  1924. X#endif SYS3
  1925. X
  1926. Xstatic int __pager = -1, __wrap, __bwrap, __col, __didwrp, __suppsp, __echo;
  1927. Xstatic TERMPARAMS __oldterm, __newterm;
  1928. Xstatic char __buf[133];
  1929. Xstatic char *__bufp;
  1930. Xstatic char __so_buf[BUFSIZ];
  1931. X
  1932. Xio_on(flag) {
  1933. X    setbuf(stdout, __so_buf);
  1934. X    __pager = 1;
  1935. X    __wrap = 1;
  1936. X    __echo = 1;
  1937. X    __bwrap = 1;
  1938. X    __didwrp = 0;
  1939. X    __col = 0;
  1940. X    __suppsp = 0;
  1941. X    __bufp = __buf;
  1942. X    if (flag) {
  1943. X        user.u_lines = 16;
  1944. X        user.u_llen = 80;
  1945. X    }
  1946. X    if (GETPARAMS(fileno(stdin), &__oldterm) < 0)
  1947. X        return;
  1948. X    __newterm = __oldterm;
  1949. X    TERM_CHARMODE(&__newterm);
  1950. X    SETPARAMS(fileno(stdout), &__newterm);
  1951. X}
  1952. X
  1953. Xio_off() {
  1954. X    if (__pager == -1)
  1955. X        return;
  1956. X    __flushwd();
  1957. X    SETPARAMS(fileno(stdout), &__oldterm);
  1958. X}
  1959. X
  1960. Xwritec(ch)
  1961. Xregister char ch; {
  1962. X    register int cnt;
  1963. X    register char *cp;
  1964. X
  1965. X    ch &= 0x7f;
  1966. X    if (ch == '\t') {
  1967. X        do {
  1968. X            writec(' ');
  1969. X        } while (__col % 8 != 0);
  1970. X        return;
  1971. X    }
  1972. X    if (ch < ' ' && ch != '\r' && ch != '\n' && ch != '\b') {
  1973. X        writec('^');
  1974. X        writec(uncntrl(ch));
  1975. X        return;
  1976. X    }
  1977. X    if (ch == '\177') {
  1978. X        writec('^');
  1979. X        writec('?');
  1980. X        return;
  1981. X    }
  1982. X    if (!__wrap) {
  1983. X        __outch(ch);
  1984. X        return;
  1985. X    }
  1986. X    __didwrp = 0;
  1987. X    if (!__bwrap) {
  1988. X        if (__col == linelen - 1 && ch != '\b' && ch != '\r' && ch != '\n') {
  1989. X            for (cnt = 0; &__buf[cnt] < __bufp; cnt++)
  1990. X                __didwrp++;
  1991. X            for (cp = __bufp - 1; cp >= __buf; cp--) {
  1992. X                __outch('\b');
  1993. X                __outch(' ');
  1994. X                __outch('\b');
  1995. X                if (*cp == '\177' || *cp < ' ') {
  1996. X                    __outch('\b');
  1997. X                    __outch(' ');
  1998. X                    __outch('\b');
  1999. X                }
  2000. X            }
  2001. X            __outch('\n');
  2002. X            __suppsp = 1;
  2003. X            for (cp++; cp < __bufp; cp++)
  2004. X                __outch(*cp);
  2005. X        }
  2006. X        __outch(ch);
  2007. X        fflush(stdout);
  2008. X    }
  2009. X    if (ch == ' ' || ch == '\n') {
  2010. X        if (__bwrap)
  2011. X            __flushwd();
  2012. X        __bufp = __buf;
  2013. X        if (__bwrap) {
  2014. X            if (ch == ' ') {
  2015. X                if (!__suppsp)
  2016. X                    __outch(' ');
  2017. X            }
  2018. X            if (ch == '\n')
  2019. X                __outch('\n');
  2020. X        }
  2021. X        return;
  2022. X    }
  2023. X    __suppsp = 0;
  2024. X    *__bufp = '\0';
  2025. X    if (__bwrap && strlen(__buf) == linelen - 1) {
  2026. X        __outch('\n');
  2027. X        __suppsp = 1;
  2028. X        for (__bufp = __buf; *__bufp != '\0'; __bufp++)
  2029. X            if (*__bufp != ' ' || !__suppsp) {
  2030. X                __outch(*__bufp);
  2031. X                __suppsp = 0;
  2032. X            }
  2033. X        __outch('\n');
  2034. X        __bufp = __buf;
  2035. X        __suppsp = 1;
  2036. X        return;
  2037. X    }
  2038. X    *__bufp++ = ch;
  2039. X}
  2040. X
  2041. X__outch(ch)
  2042. Xregister char ch; {
  2043. X    switch (ch) {
  2044. X    case '\n':
  2045. X        putchar('\r');
  2046. X        putchar('\n');
  2047. X        __col = 0;
  2048. X        if (pagelen > 0 && __pager > 0 && ++__pager == pagelen) {
  2049. X            fputs("--More--", stdout);
  2050. X            fflush(stdout);
  2051. X            ch = getchar();
  2052. X            __pager = 1;
  2053. X            fputs("\b \b\b \b\b \b\b \b\b \b\b \b\b \b\b \b", stdout);
  2054. X        }
  2055. X        fflush(stdout);
  2056. X        __suppsp = 0;
  2057. X        break;
  2058. X    case '\r':
  2059. X        putchar('\r');
  2060. X        __col = 0;
  2061. X        __suppsp = 0;
  2062. X        break;
  2063. X    case '\b':
  2064. X        if (__col == 0)
  2065. X            break;
  2066. X        putchar('\b');
  2067. X        __col--;
  2068. X        __suppsp = 0;
  2069. X        break;
  2070. X    default:
  2071. X        if (__col == linelen - 1) {
  2072. X            __outch('\n');
  2073. X            __suppsp = 1;
  2074. X        }
  2075. X        if (ch < ' ' || ch > '~')
  2076. X            putchar('.');
  2077. X        else if (ch != ' ' || !__suppsp) {
  2078. X            putchar(ch);
  2079. X            __suppsp = 0;
  2080. X        }
  2081. X        __col++;
  2082. X        break;
  2083. X    }
  2084. X}
  2085. X
  2086. Xwrites(str)
  2087. Xregister char *str; {
  2088. X    for (; *str != '\0'; str++)
  2089. X        writec(*str);
  2090. X    writec('\n');
  2091. X}
  2092. X
  2093. X/*VARARGS*/
  2094. Xwritef(va_alist)
  2095. Xva_dcl {
  2096. X    register va_list args;
  2097. X    register char *fmt;
  2098. X    register char esch;
  2099. X    register short esclen;
  2100. X    short lzflag, ljflag, width, prec, longf, precf;
  2101. X    
  2102. X    va_start(args);
  2103. X    for (fmt = va_arg(args, char *); *fmt != '\0'; fmt++) {
  2104. X        if (*fmt == '\\')
  2105. X            switch (*++fmt) {
  2106. X            case '\0':
  2107. X                va_end(args);
  2108. X                return;
  2109. X            case 'n':
  2110. X                writec('\n');
  2111. X                break;
  2112. X            case 't':
  2113. X                writec('\t');
  2114. X                break;
  2115. X            case 'r':
  2116. X                writec('\r');
  2117. X                break;
  2118. X            case 'b':
  2119. X                writec('\b');
  2120. X                break;
  2121. X            case 'f':
  2122. X                writec('\f');
  2123. X                break;
  2124. X            case '0':
  2125. X            case '1':
  2126. X            case '2':
  2127. X            case '3':
  2128. X            case '4':
  2129. X            case '5':
  2130. X            case '7':
  2131. X                esch = '\0';
  2132. X                for (esclen = 0; esclen < 3; esclen++) {
  2133. X                    esch = esch << 3;
  2134. X                    esch += *fmt - '0';
  2135. X                    if (*++fmt != '0' &&
  2136. X                          *fmt != '1' &&
  2137. X                          *fmt != '2' &&
  2138. X                          *fmt != '3' &&
  2139. X                          *fmt != '4' &&
  2140. X                          *fmt != '5' &&
  2141. X                          *fmt != '6' &&
  2142. X                          *fmt != '7')
  2143. X                              break;
  2144. X                }
  2145. X                writec(esch);
  2146. X                break;
  2147. X            default:
  2148. X                writec(*fmt);
  2149. X                break;
  2150. X            }
  2151. X        else if (*fmt != '%')
  2152. X            writec(*fmt);
  2153. X        else {
  2154. X            lzflag = 0;
  2155. X            ljflag = 0;
  2156. X            width = 0;
  2157. X            prec = 0;
  2158. X            longf = 0;
  2159. X            precf = 0;
  2160. X
  2161. Xmorefmt:
  2162. X            switch (*++fmt) {
  2163. X            case '\0':
  2164. X                writec('%');
  2165. X                va_end(args);
  2166. X                return;
  2167. X            case 'c':
  2168. X                __fmtc(va_arg(args, int), ljflag, width);
  2169. X                break;
  2170. X            case 'd':
  2171. X                if (longf)
  2172. X                    __fmti(va_arg(args, long), lzflag, ljflag, width, 10);
  2173. X                else
  2174. X                    __fmti((long) va_arg(args, int), lzflag, ljflag, width, 10);
  2175. X                break;
  2176. X            case 'x':
  2177. X                if (longf)
  2178. X                    __fmti(va_arg(args, long), lzflag, ljflag, width, 16);
  2179. X                else
  2180. X                    __fmti((long) va_arg(args, int), lzflag, ljflag, width, 16);
  2181. X                break;
  2182. X            case 'o':
  2183. X                if (longf)
  2184. X                    __fmti(va_arg(args, long), lzflag, ljflag, width, 8);
  2185. X                else
  2186. X                    __fmti((long) va_arg(args, int), lzflag, ljflag, width, 8);
  2187. X                break;
  2188. X            case 's':
  2189. X                __fmts(va_arg(args, char *), ljflag, width, prec);
  2190. X                break;
  2191. X            case 'f':
  2192. X                __fmtf(va_arg(args, double), ljflag, width, prec);
  2193. X                break;
  2194. X            case 'e':
  2195. X                __fmte(va_arg(args, double), ljflag, width, prec);
  2196. X                break;
  2197. X            case 'g':
  2198. X                __fmtg(va_arg(args, double), ljflag, width, prec);
  2199. X                break;
  2200. X            case 'l':
  2201. X                if (longf)
  2202. X                    break;
  2203. X                longf = 1;
  2204. X                goto morefmt;
  2205. X            case '-':
  2206. X                if (precf || width > 0 || lzflag || ljflag)
  2207. X                    break;
  2208. X                ljflag = 1;
  2209. X                goto morefmt;
  2210. X            case '*':
  2211. X                if (!precf)
  2212. X                    if (width != 0) {
  2213. X                        writec('*');
  2214. X                        break;
  2215. X                    }
  2216. X                    else
  2217. X                        width = va_arg(args, int);
  2218. X                else if (prec != 0) {
  2219. X                    writec('*');
  2220. X                    break;
  2221. X                }
  2222. X                else
  2223. X                    prec = va_arg(args, int);
  2224. X                goto morefmt;
  2225. X            case '0':
  2226. X                if (!precf && width == 0)
  2227. X                    lzflag = 1;
  2228. X                else if (precf)
  2229. X                    prec *= 10;
  2230. X                else
  2231. X                    width *= 10;
  2232. X                goto morefmt;
  2233. X            case '1':
  2234. X            case '2':
  2235. X            case '3':
  2236. X            case '4':
  2237. X            case '5':
  2238. X            case '6':
  2239. X            case '7':
  2240. X            case '8':
  2241. X            case '9':
  2242. X                if (precf) {
  2243. X                    prec *= 10;
  2244. X                    prec += *fmt - '0';
  2245. X                }
  2246. X                else {
  2247. X                    width *= 10;
  2248. X                    width += *fmt - '0';
  2249. X                }
  2250. X                goto morefmt;
  2251. X            case '.':
  2252. X                if (precf)
  2253. X                    break;
  2254. X                precf = 1;
  2255. X                goto morefmt;
  2256. X            default:
  2257. X                break;
  2258. X            }
  2259. X        }
  2260. X    }
  2261. X    va_end(args);
  2262. X}
  2263. X
  2264. X__fmtc(ch, ljflag, width)
  2265. Xregister int width; {
  2266. X    if (width > 255)
  2267. X        width = 255;
  2268. X    if (width < 2) {
  2269. X        writec(ch);
  2270. X        return;
  2271. X    }
  2272. X    width--;
  2273. X    if (!ljflag)
  2274. X        while (width-- > 0)
  2275. X            writec(' ');
  2276. X    writec(ch);
  2277. X    if (ljflag)
  2278. X        while (width-- > 0)
  2279. X            writec(' ');
  2280. X}
  2281. X
  2282. X__fmts(str, ljflag, width, prec)
  2283. Xregister char *str;
  2284. Xregister int width, prec; {
  2285. X    register int len;
  2286. X
  2287. X    if (str == (char *) 0)
  2288. X        str = "(null)";
  2289. X    if (prec == 0)
  2290. X        prec = strlen(str);
  2291. X    for (len = 0; str[len] != '\0' && len < prec; len++)
  2292. X        ;
  2293. X    if (width < len)
  2294. X        width = 0;
  2295. X    else
  2296. X        width -= len;
  2297. X    if (!ljflag)
  2298. X        while (width-- > 0)
  2299. X            writec(' ');
  2300. X    while (len-- > 0)
  2301. X        writec(*str++);
  2302. X    if (ljflag)
  2303. X        while (width-- > 0)
  2304. X            writec(' ');
  2305. X}
  2306. X
  2307. X__fmti(num, lzflag, ljflag, width, base)
  2308. Xlong num;
  2309. Xregister int width; {
  2310. X    char buf[19];
  2311. X    char *bufp, *dp;
  2312. X    int sign;
  2313. X    static char digit[] = "0123456789ABCDEF";
  2314. X    
  2315. X    sign = 0;
  2316. X    if (num < 0L) {
  2317. X        num = -num;
  2318. X        sign = 1;
  2319. X    }
  2320. X    if (width > 18)
  2321. X        width = 18;
  2322. X    bufp = &buf[width? width: 18];
  2323. X    *bufp-- = '\0';
  2324. X    while (bufp >= buf) {
  2325. X        *bufp-- = digit[num % base];
  2326. X        num /= base;
  2327. X    }
  2328. X    for (bufp = buf; *bufp == '0'; bufp++)
  2329. X        ;
  2330. X    if (*bufp == '\0')
  2331. X        bufp--;
  2332. X    width -= strlen(bufp) + sign;
  2333. X    if (width < 0)
  2334. X        width = 0;
  2335. X    if (lzflag)
  2336. X        ljflag = 0;
  2337. X    if (!ljflag)
  2338. X        while (width-- > 0)
  2339. X            writec(lzflag? '0': ' ');
  2340. X    if (sign)
  2341. X        writec('-');
  2342. X    while (*bufp != '\0')
  2343. X        writec(*bufp++);
  2344. X    if (ljflag)
  2345. X        while (width-- > 0)
  2346. X            writec(' ');
  2347. X}
  2348. X
  2349. X__fmte(num, ljflag, width, prec)
  2350. Xdouble num;
  2351. Xregister int width; {
  2352. X    char buf[20];
  2353. X    int isneg, expon;
  2354. X    register char *bufp;
  2355. X    
  2356. X    if (width > 18)
  2357. X        width = 18;
  2358. X    strcpy(buf, ecvt(num, (prec? prec: 18) - 6 - (num < 0.0), &expon, &isneg));
  2359. X    if (prec == 0)
  2360. X        for (bufp = &buf[12 - (num < 0.0? 1: 0)]; bufp != buf && *bufp != '\0'; bufp--)
  2361. X            *bufp = '\0';
  2362. X    if (width < strlen(buf) + 6 + (num < 0.0? 1: 0))
  2363. X        width = strlen(buf) + 6 + (num < 0.0? 1: 0);
  2364. X    width -= strlen(buf) + 6 + (num < 0.0);
  2365. X    if (!ljflag)
  2366. X        while (width-- > 0)
  2367. X            writec(' ');
  2368. X    if (isneg)
  2369. X        writec('-');
  2370. X    writec('.');
  2371. X    for (bufp = buf; *bufp != '\0'; bufp++)
  2372. X        writec(*bufp);
  2373. X    writec('E');
  2374. X    writec(expon < 0? '-': '+');
  2375. X    __fmti((long) expon, 1, 0, 2, 10);
  2376. X    if (ljflag)
  2377. X        while (width-- > 0)
  2378. X            writec(' ');
  2379. X}
  2380. X
  2381. X__fmtf(num, ljflag, width, prec)
  2382. Xdouble num;
  2383. Xregister int width; {
  2384. X    char buf[40];
  2385. X    int isneg, expon;
  2386. X    register char *bufp;
  2387. X    
  2388. X    if (width > 18)
  2389. X        width = 18;
  2390. X    strcpy(buf, ecvt(num, prec, &expon, &isneg));
  2391. X    if (width < strlen(buf) + 1 + (num < 0.0))
  2392. X        width = strlen(buf) + 1 + (num < 0.0);
  2393. X    width -= strlen(buf) + 1 + (num < 0.0);
  2394. X    if (!ljflag)
  2395. X        while (width-- > 0)
  2396. X            writec(' ');
  2397. X    if (isneg)
  2398. X        writec('-');
  2399. X    for (bufp = buf; *bufp != '\0'; bufp++) {
  2400. X        if (expon-- == 0)
  2401. X            writec('.');
  2402. X        writec(*bufp);
  2403. X    }
  2404. X    if (expon == 0)
  2405. X        writec('.');
  2406. X    if (ljflag)
  2407. X        while (width-- > 0)
  2408. X            writec(' ');
  2409. X}
  2410. X
  2411. X__fmtg(num, ljflag, width, prec)
  2412. Xdouble num;
  2413. Xregister int width; {
  2414. X    char buf[40];
  2415. X    register char *bufp;
  2416. X    
  2417. X    if (width > 18)
  2418. X        width = 18;
  2419. X    strcpy(buf, gcvt(num, prec, buf));
  2420. X    if (width < strlen(buf))
  2421. X        width = strlen(buf);
  2422. X    width -= strlen(buf);
  2423. X    if (!ljflag)
  2424. X        while (width-- > 0)
  2425. X            writec(' ');
  2426. X    for (bufp = buf; *bufp != '\0'; bufp++)
  2427. X        writec(*bufp);
  2428. X    if (ljflag)
  2429. X        while (width-- > 0)
  2430. X            writec(' ');
  2431. X}
  2432. X
  2433. Xchar *reads(buf)
  2434. Xchar *buf; {
  2435. X    short bp;
  2436. X    int savecol, rpos;
  2437. X    char ch;
  2438. X    
  2439. X    savecol = __col;
  2440. X    __pager = 0;
  2441. X    __wrap = 0;
  2442. X    __flushwd();
  2443. X    bp = 0;
  2444. X    fflush(stdout);
  2445. X    while ((ch = getchar() & 0x7f) != '\n' && ch != '\r') {
  2446. X        switch (ch) {
  2447. X        case '\177':
  2448. X        case '\b':
  2449. X            if (bp == 0)
  2450. X                putchar('\7');
  2451. X            else {
  2452. X                bp--;
  2453. X                if (__echo) {
  2454. X                    if (__col > 0) {
  2455. X                        writec('\b');
  2456. X                        writec(' ');
  2457. X                        writec('\b');
  2458. X                    }
  2459. X                    else {
  2460. X                        if (bp - linelen < -1) {
  2461. X                            while (__col < savecol)
  2462. X                                writec(' ');
  2463. X                            rpos = 0;
  2464. X                        }
  2465. X                        else
  2466. X                            rpos = bp - linelen + 1;
  2467. X                        while (rpos < bp)
  2468. X                            writec(buf[rpos++]);
  2469. X                    }
  2470. X                }
  2471. X            }
  2472. X            break;
  2473. X        case '\030':
  2474. X        case '\025':
  2475. X            if (__echo) {
  2476. X                writec('X');
  2477. X                writec('X');
  2478. X                writec('X');
  2479. X                writec('\n');
  2480. X                while (__col < savecol)
  2481. X                    writec(' ');
  2482. X            }
  2483. X            bp = 0;
  2484. X            break;
  2485. X        default:
  2486. X            if (ch < ' ' || bp == 255)
  2487. X                putchar('\7');
  2488. X            else {
  2489. X                if (__echo)
  2490. X                    __outch(ch);
  2491. X                buf[bp++] = ch;
  2492. X            }
  2493. X        }
  2494. X        fflush(stdout);
  2495. X    }
  2496. X    writec('\n');
  2497. X    fflush(stdout);
  2498. X    __wrap = 1;
  2499. X    __pager = 1;
  2500. X    buf[bp] = '\0';
  2501. X    return buf;
  2502. X}
  2503. X
  2504. Xinteract() {
  2505. X    __flushwd();
  2506. X    __bwrap = 0;
  2507. X    __pager = 0;
  2508. X}
  2509. X
  2510. Xbuffer() {
  2511. X    __bwrap = 1;
  2512. X    __bufp = __buf;
  2513. X    __pager = 1;
  2514. X}
  2515. X
  2516. Xwrapped() {
  2517. X    return __didwrp;
  2518. X}
  2519. X
  2520. X__flushwd() {
  2521. X    *__bufp = '\0';
  2522. X    if (strlen(__buf) >= linelen - __col) {
  2523. X        __outch('\n');
  2524. X        __suppsp = 1;
  2525. X    }
  2526. X    for (__bufp = __buf; *__bufp != '\0'; __bufp++)
  2527. X        if (*__bufp != ' ' || !__suppsp) {
  2528. X            __outch(*__bufp);
  2529. X            __suppsp = 0;
  2530. X        }
  2531. X    __bufp = __buf;
  2532. X    fflush(stdout);
  2533. X}
  2534. X
  2535. Xdoecho() {
  2536. X    __echo = 1;
  2537. X}
  2538. X
  2539. Xxecho() {
  2540. X    __echo = 0;
  2541. X}
  2542. X
  2543. Xcat(file)
  2544. Xchar *file; {
  2545. X    FILE *f;
  2546. X    int ch;
  2547. X
  2548. X    if ((f = fopen(file, "r")) == NULL) {
  2549. X        log("Error %d opening %s", errno, file);
  2550. X        writes("Cannot open file.");
  2551. X        return;
  2552. X    }
  2553. X    while ((ch = getc(f)) != EOF)
  2554. X        writec(ch);
  2555. X    fclose(f);
  2556. X}
  2557. X
  2558. Xreadc() {
  2559. X    char ch;
  2560. X    
  2561. X    __flushwd();
  2562. X    __pager = 0;
  2563. X    while (((ch = getchar() & 0x7f) < ' ' && ch != '\r' && ch != '\n') || ch == '\177') {
  2564. X        putchar('\7');
  2565. X        fflush(stdout);
  2566. X    }
  2567. X    if (ch > ' ') {
  2568. X        ch = ToUpper(ch);
  2569. X        writec(ch);
  2570. X    }
  2571. X    else
  2572. X        ch = ' ';
  2573. X    writec('\n');
  2574. X    fflush(stdout);
  2575. X    __pager = 1;
  2576. X    return ch;
  2577. X}
  2578. ________This_Is_The_END________
  2579. exit 0
  2580. --
  2581. ++Brandon (Resident Elf @ ncoast.UUCP)
  2582.  ____   ______________
  2583. /    \ / __   __   __ \   Brandon S. Allbery        <backbone>!ncoast!allbery
  2584.  ___  | /__> /  \ /  \    aXcess Co., Consulting    ncoast!allbery@Case.CSNET
  2585. /   \ | |    `--, `--,    6615 Center St. #A1-105        (...@relay.CS.NET)
  2586. |     | \__/ \__/ \__/    Mentor, OH 44060-4101     
  2587. \____/ \______________/   +1 216 781 6201
  2588.  
  2589.  
  2590.