home *** CD-ROM | disk | FTP | other *** search
/ rtsi.com / 2014.01.www.rtsi.com.tar / www.rtsi.com / OS9 / OSK / TELECOM / OSKBox.lzh / MAILBOX / CC / mailbox.c < prev    next >
C/C++ Source or Header  |  1993-04-25  |  36KB  |  1,745 lines

  1. #include <stdio.h>
  2. #include <ctype.h>
  3. #include <direct.h>
  4. #include <signal.h>
  5. #include <modes.h>
  6. #include <errno.h>
  7. #include <procid.h>
  8. #include "mailbox.h"
  9.  
  10. #define BBSONLY
  11. #define FWDPORT "T3"
  12. #define ALARM ((1 << 31) + 10 * 60 * 256)
  13. #define MAXLIST 50
  14.  
  15. char line[256];
  16. char *noname = "new user";
  17. char *filedir = "FILES/";
  18. char *maildir = "MAIL/";
  19. char *banner = BANNER;
  20. char *ownerfile = "file_owners";
  21. char *days[] = {"Sunday","Monday","Tuesday","Wednesday",
  22.                 "Thursday","Friday","Saturday"};
  23. int signalman(), quit = 0, interrupt = 0;
  24. int connect_time, connect_date;
  25. struct userstruct user;
  26. long user_rec;
  27. int user_nmr;
  28. int sid_bbs, mid_flag, bid_flag, hflag;
  29. extern struct dist_list *distboxes;
  30. int last_read = -1;
  31. int fwdport = 0;
  32. int msg_proc = 0;
  33.  
  34. main (argc, argv)
  35. char *argv[];
  36. {
  37.  
  38.     chdir (HOME);
  39.     intercept (signalman);
  40.     login (argc, argv);
  41.     while (!quit) {
  42.         if (msg_proc )
  43.             {
  44.             struct pdsc buffer;
  45.  
  46.             if (_get_process_desc (msg_proc, sizeof (buffer), &buffer) != -1 &&
  47.                             buffer._state & (1 << 8))
  48.                 if (wait (0) == msg_proc)
  49.                     msg_proc = 0;
  50.             }
  51.         if (!(user.usopt & ISEXPERT)) {
  52.             printf ("Commands are:\n");
  53.             printf (
  54. "     B - bye   X - expert/novice   I - info   N - enter your name\n");
  55.             printf (
  56. "     L - list messages   R - read   S - send   K - kill   C - copy   M - modify\n");
  57.             printf (
  58. "     W - list files   D - download   U - upload   Z - erase   V - rename\n");
  59.             printf (
  60. "     Q - query  E - execute  H - help\n");
  61.             }
  62.         if (sid_bbs)
  63.             printf (">\n");
  64.         else
  65.             printf ("\nCommand: >\n");
  66.         getline ();
  67.         switch (toupper (*line)) {
  68.  
  69.     case '\0':
  70.             break;
  71.     
  72.     case 'B':
  73.             logout (argc, argv);
  74.  
  75.     case 'D':
  76.             download ();
  77.             break;
  78.     
  79.     case 'E':
  80.             execute ();
  81.             break;
  82.             
  83.     case 'U':
  84.             upload ();
  85.             break;
  86.     
  87.     case 'Z':
  88.             zap ();
  89.             break;
  90.     
  91.     case 'V':
  92.             rename ();
  93.             break;
  94.     
  95.     case 'I':
  96.             if (!printfile ("info"))
  97.                 printf ("No info available at this time\n");
  98.             break;
  99.     
  100.     case 'N':
  101.             name ();
  102.             break;
  103.     
  104.     case 'W':
  105.             what ();
  106.             break;
  107.     
  108.     case 'X':
  109.             user.usopt ^= ISEXPERT;
  110.             break;
  111.     
  112.     case 'S':
  113.             send ();
  114.             break;
  115.     
  116.     case 'L':
  117.             list ();
  118.             break;
  119.     
  120.     case 'R':
  121.             readmsg ();
  122.             break;
  123.     
  124.     case 'K':
  125.             killmsg ();
  126.             break;
  127.  
  128.     case 'Q':
  129.             query ();
  130.             break;
  131.  
  132.     case 'C':
  133.             copy ();
  134.             break;
  135.  
  136.     case 'M':
  137.             modify ();
  138.             break;
  139.  
  140.     case 'H':
  141.     case '?':
  142.             help ();
  143.             break;
  144.  
  145.     case '*':
  146.             link (argc, argv);
  147.             break;
  148.                 
  149.     case '@':
  150.             if (!sysop ()) goto what;
  151.             break;
  152.  
  153.     case 'F':
  154.             if (!reverse ()) goto what;
  155.             logout (argc, argv);
  156.  
  157.     case '[':
  158.             if (!sid ()) goto what;
  159.             break;
  160.  
  161.     default:
  162. what:        if (user.usopt & ISEXPERT)
  163.                 printf ("What?  Type H for help, X for command list.\n");
  164.             else
  165.                 printf ("What?  Type H for help.\n");
  166.             break;
  167.             
  168.             }
  169.         }
  170.     logout (argc, argv);
  171.     }
  172.  
  173. #define MAXTFC 100
  174.  
  175. login (argc, argv)
  176. char *argv[];
  177. {
  178.     int ssid = 0;
  179.     int date, time, tick;
  180.     short day;
  181.     struct fildes buffer;
  182.     char *p;
  183.     int i, len, userfile, found;
  184.     struct msg_header *head;
  185.     int flag = 1;
  186.     int f;
  187.     struct {
  188.         int count;
  189.         char whoto[7];
  190.         } traffic[MAXTFC];
  191.     int traffic_count = 0;
  192.     char *usercall;
  193.     int downfile;
  194.     char downname[69];
  195.  
  196.     _sysdate (0, &time, &date, &day, &tick);
  197.     connect_time = time;
  198.     connect_date = date;
  199.     for (i = 1; i < argc; i++)
  200.         upper (argv[i]);
  201.     if (argc < 2) {
  202.         if ((usercall = getenv ("CALL")) == NULL) {
  203.             printf ("Welcome to the WD6CMU OSKbox.\n");
  204.             read_dist_list ();
  205.             user.usopt = ISEXPERT + ISSUPER;
  206.             strcpy (user.uscall, "SYSOP");
  207.             strcpy (user.usname, "Master");
  208.             return;
  209.             }
  210.         }
  211.     else
  212.         usercall = argv[1];
  213.     if ((userfile = open ("users", 1)) <= 0) {
  214.         printf ("Error: can't open user file\n");
  215.         exit (0);
  216.         }
  217.     ssid = get_ssid (usercall);
  218.     found = 0;
  219.     while (1) {
  220.         user_rec = lseek (userfile, 0L, 1);
  221.         if (read (userfile, &user, sizeof (user)) == 0) break;
  222.         if (!(user.usopt & ISDELETED) && strcmp (user.uscall, usercall) == 0) {
  223.             found = 1;
  224.             break;
  225.             }
  226.         }
  227.     if (!found) {
  228.         strcpy (user.usname, noname);
  229.         strcpy (user.uscall, usercall);
  230.         user.usopt = 0;
  231.         user.ustime = 0;
  232.         user.usdate = 0;
  233.         user.uscnt = 0;
  234.         open_mail ();
  235.         user.usnmr = 0;
  236.         while ((head = next_mail (is_gnum, 0)) != NULL)
  237.             if (head->mhnr > user.usnmr) user.usnmr = head->mhnr;
  238.         close_mail ();
  239.         close (userfile);
  240.         userfile = open ("users", 3);
  241.         user_rec = lseek (userfile, 0L, 2);
  242.         write (userfile, &user, sizeof (user));
  243.         close (userfile);
  244.         userfile = open ("users", 1);
  245.         }
  246.     close (userfile);
  247.     if (user.usopt & ISPNG) 
  248.         exit (0);   /* persona non grata */
  249.     sprintf (downname, "%s/down", FWDIR);
  250.     if (!(user.usopt & ISSUPER) && (downfile = open (downname, 1)) > 0)
  251.         {
  252.         char line[99];
  253.         int len;
  254.         
  255.         while ((len = readln (downfile, line, 99)) > 0)
  256.             writeln (0, line, len);
  257.         close (downfile);
  258.         exit (0);
  259.         }
  260.     if (user.usopt & ISSTUPID) {
  261.         printf ("You have not set the MYCALL parameter on your TNC\n");
  262.         printf ("Please read the manual for your TNC and set MYCALL to your\n");
  263.         printf ("callsign and try your connect again.\n");
  264.         exit (0);
  265.         }
  266.     if (strcmp (argv[2], FWDPORT) == 0)
  267.         fwdport++;
  268.     user_nmr = user.usnmr;
  269.     read_dist_list ();
  270.     if (user.usopt & ISBBS) {
  271.         printf ("%s\n", SID);
  272.         printbanner (date, time, day);
  273.         }
  274.     else {
  275.         strcpy (line, user.usname);
  276.         upper (line);
  277.         if (strcmp (line, "DOC") == 0 && (time & 3) == 1)
  278.             printf ("What's up, %s? %d\n", user.usname);
  279.         else
  280.             printf ("Hello %s.\n", user.usname);
  281.         printbanner (date, time, day);
  282.         if (strcmp (user.usname, "new user") == 0)
  283.             printf ("(Remember to use the 'N' command to enter your name.)\n");
  284.         if ((i = open ("motd", 1)) >= 0) {
  285.             int comp;
  286.             _gs_gfd (i, &buffer, sizeof (buffer));
  287.             if ((comp = buffer.fd_date[0] - (user.usdate >> 16) % 100) == 0)
  288.             if ((comp = buffer.fd_date[1] - ((user.usdate >> 8) & 0xff)) == 0)
  289.             if ((comp = buffer.fd_date[2] - (user.usdate & 0xff)) == 0)
  290.             if ((comp = buffer.fd_date[3] - ((user.ustime >> 16) & 0xff)) == 0)
  291.                 comp = buffer.fd_date[4] - ((user.ustime >> 8) & 0xff);
  292.             if (comp >= 0)
  293.                 while ((len = readln (i, line, sizeof (line))) > 0)
  294.                     writeln (1, line, len);
  295.             close (i);
  296.             }
  297.         open_mail ();
  298.         while ((head = next_mail (is_type, 'T')) != NULL &&
  299.                         traffic_count < MAXTFC) {
  300.             for (i = 0; i < traffic_count; i++)
  301.                 if (strcmp (head->mhto, traffic[i].whoto) == 0)
  302.                     break;
  303.                 if (i == traffic_count) {
  304.                     strcpy (traffic[traffic_count].whoto, head->mhto);
  305.                     traffic[traffic_count++].count = 1;
  306.                     }
  307.                 else
  308.                     traffic[i].count++;
  309.             }
  310.         if (traffic_count) {
  311.             printf ("QTC");
  312.             for (i = 0; i < traffic_count; i++)
  313.                 printf (" %d %s", traffic[i].count, traffic[i].whoto);
  314.             printf ("\n");
  315.             }
  316.         reset_mail ();
  317.         while ((head = next_mail (is_mail, user.uscall)) != NULL) {
  318.             if (flag) printf ("You have mail:\n");
  319.             print_header (head, 1, flag);
  320.             flag = 0;
  321.             }
  322.         close_mail ();
  323.         }
  324.     user.usssid = ssid;
  325.     user.uscnt++;
  326.     user.uspath[0] = '\0';
  327.     if (argc < 3)
  328.         strcat (user.uspath, getenv ("PORT"));
  329.     else
  330.         for (i = 2; i < argc; i++) {
  331.             strcat (user.uspath, argv[i]);
  332.             strcat (user.uspath, " ");
  333.             }
  334.     log ("c -%d %s", user.usssid, user.uspath);
  335.     }
  336.  
  337. printbanner (date, time, day)
  338. {
  339.     printf ("%s  %s %d/%d/%d %02d:%02d:%02d\n",
  340.         banner, 
  341.         days[day],
  342.         (date >> 8) & 0xff,
  343.         date & 0xff,
  344.         (date >> 16) % 100, 
  345.         (time >> 16) & 0xff,
  346.         (time >> 8) & 0xff,
  347.         time & 0xff);
  348.     }
  349.  
  350. logout (argc, argv)
  351. char *argv[];
  352. {
  353.     int date, time, tick;
  354.     short day;
  355.     int userfile, flag;
  356.  
  357.     _sysdate (0, &time, &date, &day, &tick);
  358.     if (argc >= 2 || getenv ("CALL")) {
  359.         user.usnmr = user_nmr;
  360.         user.usdate = connect_date;
  361.         user.ustime = connect_time;
  362.         userfile = open ("users", 3);
  363.         lseek (userfile, user_rec, 0);
  364.         write (userfile, &user, sizeof (user));
  365.         close (userfile);
  366.         }
  367.     if (!quit && !(user.usopt & ISBBS) && 
  368.             strcmp (user.usname, noname) != 0) {
  369.         printf ("Good ");
  370.         if ((time >> 16) < 12)
  371.             printf ("morning");
  372.         else if ((time >> 16) < 17)
  373.             printf ("afternoon");
  374.         else
  375.             printf ("evening");
  376.         printf (" %s.\n", user.usname);
  377.         }
  378.     if (strcmp (user.uscall, "SYSOP") != 0)
  379.         log ("d");
  380.     close_mail ();
  381.     exit (0);
  382.     }
  383.     
  384.  
  385. download ()
  386. {
  387.     char *p, path[80];
  388.     int f, len;
  389.  
  390. #ifdef BBSONLY
  391.     if (fwdport && !(user.usopt & ISSUPER))
  392.         {
  393.         printf ("No downloading allowed on forwarding port.\n");
  394.         return;    /* Can't download files on fwd port */
  395.         }
  396. #endif
  397.     p = line;
  398.     strcpy (path, filedir);
  399.     p += scanword (p, path+6, 80 - 6);
  400.     p += scanword (p, path+6, 80 - 6);
  401.     if (path[6] == '\0') {
  402.         printf ("File to download:\n");
  403.         getline ();
  404.         if (quit) return;
  405.         scanword (line, path+6, 80 - 6);
  406.         }
  407.     if (path[6] == '\0') return;
  408.     if (findstr (1, path, "/.")) {
  409.         return;
  410.         }
  411.     if (!printfile (path)) {
  412.         if (errno == 214)
  413.             printf ("That's a directory, not a file.\n");
  414.         else if (errno == 216)
  415.             printf ("No such file\n");
  416.         else
  417.             printf ("Error %d while trying to open %s\n", errno, path+6);
  418.         return;
  419.         }
  420.     else {
  421.         write (1, "\032", 1);
  422.         log ("D %s", path);
  423.         }
  424.     }
  425.  
  426. upload ()
  427. {
  428.     char *p, path[80];
  429.     int i, f, len;
  430.     FILE *owners;
  431.  
  432.     p = line;
  433.     strcpy (path, filedir);
  434.     i = strlen (path);
  435.     p += scanword (p, path + i, 80 - i);
  436.     p += scanword (p, path + i, 80 - i);
  437.     if (path[i] == '\0') {
  438.         printf ("File to upload:\n");
  439.         getline ();
  440.         if (quit) return;
  441.         scanword (line, path + i, 80 - i);
  442.         }
  443.     if (path[i] == '\0') return;
  444.     if (findstr (1, path, "/.")) {
  445.         return;
  446.         }
  447.     lower (path + i);
  448.     if ((f = create (path, 2, 3)) == -1) {
  449.         printf ("Error creating file.  Upload aborted.\n");
  450.         return;
  451.         }
  452.     printf ("Send the file, ^Z to end.\n");
  453.     getfile (f, 0, NULL);
  454.     close (f);
  455.     if (quit || interrupt) {
  456.         unlink (path);
  457.         return;
  458.         }
  459.     if (owners = fopen (ownerfile, "a")) {
  460.         fprintf (owners, "%s %s\n", user.uscall, path+i);
  461.         fclose (owners);
  462.         }
  463.     log ("U %s", path+i);
  464.     }
  465.  
  466. zap ()
  467. {
  468.     char *p, path[80];
  469.     int i, j, f, len;
  470.     FILE *owners;
  471.  
  472.     p = line;
  473.     strcpy (path, filedir);
  474.     i = strlen (path);
  475.     p += scanword (p, path + i, 80 - i);
  476.     p += scanword (p, path + i, 80 - i);
  477.     if (path[i] == '\0') {
  478.         printf ("File to erase:\n");
  479.         getline ();
  480.         if (quit) return;
  481.         p = line + scanword (line, path + i, 80 - i);
  482.         }
  483.     if (path[i] == '\0') return;
  484.     if (findstr (1, path, "/.")) {
  485.         return;
  486.         }
  487.     lower (path + i);
  488.     if (access (path, 0) == -1) {
  489.         printf ("No such file.\n");
  490.         return;
  491.         }
  492.     if ((j = isowner (path + i, user.uscall)) != -1) {
  493.         if (unlink (path) == -1) {
  494.             printf ("Error %d during delete\n", errno);
  495.             return;
  496.             }
  497.         if (owners = fopen (ownerfile, "r+")) {
  498.             fseek (owners, (long)j, 0);
  499.             putc ('*', owners);
  500.             fclose (owners);
  501.             }
  502.         else
  503.             printf ("Error %d opening ownerfile.\n", errno);
  504.         log ("Z %s", path+i);
  505.         }
  506.     else
  507.         printf ("Sorry, that file doesn't belong to you.\n");
  508.     }
  509.  
  510. rename ()
  511. {
  512.     char *p, path[80], path2[29];
  513.     int i, j, f, len;
  514.     FILE *owners;
  515.  
  516.     p = line;
  517.     strcpy (path, filedir);
  518.     i = strlen (path);
  519.     p += scanword (p, path + i, 80 - i);
  520.     p += scanword (p, path + i, 80 - i);
  521.     if (path[i] == '\0') {
  522.         printf ("File to rename:\n");
  523.         getline ();
  524.         if (quit) return;
  525.         p = line + scanword (line, path + i, 80 - i);
  526.         }
  527.     if (path[i] == '\0') return;
  528.     if (findstr (1, path, "/.")) {
  529.         return;
  530.         }
  531.     lower (path + i);
  532.     if (access (path, 0) == -1) {
  533.         printf ("No such file.\n");
  534.         return;
  535.         }
  536.     if ((j = isowner (path + i, user.uscall)) != -1) {
  537.         p += scanword (p, path2, 29);
  538.         if (path2[0] == '\0') {
  539.             printf ("New name:\n");
  540.             getline ();
  541.             if (quit) return;
  542.             scanword (line, path2, 29);
  543.             }
  544.         if (path2[0] == '\0') return;
  545.         lower (path2);
  546.         if (rename_file (path, path2) == -1) return;
  547.         if (j != -2 && (owners = fopen (ownerfile, "r+"))) {
  548.             fseek (owners, (long)j, 0);
  549.             putc ('*', owners);
  550.             for (p = path + strlen (path); *p != '/'; p--)
  551.                 ;
  552.             strcpy (p+1, path2);
  553.             fseek (owners, 0L, 2);
  554.             fprintf (owners, "%s %s\n", user.uscall, path + strlen (filedir));
  555.             fclose (owners);
  556.             }
  557.         log ("V %s %s", path+i, path2);
  558.         }
  559.     else
  560.         printf ("Sorry, that file doesn't belong to you.\n");
  561.     }
  562.  
  563. isowner (path, call)
  564. char *path, *call;
  565. {
  566.     int owners;
  567.     char _call[7], _path[80];
  568.     char str[90], *p;
  569.     int len;
  570.     long pos;
  571.  
  572.     if ((owners = open (ownerfile, 1)) == -1)
  573.         return ((user.usopt & ISSUPER) ? -2 : -1);
  574.     pos = lseek (owners, 0L, 1);
  575.     while (len = readln (owners, str, 90)) {
  576.         str[len-1] = '\0';
  577.         p = str + scanword (str, _call, 7);
  578.         p += scanword (p, _path, 80);
  579.         if (*_call != '*' && strcmp (path, _path) == 0) {
  580.             close (owners);
  581.             return ((user.usopt & ISSUPER) || strcmp (call, _call) == 0) ?
  582.                 pos : -1;
  583.             }
  584.         pos = lseek (owners, 0L, 1);
  585.         }
  586.     close (owners);
  587.     return ((user.usopt & ISSUPER) ? -2 : -1);
  588.     }
  589.  
  590. name ()
  591. {
  592.     char *p, str[80];
  593.  
  594.     p = line;
  595.     p += scanword (p, str, 80);
  596.     p += scanword (p, str, 80);
  597.     if (str[0] == '\0') {
  598.         printf ("Enter your name (12 chars max):\n");
  599.         getline ();
  600.         if (quit) return;
  601.         scanword (line, str, 80);
  602.         }
  603.     if (*str == '\0') return;
  604.     strncpy (user.usname, str, 13);
  605.     sprintf (str, "register %s %s", user.uscall, user.usname);
  606.     system (str);
  607.     }
  608.  
  609. what ()
  610. {
  611.     char *p, str[80], str2[90];
  612.  
  613.     p = line;
  614.     p += scanword (p, str, 80);
  615.     strcpy (str2, "dir -d ");
  616.     if (toupper (str[1]) == 'X')
  617.         strcat (str2, "-e ");
  618.     else if (toupper (str[1]) == 'N') {
  619.         whatsnew ();
  620.         return;
  621.         }
  622.     strcpy (str, filedir);
  623.     p += scanword (p, str+6, 80 - 6);
  624.     if (str[6] == '\0') 
  625.         str[5] = '\0';
  626.     if (findstr (1, str, "/.")) {
  627.         return;
  628.         }
  629.     strcat (str2, str);
  630.     system (str2);
  631.     }
  632.  
  633. whatsnew ()
  634. {
  635.     char *p, str[80], str2[90];
  636.     int year, month, day, hour, min;
  637.  
  638.     p = line;
  639.     p += scanword (p, str, 80);
  640.     p += scanword (p, str, 80);
  641.     year = (user.usdate >> 16) % 100;
  642.     month = (user.usdate >> 8) & 0xff;
  643.     day = user.usdate & 0xff;
  644.     hour = (user.ustime >> 16) & 0xff;
  645.     min = (user.ustime >> 8) & 0xff;
  646.     if (*str) {
  647.         hour = min = 0;
  648.         sscanf (str, "%d/%d/%d", &month, &day, &year);
  649.         }
  650.     sprintf (str2, "latest FILES %d/%d/%d %d:%d", month, day, year, hour, min);
  651.     system (str2);
  652.     }
  653.  
  654. send ()
  655. {
  656.     char *p, w[40], w2[40];
  657.     struct msg_header *head;
  658.     int date, time, tick;
  659.     short day;
  660.     int f, n;
  661.     int fromflag = 0, makebid = 0, repeat = 0;
  662.     char type, to[40], from[7], bbs[39], bid[13], title[90];
  663.     
  664.     p = line;
  665.     p += scanword (p, w, 40);
  666.     strcpy (from, user.uscall);
  667.     to[0] = '\0';
  668.     bbs[0] = '\0';
  669.     bid[0] = '\0';
  670.     title[0] = '\0';
  671.     type = (isalpha (w[1])) ? toupper (w[1]) : ' ';
  672.     if (type == 'R') {
  673.         int n, len;
  674.         char str[256], out[256], *p2;
  675.  
  676.         type = 'P';
  677.         p += scanword (p, w, 40);
  678.         while (!*w) {
  679.             if (last_read >= 0)
  680.                 printf ("Message number to reply to [%d]:\n", last_read);
  681.             else
  682.                 printf ("Message number to reply to:\n");
  683.             getline ();
  684.             if (quit) return;
  685.             scanword (line, w, 40);
  686.             if (!*w && last_read >= 0)
  687.                 sprintf (w, "%d", last_read);
  688.             }
  689.         n = atoi (w);
  690.         open_mail ();
  691.         if ((head = next_mail (is_num, n)) == NULL) {
  692.             printf ("Can't find message number %s\n", w);
  693.             close_mail ();
  694.             return;
  695.             }
  696.         strcpy (to, head->mhfrom);
  697.         sprintf (title, "Re: %s", head->mhtit);
  698.         f = open_msg (head);
  699.         while (len = readln (f, str, 256)) {
  700.             str[len-1] = '\0';
  701.             if (parse_head (str, out) < 2 || *out != 'R')
  702.                 break;    /* not a header */
  703.             for (p2 = out; *p2; p2 += strlen (p2) + 1)
  704.                 if (*p2 == '@') {
  705.                     scanword (p2+1, bbs, sizeof (bbs));
  706.                     get_ssid (bbs);
  707.                     upper (bbs);
  708.                     }
  709.             }
  710.         close (f);
  711.         close_mail ();
  712.         printf ("Enter new title, or <CR> for `Re:' the same title:\n");
  713.         getline ();
  714.         if (quit) return;
  715.         if (*line)
  716.             strncpy (title, line, 81);
  717.         }
  718.     else {
  719.         p += scanword (p, w, 40);
  720.         if (! *w) {
  721.             printf ("Enter callsign of addressee:\n");
  722.             getline ();
  723.             if (quit)
  724.                 return;
  725.             p = line + scanword (line, w, 40);
  726.             }
  727.         if (! *w)
  728.             return;    /* no addressee */
  729.         upper (w);
  730.         get_ssid (w);
  731.         strcpy (to, w);
  732.         }
  733.     p += scanword (p, w, 40);
  734. again:
  735.     if (*w) {
  736.         if (*w == '@') {
  737.             p += scanword (p, w, 40);
  738.             if (*w) {
  739.                 upper (w);
  740.                 get_ssid (w);
  741.                 strncpy (bbs, w, 39);
  742.                 p += scanword (p, w, 40);
  743.                 goto again;
  744.                 }
  745.             }
  746.         else if (*w == '<') {
  747.             p += scanword (p, w, 40);
  748.             if (*w) {
  749.                 upper (w);
  750.                 get_ssid (w);
  751.                 if ((user.usopt & ISBBS) || (user.usopt & ISSUPER))
  752.                     strncpy (from, w, 7);
  753.                 p += scanword (p, w, 40);
  754.                 fromflag++;
  755.                 goto again;
  756.                 }
  757.             }
  758.         else if (*w == '$') {
  759.             if (strlen (w) == 1) {
  760.                 p += scanword (p, w, 40);
  761.                 if (!*w)
  762.                     makebid++;
  763.                 }
  764.             else
  765.                 strcpy (w, w+1);
  766.             if (*w) {
  767.                 upper (w);
  768.                 strncpy (bid, w, 13);
  769.                 p += scanword (p, w, 40);
  770.                 goto again;
  771.                 }
  772.             }
  773.         }
  774.     if (p = strchr (to, '@'))
  775.         {
  776.         *p = '\0';
  777.         strncpy (bbs, p+1, 39);
  778.         }
  779.     if (type == 'T') {
  780.         bid[0] = '\0';
  781.         makebid = 0;
  782.         }
  783.     open_mail ();
  784.     if (bid[0] && (head = find_bid (bid))) {
  785.         printf ("NO - duplicate BID\n");
  786.         checkoff (head, user.uscall);
  787.         close_mail ();
  788.         return;
  789.         }
  790. #ifdef NO_WW
  791.     if (strcmp (bbs, "WW") == 0 && strcmp (to, "SALE") == 0) {
  792.         printf ("NO - don't want 'em\n");
  793.         close_mail ();
  794.         return;
  795.         }
  796.     if (strcmp (bbs, "ALLUS") == 0 && strcmp (to, "SALE") == 0) {
  797.         printf ("NO - don't want 'em\n");
  798.         close_mail ();
  799.         return;
  800.         }
  801. #endif
  802.     if ((head = new_mail (0)) == NULL) {
  803.         printf ("WAIT - mail system is full\n");
  804.         close_mail ();
  805.         return;
  806.         }
  807.     if (strcmp (from, "SYSOP") == 0)
  808.         strcpy (from, MYCALL);
  809.     strcpy (head->mhbid, bid);
  810.     head->mhtype = type;
  811.     strcpy (head->mhfrom, from);
  812.     strncpy (head->mhto, to, 7);
  813.     strcpy (head->mhbbs, bbs);
  814.     if (head->mhtype == ' ')
  815.         if (bulletin (head))
  816.             head->mhtype = 'B';
  817.         else
  818.             head->mhtype = 'P';
  819.     update_mail ();
  820.     if (!*title) {
  821.         if (sid_bbs)
  822.             printf ("OK %d\n", head->mhnr);
  823.         else
  824.             printf ("Enter title of message:\n");
  825.         getline ();
  826.         if (quit) return;
  827.         strncpy (head->mhtit, line, 81);
  828.         }
  829.     else
  830.         strncpy (head->mhtit, title, 81);
  831.     strcpy (w, maildir);
  832.     header_to_name (head, w + strlen (maildir));
  833.     if ((f = create (w, S_IWRITE, S_IOREAD+S_IREAD+S_IWRITE)) == -1) {
  834.         printf ("Error %d creating message file %s.\n", errno, w);
  835.         close_mail ();
  836.         return;
  837.         }
  838.     if (!sid_bbs)
  839.         printf ("Enter the message, ^Z to end.  It will be number %d\n",
  840.             head->mhnr);
  841.     if (getfile (f, 1, &repeat))
  842.         write (f, "\n", 1);
  843.     head->mhsize = _gs_size (f);
  844.     close (f);
  845.     header_to_name (head, w);
  846.     if (quit || interrupt) {
  847.         head->mhbid[0] = '\0';
  848.         head->mhsize = 0;
  849.         update_mail ();
  850.         close_mail ();
  851.         return;
  852.         }
  853.     if (bulletin (head) && !(user.usopt & ISBBS))
  854.         makebid++;
  855.     if (makebid && !*head->mhbid)
  856.         sprintf (head->mhbid, "%d_%s", head->mhnr, MYCALL);
  857.     checkoff (head, user.uscall);
  858.     head->mhstat = 'N';
  859.     update_mail ();
  860.     log_send (head, fromflag);
  861.     close_mail ();
  862.     process (head);
  863.     return;
  864.     }
  865.  
  866. list ()
  867. {
  868.     struct msg_header *head;
  869.     char *p, w1[20], w2[80];
  870.     int f;
  871.     int flag = 1;
  872.     int max_msg = 0;
  873.     int (*comp)();
  874.     int arg, arg2;
  875.     extern int xflag, eflag;
  876.     
  877.     p = line + scanword (line, w1, 20);
  878.     scanword (p, w2, 20);
  879.     while (*p && isspace (*p)) p++;
  880.     upper (w1);
  881.     upper (w2);
  882.     if ((user.usopt & ISSUPER) && w1[1] == 'X') {
  883.         xflag++;
  884.         strcpy (w1+1, w1+2);
  885.         }
  886.     if ((user.usopt & ISSUPER) && w1[1] == 'E') {
  887.         eflag++;
  888.         strcpy (w1+1, w1+2);
  889.         }
  890.     switch (w1[1]) {
  891. case '\0':
  892.         comp = is_gnum;
  893.         arg = (*w2) ? atoi (w2) : user.usnmr;
  894.         break;
  895. case '>':
  896.         comp = is_to;
  897.         arg = (int)w2;
  898.         break;
  899. case '<':
  900.         comp = is_from;
  901.         arg = (int)w2;
  902.         break;
  903. case '@':
  904.         comp = is_at;
  905.         arg = (int)w2;
  906.         break;
  907. case 'M':
  908.         comp = is_to;
  909.         arg = (int)user.uscall;
  910.         break;
  911. case 'Y':
  912.         comp = is_read;
  913.         arg = atoi (w2);
  914.         break;
  915. case 'F':
  916.         comp = is_forwarded;
  917.         arg = atoi (w2);
  918.         break;
  919. case 'L':
  920.         comp = is_last;
  921.         if ((arg = atoi (w2)) == 0) return;
  922.         break;
  923. case 'H':
  924.         comp = is_hold;
  925.         arg = (*w2) ? atoi (w2) : user.usnmr;
  926.         break;
  927. case 'T':
  928.         comp = is_type;
  929.         arg = w1[1];
  930.         arg2 = (*w2) ? atoi (w2) : 0;
  931.         break;
  932. case 'S':
  933.         w2[0] = '*';
  934.         strcpy (w2+1, p);
  935.         strcat (w2, "*");
  936.         comp = is_title;
  937.         arg = (int)w2;
  938.         break;
  939. default:
  940.         comp = is_type;
  941.         arg = w1[1];
  942.         arg2 = (*w2) ? atoi (w2) : user.usnmr;
  943.         break;
  944.         }
  945.     open_mail ();
  946.     interrupt = 0;
  947.     while ((head = next_mail (comp, arg, arg2)) != NULL && !interrupt) {
  948.         print_header (head, 1, flag);
  949.         flag = 0;
  950.         if (head->mhnr > max_msg) max_msg = head->mhnr;
  951.         }
  952.     close_mail ();
  953.     if (interrupt)
  954.         printf ("\n\007Listing interrupted\n");
  955.     interrupt = 0;
  956.     if (!w1[1] && !w2[0])
  957.         user_nmr = max (user_nmr, max_msg + 1);
  958.     if (flag)
  959.         printf ("*** Not found\n");
  960.     }
  961.  
  962. readmsg ()
  963. {
  964.     struct msg_header *head;
  965.     char *p, w1[20], w2[20];
  966.     char name[40], newname[40];
  967.     int f;
  968.     int flag = 1;
  969.     int (*comp)(), arg, list[MAXLIST];
  970.     int i, len;
  971.     int with_headers;
  972.  
  973.     p = line + scanword (line, w1, 20);
  974.     if (toupper (w1[1]) == 'H') {
  975.         with_headers = 1;
  976.         strcpy (w1+1, w1+2);
  977.         }
  978.     else
  979.         with_headers = 0;
  980.     p += scanword (p, w2, 20);
  981.     if (!*w2 && toupper (w1[1]) != 'M') {
  982.         printf ("Message to read:\n");
  983.         getline ();
  984.         if (quit) return;
  985.         scanword (line, w2, 20);
  986.         }
  987.     if (toupper (w1[1]) == 'M') {
  988.         comp = is_to;
  989.         arg = (int) user.uscall;
  990.         }
  991.     else if (isdigit (*w2)) {
  992.         comp = is_multnum;
  993.         arg = (int)list;
  994.         for (i = 0; i < MAXLIST - 1 && isdigit (*w2); i++) {
  995.             list[i] = atoi (w2);
  996.             p += scanword (p, w2, 20);
  997.             }
  998.         list[i] = -1;
  999.         }
  1000.     else return;
  1001.     open_mail ();
  1002.     while ((head = next_mail (comp, arg)) != NULL) {
  1003. #ifdef BBSONLY
  1004.         if (bulletin (head) && fwdport && !(user.usopt & ISSUPER))
  1005.             {
  1006.             printf ("Can't read #%d: No bulletins on forwarding port.\n", head->mhnr);
  1007.             continue;    /* Can't read bulletins on fwd port */
  1008.             }
  1009. #endif
  1010.         f = open_msg (head);
  1011.         print_header (head, 1, 1);
  1012.         if (with_headers)
  1013.             printpath (f);
  1014.         else
  1015.             printmsg (f);
  1016.         close (f);
  1017.         last_read = head->mhnr;
  1018.         if (strcmp (head->mhto, user.uscall) == 0 &&
  1019.             strcmp (user.uscall, "SYSOP") != 0 && head->mhstat == 'N') {
  1020.             head->mhstat = 'Y';
  1021.             update_mail ();
  1022.             }
  1023.         flag = 0;
  1024.         }
  1025.     close_mail ();
  1026.     if (flag)
  1027.         printf ("*** Not found\n");
  1028.     }
  1029.  
  1030. killmsg ()
  1031. {
  1032.     struct msg_header *head;
  1033.     char *p, w1[20], w2[20];
  1034.     char name[40], newname[40];
  1035.     int f;
  1036.     int flag = 1;
  1037.     int tflag = 0;
  1038.     int (*comp)(), arg, list[MAXLIST];
  1039.     int i;
  1040.  
  1041.     p = line + scanword (line, w1, 20);
  1042.     p += scanword (p, w2, 20);
  1043.     if (!*w2 && toupper (w1[1]) != 'M') {
  1044.         printf ("Message to kill:\n");
  1045.         getline ();
  1046.         if (quit) return;
  1047.         scanword (line, w2, 20);
  1048.         }
  1049.     if (toupper (w1[1]) == 'M') {
  1050.         comp = is_nmail;
  1051.         arg = (int) user.uscall;
  1052.         }
  1053.     else if (toupper (w1[1]) == 'F')
  1054.         comp = is_forwarded;
  1055.     else if (toupper (w1[1]) == 'T' && isdigit (*w2)) {
  1056.         comp = is_num;
  1057.         arg = atoi (w2);
  1058.         tflag++;
  1059.         }
  1060.     else if (isdigit (*w2)) {
  1061.         comp = is_multnum;
  1062.         arg = (int)list;
  1063.         for (i = 0; i < MAXLIST - 1 && isdigit (*w2); i++) {
  1064.             list[i] = atoi (w2);
  1065.             p += scanword (p, w2, 20);
  1066.             }
  1067.         list[i] = -1;
  1068.         }
  1069.     else return;
  1070.     open_mail ();
  1071.     while ((head = next_mail (comp, arg)) != NULL) {
  1072.         if (strcmp (user.uscall, head->mhfrom) != 0 &&
  1073.             strcmp (user.uscall, head->mhto) != 0 &&
  1074.             !(tflag && head->mhtype == 'T') &&
  1075.             !(user.usopt & ISSUPER)) continue;
  1076.         header_to_name (head, name);
  1077.         head->mhstat = 'X';
  1078.         update_mail ();
  1079.         if (tflag)
  1080.             log ("KT %d", head->mhnr);
  1081.         else
  1082.             log ("K  %d", head->mhnr);
  1083.         printf ("*** Message #%d killed.\n", head->mhnr);
  1084.         flag = 0;
  1085.         }
  1086.     close_mail ();
  1087.     if (flag)
  1088.         printf ("*** Not found\n");
  1089.     }
  1090.  
  1091. query ()
  1092. {
  1093.     char call[30], *p;
  1094.  
  1095.     p = line;
  1096.     p += scanword (p, call, 30);
  1097.     p += scanword (p, call, 30);
  1098.     if (!*call) {
  1099.         printf ("Callsign to search for:\n");
  1100.         getline ();
  1101.         if (quit) return;
  1102.         scanword (line, call, 30);
  1103.         }
  1104.     if (!*call) return;
  1105.     sprintf (line, "query %s", call);
  1106.     system (line);
  1107.     }
  1108.  
  1109. copy ()
  1110. {
  1111.     char *p, w[40];
  1112.     struct msg_header *head, newhead;
  1113.     int f1, f2, len;
  1114.     int fromflag = 0;
  1115.     int makebid = 0;
  1116.     
  1117.     open_mail ();
  1118.     p = line;
  1119.     p += scanword (p, w, 40);
  1120.     newhead.mhtype = (isalpha (w[1])) ? toupper (w[1]) : ' ';
  1121.     newhead.mhstat = 'N';
  1122.     newhead.mhbbs[0] = '\0';
  1123.     strcpy (newhead.mhfrom, user.uscall);
  1124.     p += scanword (p, w, 40);
  1125.     if (!w[0]) {
  1126.         printf ("Message number:\n");
  1127.         getline ();
  1128.         if (quit) return;
  1129.         p += scanword (line, w, 40);
  1130.         }
  1131.     if (!isdigit (*w))
  1132.         return;
  1133.     reset_mail (0);
  1134.     if ((head = next_mail (is_num, atoi (w))) != NULL) {
  1135.         p += scanword (p, w, 40);
  1136.         if (! *w) {
  1137.             printf ("Enter callsign of addressee:\n");
  1138.             getline ();
  1139.             if (quit) return;
  1140.             p = line + scanword (line, w, 40);
  1141.             }
  1142.         if (! *w)
  1143.             return;    /* no addressee */
  1144.         upper (w);
  1145.         strncpy (newhead.mhto, w, 7);
  1146.         p += scanword (p, w, 40);
  1147.     again:
  1148.         if (*w) {
  1149.             if (*w == '@') {
  1150.                 p += scanword (p, w, 40);
  1151.                 if (*w) {
  1152.                     upper (w);
  1153.                     strncpy (newhead.mhbbs, w, 39);
  1154.                     p += scanword (p, w, 40);
  1155.                     goto again;
  1156.                     }
  1157.                 }
  1158.             else if (*w == '<') {
  1159.                 p += scanword (p, w, 40);
  1160.                 if (*w) {
  1161.                     upper (w);
  1162.                     if ((user.usopt & ISBBS) || (user.usopt & ISSUPER))
  1163.                         strncpy (newhead.mhfrom, w, 7);
  1164.                     p += scanword (p, w, 40);
  1165.                     fromflag++;
  1166.                     goto again;
  1167.                     }
  1168.                 }
  1169.             else if (*w == '$') {
  1170.                 if (strlen (w) == 1) {
  1171.                     p += scanword (p, w, 40);
  1172.                     if (!*w)
  1173.                         makebid++;
  1174.                     }
  1175.                 else
  1176.                     strcpy (w, w+1);
  1177.                 if (*w) {
  1178.                     upper (w);
  1179.                     strncpy (head->mhbid, w, 13);
  1180.                     p += scanword (p, w, 40);
  1181.                     goto again;
  1182.                     }
  1183.                 }
  1184.             }
  1185.         if (strcmp (newhead.mhfrom, "SYSOP") == 0)
  1186.             strcpy (newhead.mhfrom, MYCALL);
  1187.         get_ssid (newhead.mhto);
  1188.         get_ssid (newhead.mhbbs);
  1189.         header_to_name (head, w + strlen (maildir));
  1190.         if ((f1 = open_msg (head)) == -1) {
  1191.             printf ("Error %d opening message file\n", errno);
  1192.             return;
  1193.             }
  1194.         printf ("Enter new title, or <CR> for same as original:\n");
  1195.         getline ();
  1196.         if (quit) return;
  1197.         if (*line)
  1198.             strncpy (newhead.mhtit, line, 81);
  1199.         else
  1200.             strcpy (newhead.mhtit, head->mhtit);
  1201.         newhead.mhsize = head->mhsize;
  1202.         if ((f2 = creat_msg (&newhead, &head)) == -1) {
  1203.             printf ("Error %d creating message file\n", errno);
  1204.             return;
  1205.             }
  1206.         while ((len = readln (f1, line, 256)) > 0)
  1207.             writeln (f2, line, len);
  1208.         close (f1);
  1209.         close (f2);
  1210.         if (makebid && !*head->mhbid)
  1211.             sprintf (head->mhbid, "%d_%s", head->mhnr, MYCALL);
  1212.         update_mail ();
  1213.         close_mail ();
  1214.         log_send (head, fromflag);
  1215.         printf ("Your copy is now message #%d\n", head->mhnr);
  1216.         }
  1217.     else
  1218.         printf ("*** Not found\n");
  1219.     }
  1220.  
  1221. modify ()
  1222. {
  1223.     char *p, *p2, w[81], w2[81];
  1224.     struct msg_header *head, newhead;
  1225.     int f1, f2, len, num;
  1226.     int fromflag = 0;
  1227.     extern int eflag;
  1228.     int i, list[MAXLIST];
  1229.  
  1230.     p = line;
  1231.     p += scanword (p, w, 40);
  1232.     p += scanword (p, w, 40);
  1233.     if (!*w) {
  1234.         printf ("Message to modify:\n");
  1235.         getline ();
  1236.         if (quit) return;
  1237.         scanword (line, w, 40);
  1238.         }
  1239.     else if (isdigit (*w)) {
  1240.         for (i = 0; i < MAXLIST - 1 && isdigit (*w); i++) {
  1241.             list[i] = atoi (w);
  1242.             p += scanword (p, w, 20);
  1243.             }
  1244.         list[i] = -1;
  1245.         }
  1246.     open_mail ();
  1247.     while (head = next_mail (is_multnum, list)) {
  1248.         if (!(user.usopt & ISSUPER) && strcmp (user.uscall, head->mhfrom) != 0 &&
  1249.              (head->mhtype != 'T')) {
  1250.             printf ("Sorry, can only modify messages you've sent.\n");
  1251.             close_mail ();
  1252.             return;
  1253.             }
  1254.         if (!(user.usopt & ISEXPERT)) {
  1255.             printf ("Modify commands are:\n");
  1256.             printf (
  1257. "     T - type   > - to   @ - BBS   L - title   $ - bid\n");
  1258.             if (user.usopt & ISSUPER)
  1259.                 printf (
  1260. "     < - from   S - size   D - distribution  X- expiration\n");
  1261.             }
  1262.         eflag = 1;
  1263.         while (1) {
  1264.             print_header (head, 1, 1);
  1265.             printf ("\nModify: >\n");
  1266.             getline ();
  1267.             if (quit) {
  1268.                 close_mail ();
  1269.                 return;
  1270.                 }
  1271.             p = line;
  1272.             p += scanword (p, w, 81);
  1273.             if (!*w) break;
  1274.             if (strlen (w) > 1) {
  1275.                 strcpy (w2, w+1);
  1276.                 w[1] = '\0';
  1277.                 }
  1278.             else
  1279.                 scanword (p, w2, 81);
  1280.             switch (toupper (*w)) {
  1281.   
  1282.         case 'T':
  1283.                 if (!(user.usopt & ISSUPER) &&
  1284.                              strcmp (user.uscall, head->mhfrom) != 0)
  1285.                     break;
  1286.                 if (!*w2)
  1287.                     head->mhtype = ' ';
  1288.                 else
  1289.                     head->mhtype = toupper (*w2);
  1290.                 log ("M %d T %c", head->mhnr, *w2);
  1291.                 break;
  1292.  
  1293.         case 'R':
  1294.                 if (!(user.usopt & ISSUPER))
  1295.                     break;
  1296.                 if (!*w2) break;
  1297.                 upper (w2);
  1298.                 head->mhstat = *w2;
  1299.                 log ("M %d R %c", head->mhnr, *w2);
  1300.                 break;
  1301.  
  1302.         case '>':
  1303.                 if (*w2 || head->mhstat == 'X')
  1304.                     strncpy (head->mhto, w2, 7);
  1305.                 upper (head->mhto);
  1306.                 get_ssid (newhead.mhto);
  1307.                 log ("M %d > %s", head->mhnr, head->mhto);
  1308.                 break;
  1309.  
  1310.         case '<':
  1311.                 if (!(user.usopt & ISSUPER)) break;
  1312.                 if (*w2) strncpy (head->mhfrom, w2, 39);
  1313.                 upper (head->mhfrom);
  1314.                 get_ssid (newhead.mhfrom);
  1315.                 log ("M %d < %s", head->mhnr, head->mhfrom);
  1316.                 break;
  1317.  
  1318.         case '@':
  1319.                 strncpy (head->mhbbs, w2, 39);
  1320.                 upper (head->mhbbs);
  1321.                 log ("M %d @ %s", head->mhnr, head->mhbbs);
  1322.                 break;
  1323.  
  1324.         case 'L':
  1325.                 while (isspace (*p)) p++;
  1326.                 strncpy (head->mhtit, p, 81);
  1327.                 log ("M %d L %s", head->mhnr, head->mhtit);
  1328.                 break;
  1329.  
  1330.         case 'S':
  1331.                 if (!(user.usopt & ISSUPER)) break;
  1332.                 len = (*w2) ? atoi (w2) : -1;
  1333.                 if (len >= 0)
  1334.                     head->mhsize = len;
  1335.                 log ("M %d S %d", head->mhnr, head->mhsize);
  1336.                 break;
  1337.  
  1338.         case '$':
  1339.                 strncpy (head->mhbid, w2, 13);
  1340.                 upper (head->mhbid);
  1341.                 log ("M %d $ %s", head->mhnr, head->mhbid);
  1342.                 break;
  1343.  
  1344.         case 'D':
  1345.                 if (!(user.usopt & ISSUPER)) break;
  1346.                 if (*w2) update_dist (head, xtoi (w2));
  1347.                 log ("M %d D %s", head->mhnr, w2);
  1348.                 break;
  1349.  
  1350.         case 'X':
  1351.                 if (!(user.usopt & ISSUPER)) break;
  1352.                 if (*w2) {
  1353.                     int y,m,d;
  1354.                     if (sscanf (w2, "%d/%d/%d", &m, &d, &y) == 3)
  1355.                         if (y > 50)
  1356.                             head->mhdate_xpir = ((1900+y) << 16) + (m << 8) + d;
  1357.                         else
  1358.                             head->mhdate_xpir = ((2000+y) << 16) + (m << 8) + d;
  1359.                     else
  1360.                         head->mhdate_xpir = 0;
  1361.                     log ("M %d X %s", head->mhnr, w2);
  1362.                     }
  1363.                 break;
  1364.  
  1365.                 }
  1366.             update_mail ();
  1367.             }
  1368.         }
  1369.     eflag = 0;
  1370.     close_mail ();
  1371.     }
  1372.  
  1373. help ()
  1374. {
  1375.     char *p, w[20];
  1376.     
  1377.     p = line;
  1378.     p += scanword (p, w, 20);
  1379.     p += scanword (p, w, 20);
  1380.     printf ("\n");
  1381.     switch (toupper (*w)) {
  1382. case '\0':
  1383.         if (!printfile ("help/general")) goto nohelp;
  1384.         break;
  1385.  
  1386. case 'D':
  1387.         if (!printfile ("help/download")) goto nohelp;
  1388.         break;
  1389.  
  1390. case 'W':
  1391.         if (!printfile ("help/what")) goto nohelp;
  1392.         break;
  1393.  
  1394. case 'B':
  1395.         if (!printfile ("help/bye")) goto nohelp;
  1396.         break;
  1397.  
  1398. case 'I':
  1399.         if (!printfile ("help/info")) goto nohelp;
  1400.         break;
  1401.  
  1402. case 'N':
  1403.         if (!printfile ("help/name")) goto nohelp;
  1404.         break;
  1405.  
  1406. case 'X':
  1407.         if (!printfile ("help/expert")) goto nohelp;
  1408.         break;
  1409.  
  1410. case 'U':
  1411.         if (!printfile ("help/upload")) goto nohelp;
  1412.         break;
  1413.  
  1414. case 'S':
  1415.         if (!printfile ("help/send")) goto nohelp;
  1416.         break;
  1417.  
  1418. case 'L':
  1419.         if (!printfile ("help/list")) goto nohelp;
  1420.         break;
  1421.  
  1422. case 'R':
  1423.         if (!printfile ("help/read")) goto nohelp;
  1424.         break;
  1425.  
  1426. case 'K':
  1427.         if (!printfile ("help/kill")) goto nohelp;
  1428.         break;
  1429.  
  1430. case 'E':
  1431.         if (!printfile ("help/execute")) goto nohelp;
  1432.         break;
  1433.  
  1434. case 'Z':
  1435.         if (!printfile ("help/zap")) goto nohelp;
  1436.         break;
  1437.  
  1438. case 'V':
  1439.         if (!printfile ("help/rename")) goto nohelp;
  1440.         break;
  1441.  
  1442. case 'Q':
  1443.         if (!printfile ("help/query")) goto nohelp;
  1444.         break;
  1445.  
  1446. case 'C':
  1447.         if (!printfile ("help/copy")) goto nohelp;
  1448.         break;
  1449.  
  1450. case 'M':
  1451.         if (!printfile ("help/modify")) goto nohelp;
  1452.         break;
  1453.  
  1454. default:
  1455. nohelp:
  1456.         printf ("Sorry, no help on that command.\n");
  1457.         break;
  1458.         
  1459.         }
  1460.     printf ("\n");
  1461.     }
  1462.  
  1463. printfile (path)
  1464. char *path;
  1465. {
  1466.     int f;
  1467.  
  1468.     if ((f = open (path, 1)) <= 0)
  1469.         return 0;
  1470.     printpath (f);
  1471.     close (f);
  1472.     return (1);
  1473.     }
  1474.  
  1475. printpath (f)
  1476. {
  1477.     int len;
  1478.  
  1479.     interrupt = 0;
  1480.     while ((len = readln (f, line, sizeof (line))) > 0 && !interrupt)
  1481.         writeln (1, line, len);
  1482.     if (interrupt)
  1483.         printf ("\n\007File interrupted\n");
  1484.     interrupt = 0;
  1485.     }
  1486.  
  1487. printmsg (f)
  1488. {
  1489.     int len = 0;
  1490.     char out[256], oldline[256];
  1491.  
  1492.     interrupt = 0;
  1493.     oldline[0] = line[0] = '\0';
  1494.     do {
  1495.         if (len > 1) strcpy (oldline, line);
  1496.         len = readln (f, line, sizeof (line));
  1497.         *(line+len) = '\0';
  1498.         }
  1499.     while (len > 0 && (line[0] == '\n' || parse_head (line, out) > 1 && *out == 'R'));
  1500.     if (len <= 0) return;
  1501.     if (*oldline) writeln (1, oldline, strlen (oldline));
  1502.     writeln (1, "\n", 1);
  1503.     writeln (1, line, len);
  1504.     while ((len = readln (f, line, sizeof (line))) > 0 && !interrupt)
  1505.         writeln (1, line, len);
  1506.     if (interrupt)
  1507.         printf ("\n\007File interrupted\n");
  1508.     interrupt = 0;
  1509.     }
  1510.  
  1511. getfile (f, message, repeat)
  1512. int *repeat;
  1513. {
  1514.     int len, alarm;
  1515.     char *p, *p2, header[200];
  1516.  
  1517.     alarm = alm_set (SIGQUIT, ALARM);
  1518.     while ((len = readln (0, line, 255)) > 0) {
  1519.         alm_delete (alarm);
  1520.         line[len] = '\0';
  1521.         if (stricmp (line, "/ex\n") == 0)
  1522.             continue;
  1523.         for (p = line; p - line < len; p++)
  1524.             if (*p == '\032') {
  1525.                 write (f, line, p-line);
  1526.                 goto exit;
  1527.                 }
  1528.         if (repeat && parse_head (line, header) > 1 && *header == 'R') {
  1529.             for (p = header; *p; p += strlen (p) + 1)
  1530.                 if (*p == '@') {
  1531.                     if (strncmp (p+1, MYCALL, strlen (MYCALL)) == 0)
  1532.                         (*repeat)++;
  1533.                     }
  1534.             }
  1535.         write (f, line, len);
  1536.         }
  1537.     alm_delete (alarm);
  1538. exit:
  1539.     if (quit)
  1540.         printf ("*** TIMEOUT ***\n");
  1541.     if (len <= 0 && !interrupt)
  1542.         quit++;
  1543.     return (p-line);
  1544.     }
  1545.  
  1546. signalman (signal)
  1547. {
  1548.     switch (signal) {
  1549. case SIGQUIT:
  1550.         quit = 1;
  1551.         break;
  1552. case SIGINT:
  1553.         interrupt = 1;
  1554.         break;
  1555. default:
  1556.         break;
  1557.         
  1558.         }
  1559.     }
  1560.  
  1561. execute ()
  1562. {
  1563.     char *p, w[29];
  1564.  
  1565.     p = line + scanword (line, w, 29);
  1566.     p += scanword (p, w, 29);
  1567.     if (*w == '\0') {
  1568.         system ("dir PROGRAMS");
  1569.         printf ("\nProgram to execute:\n");
  1570.         getline ();
  1571.         if (quit) return;
  1572.         scanword (line, w, 29);
  1573.         }
  1574.     if (*w == '\0') return;
  1575.     for (p = w; *p; p++)
  1576.         if (*p == '!' || *p == '&' || *p == '^' || *p == ';') return;
  1577.     sprintf (line, "/dd/MAILBOX/PROGRAMS/%s %s", w, user.uscall);
  1578.     if (system (line) == -1)
  1579.         printf ("Sorry, can't execute that program\n");
  1580.     else
  1581.         log ("E %s", w);
  1582.     }
  1583.     
  1584. process (head)
  1585. struct msg_header *head;
  1586.     {
  1587.     static char w[10];
  1588.     static char *argv[8];
  1589.     int argc = 0;
  1590.     char *bflag = "-b";
  1591.     char *sflag = "-s";
  1592.     char *qflag = "-q";
  1593.     extern char **environ;
  1594.     extern int os9fork();
  1595.  
  1596.     if (msg_proc)
  1597.         wait (msg_proc);
  1598.     argv[argc++] = "msgproc";
  1599.     argv[argc++] = qflag;
  1600.     if (user.usopt & ISBBS)   argv[argc++] = bflag;
  1601.     if (user.usopt & ISSUPER) argv[argc++] = sflag;
  1602.     sprintf (w, "%d", head->mhnr);
  1603.     argv[argc++] = w;
  1604.     argv[argc++] = NULL;
  1605.     msg_proc = os9exec (os9fork, argv[0], argv, environ, 0, 50, 3);
  1606.     }
  1607.  
  1608. sysop ()
  1609. {
  1610.     char *p, w[20];
  1611.     unsigned char str[6];
  1612.     int accum = -1;
  1613.     
  1614.     p = line + scanword (line, w, 20);
  1615.     scanword (p, w, 20);
  1616.     if (*w == '\0') {
  1617.         log ("@ x");
  1618.         return 0;
  1619.         }
  1620.     str[0] = (connect_date >> 8) & 0xff;
  1621.     str[1] = connect_date & 0xff;
  1622.     str[2] = (connect_date >> 16) % 100;
  1623.     str[3] = (connect_time >> 16) & 0xff;
  1624.     str[4] = (connect_time >> 8) & 0xff;
  1625.     str[5] = connect_time & 0xff;
  1626.     crc (str, 6, &accum);
  1627.     if (atoi (w) != (accum & 0xffffff)) {
  1628.         log ("@ %d", atoi (w));
  1629.         return 0;
  1630.         }
  1631.     log ("@");
  1632.     system ("");
  1633.     return (1);
  1634.     }
  1635.  
  1636. reverse ()
  1637. {
  1638.     char w[40];
  1639.     int flag = 0;
  1640.  
  1641.     if (!user.usopt & ISBBS || !sid_bbs)
  1642.         return 0;
  1643.     scanword (line, w, 20);
  1644.     if (strcmp (w, "F>") != 0)
  1645.         return 0;
  1646.  
  1647.     sprintf (w, "reverse %s %d %d %d\n", user.uscall, mid_flag, bid_flag, hflag);
  1648.     system (w);
  1649.     return (1);
  1650.     }
  1651.  
  1652. sid ()
  1653. {
  1654.     char *f1, *f2, *f3, *f4, *p;
  1655.  
  1656.     if (!user.usopt & ISBBS) return 0;
  1657.     if ((f1 = strchr (line, '[')) == line && (f2 = strrchr (f1, ']')) &&
  1658.            (f3 = strchr (f1, '-')) && f3 < f2 && (f4 = strrchr (f1, '-')) &&
  1659.            f4 > f3) {
  1660.         sid_bbs = 1;
  1661.         for (p = f4 + 1; p < f2; p++)
  1662.             switch (*p) {
  1663. case '$':    bid_flag++;  break;
  1664. case 'M':    mid_flag++;  break;
  1665. case 'H':    hflag++;  break;
  1666. default:        break;
  1667.                 }
  1668.         }
  1669.     else if ((f1 = strchr (line, '[')) == line && (f2 = strchr (f1, ']'))) {
  1670.         *(f1+4) = '\0';
  1671.         if (strcmp (f1+1, "MBL" == 0))
  1672.             sid_bbs = bid_flag = 1;
  1673.         }
  1674.     return sid_bbs;
  1675.     }
  1676.  
  1677. getline ()
  1678. {
  1679.     int alarm;
  1680.     
  1681.     interrupt = 0;
  1682.     alarm = alm_set (SIGQUIT, ALARM);
  1683.     while (fgets (line, 256, stdin) == 0) {
  1684.         if (quit || feof (stdin)) {
  1685.             clearerr (stdin);
  1686.             cleareof (stdin);
  1687.             if (quit)
  1688.                 printf ("*** TIMEOUT ***\n");
  1689.             if (interrupt)
  1690.                 interrupt = 0;
  1691.             else
  1692.                 quit = 1;
  1693.             *line = '\0';
  1694.             alm_delete (alarm);
  1695.             return;
  1696.             }
  1697.         clearerr (stdin);
  1698.         }
  1699.     line[strlen (line) - 1] = '\0';
  1700.     alm_delete (alarm);
  1701.     }
  1702.  
  1703. lower (s)
  1704. char *s;
  1705. {
  1706.     while (*s) {
  1707.         *s = tolower (*s);
  1708.         s++;
  1709.         }
  1710.     }
  1711.  
  1712. max (a, b)
  1713. {
  1714.     return ((a > b) ? a : b);
  1715.     }
  1716.  
  1717. link (argc, argv)
  1718. char *argv[];
  1719. {
  1720.     static char w[40];
  1721.     char *p;
  1722.  
  1723.     p = line;
  1724.     p += scanword (p, w, 40);
  1725.     if (strcmp (w, "***") != 0) return;
  1726.     p += scanword (p, w, 40);
  1727.     if (strcmp (w, "LINKED") != 0) return;
  1728.     p += scanword (p, w, 40);
  1729.     if (strcmp (w, "to") != 0) return;
  1730.     p += scanword (p, w, 40);
  1731.     log ("* %s", w);
  1732.     printf ("You don't fool me!\n");
  1733.     argv[1] = w;
  1734.     login (argc, argv);
  1735.     }
  1736.  
  1737. xtoi (str)
  1738. char *str;
  1739. {
  1740.     int i;
  1741.  
  1742.     sscanf (str, "%x", &i);
  1743.     return (i);
  1744.     }
  1745.