home *** CD-ROM | disk | FTP | other *** search
/ Garbo / Garbo.cdr / pc / source / pcmail2.lzh / pcmail.5 < prev    next >
Encoding:
Text File  |  1990-01-31  |  63.0 KB  |  2,209 lines

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