home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 2 BBS / 02-BBS.zip / msq31004.zip / FIDO.C < prev    next >
C/C++ Source or Header  |  1995-07-20  |  19KB  |  663 lines

  1. /* fido.c
  2. **
  3. ** released into the PUBLIC DOMAIN 30 jul 1990 by jim nutt
  4. ** Changes released into the PUBLIC DOMAIN 10 jul 1994 by John Dennis
  5. **
  6. ** Fido/Opus style message base support functions for msgedsq.
  7. ** NOTE:  These routines are slated for extinction in the near future.
  8. **        They're to be replaced by the Squish msgAPI.  Possibly.
  9. **
  10. ** 17/12/91  Added share support to all file routines and converted ansi file
  11. **           access code to low level read()/write().
  12. ** 26/01/92  Fixed bug in msg routines that seemed to cause a crash on zero
  13. **           length msgs (zero, as in no ctrl info and text).
  14. ** 23/02/92  Removed locking routines.
  15. ** 01/04/92  Made New msgs remain open until writing the text, also added
  16. **           some kludge code to handle the reading of opus msgs.
  17. ** 12/07/92  Added some more functions to make the interface solid.
  18. ** 03/12/92  Fix to WriteHeader.
  19. **
  20. */
  21.  
  22. #define CHUNKSZ 256
  23. #define TEXTLEN 96
  24. #define NO_STDLIB      /* causes conflicts with errno.h with MSC */
  25. #define DEBUG 0
  26.  
  27. /*#include <msgapi.h>*/
  28. #include "msged.h"
  29. #include "date.h"
  30. #include "stamp.h"
  31. #include <errno.h>
  32. #include <sys\types.h>
  33. #include <sys\stat.h>
  34. #ifdef __MSC__
  35. #   include <sys\locking.h>
  36. #endif
  37. #include <fcntl.h>
  38. #include <share.h>
  39. #if DEBUG
  40. #include <assert.h>
  41. #endif
  42.  
  43. /* file access shortcuts */
  44.  
  45. #define OPENC   O_WRONLY|O_BINARY|O_CREAT       /* open/create */
  46. #define OPENRW  O_RDWR|O_BINARY                 /* open read/write */
  47. #define OPENR   O_RDONLY|O_BINARY               /* open read-only */
  48. #define S_IMODE S_IREAD|S_IWRITE                /* open mode */
  49.  
  50. /* prototypes */
  51.  
  52. #include "normal.h"
  53.  
  54. static int    compare(const void *i, const void *j);
  55. time_t stampToTimeT(struct _stamp *st);
  56. struct _stamp *timeTToStamp(time_t);
  57.  
  58. /* externs */
  59.  
  60. extern char msgbuf[];
  61.  
  62. /* structures used in this module */
  63.  
  64. /* typedef struct _dosdate {
  65.     unsigned int day:5;
  66.     unsigned int mon:4;
  67.     unsigned int year:7;
  68.     unsigned int sec:5;
  69.     unsigned int min:6;
  70.     unsigned int hour:5;
  71. } DOSDATE; */
  72.  
  73. typedef struct _fidoheader {
  74.     char from[36];                   /* who from,             */
  75.     char to[36];                     /* who to,               */
  76.     char subj[72];                   /* message subject,      */
  77.     char date[20];                   /* creation date,        */
  78.     unsigned char times[2];          /* number of times read, */
  79.     unsigned char dest[2];           /* destination node,     */
  80.     unsigned char orig[2];           /* originating node      */
  81.     unsigned char cost[2];           /* actual cost this msg  */
  82.     unsigned char orig_net[2];       /* originating net       */
  83.     unsigned char dest_net[2];       /* destination net       */
  84.     unsigned char written[4];        /* when it was written   */
  85.     unsigned char arrived[4];        /* when it arrived       */
  86.     unsigned char reply[2];          /* thread to previous msg */
  87.     unsigned char attrib[2];         /* message attributes */
  88.     unsigned char up[2];             /* thread to next msg    */
  89. } MFIDO;
  90.  
  91. /* local vars */
  92.  
  93. static int    fp       = -1;          /* current file handle */
  94. static unsigned long *msgarr   = NULL;        /* array of *.msg numbers */
  95. static unsigned long  msgarrsz = 0;           /* # of numbers in the array */
  96. static unsigned long  oldsz    = 0;           /* total size of the array */
  97.  
  98.  
  99. static void timet_to_char(time_t now, unsigned char arr[])
  100. {
  101.     struct tm *ts;
  102.     unsigned long x;
  103.  
  104.     ts = localtime(&now);
  105.     x = ts->tm_year - 80;
  106.     x = (x << 4) | (ts->tm_mon + 1);
  107.     x = (x << 5) | ts->tm_mday;
  108.     x = (x << 5) | ts->tm_hour;
  109.     x = (x << 6) | ts->tm_min;
  110.     x = (x << 5) | (ts->tm_sec / 2);
  111.     arr[0] = (unsigned char)((x >> 16) & 0xff);
  112.     arr[1] = (unsigned char)((x >> 24) & 0xff);
  113.     arr[2] = (unsigned char)(x & 0xff);
  114.     arr[3] = (unsigned char)((x >> 8) & 0xff);
  115. }
  116.  
  117.  
  118. unsigned long FidoMsgnToUid(unsigned long n)
  119. {
  120.     if (n > msgarrsz || n == 0)
  121.         return 0;
  122.  
  123.     return msgarr[(size_t)(n - 1)];
  124. }
  125.  
  126. unsigned long FidoUidToMsgn(unsigned long n)
  127. {
  128.     unsigned long i;
  129.  
  130.     for (i = 0; i < msgarrsz; i++)
  131.         if (msgarr[(size_t)i] == n)
  132.             break;
  133.  
  134.     return (i == msgarrsz) ? 0 : i + 1;
  135. }
  136.  
  137. int FidoMsgWriteText(char *text, unsigned long n, unsigned long mlen)
  138. {
  139.     char  i = 0;
  140.  
  141.     unused(n);
  142.     unused(mlen);
  143. #if DEBUG
  144.     assert(fp!=-1);
  145. #endif
  146.  
  147.     if (text == NULL)
  148.     {
  149.         write(fp, &i, sizeof(char));
  150.         return(TRUE);
  151.     }
  152.  
  153.     write(fp, text, strlen(text));
  154.     return TRUE;
  155. }
  156.  
  157. int FidoMsgWriteHeader(msg *m, int type)
  158. {
  159.     MFIDO msghead;
  160.     char       path[PATHLEN];
  161.     time_t     now  = time(NULL);
  162.     unsigned long      n    = m->msgnum;
  163.     int        done = 0;
  164.     unsigned long x;
  165.  
  166. #if DEBUG
  167.     assert(fp==-1);
  168. #endif
  169.  
  170.     if (fp != -1)
  171.     {
  172.         close(fp);
  173.         fp = -1;
  174.     }
  175.  
  176.     sprintf(path, "%s/%ld.MSG", CurArea.path, n);
  177.     if (m->new)
  178.     {
  179.         while (!done)
  180.         {
  181.             if ((fp = sopen(path, OPENR, SH_DENYNO, S_IMODE)) != -1)
  182.             {
  183.                 close(fp); fp = -1; n++;
  184.             }
  185.             else
  186.             {
  187.                 if ((fp = sopen(path, OPENC, SH_DENYNO, S_IMODE)) == -1)
  188.                     return ERR_OPEN_MSG;
  189.  
  190.                 done = 1;
  191.             }
  192.             sprintf(path, "%s/%ld.MSG", CurArea.path, n);
  193.         }
  194.     }
  195.     else
  196.     {
  197.         if ((fp = sopen(path, OPENRW, SH_DENYNO, S_IMODE)) == -1)
  198.             return ERR_OPEN_MSG;
  199.     }
  200.  
  201.     if (m->new)
  202.     {
  203.         if ((++msgarrsz) > oldsz)
  204.         {
  205.             unsigned long *t;
  206.  
  207.             if ((t = calloc(1, 
  208.                         (size_t)((oldsz+=CHUNKSZ) * sizeof(unsigned long)))) == NULL)
  209.                 outamemory();
  210.  
  211.             memcpy(t, msgarr, (size_t)(sizeof(unsigned long) * msgarrsz));
  212.             release(msgarr);
  213.             msgarr = t;
  214.         }
  215.         msgarr[(size_t)(msgarrsz - 1)] = n;
  216.     }
  217.  
  218.     memset(&msghead,0,sizeof msghead);
  219.  
  220.     m->msgnum      = n;
  221.     
  222.     msghead.attrib[0] = (unsigned char)
  223.                         ((m->attrib.killsent << 7)
  224.                          | (m->attrib.orphan << 6)
  225.                          | (m->attrib.forward << 5)
  226.                          | (m->attrib.attached << 4)
  227.                          | (m->attrib.sent << 3)
  228.                          | (m->attrib.recvd << 2)
  229.                          | (m->attrib.crash << 1)
  230.                          | (m->attrib.private));
  231.                          
  232.     msghead.attrib[1] = (unsigned char)
  233.                         ((m->attrib.ureq << 7)
  234.                          | (m->attrib.areq << 6)
  235.                          | (m->attrib.rcpt << 5)
  236.                          | (m->attrib.rreq << 4)
  237.                          | (m->attrib.freq << 3)
  238.                          | (m->attrib.direct << 2)
  239.                          | (m->attrib.hold << 1)
  240.                          | (m->attrib.local));
  241.                          
  242.     x  = FidoMsgnToUid((unsigned long) m->replyto);
  243.     msghead.reply[0] = (unsigned char)(x & 0xff);
  244.     msghead.reply[1] = (unsigned char)((x >> 8) & 0xff);
  245.     x  = FidoMsgnToUid((unsigned long) m->replies[0]);
  246.     msghead.up[0]  = (unsigned char)(x & 0xff);
  247.     msghead.up[1]  = (unsigned char)((x >> 8) & 0xff);
  248.     msghead.times[0] = (unsigned char)(m->times_read & 0xff);
  249.     msghead.times[1] = (unsigned char)((m->times_read >> 8) & 0xff);
  250.     msghead.cost[0]   = (unsigned char)(m->cost & 0xff);
  251.     msghead.cost[1]   = (unsigned char)((m->cost >> 8) & 0xff);
  252.  
  253.     msghead.dest_net[0] = (unsigned char)(m->to.net & 0xff);
  254.     msghead.dest_net[1] = (unsigned char)((m->to.net >> 8) & 0xff);
  255.     msghead.dest[0]     = (unsigned char)(m->to.node & 0xff);
  256.     msghead.dest[1]     = (unsigned char)((m->to.node >> 8) & 0xff);
  257.  
  258.     if (m->isfrom != NULL)
  259.     {
  260.         memcpy(msghead.from,   
  261.                m->isfrom,  
  262.                min(sizeof msghead.from,   strlen(m->isfrom)));
  263.     }
  264.     else
  265.     {
  266.         msghead.from[0] = '\0';
  267.     }
  268.     if (m->isto != NULL)
  269.     {
  270.         memcpy(msghead.to,   
  271.                m->isto,  
  272.                min(sizeof msghead.to,   strlen(m->isto)));
  273.     }
  274.     else
  275.     {
  276.         msghead.to[0] = '\0';
  277.     }
  278.     if (m->subj != NULL)
  279.     {
  280.         memcpy(msghead.subj, m->subj,  min(sizeof msghead.subj, strlen(m->subj)));
  281.     }
  282.     else
  283.     {
  284.         msghead.subj[0] = '\0';
  285.     }
  286.     memcpy(msghead.date, mtime(m->timestamp), 20);
  287.  
  288.     msghead.orig_net[0] = (unsigned char)(m->from.net & 0xff);
  289.     msghead.orig_net[1] = (unsigned char)((m->from.net >> 8) & 0xff);
  290.     msghead.orig[0]     = (unsigned char)(m->from.node & 0xff);
  291.     msghead.orig[1]     = (unsigned char)((m->from.node >> 8) & 0xff);
  292.  
  293.     if (SW->opusdate)
  294.     {
  295.         timet_to_char(now, msghead.written);
  296.         memcpy(msghead.arrived, msghead.written, sizeof msghead.arrived);
  297.     }
  298.     else
  299.     {        
  300.         timet_to_char(m->timestamp, msghead.written);
  301.         if (m->time_arvd) 
  302.         {
  303.             timet_to_char(m->time_arvd, msghead.written);
  304.         }
  305.         
  306.     }
  307.  
  308.     write(fp, (char *) &msghead, sizeof(MFIDO));
  309.  
  310.     if (type == WR_HEADER)
  311.     {
  312.         close(fp);
  313.         fp = -1;
  314.     }
  315.  
  316.     return TRUE;
  317. }
  318.  
  319.  
  320. msg *FidoMsgReadHeader(unsigned long n, int type)
  321. {
  322.     MFIDO msghead;
  323.     char       path[PATHLEN];
  324.     unsigned long      msgn = msgarr[(size_t)(n - 1)];
  325.     msg       *m;
  326.  
  327. #if DEBUG
  328.     assert(fp==-1);
  329. #endif
  330.     if (fp != -1)
  331.     {
  332.         close(fp);
  333.         fp = -1;
  334.     }
  335.  
  336.     memset(&msghead,0,sizeof msghead);
  337.     sprintf(path, "%s/%ld.MSG", CurArea.path, msgn);
  338.     if ((fp = sopen(path, OPENR, SH_DENYNO, S_IMODE)) == -1)
  339.         return NULL;
  340.  
  341.     if ((m = calloc(1, sizeof(msg))) == NULL)
  342.         outamemory();
  343.  
  344.     read(fp, (char *) &msghead, (int) sizeof(MFIDO));
  345.  
  346.     m->msgnum    = msgn;
  347.     m->from.net  = (msghead.orig_net[1] << 8) | msghead.orig_net[0];
  348.     m->from.node = (msghead.orig[1] << 8) | msghead.orig[0];
  349.     m->to.net    = (msghead.dest_net[1] << 8) | msghead.dest_net[0];
  350.     m->to.node   = (msghead.dest[1] << 8) | msghead.dest[0];
  351.  
  352.     memset(path, 0, sizeof path);
  353.     memcpy(path,msghead.date,sizeof msghead.date);
  354.  
  355.     m->timestamp = parsedate(path);
  356.  
  357.     if (msghead.arrived[0] != 0 || msghead.arrived[1] != 0 || msghead.arrived[2] != 0 || msghead.arrived[3] != 0)
  358.     {
  359.         m->time_arvd = stampToTimeT((struct _stamp *)msghead.arrived);
  360.     }        
  361.  
  362.     if ((m->isto =   calloc(1, sizeof msghead.to   + 1)) == NULL) outamemory();
  363.     if ((m->isfrom = calloc(1, sizeof msghead.from + 1)) == NULL) outamemory();
  364.     if ((m->subj =   calloc(1, sizeof msghead.subj + 1)) == NULL) outamemory();
  365.  
  366.     memcpy(m->isto,   msghead.to,   sizeof msghead.to);
  367.     memcpy(m->isfrom, msghead.from, sizeof msghead.from);
  368.     memcpy(m->subj,   msghead.subj, sizeof msghead.subj);
  369.  
  370.     m->replyto    = FidoUidToMsgn((unsigned long) ((msghead.reply[1] << 8)
  371.                                            | msghead.reply[0]));
  372.     m->replies[0] = FidoUidToMsgn((unsigned long) ((msghead.up[1] << 8)
  373.                                            | msghead.up[0]));
  374.                                            
  375.     m->attrib.ureq =   ((msghead.attrib[1] >> 7) & 0x01);
  376.     m->attrib.areq =   ((msghead.attrib[1] >> 6) & 0x01);
  377.     m->attrib.rcpt =   ((msghead.attrib[1] >> 5) & 0x01);
  378.     m->attrib.rreq =   ((msghead.attrib[1] >> 4) & 0x01);
  379.     m->attrib.freq =   ((msghead.attrib[1] >> 3) & 0x01);
  380.     m->attrib.direct = ((msghead.attrib[1] >> 2) & 0x01);
  381.     m->attrib.hold  =  ((msghead.attrib[1] >> 1) & 0x01);
  382.     m->attrib.local =  ((msghead.attrib[1]) & 0x01);
  383.                          
  384.     m->attrib.killsent = ((msghead.attrib[0] >> 7) & 0x01);
  385.     m->attrib.orphan =   ((msghead.attrib[0] >> 6) & 0x01);
  386.     m->attrib.forward =  ((msghead.attrib[0] >> 5) & 0x01);
  387.     m->attrib.attached = ((msghead.attrib[0] >> 4) & 0x01);
  388.     m->attrib.sent =     ((msghead.attrib[0] >> 3) & 0x01);
  389.     m->attrib.recvd =    ((msghead.attrib[0] >> 2) & 0x01);
  390.     m->attrib.crash  =   ((msghead.attrib[0] >> 1) & 0x01);
  391.     m->attrib.private =  ((msghead.attrib[0]) & 0x01);
  392.                          
  393.     m->from.zone  = CurArea.addr.zone;
  394.     m->to.zone    = CurArea.addr.zone;
  395.     m->cost       = (msghead.cost[1] << 8) | msghead.cost[0];
  396.     m->times_read = (msghead.times[1] << 8) | msghead.times[0];
  397.  
  398.     m->to.fidonet   = 1;
  399.     m->from.fidonet = 1;
  400.     m->text         = NULL;
  401.  
  402.     if (type == RD_HEADER) {
  403.         close(fp);
  404.         fp = -1;
  405.     }
  406.  
  407.     return m;
  408. }
  409.  
  410. char *FidoMsgReadText(unsigned long n)
  411. {
  412.     static  char *next = NULL;
  413.     static  char *end = NULL;
  414.     static  unsigned long s   = 0;
  415.     int     i, l;
  416.     char    *t = NULL;
  417.     char    *text = NULL;
  418.     char    eol = '\0';
  419.  
  420. #if DEBUG
  421.     assert(fp!=-1);
  422.     assert(n>0);
  423. #else
  424.     unused(n);    
  425. #endif
  426.  
  427.     if (next == NULL && s != 0) {            /* we are finished          */
  428.         s = 0;
  429.         return NULL;
  430.     }
  431.  
  432.     if (s == 0) {
  433.         s = BUFLEN;
  434.         memset(msgbuf, 0, (size_t)(s-1));
  435.         lseek(fp, (long) sizeof(MFIDO), SEEK_SET);
  436.     }
  437.  
  438.     if (next == NULL) {
  439.         i = read(fp, msgbuf, (size_t)(s - 1));
  440.         if (i < 1) {
  441.             next = NULL;
  442.             s    = 0;
  443.             return(NULL);
  444.         }
  445.         next = msgbuf;
  446.         while (i && (*next == '\0'))
  447.             i--, next++;
  448.         normalize(next);
  449.         end = msgbuf + strlen(msgbuf);
  450.         if (end < next)
  451.             next = end;
  452.     }
  453.  
  454.     if ((end - next) == 0) t = NULL;
  455.     else t = memchr(next,'\n',(int) (end - next));
  456.  
  457.     if (t == NULL) {
  458.         l = strlen(next);
  459.         memcpy(msgbuf,next,l+1);
  460.         i = read(fp,msgbuf+l, (size_t)(s - l - 1));
  461.         if (i < 1) {
  462.             next = NULL;
  463.             return(strdup(msgbuf));
  464.         }
  465.         *(msgbuf + l + i) = '\0';
  466.         normalize(msgbuf+l);
  467.         end = msgbuf + strlen(msgbuf);
  468.         next = msgbuf;
  469.         t = memchr(next,'\n', l + i);
  470.     }
  471.  
  472.     if (t != NULL) {
  473.         eol = *(t+1);
  474.         *(t+1) = '\0';
  475.     }
  476.  
  477.     text = strdup(next);
  478.  
  479.     if (t != NULL) {
  480.         *(t+1) = eol;
  481.         next = t+1;
  482.     }
  483.     else
  484.         next = NULL;
  485.  
  486.     return text;
  487. }
  488.  
  489. int FidoMsgClose(void)
  490. {
  491.     if (fp != -1)
  492.     {
  493.         close(fp);
  494.         fp = -1;
  495.     }
  496.     return TRUE;
  497. }
  498.  
  499. int FidoMsgAreaClose(void)
  500. {
  501.     CurArea.status = 0;
  502.     return TRUE;
  503. }
  504.  
  505. int compare(const void *i, const void *j)
  506. {
  507.     return ((int)(* (unsigned long *) i - * (unsigned long *) j));
  508. }
  509.  
  510. void ScanArea(char *path)
  511. {
  512.     struct _dta fileinfo;
  513.     int         status;
  514.     unsigned long       msgnum;
  515.     unsigned long      *t = NULL;
  516.  
  517.     status     = dir_findfirst(path, 0, &fileinfo);
  518.     msgarrsz   = 0;
  519.  
  520.     while (status != -1)
  521.     {
  522.         if (fileinfo.size >= sizeof(MFIDO))
  523.         {
  524.             msgnum = atol(fileinfo.name);
  525.             msgarrsz++;
  526.             if (msgarrsz >= oldsz)
  527.             {
  528.                 if ((t = (unsigned long *) calloc((size_t)(oldsz += CHUNKSZ), 
  529.                                            sizeof(unsigned long))) == NULL) {
  530.                      outamemory();
  531.                 }
  532.                 if (msgarr != NULL)           /* copy old array accross */
  533.                 {
  534.                     memcpy(t, msgarr, (size_t)(sizeof(unsigned long) * msgarrsz));
  535.                 }
  536.                 release(msgarr);
  537.                 msgarr = t;
  538.             }
  539.             msgarr[(size_t)(msgarrsz - 1)] = msgnum; /* assign new msgnumber */
  540.         }
  541.         status = dir_findnext(&fileinfo);
  542.     }
  543.  
  544.     if (msgarr == NULL) {                      /* no files at all in dir */
  545.         msgarr = malloc(sizeof(unsigned long)*CHUNKSZ);
  546.     }
  547.     else {
  548.         qsort((void *) msgarr, (int) msgarrsz, (size_t) sizeof(unsigned long), compare);
  549.     }
  550. }
  551.  
  552. long FidoMsgAreaOpen(AREA *a)
  553. {
  554.     char    path[PATHLEN];
  555.     short int c = 10, l;
  556.     unsigned long   msgnum;
  557.  
  558.     sprintf(path,"%s/*.msg",a->path);
  559.     a->last    = a->first    = 1;
  560.     a->current = a->lastread = 1;
  561.     a->status  = 1;
  562.  
  563.     ScanArea(path);
  564.  
  565.     sprintf(path, "%s/%s",a->path, ST->lastread);
  566.     if ((fp = sopen(path, OPENR, SH_DENYNO, S_IMODE)) != -1)
  567.     {
  568.         read(fp, &c, sizeof c);
  569.         if (read(fp, &l, sizeof l) != sizeof l)
  570.             l = c;
  571.  
  572.         close(fp);
  573.         fp = -1;
  574.     }
  575.     else
  576.         l = c = 0;
  577.  
  578.     if (msgarrsz != 0)
  579.     {
  580.         a->last  = msgarrsz;
  581.         msgnum   = a->last;
  582.  
  583.         for (msgnum=msgarrsz; 
  584.              (msgnum>1) && (msgarr[(size_t)(msgnum-1)] != (unsigned long) c); 
  585.              msgnum--) ;
  586.             /* void loop */
  587.  
  588.         a->current = (!msgnum) ? a->last : msgnum;
  589.         msgnum     = a->last;
  590.  
  591.         for (msgnum=msgarrsz; 
  592.              (msgnum>1) && (msgarr[(size_t)(msgnum-1)] != (unsigned long) l); 
  593.              msgnum--);
  594.             /* void loop */
  595.  
  596.         a->lastread = (!msgnum) ? a->last : msgnum;
  597.     }
  598.     return msgarrsz;
  599. }
  600.  
  601.  
  602. int FidoAreaSetLast(AREA *a)
  603. {
  604.     int     fp;
  605.     char    path[PATHLEN];
  606.     short   i = 0;
  607.  
  608.     sprintf(path, "%s/%s", a->path, ST->lastread);
  609.     if ((fp = sopen(path, OPENRW, SH_DENYNO, S_IMODE)) == -1)
  610.     {
  611.         if (fp == -1 && (errno != EACCES && errno != EMFILE))
  612.         {
  613.             if ((fp = sopen(path, OPENC, SH_DENYNO, S_IMODE)) == -1)
  614.                 return FALSE;
  615.  
  616.             lseek(fp,0L,SEEK_SET);
  617.  
  618.             write(fp, &i, sizeof(short));
  619.             write(fp, &i, sizeof(short));
  620.  
  621.             close(fp);
  622.  
  623.             return TRUE;
  624.         }
  625.         return FALSE;
  626.     }
  627.     lseek(fp, 0L, SEEK_SET);
  628.     if (msgarr)
  629.     {
  630.         i = (short)msgarr[(size_t)(a->current - 1)];
  631.         write(fp, (char *)&i, sizeof(short));
  632.         i = (short)msgarr[(size_t)(a->lastread - 1)];
  633.         write(fp, (char *)&i, sizeof(short));
  634.     }
  635.     else
  636.     {
  637.         write(fp, &i, sizeof(short));
  638.         write(fp, &i, sizeof(short));
  639.     }
  640.     close(fp);
  641.     return TRUE;
  642. }
  643.  
  644.  
  645. int FidoMsgDelete(unsigned long n)
  646. {
  647.     char path[TEXTLEN];
  648.  
  649.     /* delete the message */
  650.  
  651.     sprintf(path, "%s/%lu.msg", CurArea.path, n);
  652.     remove(path);
  653.  
  654.     /* we now re-scan the area just for the sake of it */
  655.  
  656.     sprintf(path, "%s/*.msg", CurArea.path);
  657.     ScanArea(path);
  658.  
  659.     return TRUE;
  660. }
  661.  
  662. /* --- end of file --- */
  663.