home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume10 / pcmail2 / part05 < prev    next >
Text File  |  1990-01-24  |  65KB  |  2,216 lines

  1. Newsgroups: comp.sources.misc
  2. subject: v10i037: PC-MAIL release 2, 5/11
  3. from: wswietse@lso.win.tue.nl (Wietse Venema)
  4. Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
  5.  
  6. Posting-number: Volume 10, Issue 37
  7. Submitted-by: wswietse@lso.win.tue.nl (Wietse Venema)
  8. Archive-name: pcmail2/part05
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 5 (of 11)."
  17. # Contents:  main/GNUUCP.ins main/SLAVE.ins main/ascf.c main/gp.h
  18. #   main/kio.c main/kpres.c main/ktrans.c main/logs.c main/path.h
  19. #   main/reply.c main/spoolfil.c
  20. # Wrapped by wswietse@tuewsa on Mon Jan 22 17:27:17 1990
  21. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  22. if test -f main/GNUUCP.ins -a "${1}" != "-c" ; then 
  23.   echo shar: Will not over-write existing file \"main/GNUUCP.ins\"
  24. else
  25. echo shar: Extracting \"main/GNUUCP.ins\" \(4914 characters\)
  26. sed "s/^X//" >main/GNUUCP.ins <<'END_OF_main/GNUUCP.ins'
  27. X@(#) GNUUCP.ins 2.1 90/01/22 13:01:07
  28. X
  29. XThis document describes how to install the PC-mail software in an
  30. Xenvironment that uses GNUUCP as the message transport mechanism.  GNUUCP
  31. Xruns under more operating systems than just UNIX and MS-DOS, and offers
  32. Xfar more features than the rather minimal "cico" program for dial-up
  33. Xand file transfer. The programs that interface between GNUUCP and PC-mail
  34. Xhave undergone only little testing.
  35. X
  36. XIn order to use PC-mail in combination with GNUUCP, edit the makefile
  37. Xaccording to the directions given in that file (or execute the commands
  38. Xin the GNUUCP.bat file if you are using MS-DOS and do not have a decent
  39. Xmake program).  This disables several features in the user interface
  40. Xprogram that are not needed when GNUUCP takes care of message transport.
  41. XUnder MS-DOS, make sure that the large memory model is selected.
  42. X
  43. XSaying `make' should produce the following programs:
  44. X
  45. X - mail, the menu-driven user interface
  46. X - cmail, a program that checks if there is new mail
  47. X - smail, a program that queues messages for transmission after
  48. X      doing alias substitution on mail addresses
  49. X - nmail, extracts "From" and "Subject" info from new mail
  50. X - gmail, searches the PC-mail messade data base for unsent mail,
  51. X          and gives it to GNUUCP for delivery.  This program should
  52. X          be invoked upon exit from the "mail" program (see the 
  53. X      description of the MAILCMD enverionment variable lateron).
  54. X - lmail, installs mail received via GNUUCP into the PC-mail data base
  55. X      Since this program is to invoked by the GNUUCP "rmail" program,
  56. X      instead of the name "lmail" the program will probably have 
  57. X      to be given a different name; this depends on how the GNUUCP 
  58. X      "rmail" is configured.
  59. X
  60. XThe programs access a common data base in the form of a spool directory
  61. Xwith a setup file and message files.  Optionally there may be an alias
  62. Xfile, and header and trailer files to generate template messages.  There
  63. Xshould be no other files in the spool directory, to avoid confusion.
  64. XThe spool directory should be created by hand; the PC-mail programs will
  65. Xnot do that.
  66. X
  67. XYou will have to set some environment variables before running the mail
  68. Xprograms.
  69. X
  70. X - MAILDIR, the location of your mail data base directory
  71. X - EDITOR, the name of your favourite editor program
  72. X - PATH, in order locate the PC-mail executables, and your editor
  73. X
  74. XIt is advised to use absolute path names that include the drive name.
  75. XThe editor command may be an MS-DOS batch file; in that case you should
  76. Xinclude the '.bat' suffix in the command name.
  77. X
  78. XThe following two environment variables are optional.
  79. X
  80. X - MAILPRN, the name of a file, if printer output should not go to 
  81. X        the default printer.
  82. X - MAILCMD, a command that is executed  on  exit  from  the  mail
  83. X        program. If this is an MS-DOS batch file you should 
  84. X        include the `.bat' suffix in the command name.
  85. X
  86. XAt our site, these two variables are used to collect printer output in
  87. Xone file, and to send it to a networked printer upon exit from the
  88. Xprogram.  The MAILCMD feature can also be used to invoke the gmail
  89. Xprogram described above.
  90. X
  91. XMake sure that the limit on the number of open files is large enough (20
  92. Xor so).  On MS-DOS, this is handled by a line with `files=20' in the
  93. XCONFIG.SYS file.
  94. X
  95. XOn MS-DOS, the mail user interface requires the ANSI.SYS driver.  The
  96. XCONFIG.SYS file should specify a line with "device=ansi.sys".
  97. X
  98. XALIAS DATABASE
  99. X
  100. XThe user can define aliases for (groups of) mail addresses.  The alias
  101. Xdata base is a text file with on each line:
  102. X
  103. X    alias replacement_part
  104. X
  105. XThe alias should be a single word; words are separated by blanks, tabs
  106. Xor commas.  The replacement part may be one or more words.  Whenever the
  107. Xsmail (mail spooler) program recognizes an alias, it is replaced by the
  108. X`replacement part'.  Aliases may be defined in terms of other aliases;
  109. Xthe order in which they appear in the alias data base is not important
  110. X(except when an alias is defined more than once; the program remembers
  111. Xonly the last definition of an alias).  The alias expansion software is
  112. Xsmart enough to detect infinite loops and to eliminate multiple
  113. Xoccurrances of the same recipient.  Alias substitution is not case
  114. Xsensitive.
  115. X
  116. XBATCH-MODE OPERATION
  117. X
  118. XThe cmail program can be run from a batch file (say, each time the PC is
  119. Xturned on), to report if there is new mail.  On multi-tasking machines,
  120. Xyou may want to auto-execute the cmail command when exiting from the
  121. Xinteractive mail shell (using the MAILCMD environment variable described
  122. Xabove).
  123. X
  124. XTEMPLATE FILES
  125. X
  126. XThe user can provide message templates with standard header and trailer
  127. Xlines.  If the file "header" is present in the mail directory, its
  128. Xcontents will be included at the beginning of every mail message created
  129. Xby the user.  Similarly, the contents of a file "trailer" will be
  130. Xincluded at the end of mail messages.  The "header" and "trailer" files
  131. Xshould be ordinary text files.
  132. END_OF_main/GNUUCP.ins
  133. if test 4914 -ne `wc -c <main/GNUUCP.ins`; then
  134.     echo shar: \"main/GNUUCP.ins\" unpacked with wrong size!
  135. fi
  136. # end of overwriting check
  137. fi
  138. if test -f main/SLAVE.ins -a "${1}" != "-c" ; then 
  139.   echo shar: Will not over-write existing file \"main/SLAVE.ins\"
  140. else
  141. echo shar: Extracting \"main/SLAVE.ins\" \(5277 characters\)
  142. sed "s/^X//" >main/SLAVE.ins <<'END_OF_main/SLAVE.ins'
  143. X@(#) SLAVE.ins 2.1 90/01/22 13:01:12
  144. X
  145. XThis document describes how to install an MS-DOS pc-mail user in an
  146. Xenvironment where the user's mail directories are mounted from a UNIX
  147. Xfile server, and where PC/NFS is used for file access.  It is assumed
  148. Xthat the UNIX host uses sendmail for message routing.  You will have to
  149. Xadapt the examples if you are using different mechanisms for remote file
  150. Xaccess or message routing.
  151. X
  152. XTHE UNIX SIDE
  153. X
  154. XThe installation of daemon programs on the file server is documented
  155. Xwith the source of the pc-mail and pc-maild programs (these are provided
  156. Xin the `daemon' subdirectory.  The following text assumes that the
  157. Xdaemon programs have already been installed.
  158. X
  159. XAdd the user to the password data base.  In the pc-mail spool area on
  160. Xthe server, create a subdirectory for the pc-mail user.  The directory
  161. Xmust be owned by that user; for reasons of privacy, mode 0700 is
  162. Xrecommended.  In the following example, replace username by the actual
  163. Xlogin name of the user, and the name of the spool area by its actual
  164. Xname.
  165. X
  166. X    # mkdir /var/spool/pc-mail/username
  167. X    # chown username /var/spool/pc-mail/username
  168. X    # chmod 700 /var/spool/pc-mail/username
  169. X
  170. XThe next step is to inform the UNIX mailer of how to deliver mail for
  171. Xthis user. This is described in the documentation of the pc-mail
  172. Xand pc-maild programs.
  173. X
  174. XAfter the list of pc-mail users has been updated, kill the sendmail
  175. Xdaemon and restart it.
  176. X
  177. XNote that the sendmail program ON THE NFS SERVER will not read the
  178. Xuser's .forward file.  The file will still be useful, however, if the
  179. Xuser's home directory is exported to OTHER hosts running sendmail.  In
  180. Xthat case you will want to create a .forward file in the user's home
  181. Xdirectory containing
  182. X
  183. X    username@fully-qualified-hostname-of-the-mail-server
  184. X
  185. XThe same effect can be achieved with an alias in a network-wide alias
  186. Xdata base.
  187. X
  188. XTHE PC SIDE
  189. X
  190. XCopy the appropriate makefile.whatever file to makefile and edit it.
  191. XMake sure that the DAEMON macro is defined, and that the large memory
  192. Xmodel is selected.  You may also use the SLAVE.bat file if no decent
  193. Xmake utility is available.
  194. X
  195. XTyping `make' should produce the following programs:
  196. X
  197. X    mail, the user interface program
  198. X    cmail, checks for new mail
  199. X    nmail, extracts sender and subject from new mail
  200. X    smail, performs alias expansion and queues outgoing messages
  201. X
  202. XCreate a dedicated directory on the file server to install the mail
  203. Xbinaries.
  204. X
  205. XOn the PC, adjust the AUTOEXEC.BAT, NETWORK.BAT or DRIVES.BAT files so
  206. Xthat the following commands are executed upon startup (replace `server'
  207. Xby the name of the NFS server host, and replace `username' by the login
  208. Xname of the actual user):
  209. X
  210. X    net name username *
  211. X    net use m: \\server\var\spool\pc-mail\username
  212. X    set MAILDIR=m:\
  213. X
  214. XThe trailing \ in the last command is needed, or the mail program will
  215. Xcomplain that it "cannot access some essential data files".
  216. X
  217. XOther environment variables that need to be set are:
  218. X
  219. X    PATH, should include the location of the pc-mail binaries
  220. X    EDITOR, the editor command to be used; if this is a batch
  221. X    file, the `.bat' suffix should be included.
  222. X
  223. XIt is advisable to specify absolute path names, including drive names.
  224. X
  225. XOptional environment variables are:
  226. X
  227. X    MAILPRN, destination of printed output
  228. X    MAILCMD, command to be executed upon exit from the mail program.
  229. X    At our site, MAILPRN is the name of a file, and MAILCMD is
  230. X    the command that sends that file to a postscript printer. If 
  231. X    this is a batch file, the `.bat' suffix should be included.
  232. X
  233. XReboot the pc.
  234. X
  235. XTest the mail programs by creating a small mail message addressed to
  236. Xyourself.  Since the message will automatically be picked up by the
  237. Xpc-maild daemon program on the server, the message may arrive before you
  238. Xhad a chance to type a DIR command!
  239. X
  240. XALIAS DATABASE
  241. X
  242. XThe user can define aliases for (groups of) mail addresses.  The alias
  243. Xdata base is a text file with on each line:
  244. X
  245. X    alias replacement_part
  246. X
  247. XThe alias should be a single word; words are separated by blanks, tabs
  248. Xor commas.  The replacement part may be one or more words.  Whenever the
  249. Xsmail (mail spooler) program recognizes an alias, it is replaced by the
  250. X`replacement part'.  Aliases may be defined in terms of other aliases;
  251. Xthe order in which they appear in the alias data base is not important
  252. X(except when an alias is defined more than once; the program remembers
  253. Xonly the last definition of an alias).  The alias expansion software is
  254. Xsmart enough to detect infinite loops and to suppress multiple
  255. Xoccurrances of the same recipient.  Alias substitution is not case
  256. Xsensitive.
  257. X
  258. XBATCH-MODE OPERATION
  259. X
  260. XThe cmail program can be run from a batch file (say, each time the PC is
  261. Xturned on), to report if there is new mail.  Also, you may want to
  262. Xauto-execute the cmail command when exiting from the interactive mail
  263. Xshell (using the MAILCMD environment variable described above).
  264. X
  265. XTEMPLATE FILES
  266. X
  267. XThe user can provide message templates with standard header and trailer
  268. Xlines.  If the file "header" is present in the mail directory, its
  269. Xcontents will be included at the beginning of every mail message created
  270. Xby the user.  Similarly, the contents of a file "trailer" will be
  271. Xincluded at the end of mail messages.  The "header" and "trailer" files
  272. Xshould be ordinary text files.
  273. END_OF_main/SLAVE.ins
  274. if test 5277 -ne `wc -c <main/SLAVE.ins`; then
  275.     echo shar: \"main/SLAVE.ins\" unpacked with wrong size!
  276. fi
  277. # end of overwriting check
  278. fi
  279. if test -f main/ascf.c -a "${1}" != "-c" ; then 
  280.   echo shar: Will not over-write existing file \"main/ascf.c\"
  281. else
  282. echo shar: Extracting \"main/ascf.c\" \(5357 characters\)
  283. sed "s/^X//" >main/ascf.c <<'END_OF_main/ascf.c'
  284. X/*++
  285. X/* NAME
  286. X/*    ascf 3
  287. X/* SUMMARY
  288. X/*    stdio-like ascii filter
  289. X/* PROJECT
  290. X/*    pc-mail
  291. X/* PACKAGE
  292. X/*    ascii filtering
  293. X/* SYNOPSIS
  294. X/*    #include <stdio.h>
  295. X/*    #include "ascf.h"
  296. X/*
  297. X/*    FILE *ascopen(name,mode)
  298. X/*    char *name;
  299. X/*    char *mode;
  300. X/*
  301. X/*    int ascget(fp)
  302. X/*    FILE *fp;
  303. X/*
  304. X/*    ascpbk(c,fp)
  305. X/*    int c;
  306. X/*    FILE *fp;
  307. X/*
  308. X/*    char *ascgets(buf,buflen,fp);
  309. X/*    char *buf;
  310. X/*    int buflen;
  311. X/*    FILE *fp;
  312. X/*
  313. X/*    int ascclose(fp)
  314. X/*    FILE *fp;
  315. X/* DESCRIPTION
  316. X/*    The functions in this module provide filtered stream i/o for
  317. X/*    textfiles produced by word processors. Their calling sequence
  318. X/*    has been modelled after the standard i/o library routines.
  319. X/*
  320. X/*    The following mappings are done: cr/lf, cr, lf, lf/cr are 
  321. X/*    replaced by newline; all high bits are stripped off; wordstar
  322. X/*    hyphens are converted to normal hyphens. Except for tabs and backspace,
  323. X/*    control characters are filtered out. A newline
  324. X/*    character is appended to the last line of a file if that file
  325. X/*    does not terminate on a newline character.
  326. X/*
  327. X/*    ascopen() is the analogon of fopen(3), ascget() returns the next
  328. X/*    character in the filtered input stream, and ascclose() closes 
  329. X/*    the stream. ascget() is a macro. A "feature" of the ascopen()
  330. X/*    function is that it interprets a file name "-" as standard
  331. X/*    input (and ignores the mode argument in that case).
  332. X/*
  333. X/*    ascpbk() pushes back the last character read with ascget().
  334. X/*
  335. X/*    ascgets() reads one string and strips trailing newline or carriage
  336. X/*    return characters. A null pointer is returned if no string could
  337. X/*    be read, otherwise ascgets() returns a pointer to the buffer.
  338. X/* SEE ALSO
  339. X/*    stdio(3)    standard i/o library interface.
  340. X/* DIAGNOSTICS
  341. X/*    ascopen() returns a null pointer on failure; ascget() returns
  342. X/*    the value EOF when the end of a stream is reached. ascclose()
  343. X/*    returns whatever fclose() returns.
  344. X/* BUGS
  345. X/*    Actually works well with wordstar or clean ascii files only.
  346. X/*
  347. X/*    Only "r" modes are supported.
  348. X/*
  349. X/*    There is no way to seek() a filtered stream.
  350. X/* AUTHOR(S)
  351. X/*    W.Z. Venema
  352. X/*    Eindhoven University of Technology
  353. X/*    Department of Mathematics and Computer Science
  354. X/*    Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  355. X/* CREATION DATE
  356. X/*    Mon Jul  6 16:03:41 GMT+1:00 1987
  357. X/* LAST MODIFICATION
  358. X/*    90/01/22 13:01:14
  359. X/* VERSION/RELEASE
  360. X/*    2.1
  361. X/*--*/
  362. X
  363. X#include <stdio.h>
  364. X#include <ctype.h>
  365. X
  366. X#include "defs.h"
  367. X#include "ascf.h"
  368. X
  369. X/* some systems do not define _NFILE in stdio.h; not that they should, but.. */
  370. X
  371. X#ifndef _NFILE
  372. X#  include <sys/param.h>        /* maybe we are a sun */
  373. X#    ifdef NOFILE
  374. X#    define _NFILE NOFILE
  375. X#  else
  376. X"ERROR: cannot get max nr of open stdio streams"
  377. X#  endif
  378. X#endif
  379. X
  380. X#define CTL(x) ((x)^0100)        /* ASCII control characters */
  381. X
  382. X#ifdef MSDOS
  383. X#include <fcntl.h>            /* to turn cr/lf mapping off */
  384. X#endif
  385. X
  386. Xpublic Asc asc[_NFILE];        /* one filter structure per file */
  387. X
  388. X/* ascopen - open stream, initialize intermediate buffer */
  389. X
  390. Xpublic FILE *ascopen(file,mode)
  391. Xchar *file,*mode;
  392. X{
  393. X    register FILE *fp;
  394. X
  395. X    if (*mode != 'r')            /* Cannot do filtered writes */
  396. X    return(0);
  397. X
  398. X    if (fp = (strcmp(file, "-") ? fopen(file,mode) : stdin)) {
  399. X    register Asc *ap = asc+fileno(fp);
  400. X    if (ap->buf = malloc(BUFSIZ)) {    /* if buffer available */
  401. X        ap->cnt = 0;        /* init buffer count */
  402. X        ap->nlf = 0;        /* no newline appended yet */
  403. X#ifdef O_BINARY
  404. X        setmode(fileno(fp),O_BINARY);
  405. X#endif
  406. X    } else {
  407. X        (void) fclose(fp);        /* no room for that buffer */
  408. X        fp = 0;
  409. X     }
  410. X    }
  411. X    return(fp);
  412. X}
  413. X
  414. X/* ascclose - release intermediate buffer and close the stream */
  415. X
  416. Xpublic int ascclose(fp)
  417. Xregister FILE *fp;
  418. X{
  419. X    free(asc[fileno(fp)].buf);
  420. X    return(fclose(fp));
  421. X}
  422. X
  423. X/* ascbuf - the actual filter, fill one new buffer of text */
  424. X
  425. Xpublic int ascbuf(fp)
  426. XFILE *fp;
  427. X{
  428. X    register Asc *ap = asc+fileno(fp);    /* intermediate buffer access */
  429. X    register char *cp = ap->buf;    /* initialize write pointer */
  430. X    register int c;            /* single-character input buffer */
  431. X    int d;                /* look-ahead character */
  432. X
  433. X    while (cp < ap->buf+BUFSIZ && (c = getc(fp)) != EOF) {
  434. X    if ((c &= 0177) == ' ' || isprint(c) || c == '\t' || c == '\b') {
  435. X        *cp++ = c;            /* accept character */
  436. X    } else if ((c == '\r' && ((d = getc(fp)) == '\n' || (ungetc(d,fp),1)))
  437. X        || (c == '\n' && ((d = getc(fp)) == '\r' || (ungetc(d,fp),1)))) {
  438. X        *cp++ = '\n';        /* terminate line */
  439. X    } else if (c == CTL('_')) {
  440. X        *cp++ = '-';        /* wordstar hyphen */
  441. X    } else {
  442. X        continue;            /* ignore other characters */
  443. X    }
  444. X    }
  445. X    if (ap->cnt = cp-ap->buf) {        /* anything in the buffer? */
  446. X    ap->ptr = ap->buf;        /* yes, set read pointer */
  447. X    ap->nlf = cp[-1];        /* remember last character */
  448. X    return(ascget(fp));        /* and return first character */
  449. X    } else if (ap->nlf != '\n') {    /* make sure file ends with \n */
  450. X        return(ap->nlf = '\n');        /* append newline */
  451. X    } else {                /* now we're really done */
  452. X    return(EOF);            /* that's it. */
  453. X    }
  454. X}
  455. X
  456. X/* ascgets - read string, strip crlf */
  457. X
  458. Xpublic char *ascgets(buf, buflen, fp)
  459. Xchar   *buf;
  460. Xint     buflen;
  461. XFILE   *fp;
  462. X{
  463. X    register int c;
  464. X    register char *cp = buf;
  465. X    register char *ce = buf + buflen - 1;
  466. X
  467. X    while ((c = ascget(fp)) != EOF) {
  468. X    if (c == '\n') {            /* suppress crlf */
  469. X        break;
  470. X    } else if (cp < ce) {            /* will fit */
  471. X        *cp++ = c;
  472. X    } else {                /* push back */
  473. X        ascpbk(c, fp);
  474. X        break;
  475. X    }
  476. X    }
  477. X    *cp = 0;
  478. X    return ((c == EOF && cp == buf) ? 0 : buf);
  479. X}
  480. END_OF_main/ascf.c
  481. if test 5357 -ne `wc -c <main/ascf.c`; then
  482.     echo shar: \"main/ascf.c\" unpacked with wrong size!
  483. fi
  484. # end of overwriting check
  485. fi
  486. if test -f main/gp.h -a "${1}" != "-c" ; then 
  487.   echo shar: Will not over-write existing file \"main/gp.h\"
  488. else
  489. echo shar: Extracting \"main/gp.h\" \(5614 characters\)
  490. sed "s/^X//" >main/gp.h <<'END_OF_main/gp.h'
  491. X/*++
  492. X/* NAME
  493. X/*    gp 5
  494. X/* SUMMARY
  495. X/*    g-protocol internal definitions
  496. X/* PROJECT
  497. X/*    pc-mail
  498. X/* PACKAGE
  499. X/*    cico
  500. X/* SYNOPSIS
  501. X/*    #include "gp.h"
  502. X/* DESCRIPTION
  503. X/* .nf
  504. X
  505. X /* include-once file */
  506. X
  507. X#ifndef    GP
  508. X#define    GP
  509. X
  510. X#include <stdio.h>            /* needed for stderr */
  511. X
  512. X#define    MAXTRY        10        /* max nr of retries */
  513. X#define    CTRL(x)        ((x)^0100)    /* for ascii control characters */
  514. X#define    MIN(x,y)    ((x) < (y) ? (x) : (y))
  515. X#define    MAX(x,y)    ((x) > (y) ? (x) : (y))
  516. X
  517. X#define    ALARM        10        /* time-out interval */
  518. X#define    MAGIC        0xAAAA        /* checksum magic number */
  519. X#define    KCTRL        9        /* control packet */
  520. X
  521. X#define    FAIL        (-1)        /* corrupted packet */
  522. X#define    TIME        (-2)        /* timed out */
  523. X
  524. X /* 
  525. X  * The protocol is defined in terms of message transmissions of 8-bit
  526. X  * bytes. Each message includes one control byte plus a data segment
  527. X  * of zero or more information bytes. (...)
  528. X  * The control byte is partitioned into three fields as depicted below.
  529. X  *    bit    7    6    5    4    3    2    1    0
  530. X  *        t    t    x    x    x    y    y    y
  531. X  * The t bits indicate a packet type and determine the interpretation
  532. X  * to be placed on the xxx and yyy the fields. The various interpretations
  533. X  * are as follows:
  534. X  *    tt    interpretation
  535. X  *    00    control packet
  536. X  *    10    data packet
  537. X  *    11    short data packet
  538. X  *    01    alternate channel
  539. X  * A data segment accompanies all non-control packets. (...) Type 01 packets
  540. X  * are never used by UUCP (...)
  541. X  */
  542. X
  543. X#define    TYPE(x)        ((x)&0300)    /* extract message field */
  544. X
  545. X#define    CONTROL        0000        /* control message */
  546. X#define    DATA        0200        /* data, fixed size */
  547. X#define    SHORT        0300        /* short (variable) length data */
  548. X#define    ALTCH        0100        /* alternate channel (unused) */
  549. X
  550. X /*
  551. X  * The sequence number of a non-control packet is given by the xxx field.
  552. X  * Control packets are not sequenced. The newest sequence number,
  553. X  * excluding duplicate transmissions, accepted by a receiver is placed in 
  554. X  * the yyy field of non-control packets sent to the `other' receiver.
  555. X  */
  556. X
  557. X#define    TVAL(x)        (((x)&0377)>>6)    /* extract message type */
  558. X#define    MVAL(x)        (((x)&070)>>3)    /* extract control message */
  559. X#define    SVAL(x)        (((x)&070)>>3)    /* extract S(equence) value */
  560. X#define    RVAL(x)        ((x)&07)    /* extract R(received) value */
  561. X#define    IVAL(x)        ((x)&07)    /* extract init value */
  562. X#define    SFLD(x)        (((x)&07)<<3)    /* create S(equence) field */
  563. X#define    RFLD(x)        ((x)&07)    /* create R(received) field */
  564. X#define    IFLD(x)        ((x)&07)    /* create init field */
  565. X
  566. X /*
  567. X  * There are no data bytes associated with a control packet, the xxx field
  568. X  * is interpreted as a control message, and the yyy field is a value 
  569. X  * accompanying the control message. The control messages are listed
  570. X  * below in decreasing priority. That is, if several control messags
  571. X  * are to be sent, the lower-numbered ones are sent first.
  572. X  *    xxx    name    yyy
  573. X  *    1    CLOSE    n/a
  574. X  *    2    RJ    last correctly received sequence number
  575. X  *    3    SRJ    sequence number to retransmit
  576. X  *    4    RR    last correctly received sequence number
  577. X  *    5    INITC    window size
  578. X  *    6    INITB    data segment size
  579. X  *    7    INITA    window size
  580. X  */
  581. X
  582. X#define    MESG(x)        ((x)&070)    /* extract control message field */
  583. X
  584. X#define    CLOSE        0010        /* close message */
  585. X#define    RJ        0020        /* reject message */
  586. X#define    SRJ        0030        /* selective-reject message (unused) */
  587. X#define    RR        0040        /* received ok message */
  588. X#define    INITC        0050        /* initialization message */
  589. X#define    INITB        0060        /* initialization message */
  590. X#define    INITA        0070        /* initialization message */
  591. X
  592. X /* declarations for tiny systems without tty driver, timer support etc. */
  593. X
  594. X#ifndef    unix
  595. X
  596. X#define    read        xread
  597. X#define    write        xwrite
  598. X#define    alarm(x)    /* nothing */
  599. X#define    signal(x,y)    /* nothing */
  600. X#define    DEBUG(x,y,z)    if (dflag >= x) printf(y,z)
  601. X
  602. Xextern int dflag;
  603. X
  604. X#else
  605. X
  606. X#define    DEBUG(l,f,s)    if (Debug >= l) fprintf(stderr,f,s)
  607. X
  608. Xextern int Debug;
  609. X
  610. X#endif
  611. X
  612. X /* 
  613. X  * We use one data structre for communication between various levels
  614. X  * of the g-protocol implementation. Fields in parentheses are relevant
  615. X  * only when a packet holds data.
  616. X  *    field    meaning                set by
  617. X  *    c    message type            gwrite(), grpack()
  618. X  *    (k    data segment length        galloc(), grpack())
  619. X  *    (chk    16-bit checksum            packet i/o functions)
  620. X  *    (len    max. data segment length    galloc(), gwrite(), grpack())
  621. X  *    (data    start of "len" bytes        this field is fixed)
  622. X  *    (segl    nbr of data bytes left        gread())
  623. X  *    (segp    start of "segl" bytes        gread())
  624. X  */
  625. X
  626. X /* structure for communication between various program layers */
  627. X
  628. Xtypedef struct {
  629. X    char k;                /* message segment size */
  630. X    char c;                /* message type */
  631. X    int chk;                /* data checksum */
  632. X    short segl;                /* nr of data bytes left */
  633. X    char *segp;                /* start of the "segl" bytes */
  634. X    short len;                /* maximum data segment size */
  635. X    char data[1];            /* actually a lot of characters */
  636. X} Packet;
  637. X
  638. X /* functions that manipulate packets */
  639. X
  640. Xextern Packet *grproto();        /* take packet from input queue */
  641. Xextern void gfree();            /* release input packet */
  642. Xextern Packet *galloc();        /* allocate output packet */
  643. Xextern void gwproto();            /* place packet in output queue */
  644. Xextern void gfail();            /* panic button */
  645. Xextern void gsctrl();            /* send one control packet */
  646. Xextern void gsdata();            /* send one data packet */
  647. Xextern int grpack();            /* receive one packet */
  648. X
  649. Xextern int seglen[];            /* data segment size table */
  650. X
  651. X /* standard unix library */
  652. X
  653. Xextern char *malloc();
  654. X
  655. X#endif    /* GP */
  656. X/* AUTHOR(S)
  657. X/*    W.Z. Venema
  658. X/*    Eindhoven University of Technology
  659. X/*    Department of Mathematics and Computer Science
  660. X/*    Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  661. X/* CREATION DATE
  662. X/*    Sun Apr 19 12:41:37 GMT+1:00 1987
  663. X/* LAST MODIFICATION
  664. X/*    90/01/22 13:01:41
  665. X/* VERSION/RELEASE
  666. X/*    2.1
  667. X/*--*/
  668. END_OF_main/gp.h
  669. if test 5614 -ne `wc -c <main/gp.h`; then
  670.     echo shar: \"main/gp.h\" unpacked with wrong size!
  671. fi
  672. # end of overwriting check
  673. fi
  674. if test -f main/kio.c -a "${1}" != "-c" ; then 
  675.   echo shar: Will not over-write existing file \"main/kio.c\"
  676. else
  677. echo shar: Extracting \"main/kio.c\" \(4773 characters\)
  678. sed "s/^X//" >main/kio.c <<'END_OF_main/kio.c'
  679. X/*++
  680. X/* NAME
  681. X/*    kio 3
  682. X/* SUMMARY
  683. X/*    interface between uucico and k-protocol driver
  684. X/* PACKAGE
  685. X/*    uucp on the TUEnet
  686. X/* SYNOPSIS
  687. X/*    kturnon()
  688. X/*
  689. X/*    kwrmsg(type,str,fn)
  690. X/*    char type, *str;
  691. X/*    int fn;
  692. X/*
  693. X/*    krdmsg(str,fn)
  694. X/*    char *str;
  695. X/*    int fn;
  696. X/*
  697. X/*    krddata(fn,fp)
  698. X/*    int fn;
  699. X/*    FILE *fp;
  700. X/*
  701. X/*    kwrdata(fp,fn)
  702. X/*    FILE *fp;
  703. X/*    int fn;
  704. X/*
  705. X/*    kturnoff()
  706. X/* IMPLICIT INPUTS
  707. X/*    Ifn, Ofn, file descriptors
  708. X/*    Debug, debugging level
  709. X/* DESCRIPTION
  710. X/*    The k protocol has been developed for the Sytek Localnet local area 
  711. X/*    network at the Eindhoven University of Technology (THE).
  712. X/*    Main features of this network are:
  713. X/*
  714. X/* .IP    o 
  715. X/*    Network partners may talk at different baudrates. This implies
  716. X/*    that the network does some buffering and that it needs flow control.
  717. X/* .IP    o 
  718. X/*    The network is normally not transparent for some control 
  719. X/*    characters (XON,XOFF and locally-defined others), independent 
  720. X/*    of the value of the eigth bit.
  721. X/* .IP    o 
  722. X/*    Some network stations are connected to telephone modems.
  723. X/*
  724. X/*    For these reasons, the k protocol must (i) rely on XON/XOFF flow 
  725. X/*    control, (ii) be suitable for 7-bit data paths, (iii) avoid
  726. X/*    sending of control characters and (iv) provide reliable operation
  727. X/*    over dial-in and dial-out telephone lines.
  728. X/*
  729. X/*    Data are sent as checksummed 512-byte packets, terminated by an 
  730. X/*    ASCII CR. Except for packet headers (^P), the k protocol only uses 
  731. X/*    ASCII codes 040 through 0137. Three data bytes are expanded to four 
  732. X/*    bytes upon transmission.
  733. X/*    
  734. X/*    The functions in kio.c form the interface between the uucico
  735. X/*    controlling functions, and the k-protocol packet driver.
  736. X/*
  737. X/*    kturnon() sets the terminal line characteristics (XON/XOFF). Always
  738. X/*    returns zero status.
  739. X/*
  740. X/*    krdmsg(), kwrmsg() exchange null-terminated strings.
  741. X/*    Exit status zero, or FAIL.
  742. X/*
  743. X/*    krddata(), kwrdata() perform file i/o, and accounting. Exit status 
  744. X/*    zero or FAIL.
  745. X/*
  746. X/*    kturnoff() sends a protocol abort sequence. Always returns zero 
  747. X/*    status.
  748. X/* FUNCTIONS AND MACROS
  749. X/*    kread, kread, kwrite, kclose, k-protocol presentation layer 
  750. X/* AUTHOR(S)
  751. X/*    Wietse Venema
  752. X/*    Eindhoven University of Technology
  753. X/*    Department of Mathematics and Computer Science
  754. X/*    Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  755. X/* CREATION DATE
  756. X/*    Mon Feb  3 10:13:34 MET 1986
  757. X/* LAST MODIFICATION
  758. X/*    90/01/22 13:01:54
  759. X/* VERSION/RELEASE
  760. X/*    2.1
  761. X/*--*/
  762. X
  763. X#include "uucp.h"
  764. X
  765. X#define    BUFLEN    BUFSIZ
  766. X
  767. Xkturnon()
  768. X{
  769. X    kopen(Ifn);
  770. X    return 0;
  771. X}
  772. X
  773. X
  774. Xkturnoff()
  775. X{
  776. X    kclose(Ofn);
  777. X    return 0;
  778. X}
  779. X
  780. X
  781. Xkwrmsg(type,str,fn)
  782. Xchar type,*str;
  783. Xint fn;
  784. X{
  785. X    char bufr[BUFSIZ],*s;
  786. X
  787. X    bufr[0] = type;
  788. X    s = &bufr[1];
  789. X    while (*str)
  790. X    *s++ = *str++;
  791. X    *s = '\0';
  792. X    if (*(--s) == '\n')
  793. X    *s = '\0';
  794. X    DEBUG(6," kwrmsg: \"%s\"\n",bufr);
  795. X
  796. X    return (kwrite(fn,bufr,strlen(bufr)+1) > 0 ? 0 : FAIL);
  797. X}
  798. X
  799. X
  800. Xkrdmsg(str,fn)
  801. Xchar *str;
  802. Xint fn;
  803. X{
  804. X    int len;
  805. X
  806. X    for (;;) {
  807. X    if ((len = kread(fn,str,BUFSIZ)) == 0) {
  808. X        continue;
  809. X    } else if (len > 0) {
  810. X        str[len] = 0;
  811. X        DEBUG(6," krdmsg: \"%s\"\n",str);
  812. X        str += len;
  813. X        if (str[-1] == '\0')
  814. X        return 0;
  815. X    } else {
  816. X        return FAIL;
  817. X    }
  818. X    }
  819. X}
  820. X
  821. X
  822. Xkwrdata(fp1,fn)
  823. XFILE *fp1;
  824. X{
  825. X    char bufr[BUFLEN];
  826. X    int len;
  827. X    int ret;
  828. X    time_t t1,t2;
  829. X    long bytes;
  830. X    char text[BUFSIZ];
  831. X
  832. X    ret = FAIL;
  833. X    bytes = 0L;
  834. X    time(&t1);
  835. X    while ((len = fread(bufr,sizeof (char),BUFLEN,fp1)) > 0) {
  836. X    bytes += len;
  837. X    if (kwrblk(bufr,len,fn) != len)
  838. X        goto acct;
  839. X    if (len != BUFLEN)
  840. X        break;
  841. X    }
  842. X    ret = kwrblk(bufr,0,fn);
  843. Xacct:
  844. X    time(&t2);
  845. X    sprintf(text,ret == 0 ?
  846. X    "sent data %ld bytes %ld secs" :
  847. X    "send failed after %ld bytes",
  848. X    bytes,t2 - t1);
  849. X    DEBUG(1,"%s\n",text);
  850. X    syslog(text);
  851. X    sysacct(bytes,t2 - t1);
  852. X    if (ret)
  853. X    sysaccf(NULL);        /* force accounting */
  854. X    return ret;
  855. X}
  856. X
  857. X
  858. Xkrddata(fn,fp2)
  859. XFILE *fp2;
  860. X{
  861. X    int len,ret;
  862. X    char bufr[BUFLEN];
  863. X    time_t t1,t2;
  864. X    long bytes;
  865. X    char text[BUFSIZ];
  866. X
  867. X    ret = FAIL;
  868. X    bytes = 0L;
  869. X    time(&t1);
  870. X    for (;;) {
  871. X    len = krdblk(bufr,BUFLEN,fn);
  872. X    if (len < 0)
  873. X        goto acct;
  874. X    bytes += len;
  875. X    if (fwrite(bufr,sizeof (char),len,fp2) != len)
  876. X        goto acct;
  877. X    if (len < BUFLEN)
  878. X        break;
  879. X    }
  880. X    ret = 0;
  881. Xacct:
  882. X    time(&t2);
  883. X    sprintf(text,ret == 0 ? 
  884. X    "received data %ld bytes %ld secs" :
  885. X    "receive failed after %ld bytes",
  886. X    bytes,t2 - t1);
  887. X    DEBUG(1,"%s\n",text);
  888. X    syslog(text);
  889. X    sysacct(bytes,t2 - t1);
  890. X    if (ret)
  891. X    sysaccf(NULL);        /* force accounting */
  892. X    return ret;
  893. X}
  894. X
  895. X
  896. Xkrdblk(blk,len, fn)
  897. Xchar *blk;
  898. Xint len,fn;
  899. X{
  900. X    int i,ret;
  901. X
  902. X    for (i = 0; i < len; i += ret) {
  903. X    if ((ret = kread(fn,blk,len-i)) == 0) {
  904. X        break;
  905. X    } else if (ret > 0) {
  906. X        blk += ret;
  907. X    } else {
  908. X        return FAIL;
  909. X    }
  910. X    }
  911. X    return i;
  912. X}
  913. X
  914. X
  915. Xkwrblk(blk,len,fn)
  916. Xchar *blk;
  917. Xint len,fn;
  918. X{
  919. X    return kwrite(fn,blk,len);
  920. X}
  921. END_OF_main/kio.c
  922. if test 4773 -ne `wc -c <main/kio.c`; then
  923.     echo shar: \"main/kio.c\" unpacked with wrong size!
  924. fi
  925. # end of overwriting check
  926. fi
  927. if test -f main/kpres.c -a "${1}" != "-c" ; then 
  928.   echo shar: Will not over-write existing file \"main/kpres.c\"
  929. else
  930. echo shar: Extracting \"main/kpres.c\" \(4940 characters\)
  931. sed "s/^X//" >main/kpres.c <<'END_OF_main/kpres.c'
  932. X/*++
  933. X/* NAME
  934. X/*    kpres
  935. X/* SUMMARY
  936. X/*    k-protocol presentation layer
  937. X/* PACKAGE
  938. X/*    uucp across thenet
  939. X/* SYNOPSIS
  940. X/*    #include "kp.h"
  941. X/*
  942. X/*    kopen(fd)
  943. X/*    int fd;
  944. X/*
  945. X/*    kwrite(fd,buf,len)
  946. X/*    int fd,len;
  947. X/*    char *buf;
  948. X/*
  949. X/*    kread(fd,buf,len)
  950. X/*    int fd,len;
  951. X/*    char *buf;
  952. X/*
  953. X/*    kclose(fd)
  954. X/*    int fd;
  955. X/* DESCRIPTION
  956. X/*    This section contains functions that imitate standard unix
  957. X/*    unbuffered i/o facilities. A status code of FAIL is returned when
  958. X/*    the network partner wants to terminate the protocol, or when the
  959. X/*    the transmission error rate is excessive.
  960. X/*
  961. X/*    Eight-bit data bytes are transported as harmless six-bit data bytes
  962. X/*    in the ASCII range 32 through 95. This introduces an overhead of 33%.
  963. X/*    For textfiles, this is hardly worse than kermit (typical overhead 
  964. X/*    10 %). For binary files the overhead is much less than with kermit 
  965. X/*    (typical overhead 60%).
  966. X/*
  967. X/*    Kopen() sets up the terminal characteristics of the specified file
  968. X/*    descriptors (no echo, raw, tandem). Always returns zero status.
  969. X/*
  970. X/*    Kwrite() attempts to send the bytes in buf. A zero-length buffer 
  971. X/*    should be written to indicate an end-of-file condition. Return status: 
  972. X/*    the number of bytes requested, or FAIL.
  973. X/*
  974. X/*    Kread() attempts to read the requested number of bytes. Status code:
  975. X/*    the number of bytes actually read, or FAIL. A read of zero bytes
  976. X/*    normally indicates an end-of-file condition (see kwrite).
  977. X/*
  978. X/*    Kclose() sends a protocol abort sequence to the network partner.
  979. X/*    This function should be called to terminate the k protocol driver
  980. X/*    at the other end, or to confirm reception of a protocol abort sequence.
  981. X/*    Kclose always returns zero exit status.
  982. X/*
  983. X/*    The function kfail() is called by the strategy layer functions to 
  984. X/*    indicate protocol failure or termination.
  985. X/* FUNCTIONS AND MACROS
  986. X/*    kwproto, krproto, kclsproto
  987. X/* BUGS
  988. X/*    Zero byte read/writes are a clumsy way to handle end-of-files. 
  989. X/*    They have been implemented for the sake of compatibility with uucico.
  990. X/* AUTHOR(S)
  991. X/*    Wietse Venema
  992. X/*    Eindhoven University of Technology
  993. X/*    Department of Mathematics and Computer Science
  994. X/*    Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  995. X/* CREATION DATE
  996. X/*    Mon Feb  3 11:14:13 MET 1986
  997. X/* LAST MODIFICATION
  998. X/*    90/01/22 13:01:57
  999. X/* VERSION/RELEASE
  1000. X/*    2.1
  1001. X/*--*/
  1002. X
  1003. X#ifdef unix
  1004. X# ifdef    SIII
  1005. X#   include <termio.h>
  1006. X# else
  1007. X#   include <sgtty.h>
  1008. X# endif
  1009. X#endif
  1010. X#include <setjmp.h>
  1011. X#include "kp.h"
  1012. X
  1013. Xstatic jmp_buf Failbuf;
  1014. X
  1015. Xkfail()
  1016. X{
  1017. X    longjmp(Failbuf,TRUE);
  1018. X}
  1019. X
  1020. Xkopen(fd)
  1021. Xint fd;
  1022. X{
  1023. X#ifdef unix
  1024. X# ifdef SIII
  1025. X    struct termio ttymode;
  1026. X
  1027. X    ioctl(fd,TCGETA,&ttymode);
  1028. X    ttymode.c_iflag = IXOFF|IXON|ISTRIP;
  1029. X    ttymode.c_cc[VMIN] = 1;
  1030. X    ttymode.c_cc[VTIME] = 0;
  1031. X    ioctl(fd,TCSETA,&ttymode);
  1032. X# else
  1033. X    struct sgttyb ttymode;
  1034. X
  1035. X    gtty(fd,&ttymode);
  1036. X    ttymode.sg_flags |= (TANDEM|RAW);
  1037. X    ttymode.sg_flags &= ~(ECHO|CBREAK);
  1038. X    stty(fd,&ttymode);
  1039. X# endif
  1040. X#else
  1041. X    xioctl(1);
  1042. X#endif
  1043. X    return 0;
  1044. X}
  1045. X
  1046. Xkwrite(fd,buf,len)
  1047. Xint fd;
  1048. Xregister char *buf;
  1049. Xregister int len;
  1050. X{
  1051. X    static char  packbuf[MAXPACKSIZ];
  1052. X    static char *packptr = packbuf;
  1053. X    register int c,i,rest,shift;
  1054. X
  1055. X    /* set error trap */
  1056. X
  1057. X    if (setjmp(Failbuf))
  1058. X    return FAIL;
  1059. X
  1060. X    /* if 'end of data' send null packet */
  1061. X
  1062. X    if (len <= 0) {
  1063. X    kwproto(fd,NULLP,0);
  1064. X    return 0;
  1065. X
  1066. X    /* expand 3 eight-bit bytes to four six-bit bytes */
  1067. X
  1068. X    } else {
  1069. X    for (rest = shift = i = 0; i < len; shift = (shift+STEP)%OUT,i++) {
  1070. X
  1071. X        c = *buf++ & 0377;                /* No sign extension */
  1072. X        *packptr++ = tosix(rest|(c << shift));    /* Assemble byte */
  1073. X        rest = (c >> (OUT-shift));            /* Save unused bits */
  1074. X
  1075. X        if (shift == (OUT-STEP)) {            /* At byte boundary? */
  1076. X        *packptr++ = tosix(rest);        /* Make 'fourth' byte */
  1077. X        rest = 0;                /* No unused bits now */
  1078. X        if (packptr-packbuf > PACKSIZ-4) {    /* Check packet size */
  1079. X            kwproto(fd,packbuf,packptr-packbuf);
  1080. X            packptr = packbuf;
  1081. X        }
  1082. X        }
  1083. X    }
  1084. X    if (shift) {                    /* Any bits left? */
  1085. X        *packptr++ = tosix(rest);            /* Put them there */
  1086. X    }
  1087. X    if (packptr > packbuf) {            /* Flush buffer */
  1088. X        kwproto(fd,packbuf,packptr-packbuf);    /* Ship it off */
  1089. X        packptr = packbuf;
  1090. X    }
  1091. X    return i;
  1092. X    }
  1093. X}
  1094. X
  1095. Xkread(fd,buf,len)
  1096. Xint fd;
  1097. Xchar *buf;
  1098. Xint len;
  1099. X{
  1100. X    static char packbuf[MAXPACKSIZ] = "";
  1101. X    static char *packptr = packbuf;
  1102. X    static int  packsiz = 0;
  1103. X    register int i,c;
  1104. X    static int shift,rest;
  1105. X
  1106. X    /* set error trap */
  1107. X
  1108. X    if (setjmp(Failbuf))
  1109. X    return FAIL;
  1110. X
  1111. X    /* read packet if buffer is empty */
  1112. X
  1113. X    if (packsiz <= 0) {
  1114. X    krproto(fd,packptr = packbuf,&packsiz);
  1115. X    rest = shift = 0;
  1116. X    }
  1117. X
  1118. X    /* unpack (remainder of) buffer; return 0 if empty packet received */
  1119. X
  1120. X    for (i = 0; (i < len) && packsiz--; shift = (shift+STEP)%IN) 
  1121. X    {
  1122. X    c = unsix(*packptr++);
  1123. X    if (shift)
  1124. X        buf[i++] = (rest | (c << (IN-shift)));
  1125. X    rest = (c >> shift);
  1126. X    }
  1127. X    return i;
  1128. X}
  1129. X
  1130. Xkclose(fd)
  1131. Xint fd;
  1132. X{
  1133. X    /* not here - pass job to the lower layer that understands packet types */
  1134. X
  1135. X    kclsproto(fd);
  1136. X    return 0;
  1137. X}
  1138. X
  1139. X
  1140. END_OF_main/kpres.c
  1141. if test 4940 -ne `wc -c <main/kpres.c`; then
  1142.     echo shar: \"main/kpres.c\" unpacked with wrong size!
  1143. fi
  1144. # end of overwriting check
  1145. fi
  1146. if test -f main/ktrans.c -a "${1}" != "-c" ; then 
  1147.   echo shar: Will not over-write existing file \"main/ktrans.c\"
  1148. else
  1149. echo shar: Extracting \"main/ktrans.c\" \(4972 characters\)
  1150. sed "s/^X//" >main/ktrans.c <<'END_OF_main/ktrans.c'
  1151. X/*++
  1152. X/* NAME
  1153. X/*    ktrans 3
  1154. X/* SUMMARY
  1155. X/*    k-protocol strategy routines
  1156. X/* PACKAGE
  1157. X/*    uucp across the TUEnet
  1158. X/* SYNOPSIS
  1159. X/*    #include "kp.h"
  1160. X/*
  1161. X/*    krproto(fd,data,size) 
  1162. X/*    int fd, *size;
  1163. X/*    char data[MAXPACKSIZ];
  1164. X/*
  1165. X/*    kwproto(fd,data,size) 
  1166. X/*    int fd, size;
  1167. X/*    char data[MAXPACKSIZ];
  1168. X/*
  1169. X/*    kclsproto(fd)
  1170. X/*    int fd;
  1171. X/* DESCRIPTION
  1172. X/*    The functions in this file take care of handshake and error
  1173. X/*    detection/recovery. The read/write functions return through an
  1174. X/*    external function kfail() in case of fatal errors, or protocol 
  1175. X/*    termination by the network partner.
  1176. X/*
  1177. X/*    The following packet types are used:
  1178. X/*
  1179. X/* .nf
  1180. X/* .in +5
  1181. X/*    D packets contain data.
  1182. X/*    Y packets are sent when a correct data packet was received.
  1183. X/*    N packets are sent when incorrect data was received.
  1184. X/*    A packets are sent to shut down the k protocol.
  1185. X/* .fi
  1186. X/*
  1187. X/*    Krproto() sends the data and either returns normally, or through 
  1188. X/*    kfail().
  1189. X/*
  1190. X/*    Kwproto() returns the received data or returns through kfail().
  1191. X/*
  1192. X/*    Kclsproto() sends the protocol termination sequence to the other 
  1193. X/*    side, either to signal the end of transfers, or to confirm
  1194. X/*    reception of an end-of-protocol sequence.
  1195. X/*
  1196. X/*    The strategy for sending data is as follows:
  1197. X/*
  1198. X/*    Send packet.
  1199. X/*    If (ACK for last packet) or (NAK for next packet) received, terminate.
  1200. X/*    If (NAK for last packet) or no response received, retransmit.
  1201. X/*    If data received with previous packet nr, ignore and wait for NAK.
  1202. X/*    If data received with next packet nr, NAK that data and terminate.
  1203. X/*    Otherwise (bad packet number, unexpected packet type) abort.
  1204. X/*
  1205. X/*    The strategy for receiving data is complementary:
  1206. X/*
  1207. X/*    Wait for packet
  1208. X/*    If expected packet received, ACK it and terminate.
  1209. X/*    If previous data packet received, ACK it and wait for next packet.
  1210. X/*    If bad packet received, send NAK for expected packet.
  1211. X/*    If nothing received, wait for another packet.
  1212. X/*    Otherwise (bad packet number, unexpected packet type) abort.
  1213. X/* FUNCTIONS AND MACROS
  1214. X/*    kspack, krpack, kfail
  1215. X/* AUTHOR(S)
  1216. X/*    Wietse Venema
  1217. X/*    Eindhoven University of Technology
  1218. X/*    Department of Mathematics and Computer Science
  1219. X/*    Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  1220. X/* CREATION DATE
  1221. X/*    Mon Feb  3 13:12:08 MET 1986
  1222. X/* LAST MODIFICATION
  1223. X/*    90/01/22 13:01:59
  1224. X/* VERSION/RELEASE
  1225. X/*    2.1
  1226. X/*--*/
  1227. X
  1228. X#include "kp.h"
  1229. X
  1230. Xstatic char recpkt[MAXPACKSIZ];            /* receive packet buffer */
  1231. Xstatic int  n = 0;                /* packet number */
  1232. X
  1233. Xkwproto( fd, packet, size)
  1234. Xint fd;
  1235. Xchar *packet;
  1236. Xint size;
  1237. X{
  1238. X    int num, numtry;                            /* Packet number, tries */
  1239. X    int len;
  1240. X
  1241. X    kspack(fd, 'D',n,size,packet);          /* Send a D packet */
  1242. X
  1243. X    for (numtry = 0; numtry < MAXTRY; numtry++) {
  1244. X    switch(krpack(fd,&num,&len,recpkt))     /* What was the reply? */
  1245. X    {
  1246. X    case 'D':                    /* DATA */
  1247. X        if ((num+1)%64 == n) {        /* Previous packet ? */
  1248. X        numtry = 0;            /* Reset counter */
  1249. X        break;                /* Don't ack it; read again */
  1250. X        } else if (num != (n+1)%64)        /* Fatal error, unless it */
  1251. X        kfail();                /* carries next packet number */
  1252. X        kspack(fd,'N',num,0,NULLP);       /* Can't use data now */
  1253. X
  1254. X    case 'N':                           /* NAK */
  1255. X        if (n == num) {            /* Send another one, */
  1256. X        kspack(fd, 'D',n,size,packet);
  1257. X        break;
  1258. X        }
  1259. X        num = (--num<0 ? 63:num);     /* unless NAK for next packet */
  1260. X
  1261. X    case 'Y':                           /* ACK */
  1262. X        if (n != num) kfail();          /* If wrong ACK, fail */
  1263. X        n = (n+1)%64;                   /* Bump packet count */
  1264. X        return;
  1265. X
  1266. X    case TIME:                /* No response */
  1267. X    case FAIL:                /* Bad packet */
  1268. X        kspack(fd, 'D',n,size,packet);
  1269. X        break;                  /* Send data packet again */
  1270. X
  1271. X    default: 
  1272. X        kfail();                           /* Something else, abort */
  1273. X    }
  1274. X    }
  1275. X    kfail();                        /* Too may retries, abort */
  1276. X}
  1277. X
  1278. Xkrproto( fd, packet, size)
  1279. Xint fd;
  1280. Xchar *packet;
  1281. Xint *size;
  1282. X{
  1283. X    int num, numtry;                            /* Packet number, tries */
  1284. X
  1285. X    for (numtry = 0; numtry < MAXTRY; numtry++) 
  1286. X    {
  1287. X    switch (krpack(fd,&num,size,packet))    /* Get packet */
  1288. X    {
  1289. X    case 'D':
  1290. X        if (num == n) {            /* Right packet? */
  1291. X        kspack(fd,'Y',n,0,NULLP);    /* Acknowledge the packet */
  1292. X        n = (n+1)%64;            /* Bump packet number, mod 64 */
  1293. X        return;
  1294. X        } else if (num == ((n==0) ? 63:n-1)) { /* Previous packet? */
  1295. X        kspack(fd,'Y',num,0,NULLP);    /* Re-ack previous packet */
  1296. X        numtry = 0;                    /* Reset counter */
  1297. X        break;                /* Read another packet */
  1298. X        } else
  1299. X        kfail();            /* Sorry, wrong number */
  1300. X
  1301. X    case TIME:                /* No packet */
  1302. X        break;                /* Don't NAK */
  1303. X
  1304. X    case FAIL:                /* Bad packet */
  1305. X        kspack(fd,'N',n,0,NULLP);        /* Return a NAK */
  1306. X        break;                /* Read another packet */
  1307. X
  1308. X    default:
  1309. X        kfail();                /* Something else, abort */
  1310. X    }
  1311. X    }
  1312. X    kfail();                        /* Too may retries, abort */
  1313. X}
  1314. X
  1315. Xkclsproto( fd)
  1316. Xint fd;
  1317. X{
  1318. X    kspack( fd, 'A', 0, 0, NULLP);        /* Send an 'A' packet */
  1319. X    kspack( fd, 'A', 0, 0, NULLP);        /* and another two since */
  1320. X    kspack( fd, 'A', 0, 0, NULLP);        /* we won't get ACKs */
  1321. X    return 0;
  1322. X}
  1323. END_OF_main/ktrans.c
  1324. if test 4972 -ne `wc -c <main/ktrans.c`; then
  1325.     echo shar: \"main/ktrans.c\" unpacked with wrong size!
  1326. fi
  1327. # end of overwriting check
  1328. fi
  1329. if test -f main/logs.c -a "${1}" != "-c" ; then 
  1330.   echo shar: Will not over-write existing file \"main/logs.c\"
  1331. else
  1332. echo shar: Extracting \"main/logs.c\" \(5603 characters\)
  1333. sed "s/^X//" >main/logs.c <<'END_OF_main/logs.c'
  1334. X/*++
  1335. X/* NAME
  1336. X/*      logs 3
  1337. X/* SUMMARY
  1338. X/*      exception handling, error logging, status reports, debugging
  1339. X/* PROJECT
  1340. X/*      pc-mail
  1341. X/* PACKAGE
  1342. X/*      cico
  1343. X/* SYNOPSIS
  1344. X/*      int dbg(fmt[,args]);
  1345. X/*      char *fmt;
  1346. X/*
  1347. X/*      int open_log();
  1348. X/*
  1349. X/*      void log(fmt[,args]);
  1350. X/*      char *fmt;
  1351. X/*
  1352. X/*      void trap(code,fmt[,args]);
  1353. X/*      char *fmt;
  1354. X/* DESCRIPTION
  1355. X/*      All functions in this module do some form of logging, and accept
  1356. X/*      printf-like format strings with %s, %c, and %S, %C. The latter
  1357. X/*    two cause output mapping of arbitrary byte values to printable codes.
  1358. X/*
  1359. X/*      dbg() formats its arguments and writes the result to the standard
  1360. X/*      output.
  1361. X/*
  1362. X/*      open_log() tries to open the logfile for writing. It returns
  1363. X/*      a status E_WRITERR if the file could not be opened or created.
  1364. X/*
  1365. X/*      log() writes status info to the log file. If debugging is enabled,
  1366. X/*    the message is also written to the standard output.
  1367. X/*
  1368. X/*      trap() writes a message to the log file and performs a longjmp call
  1369. X/*      (systrap) with the status as given in the code parameter. If
  1370. X/*    debugging is enabled, the message is also written to the standard
  1371. X/*    output.
  1372. X/* FUNCTIONS AND MACROS
  1373. X/*      longjmp()
  1374. X/* FILES
  1375. X/*      LOGFILE         status reports
  1376. X/* BUGS
  1377. X/*      Logfile info may be lost if the program terminates abnormally.
  1378. X/*      We do not open/close the with each log() call since that would
  1379. X/*      slow down performance on floppy-based systems dramatically.
  1380. X/* AUTHOR(S)
  1381. X/*      W.Z. Venema
  1382. X/*      Eindhoven University of Technology
  1383. X/*      Department of Mathematics and Computer Science
  1384. X/*      Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  1385. X/* CREATION DATE
  1386. X/*      Thu Mar 26 17:45:19 GMT+1:00 1987
  1387. X/* LAST MODIFICATION
  1388. X/*    90/01/22 13:02:01
  1389. X/* VERSION/RELEASE
  1390. X/*    2.1
  1391. X/*--*/
  1392. X
  1393. X#include <stdio.h>
  1394. X#include <setjmp.h>
  1395. X#include <ctype.h>
  1396. X#include <varargs.h>
  1397. X#include <time.h>
  1398. X
  1399. X#include "defs.h"
  1400. X#include "logs.h"
  1401. X#include "path.h"
  1402. X#include "status.h"
  1403. X
  1404. X#define    dbgout    stdout            /* where debugging output should go */
  1405. X
  1406. Xhidden FILE *logfp = NULL;        /* log file file pointer */
  1407. Xhidden char *visible();            /* map characters to readable codes */
  1408. Xhidden void dprintf();            /* special-purpose formatting
  1409. X                     * function */
  1410. X
  1411. X/* now - write current time */
  1412. X
  1413. Xhidden void now(fp)
  1414. XFILE   *fp;
  1415. X{
  1416. X    struct tm *localtime();
  1417. X    char   *asctime();
  1418. X    long    time();
  1419. X    long    t;
  1420. X
  1421. X    t = time((long *) 0);
  1422. X    fprintf(fp, "%.15s ", asctime(localtime(&t)) + 4);
  1423. X}
  1424. X
  1425. X/* open_log - check the logfile can be written */
  1426. X
  1427. Xpublic int open_log()
  1428. X{
  1429. X    if (logfp == NULL && (logfp = fopen(logfile(), "a")) == NULL)
  1430. X    return (E_WRITERR);
  1431. X    else
  1432. X    return (0);
  1433. X}
  1434. X
  1435. X /*
  1436. X  * As long as we have to use old C, use two versions of variadic functions,
  1437. X  * one for real use, and one for checking with lint.
  1438. X  */
  1439. X
  1440. X#ifndef lint
  1441. X
  1442. X/* dbg - write debugging info to the debugging output */
  1443. X
  1444. Xpublic int dbg(va_alist)
  1445. Xva_dcl
  1446. X{
  1447. X    va_list s;
  1448. X    register char *fmt;
  1449. X
  1450. X    va_start(s);
  1451. X    fmt = va_arg(s, char *);
  1452. X    dprintf(dbgout, fmt, s);
  1453. X    va_end(s);
  1454. X}
  1455. X
  1456. X/* log - write status info to the log file */
  1457. X
  1458. Xpublic void log(va_alist)
  1459. Xva_dcl
  1460. X{
  1461. X    va_list s;
  1462. X    register char *fmt;
  1463. X
  1464. X    /* log file should be open! */
  1465. X
  1466. X    if (logfp == NULL)
  1467. X    exit(E_CONFUSED);
  1468. X
  1469. X    /* write status record to log file */
  1470. X
  1471. X    now(logfp);
  1472. X    va_start(s);
  1473. X    fmt = va_arg(s, char *);
  1474. X    dprintf(logfp, fmt, s);
  1475. X    putc('\n', logfp);
  1476. X    va_end(s);
  1477. X
  1478. X    /* if debugging on, write also to debugging output */
  1479. X
  1480. X    if (dflag) {
  1481. X    va_start(s);
  1482. X    fmt = va_arg(s, char *);
  1483. X    dprintf(dbgout, fmt, s);
  1484. X    putc('\n', dbgout);
  1485. X    va_end(s);
  1486. X    }
  1487. X}
  1488. X
  1489. X/* trap - exception handler */
  1490. X
  1491. Xpublic void trap(va_alist)
  1492. Xva_dcl
  1493. X{
  1494. X    va_list s;
  1495. X    int     code;
  1496. X    char   *fmt;
  1497. X
  1498. X    /* write exception record to log file */
  1499. X
  1500. X    now(logfp);
  1501. X    va_start(s);
  1502. X    code = va_arg(s, int);
  1503. X    fmt = va_arg(s, char *);
  1504. X    dprintf(logfp, fmt, s);
  1505. X    putc('\n', logfp);
  1506. X    va_end(s);
  1507. X
  1508. X    /* if debugging on, write also to debugging output */
  1509. X
  1510. X    if (dflag) {
  1511. X    va_start(s);
  1512. X    code = va_arg(s, int);
  1513. X    fmt = va_arg(s, char *);
  1514. X    dprintf(dbgout, fmt, s);
  1515. X    putc('\n', dbgout);
  1516. X    va_end(s);
  1517. X    }
  1518. X    longjmp(systrap, code);
  1519. X}
  1520. X
  1521. X#else
  1522. X
  1523. X/* VARARGS1 */
  1524. X
  1525. Xpublic int dbg(fmt)
  1526. Xchar   *fmt;
  1527. X{
  1528. X}
  1529. X
  1530. X/* VARARGS2 */
  1531. X
  1532. Xpublic void trap(err, fmt)
  1533. Xint   err;
  1534. Xchar *fmt;
  1535. X{
  1536. X}
  1537. X
  1538. X/* VARARGS1 */
  1539. X
  1540. Xpublic void log(fmt)
  1541. Xchar   *fmt;
  1542. X{
  1543. X}
  1544. X
  1545. X#endif
  1546. X
  1547. X/* visible - turn arbitrary character into something visible */
  1548. X
  1549. Xstatic char *visible(c)
  1550. Xregister int c;
  1551. X{
  1552. X    static char buf[5];
  1553. X
  1554. X    switch (c &= 0377) {
  1555. X    default:
  1556. X    sprintf(buf, isascii(c) && isprint(c) ? "%c" : "\\%03o", c);
  1557. X    return (buf);
  1558. X    case ' ':
  1559. X    return ("\\s");
  1560. X    case '\b':
  1561. X    return ("\\b");
  1562. X    case '\t':
  1563. X    return ("\\t");
  1564. X    case '\r':
  1565. X    return ("\\r");
  1566. X    case '\n':
  1567. X    return ("\\n");
  1568. X    case '\f':
  1569. X    return ("\\f");
  1570. X    case '\\':
  1571. X    return ("\\\\");
  1572. X    }
  1573. X}
  1574. X
  1575. X/* dprintf - handle %s, %c, %S and %C format requests */
  1576. X
  1577. Xstatic void dprintf(fp, fmt, s)
  1578. Xregister FILE *fp;
  1579. Xregister char *fmt;
  1580. Xva_list s;
  1581. X{
  1582. X    register int c;
  1583. X
  1584. X    for ( /* void */ ; c = *fmt; fmt++) {
  1585. X    if (c != '%') {
  1586. X        putc(c, fp);
  1587. X    } else if ((c = *++fmt) == 'S') {    /* %S: translated */
  1588. X        register char *cp = va_arg(s, char *);
  1589. X
  1590. X        while (*cp)
  1591. X        fputs(visible(*cp++ & 0377), fp);
  1592. X    } else if (c == 'C') {            /* %C: translated */
  1593. X        fputs(visible(va_arg(s, int)), fp);
  1594. X    } else if (c == 's') {            /* %s: string, as is */
  1595. X        fputs(va_arg(s, char *), fp);
  1596. X    } else if (c == 'c') {            /* %c: char, as is */
  1597. X        putc(va_arg(s, int), fp);
  1598. X    } else if (c == '%') {            /* real % character */
  1599. X        putc(c, fp);
  1600. X    }
  1601. X    }
  1602. X    (void) fflush(fp);
  1603. X}
  1604. END_OF_main/logs.c
  1605. if test 5603 -ne `wc -c <main/logs.c`; then
  1606.     echo shar: \"main/logs.c\" unpacked with wrong size!
  1607. fi
  1608. # end of overwriting check
  1609. fi
  1610. if test -f main/path.h -a "${1}" != "-c" ; then 
  1611.   echo shar: Will not over-write existing file \"main/path.h\"
  1612. else
  1613. echo shar: Extracting \"main/path.h\" \(5231 characters\)
  1614. sed "s/^X//" >main/path.h <<'END_OF_main/path.h'
  1615. X/*++
  1616. X/* NAME
  1617. X/*    path
  1618. X/* SUMMARY
  1619. X/*    system-dependent file name definitions
  1620. X/* PROJECT
  1621. X/*    pc-mail
  1622. X/* PACKAGE
  1623. X/*    general
  1624. X/* SYNOPSIS
  1625. X/*    #include "path.h"
  1626. X/* DESCRIPTION
  1627. X/*    File-system dependent definitions should be changed here.
  1628. X/* .nf
  1629. X
  1630. X /* the minmal number of open files we think we need */
  1631. X
  1632. X#define    MINFILES    10
  1633. X
  1634. X /* system-dependent defaults */
  1635. X
  1636. X#ifdef    unix
  1637. X#define    THISDIR        "."        /* current directory */
  1638. X#define    PATHSEP        "/"        /* path-element separator */
  1639. X#define    DEFSPOOL    "./spool"    /* default spool directory */
  1640. X#define    DEFEDIT        "vi"        /* default editor */
  1641. X#ifdef SIII
  1642. X#define    DEFPRINT    "lp"        /* printer spooler */
  1643. X#else
  1644. X#define    DEFPRINT    "lpr"        /* printer spooler */
  1645. X#endif
  1646. X#define    MAILFILE    "mail.msg"    /* temporary message file */
  1647. X#define    TMPALIAS    "tmp.alias"    /* temp alias file */
  1648. X#define    NULLDEV        "/dev/null"    /* bit dump */
  1649. X#endif
  1650. X
  1651. X#ifdef    MSDOS
  1652. X#define    THISDIR        "."        /* current directory */
  1653. X#define    PATHSEP        "\\"        /* path-element separator */
  1654. X#define    DEFSPOOL    "\\spool"    /* spool directory */
  1655. X#define    DEFEDIT        "edlin"        /* default editor */
  1656. X#define DEFPRINT    "PRN"        /* default printer */
  1657. X#define    MAILFILE    "mail.msg"    /* temp message file */
  1658. X#define    TMPALIAS    "alias.tmp"    /* temp alias file */
  1659. X#define    NULLDEV        "NUL"        /* bit dump */
  1660. X#endif
  1661. X
  1662. X /* system-dependent function calls for file & printer access */
  1663. X
  1664. X#ifdef unix
  1665. X#define    propen()    popen(mailprn,"w")    /* open print stream */
  1666. X#define    prclose(p)    pclose(p)    /* close print stream */
  1667. X#define    fspool(file)    strcons("%s/%s",maildir,file)
  1668. X#endif
  1669. X
  1670. X#ifdef MSDOS
  1671. X#define    propen()    fopen(mailprn,"a")    /* open print stream */
  1672. X#define    prclose(p)    (putc('\014',p),fclose(p))    /* close print stream */
  1673. X#define    fspool(file)    strcons("%s\\%s",maildir,file)
  1674. X#endif
  1675. X
  1676. X#if (!defined(unix)&& !defined(MSDOS))
  1677. X"Specify here how things should be handled with your compiler"
  1678. X#endif
  1679. X
  1680. X /* system-independent file names */
  1681. X
  1682. X#define    SMAIL    "smail"            /* queues a mail message */
  1683. X#define    CICO    "cico"            /* file transfer program */
  1684. X#define    NMAIL    "nmail"            /* extract originator address */
  1685. X
  1686. X /*
  1687. X  * The spool directory is used for storage of all files manipulated by the
  1688. X  * mail programs. Message files should always have a meta file with
  1689. X  * information about the destination or origin of a message file.
  1690. X  * 
  1691. X  * Message/meta file names are of the form <letter><sequence number>.
  1692. X  * Corresponding message/meta files have the same sequene number. The
  1693. X  * following definitions are for the <letter> part of spool files.
  1694. X  */
  1695. X
  1696. X#define    LOGFILE        "LOGFILE"    /* transaction logs */
  1697. X#define    HEADER        "header"    /* template message header */
  1698. X#define    TRAILER     "trailer"    /* template message trailer */
  1699. X
  1700. X#define    NEW_MESG    'n'        /* received message */
  1701. X#define    NEW_META    'h'        /* originator of new mail */
  1702. X
  1703. X#define    OLD_MESG    'n'        /* received message */
  1704. X#define    OLD_META    'o'        /* originator of old mail */
  1705. X
  1706. X#define    OUT_MESG    'd'        /* message ready to be sent */
  1707. X#define    OUT_META    'x'        /* its destination */
  1708. X
  1709. X#define    SENT_MESG    'q'        /* delivered message */
  1710. X#define    SENT_META    'r'        /* its destination */
  1711. X
  1712. X#define    WORK_MESG    'e'        /* message being worked on */
  1713. X#define    WORK_META    'c'        /* its description */
  1714. X
  1715. X#define    SETUP        's'        /* system parameter file */
  1716. X
  1717. X#define    ALIAS        'a'        /* alias data base */
  1718. X
  1719. X#define    SPOOLFMT    "%c%05u"    /* spool-file name format */
  1720. X#define    NAMELEN        6        /* length of spool file name */
  1721. X
  1722. Xunsigned newseqno();            /* generate sequence number */
  1723. Xunsigned seqno();            /* extract seq. nr. from name */
  1724. X
  1725. X /*
  1726. X  * The following macros provide convenient access of spool files, so we
  1727. X  * don't have to remember the spool file name format and prefix stuff.
  1728. X  */
  1729. X
  1730. X#define    sendmail(file,to)    spoolfil(file,to,OUT_MESG,OUT_META)
  1731. X#define    workon(fname,meta)    spoolfil(fname,meta,WORK_MESG,WORK_META)
  1732. X
  1733. X#define    parm_file()        fspool(strcons(SPOOLFMT,SETUP,0))
  1734. X#define    aliases()        fspool(strcons(SPOOLFMT,ALIAS,0))
  1735. X#define logfile()        fspool(LOGFILE)
  1736. X#define    header_file()        fspool(HEADER)
  1737. X#define    trailer_file()        fspool(TRAILER)
  1738. X
  1739. X#define meta_file(type,id)    fspool(strcons(SPOOLFMT,type,id))
  1740. X#define mesg_file(type,id)    fspool(strcons(SPOOLFMT,type,id))
  1741. X
  1742. X#define    work_meta(id)        fspool(strcons(SPOOLFMT,WORK_META,id))
  1743. X#define    work_mesg(id)        fspool(strcons(SPOOLFMT,WORK_MESG,id))
  1744. X
  1745. X#define    old_mesg(id)        fspool(strcons(SPOOLFMT,OLD_MESG,id))
  1746. X#define    old_meta(id)        fspool(strcons(SPOOLFMT,OLD_META,id))
  1747. X
  1748. X#define    new_mesg(id)        fspool(strcons(SPOOLFMT,NEW_MESG,id))
  1749. X#define    new_meta(id)        fspool(strcons(SPOOLFMT,NEW_META,id))
  1750. X
  1751. X#define    out_mesg(id)        fspool(strcons(SPOOLFMT,OUT_MESG,id))
  1752. X#define out_meta(id)        fspool(strcons(SPOOLFMT,OUT_META,id))
  1753. X
  1754. X#define    sent_mesg(id)        fspool(strcons(SPOOLFMT,SENT_MESG,id))
  1755. X#define sent_meta(id)        fspool(strcons(SPOOLFMT,SENT_META,id))
  1756. X
  1757. X /* stuff taken from the environment */
  1758. X
  1759. Xextern char *editor;            /* path to editor */
  1760. Xextern char *maildir;            /* spool directory */
  1761. Xextern char *mailprn;            /* how to print */
  1762. Xextern char *mailcmd;            /* do this on exit */
  1763. X
  1764. Xextern int pathinit();            /* get path info from environment */
  1765. X
  1766. X/* AUTHOR(S)
  1767. X/*    W.Z. Venema
  1768. X/*    Eindhoven University of Technology
  1769. X/*    Department of Mathematics and Computer Science
  1770. X/*    Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  1771. X/* CREATION DATE
  1772. X/*    Sun Apr  5 13:23:45 GMT+1:00 1987
  1773. X/* LAST MODIFICATION
  1774. X/*    90/01/22 13:02:27
  1775. X/* VERSION/RELEASE
  1776. X/*    2.1
  1777. X/*--*/
  1778. END_OF_main/path.h
  1779. if test 5231 -ne `wc -c <main/path.h`; then
  1780.     echo shar: \"main/path.h\" unpacked with wrong size!
  1781. fi
  1782. # end of overwriting check
  1783. fi
  1784. if test -f main/reply.c -a "${1}" != "-c" ; then 
  1785.   echo shar: Will not over-write existing file \"main/reply.c\"
  1786. else
  1787. echo shar: Extracting \"main/reply.c\" \(5418 characters\)
  1788. sed "s/^X//" >main/reply.c <<'END_OF_main/reply.c'
  1789. X/*++
  1790. X/* NAME
  1791. X/*      reply 3
  1792. X/* SUMMARY
  1793. X/*      reply to a message
  1794. X/* PROJECT
  1795. X/*      pc-mail
  1796. X/* PACKAGE
  1797. X/*      mail
  1798. X/* SYNOPSIS
  1799. X/*      int reply()
  1800. X/* DESCRIPTION
  1801. X/*      reply() is invoked when the user has selected a mail message
  1802. X/*    and wants to send a reply.
  1803. X/*
  1804. X/*    If possible, the reply address and subject are extracted from
  1805. X/*    the original message file. Reply-To: addresses are given precedence 
  1806. X/*    over From: addresses.
  1807. X/*
  1808. X/*    The reply may include a quoted copy of the body of the original
  1809. X/*    message.
  1810. X/*
  1811. X/*    After editing the reply, the user gets a chance to modify the 
  1812. X/*    extracted reply address.
  1813. X/* FILES
  1814. X/*    mail.msg, file being edited (in current directory)
  1815. X/*      $MAILDIR/ennnnn, message file (body)
  1816. X/*    $MAILDIR/cnnnnn, meta file (summary)
  1817. X/*    $MAILDIR/header, template mail header file
  1818. X/*    $MAILDIR/trailer, template signature file
  1819. X/* SEE ALSO
  1820. X/*      email(3)
  1821. X/* DIAGNOSTICS
  1822. X/*      If i/o errors are detected, an error message to that effect is
  1823. X/*      displayed.
  1824. X/* BUGS
  1825. X/*    Only understands From: and Reply-To: addresses. Reply-To: has higher
  1826. X/*    precedence. No attempt is made to reconstruct BANG paths from 
  1827. X/*    successive UUCP-style From_ lines.
  1828. X/* AUTHOR(S)
  1829. X/*      W.Z. Venema
  1830. X/*      Eindhoven University of Technology
  1831. X/*      Department of Mathematics and Computer Science
  1832. X/*      Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  1833. X/* CREATION DATE
  1834. X/*    Sun Dec 10 15:48:35 MET 1989
  1835. X/* LAST MODIFICATION
  1836. X/*    90/01/22 13:02:29
  1837. X/* VERSION/RELEASE
  1838. X/*    2.1
  1839. X/*--*/
  1840. X
  1841. X#include <stdio.h>
  1842. X
  1843. X#include "defs.h"
  1844. X#include "path.h"
  1845. X#include "pager.h"
  1846. X#include "screen.h"
  1847. X#include "status.h"
  1848. X#include "mail.h"
  1849. X#include "ascf.h"
  1850. X#include "ms_parse.h"
  1851. X
  1852. X/* forward declarations */
  1853. X
  1854. Xhidden int make_reply();
  1855. Xhidden int init_reply();
  1856. Xhidden void doquote();
  1857. Xhidden int getsubfrom();
  1858. X
  1859. Xhidden char original[BUFSIZ];        /* file name of original message */
  1860. X
  1861. X#define    LINE    256            /* max. line length supported here */
  1862. X
  1863. Xhidden char from[LINE];            /* reply address */
  1864. X
  1865. X/* reply - user wants to reply to a message */
  1866. X
  1867. Xpublic int reply()
  1868. X{
  1869. X    static Screen screen[] = {
  1870. X    YESNO,    0,    init_reply, int_error,
  1871. X    0,    0,    0,
  1872. X    "Press ESC to cancel. Include original message?",
  1873. X    };
  1874. X
  1875. X    kbdinp(screen);
  1876. X    return(S_BREAK);
  1877. X}
  1878. X
  1879. X/* init_reply - initial reply handling */
  1880. X
  1881. Xhidden int init_reply(need_quote)
  1882. Xregister int need_quote;
  1883. X{
  1884. X    register unsigned msgno;
  1885. X    register int stat;
  1886. X
  1887. X    strcpy(original, message);            /* keep original message name */
  1888. X    msgno = newseqno();
  1889. X    strcpy(message, work_mesg(msgno));        /* create message file name */
  1890. X    strcpy(comment, work_meta(msgno));        /* create meta file name */
  1891. X
  1892. X    if ((stat = make_reply(need_quote))        /* create template message */
  1893. X    ||(stat = edit(message, MAILFILE)))    /* and invoke editor */
  1894. X    errdisp(stat);
  1895. X    work_disp(from);                /* ask disposition */
  1896. X    return (S_REDRAW | S_BREAK);        /* say screen was changed */
  1897. X}
  1898. X
  1899. X/* make_reply - create response file */
  1900. X
  1901. Xhidden int make_reply(need_quote)
  1902. Xint     need_quote;
  1903. X{
  1904. X    register FILE *out;
  1905. X    char    subj[LINE];
  1906. X    int     err;
  1907. X
  1908. X    if (getsubfrom(original, subj, from)) {    /* extract subject and sender */
  1909. X    return (E_READERR);
  1910. X    } else if (out = fopen(message, "w")) {    /* build response file */
  1911. X    (void) fprintf(out, "Subject: Re: %s\n", subj[0] ? subj : "");
  1912. X    (void) textcopy(header_file(), out);    /* append custom headers */
  1913. X    (void) putc('\n', out);
  1914. X    if (need_quote) {
  1915. X        doquote(original, out);        /* quote original text */
  1916. X        (void) putc('\n', out);
  1917. X    }
  1918. X    (void) textcopy(trailer_file(), out);    /* append custom signature */
  1919. X
  1920. X    err = (fflush(out) || ferror(out));    /* do limited error checking */
  1921. X    (void) fclose(out);
  1922. X    return (err ? E_WRITERR : 0);
  1923. X    } else {
  1924. X    return (E_WRITERR);
  1925. X    }
  1926. X}
  1927. X
  1928. X/* getsubfrom - extract Sender and Subject from original message */
  1929. X
  1930. Xhidden int getsubfrom(original, subj, from)
  1931. Xchar   *original;
  1932. Xchar   *subj;
  1933. Xchar   *from;
  1934. X{
  1935. X    FILE   *in;
  1936. X    char    line[LINE];
  1937. X    int     context = MS_UUCP;
  1938. X    int     err = 0;
  1939. X
  1940. X    /*
  1941. X     * Reply-To: addresses have higher precedence than From: addresses. Skip
  1942. X     * "Re: " at the beginning of a subject.
  1943. X     */
  1944. X
  1945. X    subj[0] = from[0] = 0;
  1946. X
  1947. X    if (in = ascopen(original, "r")) {
  1948. X    while ((context != MS_BODY) && ascgets(line, sizeof(line), in)) {
  1949. X        if ((context = ms_parse(context, line)) == MS_HEADER) {
  1950. X        /* Process From: only if we did not see Reply-To: */
  1951. X        if (from[0] == 0
  1952. X        && !hscanf(line, "From:", " %*[^<] < %[^>]", from))
  1953. X            (void) hscanf(line, "From:", "%s", from);
  1954. X        /* Process Reply-To: even if we found a From: address */
  1955. X        if (!hscanf(line, "Subject: Re:", " %[^\n]", subj)
  1956. X        && !hscanf(line, "Subject:", " %[^\n]", subj)
  1957. X        && !hscanf(line, "Reply-To:", " %*[^<] < %[^>]", from))
  1958. X            (void) hscanf(line, "Reply-To:", " %s", from);
  1959. X        }
  1960. X    }
  1961. X    err = ferror(in);
  1962. X    (void) ascclose(in);
  1963. X    }
  1964. X    return (err);
  1965. X}
  1966. X
  1967. X/* doquote - quote text from original message */
  1968. X
  1969. Xhidden void doquote(original, out)
  1970. Xchar   *original;
  1971. XFILE   *out;
  1972. X{
  1973. X    int     context = MS_UUCP;
  1974. X    char    line[LINE];
  1975. X    FILE   *in;
  1976. X
  1977. X    /* Suppress the first line of the message body if it is empty. */
  1978. X
  1979. X    if (in = ascopen(original, "r")) {
  1980. X    while (ascgets(line, sizeof(line), in)) {
  1981. X        switch (context = ms_parse(context, line)) {
  1982. X        case MS_BODY:
  1983. X        context++;            /* hack */
  1984. X        if (line[0] == 0)        /* hack */
  1985. X            break;
  1986. X        /* FALLTHROUGH */
  1987. X        case MS_BODY + 1:            /* hack */
  1988. X        fprintf(out, ">%s\n", line);
  1989. X        break;
  1990. X        }
  1991. X    }
  1992. X    (void) ascclose(in);
  1993. X    }
  1994. X}
  1995. END_OF_main/reply.c
  1996. if test 5418 -ne `wc -c <main/reply.c`; then
  1997.     echo shar: \"main/reply.c\" unpacked with wrong size!
  1998. fi
  1999. # end of overwriting check
  2000. fi
  2001. if test -f main/spoolfil.c -a "${1}" != "-c" ; then 
  2002.   echo shar: Will not over-write existing file \"main/spoolfil.c\"
  2003. else
  2004. echo shar: Extracting \"main/spoolfil.c\" \(5014 characters\)
  2005. sed "s/^X//" >main/spoolfil.c <<'END_OF_main/spoolfil.c'
  2006. X/*++
  2007. X/* NAME
  2008. X/*    spoolfil,metafile 3
  2009. X/* SUMMARY
  2010. X/*    create message file and meta file
  2011. X/* PROJECT
  2012. X/*    pc-mail
  2013. X/* PACKAGE
  2014. X/*    general utilities
  2015. X/* SYNOPSIS
  2016. X/*    int spoolfil(path,meta_info,mesg_prefix,meta_prefix)
  2017. X/*    char *path;
  2018. X/*    char *meta_info;
  2019. X/*    int mesg_prefix;
  2020. X/*    int meta_prefix;
  2021. X/*
  2022. X/*    int metafile(path,string,...,(char *) 0)
  2023. X/*    char *path;
  2024. X/*    char *string;
  2025. X/* DESCRIPTION
  2026. X/*    spoolfil() creates a (message, meta) file pair in the spool
  2027. X/*    directory.
  2028. X/*
  2029. X/*    "path" should be null-terminated string with the name of an existing
  2030. X/*    file. The contents of that file are filtered to produce a
  2031. X/*    clean ASCII file.
  2032. X/*
  2033. X/*    "meta-info" is a string with additional information that is written to
  2034. X/*    the first line of a meta file (usually name of mail recipient, mail
  2035. X/*    originator or a comment describing the contents of the message file).
  2036. X/*    There should not be any embedded newline characters in this string.
  2037. X/*
  2038. X/*    "mesg_prefix," "meta_prefix" are prefixes that will be used for building
  2039. X/*    names for files in the spool directory.
  2040. X/*
  2041. X/*    If the message file given to spoolfil() looks like a mail message, a
  2042. X/*    line with Subject: information, extracted from the message, will be
  2043. X/*    appended to the meta file.
  2044. X/*
  2045. X/*    metafile() creates a file, writes the successive string arguments to
  2046. X/*    that file, each followed by a newline character. This function is
  2047. X/*    typically used to create a file with meta information (originator,
  2048. X/*    subject etc.).
  2049. X/* FUNCTIONS AND MACROS
  2050. X/*    ascopen(), ascget(), ascclose(), newseqno()
  2051. X/* DIAGNOSTICS
  2052. X/*    A nonzero return value indicates an error condition (see status.h)
  2053. X/* SEE ALSO
  2054. X/*    status(5)    return values
  2055. X/*    ascf(3)        ASCII filter
  2056. X/* BUGS
  2057. X/*    Wordprocessor control codes etc will be lost when spoolfil copies
  2058. X/*    a file.
  2059. X/* AUTHOR(S)
  2060. X/*    W.Z. Venema
  2061. X/*    Eindhoven University of Technology
  2062. X/*    Department of Mathematics and Computer Science
  2063. X/*    Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  2064. X/* CREATION DATE
  2065. X/*    Mon May 18 18:45:10 GMT+1:00 1987
  2066. X/* LAST MODIFICATION
  2067. X/*    90/01/22 13:02:40
  2068. X/* VERSION/RELEASE
  2069. X/*    2.1
  2070. X/*--*/
  2071. X
  2072. X#include <stdio.h>
  2073. X#include <varargs.h>
  2074. X
  2075. X#include "defs.h"
  2076. X#include "path.h"
  2077. X#include "ascf.h"
  2078. X#include "status.h"
  2079. X#include "ms_parse.h"
  2080. X
  2081. X/* metafile - create a meta file */
  2082. X
  2083. X/* VARARGS */
  2084. X
  2085. Xpublic int metafile(va_alist) 
  2086. Xva_dcl
  2087. X{
  2088. X    char   *path;
  2089. X    char   *string;
  2090. X    FILE   *fp;
  2091. X    va_list ap;
  2092. X    int     ret = 0;
  2093. X
  2094. X    va_start(ap);
  2095. X    path = va_arg(ap, char *);
  2096. X
  2097. X    if ((fp = fopen(path, "w")) == 0) {
  2098. X    ret = E_WRITERR;
  2099. X    } else {
  2100. X    while ((string = va_arg(ap, char *)) != 0)
  2101. X        (void) fprintf(fp, "%s\n", string);
  2102. X    if (fflush(fp) || ferror(fp))
  2103. X        ret = E_WRITERR;
  2104. X    (void) fclose(fp);
  2105. X    }
  2106. X    va_end(ap);
  2107. X    return (ret);
  2108. X}
  2109. X
  2110. X/* spoolfil - make arbitrary spool file */
  2111. X
  2112. Xpublic int spoolfil(fname, meta, msgpfx, auxpfx)
  2113. Xchar   *fname;
  2114. Xchar   *meta;
  2115. Xint     msgpfx;
  2116. Xint     auxpfx;
  2117. X{
  2118. X    register int newid = newseqno();    /* new message id */
  2119. X    register int stat;            /* some status */
  2120. X    char   *msgpath;            /* new message file */
  2121. X    char   *auxpath;            /* new meta file */
  2122. X    char    subj[BUFSIZ];        /* subject: info */
  2123. X
  2124. X    msgpath = mesg_file(msgpfx, newid);        /* message file name */
  2125. X    auxpath = meta_file(auxpfx, newid);        /* meta file name */
  2126. X
  2127. X    /* copy input file to spool file, try to get subject, check for errors */
  2128. X
  2129. X    if (stat = copyfile(fname, msgpath, subj)) {/* read/write error */
  2130. X    (void) unlink(msgpath);            /* delete msg file */
  2131. X    return (stat);                /* notify caller */
  2132. X    }
  2133. X    /* create file for meta information, check for errors */
  2134. X
  2135. X    if (stat = metafile(auxpath, meta, subj, (char *) 0)) {
  2136. X    (void) unlink(msgpath);            /* delete msg file */
  2137. X    (void) unlink(auxpath);            /* delete meta file */
  2138. X    return (stat);                /* notify caller */
  2139. X    }
  2140. X    /* when nothing went wrong */
  2141. X
  2142. X    (void) chmod(msgpath, 0444);        /* make message read-only */
  2143. X    (void) chmod(auxpath, 0444);        /* make metafile read-only */
  2144. X    return (0);                    /* own error handling */
  2145. X}
  2146. X
  2147. X/* copyfile - copy a file, filter it, optionally extract subject: info */
  2148. X
  2149. Xpublic int copyfile(from, to, subj)
  2150. Xchar   *from;
  2151. Xchar   *to;
  2152. Xchar   *subj;                /* may be a null pointer */
  2153. X{
  2154. X    register FILE *in,
  2155. X           *out;            /* file pointers */
  2156. X    int     ret = 0;            /* error status */
  2157. X
  2158. X    if ((in = ascopen(from, "r")) == 0) {    /* cannot read ?? */
  2159. X    return (E_READERR);
  2160. X    } else if ((out = fopen(to, "w")) == 0) {    /* cannot write ?? */
  2161. X    (void) ascclose(in);
  2162. X    return (E_WRITERR);
  2163. X    } else {
  2164. X    char    buf[BUFSIZ];
  2165. X    register int context = MS_UUCP;
  2166. X
  2167. X    if (subj)
  2168. X        *subj = 0;
  2169. X
  2170. X    while (ascgets(buf, sizeof(buf), in)) {
  2171. X        (void) fputs(buf, out);
  2172. X        (void) putc('\n', out);
  2173. X
  2174. X        /* extract the subject "on the fly" */
  2175. X
  2176. X        if (subj != 0 && *subj == 0
  2177. X        && (context = ms_parse(context, buf)) == MS_HEADER)
  2178. X        (void) hscanf(buf, "Subject:", " %[^\n]", subj);
  2179. X    }
  2180. X
  2181. X    /* perform the usual error checking */
  2182. X
  2183. X    if (ferror(in))
  2184. X        ret = E_READERR;
  2185. X    else if (fflush(out) || ferror(out))
  2186. X        ret = E_WRITERR;
  2187. X    (void) ascclose(in);
  2188. X    (void) fclose(out);
  2189. X    return (ret);
  2190. X    }
  2191. X}
  2192. END_OF_main/spoolfil.c
  2193. if test 5014 -ne `wc -c <main/spoolfil.c`; then
  2194.     echo shar: \"main/spoolfil.c\" unpacked with wrong size!
  2195. fi
  2196. # end of overwriting check
  2197. fi
  2198. echo shar: End of archive 5 \(of 11\).
  2199. cp /dev/null ark5isdone
  2200. MISSING=""
  2201. for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
  2202.     if test ! -f ark${I}isdone ; then
  2203.     MISSING="${MISSING} ${I}"
  2204.     fi
  2205. done
  2206. if test "${MISSING}" = "" ; then
  2207.     echo You have unpacked all 11 archives.
  2208.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2209. else
  2210.     echo You still need to unpack the following archives:
  2211.     echo "        " ${MISSING}
  2212. fi
  2213. ##  End of shell archive.
  2214. exit 0
  2215.  
  2216.