1 /*
2  *  FIDO.C
3  *
4  *  Written on 30-Jul-90 by jim nutt.  Changes on 10-Jul-94 by John Dennis.
5  *  Released to the public domain.
6  *
7  *  Fido/Opus style message base support functions for Msged.
8  *
9  *  17-Dec-91  Added share support to all file routines and converted ANSI
10  *             file access code to low level read()/write().
11  *  26-Jan-92  Fixed bug in msg routines that seemed to cause a crash on
12  *             zero length msgs (zero, as in no ctrl info and text).
13  *  23-Feb-92  Removed locking routines.
14  *  01-Apr-92  Made New msgs remain open until writing the text, also added
15  *             some kludge code to handle the reading of Opus msgs.
16  *  12-Jul-92  Added some more functions to make the interface solid.
17  *  03-Dec-92  Fix to WriteHeader.
18  */
19 
20 #define CHUNKSZ 256
21 #define TEXTLEN 96
22 
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <time.h>
27 #include <errno.h>
28 #include <huskylib/huskylib.h>
29 #include <smapi/msgapi.h>
30 #include <assert.h>
31 #include "addr.h"
32 #include "nedit.h"
33 #include "msged.h"
34 #include "unused.h"
35 #include "date.h"
36 #include "memextra.h"
37 #include "dirute.h"
38 #include "fido.h"
39 
40 
41 #ifdef __MSC__
42 #include <sys/locking.h>
43 #endif
44 
45 #if defined(PACIFIC)
46 
47 #include <unixio.h>
48 #define O_WRONLY 0x0001
49 #define O_BINARY 0x0000
50 #define O_CREAT  0x0000
51 #define O_RDWR   0x0002
52 #define O_RDONLY 0x0000
53 #define S_IREAD  0x0100
54 #define S_IWRITE 0x0080
55 #define EACCES   0x18
56 #define EMFILE   0x19
57 #define SH_DENYNO 0x40
58 
59 int sopen(char *filename, unsigned int access, int flags,...);
60 
61 #elif defined(SASC)
62 
63 #define SH_DENYNO 0x40
64 #define sopen(a,b,c,d) open((a),(b))
65 #include <fcntl.h>
66 #ifndef O_BINARY
67 #define O_BINARY 0x0000
68 #endif
69 
70 #elif defined(UNIX) || defined(__DJGPP__) || defined(__CYGWIN__)
71 
72 #include <sys/types.h>
73 #include <sys/stat.h>
74 #include <unistd.h>
75 #include <fcntl.h>
76 
77 #ifndef sopen
78 #define sopen(a,b,c,d) open((a),(b),(d))
79 #endif
80 
81 #ifndef O_BINARY
82 #define O_BINARY 0x0000
83 #endif
84 
85 #else
86 
87 #include <io.h>
88 #include <sys/types.h>
89 #include <sys/stat.h>
90 #include <share.h>
91 #include <fcntl.h>
92 
93 #endif
94 
95 /* file access shortcuts */
96 
97 #if defined(_MSC_VER) && (_MSC_VER >= 1200) && defined(_MAKE_DLL)
98 #   define O_RDONLY        _O_RDONLY
99 #   define O_WRONLY        _O_WRONLY
100 #   define O_RDWR          _O_RDWR
101 #   define O_CREAT         _O_CREAT
102 #   define O_BINARY        _O_BINARY
103 #   define S_IWRITE        _S_IWRITE
104 #   define S_IREAD         _S_IREAD
105 #   define SH_DENYNO       _SH_DENYNO
106 #endif
107 
108 
109 #define OPENR   O_RDONLY | O_BINARY             /* open read-only */
110 #define OPENC   O_WRONLY | O_BINARY | O_CREAT   /* open/create */
111 #define OPENRW  O_RDWR | O_BINARY               /* open read/write */
112 
113 
114 /* prototypes */
115 
116 #include "normal.h"
117 #include "charset.h"
118 
119 static int compare(const void *i, const void *j);
120 
121 static void timet_to_char(time_t now, unsigned char arr[]);
122 static time_t char_to_timet(unsigned char arr[]);
123 
124 typedef struct _fidoheader
125 {
126     char from[36];              /* who from,             */
127     char to[36];                /* who to,               */
128     char subj[72];              /* message subject,      */
129     char date[20];              /* creation date,        */
130     unsigned char times[2];     /* number of times read, */
131     unsigned char dest[2];      /* destination node,     */
132     unsigned char orig[2];      /* originating node      */
133     unsigned char cost[2];      /* actual cost this msg  */
134     unsigned char orig_net[2];  /* originating net       */
135     unsigned char dest_net[2];  /* destination net       */
136     unsigned char written[4];   /* when it was written   */
137     unsigned char arrived[4];   /* when it arrived       */
138     unsigned char reply[2];     /* thread to previous msg */
139     unsigned char attrib[2];    /* message attributes */
140     unsigned char up[2];        /* thread to next msg    */
141 }
142 MFIDO;
143 #define MFIDO_SIZE 36+36+72+20+2+2+2+2+2+2+4+4+2+2+2
144 /* local vars */
145 
146 static int fd = -1;                   /* current file handle */
147 static unsigned long *msgarr = NULL;  /* array of *.msg numbers */
148 static unsigned long msgarrsz = 0;    /* # of numbers in the array */
149 static unsigned long oldsz = 0;       /* total size of the array */
150 
FidoMsgnToUid(unsigned long n)151 unsigned long FidoMsgnToUid(unsigned long n)
152 {
153     if (n > msgarrsz || n == 0)
154     {
155         return 0;
156     }
157     return msgarr[(size_t) (n - 1)];
158 }
159 
FidoUidToMsgn(unsigned long n)160 unsigned long FidoUidToMsgn(unsigned long n)
161 {
162     unsigned long i;
163 
164     for (i = 0; i < msgarrsz; i++)
165     {
166         if (msgarr[(size_t) i] == n)
167         {
168             break;
169         }
170     }
171 
172     return (i == msgarrsz) ? 0 : i + 1;
173 }
174 
FidoMsgWriteText(char * text,unsigned long n,unsigned long mlen)175 int FidoMsgWriteText(char *text, unsigned long n, unsigned long mlen)
176 {
177     char i = 0;
178 
179     unused(n);
180     unused(mlen);
181 
182     if (text == NULL)
183     {
184         farwrite(fd, &i, sizeof(char));
185         return (TRUE);
186     }
187     farwrite(fd, text, strlen(text));
188     return TRUE;
189 }
190 
191 static char *path = NULL;
192 
193 
FidoMsgWriteHeader(msg * m,int type)194 int FidoMsgWriteHeader(msg * m, int type)
195 {
196     MFIDO msghead;
197     time_t now = time(NULL);
198     unsigned long n = m->msgnum;
199     int done = 0;
200     unsigned long x;
201 
202     if (path == NULL) path = xmalloc(PATHLEN);
203 
204     if (fd != -1)
205     {
206         close(fd);
207         fd = -1;
208     }
209     sprintf(path, "%s/%lu.msg", CurArea.path, n);
210     if (m->new)
211     {
212         while (!done)
213         {
214             fd = sopen(path, OPENR, SH_DENYNO, S_IMODE);
215             if (fd != -1)
216             {
217                 close(fd);
218                 fd = -1;
219                 n++;
220             }
221             else
222             {
223                 fd = sopen(path, OPENC, SH_DENYNO, S_IMODE);
224                 if (fd == -1)
225                 {
226                     return ERR_OPEN_MSG;
227                 }
228                 done = 1;
229             }
230             sprintf(path, "%s/%lu.msg", CurArea.path, n);
231         }
232     }
233     else
234     {
235         fd = sopen(path, OPENRW, SH_DENYNO, S_IMODE);
236         if (fd == -1)
237         {
238             return ERR_OPEN_MSG;
239         }
240     }
241 
242     if (m->new)
243     {
244         msgarrsz++;
245         if (msgarrsz > oldsz)
246         {
247             unsigned long *t;
248             t = xcalloc(1, (size_t) ((oldsz += CHUNKSZ) * sizeof *t));
249             memcpy(t, msgarr, (size_t) (sizeof(unsigned long) * msgarrsz));
250             release(msgarr);
251             msgarr = t;
252         }
253         msgarr[(size_t) (msgarrsz - 1)] = n;
254     }
255 
256     memset(&msghead, 0, sizeof msghead);
257 
258     m->msgnum = n;
259 
260     msghead.attrib[0] = (unsigned char)((m->attrib.killsent << 7) |
261       (m->attrib.orphan << 6) | (m->attrib.forward << 5) |
262       (m->attrib.attach << 4) | (m->attrib.sent << 3) | (m->attrib.rcvd << 2) |
263       (m->attrib.crash << 1) | (m->attrib.priv));
264 
265     msghead.attrib[1] = (unsigned char)((m->attrib.ureq << 7) |
266       (m->attrib.areq << 6) | (m->attrib.rcpt << 5) | (m->attrib.rreq << 4) |
267       (m->attrib.freq << 3) | (m->attrib.direct << 2) | (m->attrib.hold << 1) |
268       (m->attrib.local));
269 
270     x = FidoMsgnToUid((unsigned long)m->replyto);
271     msghead.reply[0] = (unsigned char)(x & 0xff);
272     msghead.reply[1] = (unsigned char)((x >> 8) & 0xff);
273     x = FidoMsgnToUid((unsigned long)m->replies[0]);
274     msghead.up[0] = (unsigned char)(x & 0xff);
275     msghead.up[1] = (unsigned char)((x >> 8) & 0xff);
276     msghead.times[0] = (unsigned char)(m->times_read & 0xff);
277     msghead.times[1] = (unsigned char)((m->times_read >> 8) & 0xff);
278     msghead.cost[0] = (unsigned char)(m->cost & 0xff);
279     msghead.cost[1] = (unsigned char)((m->cost >> 8) & 0xff);
280 
281     msghead.dest_net[0] = (unsigned char)(m->to.net & 0xff);
282     msghead.dest_net[1] = (unsigned char)((m->to.net >> 8) & 0xff);
283     msghead.dest[0] = (unsigned char)(m->to.node & 0xff);
284     msghead.dest[1] = (unsigned char)((m->to.node >> 8) & 0xff);
285 
286     if (m->isfrom != NULL)
287     {
288         size_t len_from;
289         len_from = strlen(m->isfrom);
290         memcpy(msghead.from, m->isfrom, min(sizeof msghead.from, len_from));
291         msghead.from[sizeof(msghead.from) - 1] = '\0';
292     }
293     else
294     {
295         msghead.from[0] = '\0';
296     }
297 
298     if (m->isto != NULL)
299     {
300         size_t len_to;
301         len_to = strlen(m->isto);
302         memcpy(msghead.to, m->isto, min(sizeof msghead.to, len_to));
303         msghead.to[sizeof(msghead.to) - 1] = '\0';
304     }
305     else
306     {
307         msghead.to[0] = '\0';
308     }
309 
310     if (m->subj != NULL)
311     {
312         size_t len_subj;
313         len_subj = strlen(m->subj);
314         memcpy(msghead.subj, m->subj, min(sizeof msghead.subj, len_subj));
315         msghead.subj[sizeof(msghead.subj) - 1] = '\0';
316     }
317     else
318     {
319         msghead.subj[0] = '\0';
320     }
321 
322     memcpy(msghead.date, mtime(m->timestamp), 20);
323 
324     msghead.orig_net[0] = (unsigned char)(m->from.net & 0xff);
325     msghead.orig_net[1] = (unsigned char)((m->from.net >> 8) & 0xff);
326     msghead.orig[0] = (unsigned char)(m->from.node & 0xff);
327     msghead.orig[1] = (unsigned char)((m->from.node >> 8) & 0xff);
328 
329     if (SW->opusdate)
330     {
331         timet_to_char(now, msghead.written);
332         memcpy(msghead.arrived, msghead.written, sizeof msghead.arrived);
333     }
334     else
335     {
336         timet_to_char(m->timestamp, msghead.written);
337         if (m->time_arvd)
338         {
339             timet_to_char(m->time_arvd, msghead.arrived);
340         } else  /* don't output bogus ... */
341         {
342             memcpy(msghead.arrived, msghead.written, sizeof msghead.arrived);
343         }
344     }
345 
346     assert(sizeof(MFIDO) == MFIDO_SIZE);
347     farwrite(fd, (char *)&msghead, sizeof(MFIDO));
348 
349     if (type == WR_HEADER)
350     {
351         close(fd);
352         fd = -1;
353     }
354 
355     return TRUE;
356 }
357 
FidoMsgReadHeader(unsigned long n,int type)358 msg *FidoMsgReadHeader(unsigned long n, int type)
359 {
360     MFIDO msghead;
361     unsigned long msgn;
362     msg *m;
363 
364     if (path == NULL) path = xmalloc(PATHLEN);
365 
366 
367     if (n > 0 && n <= msgarrsz)
368     {
369         msgn = msgarr[(size_t) (n - 1)];
370     }
371     else
372     {
373         return NULL;
374     }
375 
376     if (fd != -1)
377     {
378         close(fd);
379         fd = -1;
380     }
381     memset(&msghead, 0, sizeof msghead);
382     sprintf(path, "%s/%lu.msg", CurArea.path, msgn);
383     fd = sopen(path, OPENR, SH_DENYNO, S_IMODE);
384     if (fd == -1)
385     {
386         return NULL;
387     }
388 
389     m = xcalloc(1, sizeof *m);
390 
391     assert(sizeof(MFIDO) == MFIDO_SIZE);
392     farread(fd, (char *)&msghead, (int)sizeof(MFIDO));
393 
394     m->msgnum = msgn;
395 
396     m->from.net = (msghead.orig_net[1] << 8) | msghead.orig_net[0];
397     m->from.node = (msghead.orig[1] << 8) | msghead.orig[0];
398     m->to.net = (msghead.dest_net[1] << 8) | msghead.dest_net[0];
399     m->to.node = (msghead.dest[1] << 8) | msghead.dest[0];
400 
401     memset(path, 0, sizeof path);
402     memcpy(path, msghead.date, sizeof msghead.date);
403 
404     m->timestamp = parsedate(path);
405 
406     if (msghead.arrived[0] != 0 || msghead.arrived[1] != 0 || msghead.arrived[2] != 0 || msghead.arrived[3] != 0)
407     {
408         m->time_arvd = char_to_timet(msghead.arrived);
409     }
410 
411     m->isto = xcalloc(1, sizeof msghead.to + 1);
412     m->isfrom = xcalloc(1, sizeof msghead.from + 1);
413     m->subj = xcalloc(1, sizeof msghead.subj + 1);
414 
415     memcpy(m->isto, msghead.to, sizeof msghead.to);
416     memcpy(m->isfrom, msghead.from, sizeof msghead.from);
417     memcpy(m->subj, msghead.subj, sizeof msghead.subj);
418 
419     if (type != RD_HEADER_BRIEF)
420     {
421         m->replyto = FidoUidToMsgn((unsigned long)((msghead.reply[1] << 8)
422                                                    | msghead.reply[0]));
423         m->replies[0] = FidoUidToMsgn((unsigned long)((msghead.up[1] << 8)
424                                                       | msghead.up[0]));
425     }
426 
427     m->attrib.ureq = ((msghead.attrib[1] >> 7) & 0x01);
428     m->attrib.areq = ((msghead.attrib[1] >> 6) & 0x01);
429     m->attrib.rcpt = ((msghead.attrib[1] >> 5) & 0x01);
430     m->attrib.rreq = ((msghead.attrib[1] >> 4) & 0x01);
431     m->attrib.freq = ((msghead.attrib[1] >> 3) & 0x01);
432     m->attrib.direct = ((msghead.attrib[1] >> 2) & 0x01);
433     m->attrib.hold = ((msghead.attrib[1] >> 1) & 0x01);
434     m->attrib.local = ((msghead.attrib[1]) & 0x01);
435 
436     m->attrib.killsent = ((msghead.attrib[0] >> 7) & 0x01);
437     m->attrib.orphan = ((msghead.attrib[0] >> 6) & 0x01);
438     m->attrib.forward = ((msghead.attrib[0] >> 5) & 0x01);
439     m->attrib.attach = ((msghead.attrib[0] >> 4) & 0x01);
440     m->attrib.sent = ((msghead.attrib[0] >> 3) & 0x01);
441     m->attrib.rcvd = ((msghead.attrib[0] >> 2) & 0x01);
442     m->attrib.crash = ((msghead.attrib[0] >> 1) & 0x01);
443     m->attrib.priv = ((msghead.attrib[0]) & 0x01);
444 
445     m->from.zone = CurArea.addr.zone;
446     m->to.zone = CurArea.addr.zone;
447     m->cost = (msghead.cost[1] << 8) | msghead.cost[0];
448     m->times_read = (msghead.times[1] << 8) | msghead.times[0];
449 
450     m->to.fidonet = 1;
451     m->from.fidonet = 1;
452     m->text = NULL;
453 
454     if (type == RD_HEADER || type == RD_HEADER_BRIEF)
455     {
456         close(fd);
457         fd = -1;
458     }
459 
460     return m;
461 }
462 
FidoMsgReadText(unsigned long n)463 char *FidoMsgReadText(unsigned long n)
464 {
465     static char *next = NULL;
466     static char *end = NULL;
467     static unsigned long s = 0;
468     int i, l;
469     char *t;
470     char *text;
471     char eol = '\0';
472 
473     unused(n);
474     if (next == NULL && s != 0)
475     {
476         s = 0;
477         return NULL;
478     }
479 
480     if (s == 0)
481     {
482         s = BUFLEN;
483         memset(msgbuf, 0, (size_t) (s - 1));
484         lseek(fd, (long)sizeof(MFIDO), SEEK_SET);
485     }
486 
487     if (next == NULL)
488     {
489         i = farread(fd, msgbuf, (size_t) (s - 1));
490         if (i < 1)
491         {
492             next = NULL;
493             s = 0;
494             return (NULL);
495         }
496         next = msgbuf;
497         while (i && *next == '\0')
498         {
499             i--;
500             next++;
501         }
502         normalize(next);
503         end = msgbuf + strlen(msgbuf);
504         if (end < next)
505         {
506             next = end;
507         }
508     }
509 
510     if (end - next == 0)
511     {
512         t = NULL;
513     }
514     else
515     {
516         t = memchr(next, '\n', (int)(end - next));
517     }
518 
519     if (t == NULL)
520     {
521         l = strlen(next);
522         memcpy(msgbuf, next, l + 1);
523         i = farread(fd, msgbuf + l, (size_t) (s - l - 1));
524         if (i < 1)
525         {
526             next = NULL;
527             return xstrdup(msgbuf);
528         }
529         *(msgbuf + l + i) = '\0';
530         normalize(msgbuf + l);
531         end = msgbuf + strlen(msgbuf);
532         next = msgbuf;
533         t = memchr(next, '\n', l + i);
534     }
535 
536     if (t != NULL)
537     {
538         eol = *(t + 1);
539         *(t + 1) = '\0';
540     }
541 
542     text = xstrdup(next);
543 
544     if (t != NULL)
545     {
546         *(t + 1) = eol;
547         next = t + 1;
548     }
549     else
550     {
551         next = NULL;
552     }
553 
554     return text;
555 }
556 
FidoMsgClose(void)557 int FidoMsgClose(void)
558 {
559     if (fd != -1)
560     {
561         close(fd);
562         fd = -1;
563     }
564     return TRUE;
565 }
566 
FidoMsgAreaClose(void)567 int FidoMsgAreaClose(void)
568 {
569     CurArea.status = 0;
570     return TRUE;
571 }
572 
compare(const void * i,const void * j)573 static int compare(const void *i, const void *j)
574 {
575     return ((int)(*(unsigned long *)i - *(unsigned long *)j));
576 }
577 
ScanArea(char * path)578 void ScanArea(char *path)
579 {
580     struct _dta fileinfo;
581     int status;
582     unsigned long msgnum;
583     unsigned long *t;
584 
585     status = dir_findfirst(path, DIR_NORMAL | DIR_ICASE, &fileinfo);
586     msgarrsz = 0;
587 
588     while (status != -1)
589     {
590         if (fileinfo.size >= sizeof(MFIDO))
591         {
592             msgnum = atol(fileinfo.name);
593             msgarrsz++;
594             if (msgarrsz >= oldsz)
595             {
596                 t = xcalloc((size_t) (oldsz += CHUNKSZ), sizeof *t);
597                 if (msgarr != NULL)
598                 {
599                     /* copy old array across */
600                     memcpy(t, msgarr, (size_t) (sizeof(unsigned long) * msgarrsz));
601                 }
602                 release(msgarr);
603                 msgarr = t;
604             }
605             /* assign new msgnumber */
606             msgarr[(size_t) (msgarrsz - 1)] = msgnum;
607         }
608         status = dir_findnext(&fileinfo);
609     }
610 
611     if (msgarr == NULL)
612     {
613         /* no files at all in dir */
614         msgarr = malloc(sizeof(unsigned long) * CHUNKSZ);
615     }
616     else
617     {
618         qsort((void *)msgarr, (int)msgarrsz, (size_t) sizeof(unsigned long), compare);
619     }
620 }
621 
FidoMsgAreaOpen(AREA * a)622 long FidoMsgAreaOpen(AREA * a)
623 {
624     short int c = 10, l;
625     unsigned long msgnum;
626     unsigned char shortbuf[2];
627 
628     if (path == NULL) path = xmalloc(PATHLEN);
629 
630     sprintf(path, "%s/*.msg", a->path);
631     a->last = a->first = 1;
632     a->current = a->lastread = 1;
633     a->status = 1;
634 
635     ScanArea(path);
636     a->scanned = 1;
637 
638     sprintf(path, "%s/%s", a->path, ST->lastread);
639     fd = sopen(path, OPENR, SH_DENYNO, S_IMODE);
640     if (fd != -1)
641     {
642         farread(fd, (char *) shortbuf, sizeof shortbuf);
643         c = get_word(shortbuf);
644         if (farread(fd, (char *) shortbuf, sizeof shortbuf) != sizeof shortbuf)
645         {
646             l = c;
647         }
648         else
649         {
650             l = get_word(shortbuf);
651         }
652         close(fd);
653         fd = -1;
654     }
655     else
656     {
657         l = 0;
658         c = 0;
659     }
660 
661     if (msgarrsz != 0)
662     {
663         a->last = msgarrsz;
664 
665         msgnum = msgarrsz;
666         while (msgnum > 1 && msgarr[(size_t) (msgnum - 1)] > (unsigned long)c)
667         {
668              msgnum--;
669         }
670 
671         a->current = (!msgnum) ? a->last : msgnum;
672 
673         msgnum = msgarrsz;
674         while (msgnum > 1 && msgarr[(size_t) (msgnum - 1)] != (unsigned long)l)
675         {
676             msgnum--;
677         }
678 
679         a->lastread = (!msgnum) ? a->last : msgnum;
680     }
681     return (long)msgarrsz;
682 }
683 
FidoAreaSetLast(AREA * a)684 int FidoAreaSetLast(AREA * a)
685 {
686     int fd;
687     short i = 0;
688     unsigned char shortbuf[2];
689 
690     if (path == NULL) path = xmalloc(PATHLEN);
691 
692     sprintf(path, "%s/%s", a->path, ST->lastread);
693     fd = sopen(path, OPENRW, SH_DENYNO, S_IMODE);
694     if (fd == -1)
695     {
696         if (fd == -1 && errno != EACCES && errno != EMFILE)
697         {
698             fd = sopen(path, OPENC, SH_DENYNO, S_IMODE_LASTREAD);
699             if (fd == -1)
700             {
701                 return FALSE;
702             }
703             lseek(fd, 0L, SEEK_SET);
704             farwrite(fd, (byte far *)&i, sizeof(short));
705             farwrite(fd, (byte far *)&i, sizeof(short));
706             close(fd);
707             return TRUE;
708         }
709         return FALSE;
710     }
711 
712     lseek(fd, 0L, SEEK_SET);
713     if (msgarr && a->lastread > 0 && a->current > 0 &&
714         a->lastread <=msgarrsz && a->current <= msgarrsz)
715     {
716         i = (short)msgarr[(size_t) (a->current - 1)];
717         shortbuf[0] = i & 0xFF; shortbuf[1] = (i >> 8) & 0xFF;
718         farwrite(fd, (char *) shortbuf, sizeof(shortbuf));
719         i = (short)msgarr[(size_t) (a->lastread - 1)];
720         shortbuf[0] = i & 0xFF; shortbuf[1] = (i >> 8) & 0xFF;
721         farwrite(fd, (char *) shortbuf, sizeof(shortbuf));
722     }
723     else
724     {
725         farwrite(fd, (byte far *)&i, sizeof(short));
726         farwrite(fd, (byte far *)&i, sizeof(short));
727     }
728     close(fd);
729     return TRUE;
730 }
731 
FidoMsgDelete(unsigned long n)732 int FidoMsgDelete(unsigned long n)
733 {
734     if (path == NULL) path = xmalloc(PATHLEN);
735 
736     /* delete the message */
737 
738     sprintf(path, "%s/%lu.msg", CurArea.path, n);
739     remove(path);
740 
741     /* we now re-scan the area just for the sake of it */
742 
743     sprintf(path, "%s/*.msg", CurArea.path);
744     ScanArea(path);
745 
746     return TRUE;
747 }
748 
749 /*
750  *  This is what the "dos date" looks like, but we don't rely on the
751  *  internal structure of the compiler to do our routines.
752  */
753 
754 #if 0
755 typedef struct _dosdate
756 {
757     unsigned int day  : 5;
758     unsigned int mon  : 4;
759     unsigned int year : 7;
760     unsigned int sec  : 5;
761     unsigned int min  : 6;
762     unsigned int hour : 5;
763 }
764 DOSDATE;
765 #endif
766 
timet_to_char(time_t now,unsigned char arr[])767 static void timet_to_char(time_t now, unsigned char arr[])
768 {
769     struct tm *ts;
770     unsigned long x;
771     ts = localtime(&now);
772     x = ts->tm_year - 80;
773     x = (x << 4) | (ts->tm_mon + 1);
774     x = (x << 5) | ts->tm_mday;
775     x = (x << 5) | ts->tm_hour;
776     x = (x << 6) | ts->tm_min;
777     x = (x << 5) | (ts->tm_sec / 2);
778     arr[0] = (unsigned char)((x >> 16) & 0xff);
779     arr[1] = (unsigned char)((x >> 24) & 0xff);
780     arr[2] = (unsigned char)(x & 0xff);
781     arr[3] = (unsigned char)((x >> 8) & 0xff);
782 }
783 
char_to_timet(unsigned char arr[])784 static time_t char_to_timet(unsigned char arr[])
785 {
786     struct tm tms;
787     time_t tt;
788     unsigned long x;
789 
790                         /* the many unsigned long casts are needed  */
791                         /* to make it work in a 16 bit environment */
792     x = ( ((unsigned long) arr[0]) << 16) |
793         ( ((unsigned long) arr[1]) << 24) |
794            (unsigned long) arr[2]         |
795         ( ((unsigned long) arr[3]) << 8);
796 
797     tms.tm_sec = (int) ((x & 0x1f) * 2);
798     x >>= 5;
799     tms.tm_min = (int) (x & 0x3f);
800     x >>= 6;
801     tms.tm_hour = (int) (x & 0x1f);
802     x >>= 5;
803     tms.tm_mday = (int) (x & 0x1f);
804     x >>= 5;
805     tms.tm_mon = (int) ((x & 0x0f) - 1);
806     x >>= 4;
807     tms.tm_year = (int) ((x & 0x7f) + 80);
808     tms.tm_isdst = -1;
809     tt = mktime(&tms);
810     return tt;
811 }
812 
FidoMsgLock(void)813 int FidoMsgLock(void)
814 {
815     return 0;
816 }
817 
FidoMsgUnlock(void)818 int FidoMsgUnlock(void)
819 {
820     return 0;
821 }
822