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 / mail.c < prev    next >
C/C++ Source or Header  |  1993-02-16  |  20KB  |  936 lines

  1. #include <stdio.h>
  2. #include <ctype.h>
  3. #include <modes.h>
  4. #include <direct.h>
  5. #include <module.h>
  6. #include <dir.h>
  7. #include <errno.h>
  8. #include "mailbox.h"
  9.  
  10. #define BUFFSIZE 25
  11.  
  12. int read_event, write_event;
  13. mod_exec *mail_module, *modlink();
  14. struct msg_header *mail_dir, *curdir,
  15.        dir_buff[BUFFSIZE], *buff_start, *buff_end;
  16. extern struct userstruct user;
  17. static int passed_count;
  18. int xflag = 0, eflag = 0;
  19. static struct msg_header mail_head, org_head, *mail_ptr;
  20. struct dist_list *distboxes = NULL;
  21. int mail_open = 0;
  22.  
  23. open_mail ()
  24. {
  25.     if (mail_open) return;
  26.     if ((read_event = _ev_link ("mail_read")) == -1)
  27.         exit (_errmsg (0, "Error %d linking to read event.\n", errno));
  28.     if ((write_event = _ev_link ("mail_write")) == -1)
  29.         exit (_errmsg (0, "Error %d linking to write event.\n", errno));
  30.     if ((int)(mail_module = modlink ("mail_dir", 0x0400)) == -1)
  31.         exit (_errmsg (0, "Error %d linking to mail directory module.\n", errno));
  32.     mail_dir = (struct msg_header *)((char *)mail_module + mail_module->_mexec);
  33.     curdir = mail_dir;
  34.     passed_count = -1;
  35.     buff_start = buff_end = dir_buff;
  36.     mail_open++;
  37.     }
  38.  
  39. reset_mail ()
  40. {
  41.     curdir = mail_dir;
  42.     buff_start = buff_end = dir_buff;
  43.     passed_count = -1;
  44.     }
  45.  
  46. struct msg_header *next_mail (comp, arg, arg2)
  47. int (*comp)(), arg, arg2;
  48. {
  49.     char *entry;
  50.     int f;
  51.  
  52.     while (get_dir (&mail_head)) {
  53.         if ((*comp)(&mail_head, arg, arg2)) {
  54.             _strass (&org_head, &mail_head, sizeof (struct msg_header));
  55.             return (&mail_head);
  56.             }
  57.         }
  58.     return NULL;
  59.     }
  60.  
  61. get_dir (head)
  62. struct msg_header *head;
  63. {
  64.     if (buff_start >= buff_end) {
  65.         read_lock ();
  66.         buff_start = buff_end = dir_buff;
  67.         while (buff_end - buff_start < BUFFSIZE) {
  68.             if (curdir - mail_dir >= MAXMAIL) break;
  69.             if (curdir->mhstat != ' ')
  70.                 _strass (buff_end++, curdir, sizeof (struct msg_header));
  71.             curdir++;
  72.             }
  73.         read_unlock ();
  74.         }
  75.     if (buff_start < buff_end) {
  76.         _strass (head, buff_start++, sizeof (struct msg_header));
  77.         return (1);
  78.         }
  79.     else
  80.         return (0);
  81.     }
  82.  
  83. read_lock ()
  84. {
  85.     _ev_wait (write_event, 0, 0);
  86.     _ev_wait (read_event, 0, 9999);
  87.     _ev_signal (write_event, 0);
  88.     }
  89.  
  90. read_unlock ()
  91. {
  92.     _ev_signal (read_event, 0);
  93.     }
  94.  
  95. write_lock ()
  96. {
  97.     _ev_wait (write_event, 0, 0);
  98.     _ev_wait (read_event, 0, 0);
  99.     }
  100.  
  101. write_unlock ()
  102. {
  103.     int f=0;
  104.     struct msg_header *entry;
  105.  
  106.     /* write-through to disk */
  107.     for (entry = mail_dir; entry - mail_dir < MAXMAIL; entry++)
  108.         if (entry->mhstat != ' ' && entry->mhdirty) {
  109.             entry->mhdirty = 0;
  110.             if (!f)
  111.                 f = open ("mail_dir", S_IWRITE);
  112.             lseek (f, (char *)entry - (char *)mail_dir, 0);
  113.             write (f, entry, sizeof (struct msg_header));
  114.             }
  115.     if (f) close (f);
  116.     _ev_signal (read_event, 0);
  117.     _ev_signal (write_event, 0);
  118.     }    
  119.  
  120. close_mail ()
  121. {
  122.     if (!mail_open) return;
  123.     _ev_unlink (read_event);
  124.     _ev_unlink (write_event);
  125.     if (munlink (mail_module) == -1)
  126.         printf ("Error %d unlinking mail directory module.\n", errno);
  127.     xflag = eflag = mail_open = 0;
  128.     }
  129.  
  130. struct msg_header *new_mail (number)
  131. {
  132.     int max = 0;
  133.     struct msg_header *entry;
  134.     int time, date, tick;
  135.     short day;
  136.  
  137.     write_lock ();
  138.     if (number == 0)
  139.         {
  140.         for (entry = mail_dir; entry - mail_dir < MAXMAIL; entry++)
  141.             if (entry->mhstat != ' ' && entry->mhnr > max)
  142.                 max = entry->mhnr;
  143.         number = max+1;
  144.         }
  145.     for (entry = mail_dir; entry - mail_dir < MAXMAIL; entry++)
  146.         if (entry->mhstat == ' ') break;
  147.     if (entry - mail_dir == MAXMAIL)
  148.         return (NULL);        /* no mail entries left */
  149.     entry->mhnr = number;
  150.     entry->mhstat = 'X';
  151.     entry->mhdirty = 1;
  152.     _sysdate (0, &time, &date, &day, &tick);
  153.     entry->mhdate = entry->mhdate_mod = date;
  154.     _julian (&time, &date);
  155.     date += 7;
  156.     gregorian (&time, &date);
  157.     entry->mhdate_xpir = date;
  158.     entry->mhtime = time;
  159.     entry->mhdist = 0;
  160.     entry->mhsize = 0;
  161.     _strass (&mail_head, entry, sizeof (struct msg_header));
  162.     write_unlock ();
  163.     _strass (&org_head, &mail_head, sizeof (struct msg_header));
  164.     return (&mail_head);
  165.     }
  166.  
  167. struct msg_header *find_bid (bid)
  168. char *bid;
  169. {
  170.     struct msg_header *entry;
  171.  
  172.     read_lock ();
  173.     for (entry = mail_dir; entry - mail_dir < MAXMAIL; entry++)
  174.         if (entry->mhstat != ' ' && strcmp (bid, entry->mhbid) == 0) {
  175.             _strass (&mail_head, entry, sizeof (struct msg_header));
  176.             _strass (&org_head, entry, sizeof (struct msg_header));
  177.             break;
  178.             }
  179.     read_unlock ();
  180.     return ((entry - mail_dir < MAXMAIL) ? &mail_head : NULL);
  181.     }
  182.  
  183. update_mail ()
  184. {
  185.     struct msg_header *entry;
  186.     int time, date, tick;
  187.     short day;
  188.  
  189.     write_lock ();
  190.     for (entry = mail_dir; entry - mail_dir < MAXMAIL; entry++)
  191.         if (entry->mhnr == mail_head.mhnr) break;
  192.     if (entry - mail_dir >= MAXMAIL) {
  193.         write_unlock ();
  194.         return (0);
  195.         }
  196.     if (mail_head.mhtype != org_head.mhtype)
  197.         entry->mhtype = mail_head.mhtype;
  198.     if (mail_head.mhstat != org_head.mhstat)
  199.         entry->mhstat = mail_head.mhstat;
  200.     if (mail_head.mhsize != org_head.mhsize)
  201.         entry->mhsize = mail_head.mhsize;
  202.     if (mail_head.mhdate != org_head.mhdate)
  203.         entry->mhdate = mail_head.mhdate;
  204.     if (mail_head.mhtime != org_head.mhtime)
  205.         entry->mhtime = mail_head.mhtime;
  206.     if (mail_head.mhdate_xpir != org_head.mhdate_xpir)
  207.         entry->mhdate_xpir = mail_head.mhdate_xpir;
  208.     if (strcmp (mail_head.mhto, org_head.mhto))
  209.         strcpy (entry->mhto, mail_head.mhto);
  210.     if (strcmp (mail_head.mhfrom, org_head.mhfrom))
  211.         strcpy (entry->mhfrom, mail_head.mhfrom);
  212.     if (strcmp (mail_head.mhbbs, org_head.mhbbs))
  213.         strcpy (entry->mhbbs, mail_head.mhbbs);
  214.     if (strcmp (mail_head.mhtit, org_head.mhtit))
  215.         strcpy (entry->mhtit, mail_head.mhtit);
  216.     if (strcmp (mail_head.mhbid, org_head.mhbid))
  217.         strcpy (entry->mhbid, mail_head.mhbid);
  218.     _sysdate (0, &time, &date, &day, &tick);
  219.     entry->mhdate_mod = date;
  220.     entry->mhdirty = 1;
  221.     _strass (&org_head, entry, sizeof (struct msg_header));
  222.     write_unlock ();
  223.     return (1);
  224.     }
  225.  
  226. update_dist (head, bit)
  227. struct msg_header *head;
  228. int bit;    /* bits are 1 thru 16 or -1 thru -16 */
  229. {
  230.     struct msg_header *entry;
  231.     char *p1, *p2, *p3;
  232.  
  233.     if (bit == 0) return (0);
  234.     write_lock ();
  235.     for (entry = mail_dir; entry - mail_dir < MAXMAIL; entry++)
  236.         if (entry->mhnr == head->mhnr) break;
  237.     if (entry - mail_dir >= MAXMAIL) {
  238.         write_unlock ();
  239.         return (0);
  240.         }
  241.     if (bit < 0)
  242.         entry->mhdist &= ~(1 << (-bit - 1));    /* remove a bit */
  243.     else
  244.         entry->mhdist |= 1 << (bit - 1);        /* add a bit */
  245.     entry->mhdirty = 1;
  246.     mail_head.mhdist = org_head.mhdist = entry->mhdist;
  247.     write_unlock ();
  248.     return (1);
  249.     }
  250.  
  251. rename_file (name, newname)
  252. char *name, *newname;
  253. {
  254.     char *argv[4];
  255.     int stat;
  256.     extern char **environ;
  257.     extern int os9fork();
  258.  
  259.     argv[0] = "rename";
  260.     argv[1] = name;
  261.     argv[2] = newname;
  262.     argv[3] = 0;
  263.     os9exec (os9fork, argv[0], argv, environ, 0, 0, 3);
  264.     wait (&stat);
  265.     return ((stat == 0) ? 0 : -1);
  266.     }
  267.  
  268. is_arbitrary (head, func)
  269. struct msg_header *head;
  270. int (*func)();
  271. {
  272.     return ((*func) (head));
  273.     }
  274.  
  275. is_private (head)
  276. struct msg_header *head;
  277. {
  278.     return (head->mhtype == 'P' &&
  279.             strcmp (head->mhfrom, user.uscall) != 0 &&
  280.             strcmp (head->mhto, user.uscall) != 0 &&
  281.             !(user.usopt & ISSUPER));
  282.     }
  283.  
  284. is_deleted (head)
  285. struct msg_header *head;
  286. {
  287.     if (xflag) return 0;
  288.     return (head->mhstat == 'X' ||
  289.            (head->mhstat == 'H' && !((user.usopt & ISSUPER) ||
  290.                                      (head->mhtype == 'T') ||
  291.                                      (strcmp (head->mhfrom, user.uscall) == 0))));
  292.     }
  293.  
  294. is_to (head, call)
  295. struct msg_header *head;
  296. char *call;
  297. {
  298.     if (is_deleted (head) || is_private (head)) return 0;
  299.     return (strcmp (head->mhto, call) == 0);
  300.     }
  301.  
  302. is_from (head, call)
  303. struct msg_header *head;
  304. char *call;
  305. {
  306.     if (is_deleted (head) || is_private (head)) return 0;
  307.     return (strcmp (head->mhfrom, call) == 0);
  308.     }
  309.  
  310. is_at (head, call)
  311. struct msg_header *head;
  312. char *call;
  313. {
  314.     char w[10];
  315.     
  316.     if (is_deleted (head) || is_private (head)) return 0;
  317.     scanaddr (head->mhbbs, w, 10);
  318.     return (strcmp (w, call) == 0);
  319.     }
  320.  
  321. is_mail (head, call)
  322. struct msg_header *head;
  323. char *call;
  324. {
  325.     if (is_deleted (head) || is_private (head)) return 0;
  326.     return (is_to (head, call) && head->mhstat == 'N');
  327.     }
  328.  
  329. is_new (head)
  330. struct msg_header *head;
  331. {
  332.     if (is_deleted (head)) return 0;
  333.     return (head->mhstat == 'N' && head->mhtype != 'B');
  334.     }
  335.  
  336. is_nmail (head, call)
  337. struct msg_header *head;
  338. char *call;
  339. {
  340.     if (is_deleted (head) || is_private (head)) return 0;
  341.     return (is_to (head, call) && head->mhstat == 'Y');
  342.     }
  343.  
  344. is_type (head, type, num)
  345. struct msg_header *head;
  346. {
  347.     if (is_deleted (head) || is_private (head)) return 0;
  348.     if (head->mhtype != type) return 0;
  349.     return (head->mhnr >= num);
  350.     }
  351.  
  352. is_hold (head, num)
  353. struct msg_header *head;
  354. {
  355.     if (is_deleted (head) || is_private (head)) return 0;
  356.     if (head->mhstat != 'H') return 0;
  357.     return (head->mhnr >= num);
  358.     }
  359.  
  360. is_num (head, num)
  361. struct msg_header *head;
  362. {
  363.     if ((is_deleted (head) && !(user.usopt & ISSUPER)) || 
  364.          is_private (head))
  365.         return 0;
  366.     return (head->mhnr == num);
  367.     }
  368.  
  369. is_multnum (head, num)
  370. struct msg_header *head;
  371. int num[];
  372. {
  373.     int i;
  374.     
  375.     if ((is_deleted (head) && !(user.usopt & ISSUPER)) || 
  376.          is_private (head))
  377.         return 0;
  378.     for (i = 0; num[i] >= 0; i++)
  379.         if (num[i] == head->mhnr) return 1;
  380.     return (0);
  381.     }
  382.  
  383. is_gnum (head, num)
  384. struct msg_header *head;
  385. {
  386.     if (is_deleted (head) || is_private (head)) return 0;
  387.     return (head->mhnr >= num);
  388.     }
  389.  
  390. is_forwarded (head, num)
  391. struct msg_header *head;
  392. {
  393.     if (is_deleted (head) || is_private (head)) return 0;
  394.     if (head->mhnr < num) return 0;
  395.     return (head->mhstat == 'F');
  396.     }
  397.  
  398. is_nforwarded (head, num)
  399. struct msg_header *head;
  400. {
  401.     if (is_deleted (head) || is_private (head)) return 0;
  402.     if (head->mhnr < num) return 0;
  403.     return (head->mhstat == 'N' ||
  404.             (head->mhstat == 'Y' && strcmp (head->mhto, "WP") == 0));
  405.     }
  406.  
  407. is_read (head, num)
  408. struct msg_header *head;
  409. {
  410.     if (is_deleted (head) || is_private (head)) return 0;
  411.     if (head->mhnr < num) return 0;
  412.     return (head->mhstat == 'Y');
  413.     }
  414.  
  415. is_last (head, num)
  416. struct msg_header *head;
  417. {
  418.     struct msg_header *head2;
  419.  
  420.     if (passed_count == -1) {
  421.         read_lock ();
  422.         for (head2 = mail_dir + MAXMAIL-1; head2 >= mail_dir; head2--)
  423.             if (head2->mhstat != ' ' &&
  424.               !is_deleted (head2) && !is_private (head2))
  425.                 if (--num <= 0)    break;
  426.         read_unlock ();
  427.         passed_count = head2->mhnr;
  428.         }
  429.     return (head->mhnr >= passed_count &&
  430.       !is_deleted (head) && !is_private (head));
  431.     }
  432.  
  433. is_title (head, str)
  434. struct msg_header *head;
  435. char *str;
  436. {
  437.     if (is_deleted (head) || is_private (head)) return 0;
  438.     return (_cmpnam (head->mhtit, str, strlen (str))+1);
  439.     }
  440.  
  441. header_to_name (head, name)
  442. struct msg_header *head;
  443. char *name;
  444. {
  445.     sprintf (name, "%06d", head->mhnr);
  446.     }
  447.  
  448. print_header (head, file, flag)
  449. struct msg_header *head;
  450. {
  451.     char str[200];
  452.     char bbs[7];
  453.     int date, time, tick, day;
  454.     int jdate, jtime;
  455.     char datestr[10];
  456.  
  457.     _sysdate (0, &time, &date, &day, &tick);
  458.     _julian (&time, &date);
  459.     jdate = head->mhdate;  jtime = head->mhtime;
  460.     _julian (&jtime, &jdate);
  461.      if (date - jdate < 365)
  462.         sprintf (datestr, "%02d%02d/%02d%02d",
  463.                 (head->mhdate >> 8) & 0xff,
  464.                 head->mhdate & 0xff,
  465.                 (head->mhtime >> 16) & 0xff,
  466.                 (head->mhtime >> 8) & 0xff);
  467.     else
  468.         sprintf (datestr, " %02d/%02d/%02d",
  469.                 (head->mhdate >> 8) & 0xff,
  470.                 head->mhdate & 0xff,
  471.                 (head->mhdate >> 16) % 100);
  472.     if (flag) {
  473.         sprintf (str, "  Msg# TR  Size From   To     @ BBS  Date/Time   Title\n");
  474.         writeln (file, str, strlen (str));
  475.         }
  476.     scanaddr (head->mhbbs, bbs, 7);
  477.     sprintf (str, "%6d %c%c%6d %-6s %-6s %-6s %9s %s\n",
  478.             head->mhnr,
  479.             head->mhtype,
  480.             head->mhstat,
  481.             head->mhsize,
  482.             head->mhfrom,
  483.             head->mhto,
  484.             bbs,
  485.             datestr,
  486.             head->mhtit);
  487.     writeln (file, str, strlen (str));
  488.     if (eflag) {
  489.         sprintf (str, "    XPR: %02d/%02d/%02d MOD:%02d/%02d DIST:%04X HROUTE:%s BID:%-12s\n",
  490.                 (head->mhdate_xpir >> 8) & 0xff,
  491.                 head->mhdate_xpir & 0xff,
  492.                 (head->mhdate_xpir >> 16) % 100,
  493.                 (head->mhdate_mod >> 8) & 0xff,
  494.                 head->mhdate_mod & 0xff,
  495.                 head->mhdist,
  496.                 head->mhbbs,
  497.                 head->mhbid);
  498.         writeln (file, str, strlen (str));
  499.         }
  500.     }
  501.  
  502. log (str, a1, a2, a3, a4, a5, a6, a7, a8)
  503. char *str;
  504. {
  505.     int f;
  506.     char s1[20], s2[100], s3[128];
  507.     int date, time, tick;
  508.     short day;
  509.  
  510.     _sysdate (0, &time, &date, &day, &tick);
  511.     sprintf (s1, "%-6s %02d%02d%02d%02d%02d", user.uscall,
  512.         (date >> 16) % 100,
  513.         (date >> 8) & 0xff,
  514.         date & 0xff,
  515.         (time >> 16) & 0xff,
  516.         (time >> 8) & 0xff);
  517.     sprintf (s2, str, a1, a2, a3, a4, a5, a6, a7, a8);
  518.     sprintf (s3, "%s%s\n", s1, s2);
  519.     if ((f = open ("logfile", 2)) < 0) return;
  520.     lseek (f, 0L, 2);
  521.     write (f, s3, strlen (s3));
  522.     close (f);
  523.     }
  524.  
  525. log_send (head, fromflag)
  526. struct msg_header *head;
  527. {
  528.     char ctl[30];
  529.     char fields[3][40];
  530.     int count = 0;
  531.  
  532.     strcpy (ctl, "S%c %d %s");
  533.     if (*head->mhbbs) {
  534.         strcpy (fields[count++], head->mhbbs);
  535.         strcat (ctl, " @%s");
  536.         }
  537.     if (fromflag) {
  538.         strcpy (fields[count++], head->mhfrom);
  539.         strcat (ctl, " <%s");
  540.         }
  541.     if (*head->mhbid) {
  542.         strcpy (fields[count++], head->mhbid);
  543.         strcat (ctl, " $%s");
  544.         }
  545.     strcat (ctl, " %s");
  546.     switch (count) {
  547.  
  548. case 0:    log (ctl, head->mhtype, head->mhnr, head->mhto, head->mhtit);
  549.         break;
  550.  
  551. case 1: log (ctl, head->mhtype, head->mhnr, head->mhto,
  552.                 fields[0], head->mhtit);
  553.         break;
  554.  
  555. case 2: log (ctl, head->mhtype, head->mhnr, head->mhto,
  556.                 fields[0], fields[1], head->mhtit);
  557.         break;
  558.  
  559. case 3: log (ctl, head->mhtype, head->mhnr, head->mhto,
  560.                 fields[0], fields[1], fields[2], head->mhtit);
  561.         break;
  562.  
  563.         }
  564.     }
  565.  
  566. get_ssid (call)
  567. char *call;
  568. {
  569.     /* strips ssid from callsign and returns its value */
  570.     int ssid = 0;
  571.  
  572.     for ( ; *call && *call != '-'; call++)
  573.         ;
  574.     if (*call == '-') {
  575.         ssid = atoi (call+1);
  576.         *call = '\0';
  577.         }
  578.     return ssid;
  579.     }
  580.  
  581. open_msg (head)
  582. struct msg_header *head;
  583. {
  584.     int f, len;
  585.     char name[40];
  586.     struct fildes buffer;
  587.     char *maildir = "MAIL/";
  588.  
  589.     strcpy (name, maildir);
  590.     header_to_name (head, name + strlen (maildir));
  591.     if ((f = open (name, 1)) < 0) {
  592.         printf ("error %d opening %s.\n", errno, name);
  593.         return -1;
  594.         }
  595.     return f;
  596.     }
  597.  
  598. strncpy (s1, s2, len)
  599. register char *s1, *s2;
  600. register int len;
  601. {
  602.     while (*s2 && --len)
  603.         *s1++ = *s2++;
  604.     *s1 = '\0';
  605.     }
  606.  
  607. strncmp (s1, s2, len)
  608. register char *s1, *s2;
  609. register int len;
  610. {
  611.     while (*s1 == *s2 && --len)
  612.         s1++, s2++;
  613.     return (*s1 - *s2);
  614.     }
  615.  
  616. movmem (from, to, count)
  617. register char *from, *to;
  618. register int count;
  619. {
  620.     if (from > to)
  621.         while (count--)
  622.             *to++ = *from++;
  623.     else {
  624.         from += count;
  625.         to += count;
  626.         while (count--)
  627.             *--to = *--from;
  628.         }
  629.     }
  630.  
  631. char *strchr (str, c)
  632. char *str;
  633. {
  634.     while (*str && *str != c)
  635.         str++;
  636.     return ((*str) ? str : 0);
  637.     }
  638.  
  639. char *strrchr (str, c)
  640. char *str;
  641. {
  642.     char *p;
  643.  
  644.     for (p = str; *p; p++) ;
  645.     while (p >= str && *p != c)
  646.         p--;
  647.     return ((p >= str) ? p : 0);
  648.     }
  649.  
  650. bulletin (head)
  651. struct msg_header *head;
  652. {
  653.     struct dist_list *dp;
  654.  
  655.     if (head->mhtype == 'T')
  656.         return 0;
  657.     else if (head->mhtype == 'B')
  658.         return 1;
  659.     else
  660.         {
  661.         for (dp = distboxes; dp; dp = dp->dlnext)
  662.             if (strcmp (head->mhbbs, dp->dlname) == 0) break;
  663.         return (dp != 0);
  664.         }
  665.     }
  666.  
  667. callsign (s)
  668. char *s;
  669. {
  670.     char *p;
  671.     int i;
  672.  
  673.     for (i = 0, p = s; *p; p++) {
  674.         if (p - s >= 6)
  675.             return 0;
  676.         if (isalpha (*p))
  677.             continue;
  678.         else if (isdigit (*p)) {
  679.             if (p == s)
  680.                 return (callsign (p+1));
  681.             if (*(p+1) == '\0')
  682.                 return 0;
  683.             if (++i > 1)
  684.                 return 0;
  685.             }
  686.         else
  687.             return 0;
  688.         }
  689.     if (p - s < 4 || i == 0)
  690.         return 0;
  691.     return 1;
  692.     }
  693.  
  694. read_dist_list ()
  695. {
  696.     DIR *dirptr;
  697.     struct direct *entry;
  698.     char str[80], w[32], *p;
  699.     struct dist_list *new;
  700.     int f, len;
  701.     static char target[] = "*.dis";
  702.  
  703.     if ((dirptr = opendir (DISDIR)) == NULL)
  704.         exit (_errmsg (0, "Error %d opening mailbox directory.\n", errno));
  705.     while (entry = readdir (dirptr)) {
  706.         if (_cmpnam (entry->d_name, target, strlen (target)) == 0) {
  707.             sprintf (str, "%s/%s", DISDIR, entry->d_name);
  708.             if ((f = open (str, S_IREAD)) < 0) continue;
  709.             new = (struct dist_list *)malloc (sizeof (struct dist_list));
  710.             new->dlnext = distboxes;
  711.             distboxes = new;
  712.             strncpy (new->dlname, entry->d_name, 7);
  713.             for (p = new->dlname; *p && *p != '.'; p++) ;
  714.             *p = '\0';
  715.             upper (new->dlname);
  716.             for (new->dlcount = 0; len = readln (f, str, 80); new->dlcount++) {
  717.                 str[len+1] = '\0';
  718.                 scanword (str, w, 32);
  719.                 upper (w);
  720.                 get_ssid (w);
  721.                 strcpy (new->dlbbs[new->dlcount], w);
  722.                 }
  723.             close (f);
  724.             }
  725.         }
  726.     closedir (dirptr);
  727.     }
  728.  
  729. /* 
  730. **    Flags the message *head as having been distributed to the mailbox <mbox>.
  731. **    Sets appropriate bit in message distribution flag field and, if all bits
  732. **    are set, changes the status to 'F'.  mail_dir is updated.  If the message
  733. **    is not addressed to a distribution list designator, returns FALSE,
  734. **    otherwise returns TRUE.
  735. */ 
  736.  
  737. checkoff (head, mbox)
  738. struct msg_header *head;
  739. char *mbox;
  740. {
  741.     struct dist_list *dp;
  742.     int i;
  743.  
  744.     if (*head->mhbbs) {
  745.         for (dp = distboxes; dp; dp = dp->dlnext)
  746.             if (strcmp (head->mhbbs, dp->dlname) == 0) break;
  747.         if (dp) {
  748.             for (i = 0; i < dp->dlcount; i++)
  749.                 if (strcmp (mbox, dp->dlbbs[i]) == 0)
  750.                     update_dist (head, i+1);
  751.             if (head->mhdist == (1 << dp->dlcount) - 1) {
  752.                 head->mhstat = 'F';
  753.                 }
  754. /*            if (!bulletin (head))
  755.                 head->mhtype = 'B'; */
  756.             update_mail ();
  757.             return (1);
  758.             }
  759.         else
  760.             return 0;
  761.         }
  762.     return (0);
  763.     }
  764.  
  765. creat_msg (head, new_head)
  766. struct msg_header *head, **new_head;
  767. {
  768.     char *maildir = "MAIL/";
  769.     char str[40], str2[40];
  770.     int f;
  771.  
  772.     *new_head = new_mail (0);
  773.     (*new_head)->mhsize = head->mhsize;
  774.     (*new_head)->mhtype = head->mhtype;
  775.     (*new_head)->mhstat = head->mhstat;
  776.     strcpy ((*new_head)->mhfrom, head->mhfrom);
  777.     strcpy ((*new_head)->mhto, head->mhto);
  778.     strcpy ((*new_head)->mhbbs, head->mhbbs);
  779.     strcpy ((*new_head)->mhtit, head->mhtit);
  780.     strcpy (str, maildir);
  781.     strcpy ((*new_head)->mhbid, "");
  782.     header_to_name (*new_head, str + strlen (str));
  783.     if ((f = create (str, S_IWRITE, S_IOREAD+S_IREAD+S_IWRITE)) == -1) {
  784.         return -1;
  785.         }
  786.     return (f);
  787.     }
  788.  
  789. scanword (s, d, len)
  790. char *s, *d;
  791. {
  792.     char *p;
  793.     int num = 0;
  794.  
  795.     while (*s && isspace (*s)) {
  796.         s++;
  797.         num++;
  798.         }
  799.     p = d;
  800.     while (*s && !isspace (*s)) {
  801.         if (p - d < len - 1) *p++ = *s;
  802.         s++;
  803.         num++;
  804.         }
  805.     *p = '\0';
  806.     return (num);
  807.     }
  808.  
  809. scanaddr (s, d, len)
  810. char *s, *d;
  811. {
  812.     char *p;
  813.     int num = 0;
  814.  
  815.     while (*s && *s == '.') {
  816.         s++;
  817.         num++;
  818.         }
  819.     p = d;
  820.     while (*s && !(*s == '.')) {
  821.         if (p - d < len - 1) *p++ = *s;
  822.         s++;
  823.         num++;
  824.         }
  825.     *p = '\0';
  826.     return (num);
  827.     }
  828.  
  829. upper (s)
  830. char *s;
  831. {
  832.     while (*s) {
  833.         *s = toupper (*s);
  834.         s++;
  835.         }
  836.     }
  837.  
  838. int stricmp (a, b)
  839. register char *a, *b;
  840. {
  841.     while (*a && (*a == *b || (*a ^ *b) == ' ' && toupper (*a) == toupper (*b)))
  842.         a++, b++;
  843.     return (toupper (*a) - toupper (*b));
  844.     }
  845.     
  846. int strnicmp (a, b, len)
  847. register char *a, *b;
  848. register int len;
  849. {
  850.     while (--len && *a &&
  851.            (*a == *b || (*a ^ *b) == ' ' && toupper (*a) == toupper (*b)) )
  852.         a++, b++;
  853.     return (toupper (*a) - toupper (*b));
  854.     }
  855.     
  856. parse_head (line, out)
  857. char *line, *out;
  858. {
  859.     int field_count = 0;
  860.     char *p, *p2, *p3;
  861.     int num;
  862.     char bbs[80], w[40];
  863.     
  864.     *out = '\0';
  865.     if (*line != 'R' || *(line+1) != ':')
  866.         return 0;
  867.     p = line;
  868.     p += scanword (p, w, 40);
  869.     p += scanword (p, w, 40);
  870.     if (sscanf (w, "%d@%s ", &num, bbs) == 2) {
  871.         p2 = out;
  872.         *p2++ = 'R';
  873.         for (p3 = line+2; p3 < p; )
  874.             *p2++ = *p3++;
  875.         *p2++ = '\0';
  876.         *p2++ = '#';
  877.         p2 += sprintf (p2, "%d", num) + 1;
  878.         *p2++ = '@';
  879.         p2 += sprintf (p2, "%s", bbs) + 1;
  880.         *p2++ = '\0';
  881.         return (3);
  882.         }
  883.     p = line;
  884.     while (*p) {
  885.         if (*p == ':') {
  886.             if (field_count) {
  887.                 out--;
  888.                 while (isspace (*(out-1))) out--;
  889.                 *out++ = '\0';
  890.                 }
  891.             *out++ = *(p-1);
  892.             p++;
  893.             field_count++;
  894.             }
  895.         else if (field_count)
  896.             *out++ = *p++;
  897.         else
  898.             p++;
  899.         }
  900.     if (field_count)
  901.         while (isspace (*(out-1))) out--;
  902.     *out++ = '\0';
  903.     *out++ = '\0';
  904.     return (field_count);
  905.     }
  906.  
  907. #asm
  908. gregorian:
  909.         link.w          a5,#0
  910.         movem.l         d1-d2/a0,-(a7)
  911.         move.l          a1,-(a7)
  912.         movea.l         d0,a0
  913.         movea.l         d1,a1
  914.         move.l          (a0),d0
  915.         move.l          (a1),d1
  916.         os9             F$Gregor
  917.         bcs               _sysret
  918.         move.l          d0,(a0)
  919.         move.l          d1,(a1)
  920.         bra.w           _sysret
  921. #endasm
  922.  
  923. ztime (time, date, weekday)
  924. int *time, *date, *weekday;
  925. {
  926.     int oneday = 60 * 60 * 24;
  927.     _julian (time, date);
  928.     *time += 60 * 60 * UTC;
  929.     if (*time >= oneday) {
  930.         *time -= oneday;
  931.         (*date)++;
  932.         *weekday = (*weekday + 1) % 7;
  933.         }
  934.     gregorian (time, date);
  935.     }
  936.