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