1 /*
2  *  SMAPI; Modified Squish MSGAPI
3  *
4  *  Squish MSGAPI0 is copyright 1991 by Scott J. Dudley.  All rights reserved.
5  *  Modifications released to the public domain.
6  *
7  *  Use of this file is subject to the restrictions contain in the Squish
8  *  MSGAPI0 licence agreement.  Please refer to licence.txt for complete
9  *  details of the licencing restrictions.  If you do not find the text
10  *  of this agreement in licence.txt, or if you do not have this file,
11  *  you should contact Scott Dudley at FidoNet node 1:249/106 or Internet
12  *  e-mail Scott.Dudley@f106.n249.z1.fidonet.org.
13  *
14  *  In no event should you proceed to use any of the source files in this
15  *  archive without having accepted the terms of the MSGAPI0 licensing
16  *  agreement, or such other agreement as you are able to reach with the
17  *  author.
18  */
19 
20 /*  STRUCTRW.C written 1998 by Tobias Ernst
21  *
22  *  This file contains routines read and write packed structures like the
23  *  struct XMSG in an platform-independent manner.
24  *
25  *  Background information: You should never ever read or write any
26  *  structure directly from disk with something like
27  *  fread(&structure, sizeof(structure), 1, f)
28  *  This will fail on some compliers that can't be told to pack structures
29  *  in exactly the way that they are supposed to be. It will also fail
30  *  when trying to read a file that is supposed to be used by a little-
31  *  endian machine (like Intel) on a big endian machine (like PPC).
32  *
33  *  So the conclusion: Never use fread, fwrite, farread, farwrite on
34  *  structures - use the routines from this module instead, or if you are
35  *  introducing a new structure, add a routine for it to this file.
36  *
37  *  If you have any questions on this topic, feel free to contact me
38  *  at 2:2476/418 or tobi@bland.fido.de.
39  */
40 
41 #include <stdlib.h>
42 #include <string.h>
43 #include <assert.h>
44 #include <sys/types.h>
45 #include <sys/stat.h>
46 #include <fcntl.h>
47 #include <errno.h>
48 
49 
50 #define MSGAPI_HANDLERS
51 
52 #include <huskylib/compiler.h>
53 
54 #ifdef HAS_UNISTD_H
55 #include <unistd.h>
56 #endif
57 #ifdef HAS_IO_H
58 #  include <io.h>
59 #endif
60 
61 #include <huskylib/huskylib.h>
62 
63 /* Swith for build DLL */
64 #define DLLEXPORT
65 #include <huskylib/huskyext.h>
66 
67 #include "msgapi.h"
68 #include "api_sq.h"
69 #include "old_msg.h"
70 #include "api_jam.h"
71 
72 #define MAXHDRINCORE  (1024l*1024*10) /* Maximum jam hdr size for incore, 10M */
73 
74 #ifdef NEED_trivial_farread
75   #ifdef HAS_dos_read
76   /* "Text mode" not implemented !!! */
trivial_farread(int handle,void far * buffer,unsigned len)77   int trivial_farread( int handle, void far *buffer, unsigned len )
78   { unsigned r_len=0;
79 
80     if(dos_read( handle, buffer, len, &r_len ) )
81       return 0;
82 
83     return r_len;
84   }
85   #else
86     #error "Can't implement trivial_farread() without dos_read()"
87   #endif
88 #endif
89 
90 #ifdef NEED_trivial_farwrite
91   #ifdef HAS_dos_write
92   /* "Text mode" not implemented !!! */
trivial_farwrite(int handle,void far * buffer,unsigned len)93   int trivial_farwrite( int handle, void far *buffer, unsigned len )
94   { unsigned r_len=0;
95 
96     if(dos_write( handle, buffer, len, &r_len ) )
97       return 0;
98 
99     return r_len;
100   }
101   #else
102     #error "Can't implement trivial_farwrite() without dos_write()"
103   #endif
104 #endif
105 
106 
107 
read_xmsg(int handle,XMSG * pxmsg)108 int read_xmsg(int handle, XMSG *pxmsg)
109 {
110     byte buf[XMSG_SIZE], *pbuf = buf;
111     word rawdate, rawtime;
112     int i;
113 
114     if (farread(handle, (byte far *)buf, XMSG_SIZE) != XMSG_SIZE)
115     {
116         return 0;
117     }
118 
119                                 /* 04 bytes "attr" */
120     pxmsg->attr = get_dword(pbuf);
121     pbuf += 4;
122 
123                                 /* 36 bytes "from" */
124     memmove(pxmsg->from, pbuf, XMSG_FROM_SIZE);
125     pbuf += XMSG_FROM_SIZE;
126 
127                                 /* 36 bytes "to"   */
128     memmove(pxmsg->to, pbuf, XMSG_TO_SIZE);
129     pbuf += XMSG_TO_SIZE;
130 
131                                 /* 72 bytes "subj" */
132     memmove(pxmsg->subj, pbuf, XMSG_SUBJ_SIZE);
133     pbuf += XMSG_SUBJ_SIZE;
134 
135                                 /* 8 bytes "orig"  */
136     pxmsg->orig.zone = get_word(pbuf); pbuf += 2;
137     pxmsg->orig.net  = get_word(pbuf); pbuf += 2;
138     pxmsg->orig.node = get_word(pbuf); pbuf += 2;
139     pxmsg->orig.point= get_word(pbuf); pbuf += 2;
140 
141                                 /* 8 bytes "dest"  */
142     pxmsg->dest.zone = get_word(pbuf); pbuf += 2;
143     pxmsg->dest.net  = get_word(pbuf); pbuf += 2;
144     pxmsg->dest.node = get_word(pbuf); pbuf += 2;
145     pxmsg->dest.point= get_word(pbuf); pbuf += 2;
146 
147                                 /* 4 bytes "date_written" */
148     rawdate = get_word(pbuf); pbuf += 2;
149     rawtime = get_word(pbuf); pbuf += 2;
150     pxmsg->date_written.date.da = rawdate & 31;
151     pxmsg->date_written.date.mo = (rawdate >> 5) & 15;
152     pxmsg->date_written.date.yr = (rawdate >> 9) & 127;
153     pxmsg->date_written.time.ss = rawtime & 31;
154     pxmsg->date_written.time.mm = (rawtime >> 5) & 63;
155     pxmsg->date_written.time.hh = (rawtime >> 11) & 31;
156 
157                                 /* 4 bytes "date_arrived" */
158     rawdate = get_word(pbuf); pbuf += 2;
159     rawtime = get_word(pbuf); pbuf += 2;
160     pxmsg->date_arrived.date.da = rawdate & 31;
161     pxmsg->date_arrived.date.mo = (rawdate >> 5) & 15;
162     pxmsg->date_arrived.date.yr = (rawdate >> 9) & 127;
163     pxmsg->date_arrived.time.ss = rawtime & 31;
164     pxmsg->date_arrived.time.mm = (rawtime >> 5) & 63;
165     pxmsg->date_arrived.time.hh = (rawtime >> 11) & 31;
166 
167                                 /* 2 byte "utc_ofs" */
168     pxmsg->utc_ofs = get_word(pbuf);
169     pbuf += 2;
170 
171                                 /* 4 bytes "replyto" */
172     pxmsg->replyto = get_dword(pbuf);
173     pbuf += 4;
174 
175                                 /* 10 times 4 bytes "replies" */
176     for (i = 0; i < MAX_REPLY; i++)
177     {
178         pxmsg->replies[i] = get_dword(pbuf);
179         pbuf += 4;
180     }
181 
182                                 /* 4 bytes "umsgid" */
183     pxmsg->umsgid = get_dword(pbuf);
184     pbuf += 4;
185 
186                                 /* 20 times FTSC date stamp */
187     memmove(pxmsg->__ftsc_date, pbuf, 20);
188     pbuf += 20;
189 
190     assert(pbuf - buf == XMSG_SIZE);
191     return 1;
192 }
193 
write_xmsg(int handle,XMSG * pxmsg)194 int write_xmsg(int handle, XMSG *pxmsg)
195 {
196     byte buf[XMSG_SIZE], *pbuf = buf;
197     word rawdate, rawtime;
198     int i;
199 
200                                 /* 04 bytes "attr" */
201     put_dword(pbuf, pxmsg->attr);
202     pbuf += 4;
203 
204                                 /* 36 bytes "from" */
205     memmove(pbuf, pxmsg->from, XMSG_FROM_SIZE);
206     pbuf += XMSG_FROM_SIZE;
207 
208                                 /* 36 bytes "to"   */
209     memmove(pbuf, pxmsg->to, XMSG_TO_SIZE);
210     pbuf += XMSG_TO_SIZE;
211 
212                                 /* 72 bytes "subj" */
213     memmove(pbuf, pxmsg->subj, XMSG_SUBJ_SIZE);
214     pbuf += XMSG_SUBJ_SIZE;
215 
216                                 /* 8 bytes "orig"  */
217     put_word(pbuf, pxmsg->orig.zone);  pbuf += 2;
218     put_word(pbuf, pxmsg->orig.net);   pbuf += 2;
219     put_word(pbuf, pxmsg->orig.node);  pbuf += 2;
220     put_word(pbuf, pxmsg->orig.point); pbuf += 2;
221 
222                                     /* 8 bytes "dest"  */
223     put_word(pbuf, pxmsg->dest.zone);  pbuf += 2;
224     put_word(pbuf, pxmsg->dest.net);   pbuf += 2;
225     put_word(pbuf, pxmsg->dest.node);  pbuf += 2;
226     put_word(pbuf, pxmsg->dest.point); pbuf += 2;
227 
228 
229                                 /* 4 bytes "date_written" */
230     rawdate = rawtime = 0;
231 
232     rawdate |= (((word)pxmsg->date_written.date.da) & 31);
233     rawdate |= (((word)pxmsg->date_written.date.mo) & 15) << 5;
234     rawdate |= (((word)pxmsg->date_written.date.yr) & 127) << 9;
235 
236     rawtime |= (((word)pxmsg->date_written.time.ss) & 31);
237     rawtime |= (((word)pxmsg->date_written.time.mm) & 63) << 5;
238     rawtime |= (((word)pxmsg->date_written.time.hh) & 31) << 11;
239 
240     put_word(pbuf, rawdate); pbuf += 2;
241     put_word(pbuf, rawtime); pbuf += 2;
242 
243 
244                                 /* 4 bytes "date_arrvied" */
245     rawdate = rawtime = 0;
246 
247     rawdate |= (((word)pxmsg->date_arrived.date.da) & 31);
248     rawdate |= (((word)pxmsg->date_arrived.date.mo) & 15) << 5;
249     rawdate |= (((word)pxmsg->date_arrived.date.yr) & 127) << 9;
250 
251     rawtime |= (((word)pxmsg->date_arrived.time.ss) & 31);
252     rawtime |= (((word)pxmsg->date_arrived.time.mm) & 63) << 5;
253     rawtime |= (((word)pxmsg->date_arrived.time.hh) & 31) << 11;
254 
255     put_word(pbuf, rawdate); pbuf += 2;
256     put_word(pbuf, rawtime); pbuf += 2;
257 
258 
259                                 /* 2 byte "utc_ofs" */
260     put_word(pbuf, pxmsg->utc_ofs);
261     pbuf += 2;
262 
263                                 /* 4 bytes "replyto" */
264     put_dword(pbuf, pxmsg->replyto);
265     pbuf += 4;
266 
267                                 /* 10 times 4 bytes "replies" */
268     for (i = 0; i < MAX_REPLY; i++)
269     {
270         put_dword(pbuf, pxmsg->replies[i]);
271         pbuf += 4;
272     }
273                                 /* 4 bytes "umsgid" */
274     put_dword(pbuf, pxmsg->umsgid);
275     pbuf += 4;
276 
277 
278                                 /* 20 times FTSC date stamp */
279     memmove(pbuf, pxmsg->__ftsc_date, 20);
280     pbuf += 20;
281 
282     assert(pbuf - buf == XMSG_SIZE);
283     return (farwrite(handle, (byte far *)buf, XMSG_SIZE) == XMSG_SIZE);
284 }
285 
read_sqhdr(int handle,SQHDR * psqhdr)286 int read_sqhdr(int handle, SQHDR *psqhdr)
287 {
288     byte buf[SQHDR_SIZE], *pbuf = buf;
289 
290     if (farread(handle, (byte far *)buf, SQHDR_SIZE) != SQHDR_SIZE)
291     {
292         return 0;
293     }
294                                 /* 4 bytes "id" */
295     psqhdr->id = get_dword(pbuf);
296     pbuf += 4;
297 
298                                 /* 4 bytes "next_frame" */
299     psqhdr->next_frame = get_dword(pbuf);
300     pbuf += 4;
301 
302                                 /* 4 bytes "prev_frame" */
303     psqhdr->prev_frame = get_dword(pbuf);
304     pbuf += 4;
305 
306                                 /* 4 bytes "frame_length" */
307     psqhdr->frame_length = get_dword(pbuf);
308     pbuf += 4;
309 
310                                 /* 4 bytes "msg_length" */
311     psqhdr->msg_length = get_dword(pbuf);
312     pbuf += 4;
313                                 /* 4 bytes "clen" */
314     psqhdr->clen = get_dword(pbuf);
315     pbuf += 4;
316 
317                                 /* 2 bytes "frame_type" */
318     psqhdr->frame_type = get_word(pbuf);
319     pbuf += 2;
320                                 /* 4 bytes "rsvd" */
321     psqhdr->rsvd = get_word(pbuf);
322     pbuf += 2;
323 
324     assert(pbuf - buf == SQHDR_SIZE);
325 
326     return 1;
327 }
328 
write_sqhdr(int handle,SQHDR * psqhdr)329 int write_sqhdr(int handle, SQHDR *psqhdr)
330 {
331     byte buf[SQHDR_SIZE], *pbuf = buf;
332 
333                                 /* 4 bytes "id" */
334     put_dword(pbuf, psqhdr->id);
335     pbuf += 4;
336 
337                                 /* 4 bytes "next_frame" */
338     put_dword(pbuf, psqhdr->next_frame);
339     pbuf += 4;
340 
341                                 /* 4 bytes "prev_frame" */
342     put_dword(pbuf, psqhdr->prev_frame);
343     pbuf += 4;
344 
345                                 /* 4 bytes "frame_length" */
346     put_dword(pbuf, psqhdr->frame_length);
347     pbuf += 4;
348 
349                                 /* 4 bytes "msg_length" */
350     put_dword(pbuf, psqhdr->msg_length);
351     pbuf += 4;
352                                 /* 4 bytes "clen" */
353     put_dword(pbuf, psqhdr->clen);
354     pbuf += 4;
355 
356                                 /* 2 bytes "frame_type" */
357     put_word(pbuf, psqhdr->frame_type);
358     pbuf += 2;
359                                 /* 4 bytes "rsvd" */
360     put_word(pbuf, psqhdr->rsvd);
361     pbuf += 2;
362 
363     assert(pbuf - buf == SQHDR_SIZE);
364 
365     return (farwrite(handle, (byte far *)buf, SQHDR_SIZE) == SQHDR_SIZE);
366 }
367 
368 /*
369  * read_sqidx
370  *
371  * This function needs a little explanation. Just like the other functions,
372  * it reads in a special structure, the SQIDX structure. The problem is
373  * that this is done very often: It is not uncommon that 5000 SQIDXs are
374  * being read in seqeuence. Therefore, I had to do a little performance
375  * tuning here. I try to read in as much SQIDX structures as possible
376  * at once, while at the same time being able to cope with the fact that
377  * the OS might not be able to provide me with enough temporrary storage.
378  *
379  * Normally, you will not have to care about the buffering thing. Only
380  * the code between "begin reading in a single structre" and "end reading
381  * in a single structure" must be change if the structure layout changes.
382  */
383 
read_sqidx(int handle,SQIDX * psqidx,dword n)384 int read_sqidx(int handle, SQIDX *psqidx, dword n)
385 {
386     byte buf[SQIDX_SIZE], *pbuf = NULL;
387     byte *accel_buffer = NULL;
388     dword i, maxbuf = 0, rd;
389 
390     if (n > 1)
391     {
392         maxbuf = n;
393         if ((dword)SQIDX_SIZE * (dword)n >= 32768L)
394         {
395             maxbuf = (dword)32768L / SQIDX_SIZE;
396         }
397         accel_buffer = malloc(SQIDX_SIZE * maxbuf);
398     }
399 
400     for (i = 0; i < n; i++)
401     {
402         if (accel_buffer == NULL)
403         {
404             if (farread(handle, buf, SQIDX_SIZE) != SQIDX_SIZE)
405             {
406                 return 0;
407             }
408             pbuf = buf;
409         }
410         else
411         {
412             if (!(i % maxbuf))
413             {
414                 rd = (i + maxbuf > n) ? (n - i) : maxbuf;
415                 if (farread(handle, accel_buffer, rd * SQIDX_SIZE) !=
416                     (int)(rd * SQIDX_SIZE))
417                 {
418                     free(accel_buffer);
419                     return 0;
420                 }
421                 pbuf = accel_buffer;
422             }
423         }
424 
425         /* Begin reading in a single structure */
426 
427                                 /* 4 bytes "ofs" */
428         psqidx[i].ofs = get_dword(pbuf);
429         pbuf += 4;
430 
431                                 /* 4 bytes "umsgid" */
432         psqidx[i].umsgid = get_dword(pbuf);
433         pbuf += 4;
434 
435                                 /* 4 bytes "hash" */
436         psqidx[i].hash = get_dword(pbuf);
437         pbuf += 4;
438 
439         /* Stop reading in a single structure */
440     }
441 
442     if (accel_buffer != NULL)
443     {
444         free(accel_buffer);
445     }
446 
447     return 1;
448 }
449 
450 
write_sqidx(int handle,SQIDX * psqidx,dword n)451 int write_sqidx(int handle, SQIDX *psqidx, dword n)
452 {
453     byte buf[SQIDX_SIZE], *pbuf = NULL;
454     byte *accel_buffer = NULL;
455     dword i, maxbuf = 0;
456 	int wr;
457 
458     if (n > 1)
459     {
460         maxbuf = n;
461         if ((dword)SQIDX_SIZE * (dword)n >= 32768L)
462         {
463             maxbuf = (dword)32768L / SQIDX_SIZE;
464         }
465         accel_buffer = malloc(SQIDX_SIZE * maxbuf);
466         pbuf = accel_buffer;
467     }
468 
469     for (i = 0; i < n; i++)
470     {
471         if (accel_buffer == NULL)
472         {
473             pbuf = buf;
474         }
475 
476                                 /* 4 bytes "ofs" */
477         put_dword(pbuf, psqidx[i].ofs);
478         pbuf += 4;
479 
480                                 /* 4 bytes "umsgid" */
481         put_dword(pbuf, psqidx[i].umsgid);
482         pbuf += 4;
483 
484                                 /* 4 bytes "hash" */
485         put_dword(pbuf, psqidx[i].hash);
486         pbuf += 4;
487 
488         if (accel_buffer == NULL)
489         {
490             if (farwrite(handle, buf, SQIDX_SIZE) != SQIDX_SIZE)
491             {
492                 return 0;
493             }
494         }
495         else
496         {
497             if (i == n - 1 || (!((i + 1) % maxbuf)))
498             {
499                 wr = (!((i + 1) % maxbuf)) ? maxbuf : (n % maxbuf);
500 
501                 if (farwrite(handle, accel_buffer, wr * SQIDX_SIZE) !=
502                     (wr * SQIDX_SIZE))
503                 {
504                     free(accel_buffer);
505                     return 0;
506                 }
507                 pbuf = accel_buffer;
508             }
509         }
510     }
511 
512     if (accel_buffer != NULL)
513     {
514         free(accel_buffer);
515     }
516 
517     return 1;
518 }
519 
read_sqbase(int handle,struct _sqbase * psqbase)520 int read_sqbase(int handle, struct _sqbase *psqbase)
521 {
522     byte buf[SQBASE_SIZE], *pbuf = buf;
523 
524     if (farread(handle, (byte far *)buf, SQBASE_SIZE) != SQBASE_SIZE)
525     {
526         return 0;
527     }
528 
529     psqbase->len = get_word(pbuf);
530     pbuf += 2;
531 
532     psqbase->rsvd1 = get_word(pbuf);
533     pbuf += 2;
534 
535     psqbase->num_msg = get_dword(pbuf);
536     pbuf += 4;
537 
538     psqbase->high_msg = get_dword(pbuf);
539     pbuf += 4;
540 
541     psqbase->skip_msg = get_dword(pbuf);
542     pbuf += 4;
543 
544     psqbase->high_water = get_dword(pbuf);
545     pbuf += 4;
546 
547     psqbase->uid = get_dword(pbuf);
548     pbuf += 4;
549 
550     memmove(psqbase->base, pbuf, 80);
551     pbuf += 80;
552 
553     psqbase->begin_frame = get_dword(pbuf);
554     pbuf += 4;
555 
556     psqbase->last_frame = get_dword(pbuf);
557     pbuf += 4;
558 
559     psqbase->free_frame = get_dword(pbuf);
560     pbuf += 4;
561 
562     psqbase->last_free_frame = get_dword(pbuf);
563     pbuf += 4;
564 
565     psqbase->end_frame = get_dword(pbuf);
566     pbuf += 4;
567 
568     psqbase->max_msg = get_dword(pbuf);
569     pbuf += 4;
570 
571     psqbase->keep_days = get_word(pbuf);
572     pbuf += 2;
573 
574     psqbase->sz_sqhdr = get_word(pbuf);
575     pbuf += 2;
576 
577     memmove(psqbase->rsvd2, pbuf, 124);
578     pbuf += 124;
579 
580     assert(pbuf-buf == SQBASE_SIZE);
581 
582     return 1;
583 }
584 
write_sqbase(int handle,struct _sqbase * psqbase)585 int write_sqbase(int handle, struct _sqbase *psqbase)
586 {
587     byte buf[SQBASE_SIZE], *pbuf = buf;
588 
589     put_word(pbuf, psqbase->len);
590     pbuf += 2;
591 
592     put_word(pbuf, psqbase->rsvd1);
593     pbuf += 2;
594 
595     put_dword(pbuf, psqbase->num_msg);
596     pbuf += 4;
597 
598     put_dword(pbuf, psqbase->high_msg);
599     pbuf += 4;
600 
601     put_dword(pbuf, psqbase->skip_msg);
602     pbuf += 4;
603 
604     put_dword(pbuf, psqbase->high_water);
605     pbuf += 4;
606 
607     put_dword(pbuf, psqbase->uid);
608     pbuf += 4;
609 
610     memmove(pbuf, psqbase->base, 80);
611     pbuf += 80;
612 
613     put_dword(pbuf, psqbase->begin_frame);
614     pbuf += 4;
615 
616     put_dword(pbuf, psqbase->last_frame);
617     pbuf += 4;
618 
619     put_dword(pbuf, psqbase->free_frame);
620     pbuf += 4;
621 
622     put_dword(pbuf, psqbase->last_free_frame);
623     pbuf += 4;
624 
625     put_dword(pbuf, psqbase->end_frame);
626     pbuf += 4;
627 
628     put_dword(pbuf, psqbase->max_msg);
629     pbuf += 4;
630 
631     put_word(pbuf, psqbase->keep_days);
632     pbuf += 2;
633 
634     put_word(pbuf, psqbase->sz_sqhdr);
635     pbuf += 2;
636 
637     memmove(pbuf, psqbase->rsvd2, 124);
638     pbuf += 124;
639 
640     assert(pbuf - buf == SQBASE_SIZE);
641 
642     return (farwrite(handle, (byte far *)buf, SQBASE_SIZE) == SQBASE_SIZE);
643 }
644 
read_omsg(int handle,struct _omsg * pomsg)645 int read_omsg(int handle, struct _omsg *pomsg)
646 {
647     byte buf[OMSG_SIZE], *pbuf = buf;
648     word rawdate, rawtime;
649 
650     if (farread(handle, (byte far *)buf, OMSG_SIZE) != OMSG_SIZE)
651     {
652         return 0;
653     }
654 
655     memmove(pomsg->from, pbuf, 36);
656     pbuf += 36;
657 
658     memmove(pomsg->to, pbuf, 36);
659     pbuf += 36;
660 
661     memmove(pomsg->subj, pbuf, 72);
662     pbuf += 72;
663 
664     memmove(pomsg->date, pbuf, 20);
665     pbuf += 20;
666 
667     pomsg->times = get_word(pbuf);
668     pbuf += 2;
669 
670     pomsg->dest = get_word(pbuf);
671     pbuf += 2;
672 
673     pomsg->orig = get_word(pbuf);
674     pbuf += 2;
675 
676     pomsg->cost = get_word(pbuf);
677     pbuf += 2;
678 
679     pomsg->orig_net = get_word(pbuf);
680     pbuf += 2;
681 
682     pomsg->dest_net = get_word(pbuf);
683     pbuf += 2;
684 
685                                 /* 4 bytes "date_written" */
686     rawdate = get_word(pbuf); pbuf += 2;
687     rawtime = get_word(pbuf); pbuf += 2;
688     pomsg->date_written.date.da = rawdate & 31;
689     pomsg->date_written.date.mo = (rawdate >> 5) & 15;
690     pomsg->date_written.date.yr = (rawdate >> 9) & 127;
691     pomsg->date_written.time.ss = rawtime & 31;
692     pomsg->date_written.time.mm = (rawtime >> 5) & 63;
693     pomsg->date_written.time.hh = (rawtime >> 11) & 31;
694 
695                                 /* 4 bytes "date_arrived" */
696     rawdate = get_word(pbuf); pbuf += 2;
697     rawtime = get_word(pbuf); pbuf += 2;
698     pomsg->date_arrived.date.da = rawdate & 31;
699     pomsg->date_arrived.date.mo = (rawdate >> 5) & 15;
700     pomsg->date_arrived.date.yr = (rawdate >> 9) & 127;
701     pomsg->date_arrived.time.ss = rawtime & 31;
702     pomsg->date_arrived.time.mm = (rawtime >> 5) & 63;
703     pomsg->date_arrived.time.hh = (rawtime >> 11) & 31;
704 
705     pomsg->reply = get_word(pbuf);
706     pbuf += 2;
707 
708     pomsg->attr = get_word(pbuf);
709     pbuf += 2;
710 
711     pomsg->up = get_word(pbuf);
712     pbuf += 2;
713 
714     assert(pbuf - buf == OMSG_SIZE);
715 
716     return 1;
717 }
718 
write_omsg(int handle,struct _omsg * pomsg)719 int write_omsg(int handle, struct _omsg *pomsg)
720 {
721     byte buf[OMSG_SIZE], *pbuf = buf;
722     word rawdate, rawtime;
723 
724     memmove(pbuf, pomsg->from, 36);
725     pbuf += 36;
726 
727     memmove(pbuf, pomsg->to, 36);
728     pbuf += 36;
729 
730     memmove(pbuf, pomsg->subj, 72);
731     pbuf += 72;
732 
733     memmove(pbuf, pomsg->date, 20);
734     pbuf += 20;
735 
736     put_word(pbuf, pomsg->times);
737     pbuf += 2;
738 
739     put_word(pbuf, pomsg->dest);
740     pbuf += 2;
741 
742     put_word(pbuf, pomsg->orig);
743     pbuf += 2;
744 
745     put_word(pbuf, pomsg->cost);
746     pbuf += 2;
747 
748     put_word(pbuf, pomsg->orig_net);
749     pbuf += 2;
750 
751     put_word(pbuf, pomsg->dest_net);
752     pbuf += 2;
753 
754                                 /* 4 bytes "date_written" */
755     rawdate = rawtime = 0;
756 
757     rawdate |= (((word)pomsg->date_written.date.da) & 31);
758     rawdate |= (((word)pomsg->date_written.date.mo) & 15) << 5;
759     rawdate |= (((word)pomsg->date_written.date.yr) & 127) << 9;
760 
761     rawtime |= (((word)pomsg->date_written.time.ss) & 31);
762     rawtime |= (((word)pomsg->date_written.time.mm) & 63) << 5;
763     rawtime |= (((word)pomsg->date_written.time.hh) & 31) << 11;
764 
765     put_word(pbuf, rawdate); pbuf += 2;
766     put_word(pbuf, rawtime); pbuf += 2;
767 
768 
769                                 /* 4 bytes "date_arrvied" */
770     rawdate = rawtime = 0;
771 
772     rawdate |= (((word)pomsg->date_arrived.date.da) & 31);
773     rawdate |= (((word)pomsg->date_arrived.date.mo) & 15) << 5;
774     rawdate |= (((word)pomsg->date_arrived.date.yr) & 127) << 9;
775 
776     rawtime |= (((word)pomsg->date_arrived.time.ss) & 31);
777     rawtime |= (((word)pomsg->date_arrived.time.mm) & 63) << 5;
778     rawtime |= (((word)pomsg->date_arrived.time.hh) & 31) << 11;
779 
780     put_word(pbuf, rawdate); pbuf += 2;
781     put_word(pbuf, rawtime); pbuf += 2;
782 
783     put_word(pbuf, pomsg->reply);
784     pbuf += 2;
785 
786     put_word(pbuf, pomsg->attr);
787     pbuf += 2;
788 
789     put_word(pbuf, pomsg->up);
790     pbuf += 2;
791 
792     assert(pbuf - buf == OMSG_SIZE);
793 
794     return (farwrite(handle, (byte far *)buf, OMSG_SIZE) == OMSG_SIZE);
795 }
796 
read_hdrinfo(int handle,JAMHDRINFO * HdrInfo)797 int read_hdrinfo(int handle, JAMHDRINFO *HdrInfo)
798 {
799    byte buf[HDRINFO_SIZE], *pbuf = buf;
800 
801    if (farread(handle, (byte far *)buf, HDRINFO_SIZE) != HDRINFO_SIZE) {
802       return 0;
803    } /* endif */
804 
805    /* 04 bytes Signature */
806    memmove(HdrInfo->Signature, pbuf, (size_t)4);
807    pbuf += 4;
808 
809    /* 04 bytes DateCreated */
810    HdrInfo->DateCreated = get_dword(pbuf);
811    pbuf += 4;
812 
813    /* 04 bytes ModCounter */
814    HdrInfo->ModCounter = get_dword(pbuf);
815    pbuf += 4;
816 
817    /* 04 bytes ActiveMsgs */
818    HdrInfo->ActiveMsgs = get_dword(pbuf);
819    pbuf += 4;
820 
821    /* 04 bytes PasswordCRC */
822    HdrInfo->PasswordCRC = get_dword(pbuf);
823    pbuf += 4;
824 
825    /* 04 bytes BaseMsgNum */
826    HdrInfo->BaseMsgNum = get_dword(pbuf);
827    pbuf += 4;
828 
829    /* 04 bytes highwater */
830    HdrInfo->highwater = get_dword(pbuf);
831    pbuf += 4;
832 
833    /* 996 bytes RSRVD */
834    memmove(HdrInfo->RSRVD, pbuf, (size_t)996);
835    pbuf += 996;
836 
837    assert(pbuf - buf == HDRINFO_SIZE);
838 
839    return 1;
840 }
841 
read_idx(int handle,JAMIDXREC * Idx)842 int read_idx(int handle, JAMIDXREC *Idx)
843 {
844    byte buf[IDX_SIZE], *pbuf = buf;
845 
846    if (farread(handle, (byte far *)buf, IDX_SIZE) != IDX_SIZE) {
847       return 0;
848    } /* endif */
849 
850    /* 04 bytes UserCRC */
851    Idx->UserCRC = get_dword(pbuf);
852    pbuf += 4;
853 
854    /* 04 bytes HdrOffset */
855    Idx->HdrOffset = get_dword(pbuf);
856    pbuf += 4;
857 
858    assert(pbuf - buf == IDX_SIZE);
859 
860    return 1;
861 }
862 
decode_hdr(byte * pbuf,JAMHDR * Hdr)863 static void decode_hdr(byte *pbuf, JAMHDR *Hdr)
864 {
865    /* 04 bytes Signature */
866    memmove(Hdr->Signature, pbuf, (size_t)4);
867    pbuf += 4;
868 
869    /* 02 bytes Revision */
870    Hdr->Revision = get_word(pbuf);
871    pbuf += 2;
872 
873    /* 02 bytes ReservedWord */
874    Hdr->ReservedWord = get_word(pbuf);
875    pbuf += 2;
876 
877    /* 04 bytes SubfieldLen */
878    Hdr->SubfieldLen = get_dword(pbuf);
879    pbuf += 4;
880 
881    /* 04 bytes TimesRead */
882    Hdr->TimesRead = get_dword(pbuf);
883    pbuf += 4;
884 
885    /* 04 bytes MsgIdCRC */
886    Hdr->MsgIdCRC = get_dword(pbuf);
887    pbuf += 4;
888 
889    /* 04 bytes ReplyCRC */
890    Hdr->ReplyCRC = get_dword(pbuf);
891    pbuf += 4;
892 
893    /* 04 bytes ReplyTo */
894    Hdr->ReplyTo = get_dword(pbuf);
895    pbuf += 4;
896 
897    /* 04 bytes Reply1st */
898    Hdr->Reply1st = get_dword(pbuf);
899    pbuf += 4;
900 
901    /* 04 bytes ReplyNext */
902    Hdr->ReplyNext = get_dword(pbuf);
903    pbuf += 4;
904 
905    /* 04 bytes DateWritten */
906    Hdr->DateWritten = get_dword(pbuf);
907    pbuf += 4;
908 
909    /* 04 bytes DateReceived */
910    Hdr->DateReceived = get_dword(pbuf);
911    pbuf += 4;
912 
913    /* 04 bytes DateProcessed */
914    Hdr->DateProcessed = get_dword(pbuf);
915    pbuf += 4;
916 
917    /* 04 bytes MsgNum */
918    Hdr->MsgNum = get_dword(pbuf);
919    pbuf += 4;
920 
921    /* 04 bytes Attribute */
922    Hdr->Attribute = get_dword(pbuf);
923    pbuf += 4;
924 
925    /* 04 bytes Attribute2 */
926    Hdr->Attribute2 = get_dword(pbuf);
927    pbuf += 4;
928 
929    /* 04 bytes TxtOffset */
930    Hdr->TxtOffset = get_dword(pbuf);
931    pbuf += 4;
932 
933    /* 04 bytes TxtLen */
934    Hdr->TxtLen = get_dword(pbuf);
935    pbuf += 4;
936 
937    /* 04 bytes PasswordCRC */
938    Hdr->PasswordCRC = get_dword(pbuf);
939    pbuf += 4;
940 
941    /* 04 bytes Cost */
942    Hdr->Cost = get_dword(pbuf);
943 }
944 
read_hdr(int handle,JAMHDR * Hdr)945 int read_hdr(int handle, JAMHDR *Hdr)
946 {
947    byte buf[HDR_SIZE];
948 
949    if (farread(handle, (byte far *)buf, HDR_SIZE) != HDR_SIZE) {
950       return 0;
951    } /* endif */
952 
953    decode_hdr(buf, Hdr);
954 
955    return 1;
956 }
957 
copy_subfield(JAMSUBFIELD2LISTptr * to,JAMSUBFIELD2LISTptr from)958 int copy_subfield(JAMSUBFIELD2LISTptr *to, JAMSUBFIELD2LISTptr from)
959 {
960    dword i;
961 
962    *to = palloc(from->arraySize);
963    if (*to == NULL) return 1;
964    memcpy(*to, from, from->arraySize);
965    for (i=0; i<from->subfieldCount; i++)
966      to[0]->subfield[i].Buffer+=((char *)*to-(char *)from);
967    return 0;
968 }
969 
970 /* Define DEBUG to catch more weirdness in databases */
decode_subfield(byte * buf,JAMSUBFIELD2LISTptr * subfield,dword * SubfieldLen)971 static void decode_subfield(byte *buf, JAMSUBFIELD2LISTptr *subfield, dword *SubfieldLen)
972 {
973    JAMSUBFIELD2ptr subfieldNext;
974    dword datlen;
975    unsigned int count, len;
976    byte *pbuf, *limit;
977 
978    pbuf = buf;
979    limit = buf + *SubfieldLen;
980    assert(limit >= buf);
981 
982    count = 0;
983    while (pbuf + JAM_SF_HEADER_SIZE <= limit) {
984       dword size;
985 #ifdef DEBUG
986 	  word loID, hiID;
987 	  loID = get_word(pbuf);
988 	  hiID = get_word(pbuf+2);
989 	  if(!(loID <= JAMSFLD_ENCLINDFILE ||
990 		  loID == JAMSFLD_EMBINDAT ||
991 		  loID >= JAMSFLD_FTSKLUDGE && loID <= JAMSFLD_TZUTCINFO))
992 	  { /* This subfield type is not supported and is most
993 		   probably sign of error in messagebase */
994          printf("SMAPI ERROR: weird subfield type! (%X)\n", (unsigned int)loID);
995         /* Keep going, these fields won't hurt unless they have improper size too */
996 	  }
997 #endif
998 	  size = get_dword(pbuf+4);
999 #ifdef DEBUG
1000 	  if(size == 0 && loID != JAMSFLD_SUBJECT) /* While possible, it isn't normal value */
1001 	  {
1002          printf("SMAPI ERROR: subfield of 0 size! (%X)\n", (unsigned int)loID);
1003 	  }
1004 #endif
1005       if(pbuf + JAM_SF_HEADER_SIZE + size > limit)
1006 		/* it means that subfield claims to be longer
1007 		   than header says. can't be. */
1008 	  { /* just break, ideally there shall be a setting for lax treatment of messagebase */
1009          printf("SMAPI ERROR: wrongly sized subfield occured!\n");
1010 		 break;
1011 	  }
1012 	  if(size >=0xFFFF) /* realistic check: single subfield
1013 						   longer than 64k is not realistic */
1014 	  {
1015          printf("SMAPI ERROR: subfield is suspiciously large! (%lu bytes)\n", (unsigned long)size);
1016 		 break;
1017 	  }
1018       ++count;
1019       pbuf += JAM_SF_HEADER_SIZE + size;
1020    }
1021    len = sizeof(JAMSUBFIELD2LIST)+count*(sizeof(JAMSUBFIELD2)-JAM_SF_HEADER_SIZE+1)+*SubfieldLen;
1022    *subfield = palloc(len);
1023    subfield[0]->arraySize = len;
1024    subfield[0]->subfieldCount = 0;
1025    /* reserve memory for (real count + 1)*JAMSUBFIELD2 */
1026    subfield[0]->subfield[0].Buffer = (byte *)&(subfield[0]->subfield[count+1]);
1027 
1028    subfieldNext = subfield[0]->subfield;
1029    pbuf = buf;
1030 
1031    while ( subfield[0]->subfieldCount < count && pbuf + JAM_SF_HEADER_SIZE <= limit ) {
1032       /* 02 bytes LoID */
1033       subfieldNext->LoID = get_word(pbuf);
1034       pbuf += 2;
1035 
1036       /* 02 bytes HiID */
1037       subfieldNext->HiID = get_word(pbuf);
1038       pbuf += 2;
1039 
1040       /* 04 bytes DatLen */
1041       subfieldNext->DatLen = 0;
1042       subfieldNext->Buffer[0] = '\0';
1043       datlen = get_dword(pbuf);
1044       pbuf += 4;
1045 
1046       subfield[0]->subfieldCount++;
1047 
1048       if (*SubfieldLen - (pbuf - buf) < datlen)
1049           break;
1050       /* DatLen bytes Buffer */
1051       subfieldNext->DatLen = datlen;
1052       memmove(subfieldNext->Buffer, pbuf, datlen);
1053 
1054       /* Set up next element */
1055       assert((byte *)(subfieldNext + 1) < subfield[0]->subfield[0].Buffer);
1056       subfieldNext[1].Buffer = subfieldNext->Buffer + subfieldNext->DatLen + 1;
1057       subfieldNext++;
1058       assert(subfieldNext->Buffer <= (byte *)*subfield + subfield[0]->arraySize);
1059       pbuf += datlen;
1060 
1061    } /* endwhile */
1062 
1063    *SubfieldLen = pbuf - buf;
1064 }
1065 
read_subfield(int handle,JAMSUBFIELD2LISTptr * subfield,dword * SubfieldLen)1066 int read_subfield(int handle, JAMSUBFIELD2LISTptr *subfield, dword *SubfieldLen)
1067 {
1068    byte *buf;
1069 
1070    buf = (byte*)palloc(*SubfieldLen);
1071 
1072    if ((dword)farread(handle, (byte far *)buf, *SubfieldLen) != *SubfieldLen) {
1073       pfree(buf);
1074       return 0;
1075    } /* endif */
1076 
1077    decode_subfield(buf, subfield, SubfieldLen);
1078 
1079    pfree(buf);
1080 
1081    return 1;
1082 }
1083 
read_allidx(JAMBASEptr jmb)1084 int read_allidx(JAMBASEptr jmb)
1085 {
1086    byte  *buf, *pbuf, *hdrbuf = NULL;
1087    JAMACTMSGptr newptr;
1088    JAMHDR  hbuf;
1089    int   len;
1090    dword i, allocated, hlen;
1091    dword offset;
1092 
1093    lseek(jmb->IdxHandle, 0, SEEK_END);
1094    len = tell(jmb->IdxHandle);
1095    lseek(jmb->IdxHandle, 0, SEEK_SET);
1096 
1097    buf = (byte *)palloc(len);
1098    pbuf = buf;
1099 
1100    if (farread(jmb->IdxHandle, (byte far *)buf, len) != len) {
1101       pfree(buf);
1102       return 0;
1103    } /* endif */
1104 
1105    lseek(jmb->HdrHandle, 0, SEEK_END);
1106    hlen = tell(jmb->HdrHandle);
1107    lseek(jmb->HdrHandle, 0, SEEK_SET);
1108    if (hlen<MAXHDRINCORE) {
1109       /* read all headers in core */
1110       hdrbuf = (byte *)palloc(hlen);
1111 
1112       if ((dword)farread(jmb->HdrHandle, (byte far *)hdrbuf, hlen) != hlen) {
1113          pfree(hdrbuf);
1114          pfree(buf);
1115          return 0;
1116       } /* endif */
1117       jmb->actmsg_read = 1;
1118    } else
1119       jmb->actmsg_read = 2;
1120    allocated = jmb->HdrInfo.ActiveMsgs;
1121    if (allocated > (dword)len/IDX_SIZE) allocated = (dword)len/IDX_SIZE;
1122    if (allocated) {
1123       jmb->actmsg = (JAMACTMSGptr)farmalloc(allocated * sizeof(JAMACTMSG));
1124       if (jmb->actmsg == NULL) {
1125          if (hdrbuf) pfree(hdrbuf);
1126          pfree(buf);
1127          return 0;
1128       }
1129    }
1130 
1131    for (i = 0; (pbuf - buf) < len;) {
1132       offset = get_dword(pbuf+4);
1133       if (offset != 0xFFFFFFFFUL) {
1134          if (offset+HDR_SIZE<=hlen) {
1135             if (hdrbuf)
1136                decode_hdr(hdrbuf+offset, &hbuf);
1137             else {
1138                lseek(jmb->HdrHandle, offset, SEEK_SET);
1139                read_hdr(jmb->HdrHandle, &hbuf);
1140             }
1141             if (!(hbuf.Attribute & JMSG_DELETED)) {
1142                if (i >= allocated) {
1143                   newptr = (JAMACTMSGptr)farrealloc(jmb->actmsg, sizeof(JAMACTMSG)*(allocated += 16));
1144                   if (newptr == NULL) {
1145                      pfree(jmb->actmsg);
1146                      if (hdrbuf) pfree(hdrbuf);
1147                      pfree(buf);
1148                      return 0;
1149                   }
1150                   jmb->actmsg = newptr;
1151                }
1152                jmb->actmsg[i].IdxOffset = pbuf - buf;
1153                jmb->actmsg[i].TrueMsg = offset;
1154                jmb->actmsg[i].UserCRC = get_dword(pbuf);
1155                memcpy(&(jmb->actmsg[i].hdr), &hbuf, sizeof(hbuf));
1156                if (hdrbuf && offset+HDR_SIZE+jmb->actmsg[i].hdr.SubfieldLen<=hlen) {
1157                   decode_subfield(hdrbuf+offset+HDR_SIZE, &(jmb->actmsg[i].subfield), &(jmb->actmsg[i].hdr.SubfieldLen));
1158                   i++;
1159                } else
1160                   jmb->actmsg[i++].subfield = NULL;
1161             } /* endif */
1162          } /* endif */
1163       } /* endif */
1164       pbuf += 8;
1165    } /* endfor */
1166 
1167    pfree(buf);
1168    if (hdrbuf) pfree(hdrbuf);
1169 
1170    if (i != jmb->HdrInfo.ActiveMsgs) {
1171       /* warning: database corrupted! */
1172       jmb->HdrInfo.ActiveMsgs = i;
1173       jmb->modified = 1;
1174       if (i == 0) {
1175          if (jmb->actmsg) {
1176             pfree(jmb->actmsg);
1177             jmb->actmsg = NULL;
1178          }
1179       } else if (i != allocated) {
1180          newptr = (JAMACTMSGptr)farrealloc(jmb->actmsg, sizeof(JAMACTMSG)*i);
1181          if (newptr) jmb->actmsg = newptr;
1182       }
1183    } /* endif */
1184 
1185    return 1;
1186 }
1187 
write_hdrinfo(int handle,JAMHDRINFO * HdrInfo)1188 int write_hdrinfo(int handle, JAMHDRINFO *HdrInfo)
1189 {
1190    byte buf[HDRINFO_SIZE], *pbuf = buf;
1191 
1192    /* 04 bytes Signature */
1193    memmove(pbuf, HdrInfo->Signature, (size_t)4);
1194    pbuf += 4;
1195 
1196    /* 04 bytes DateCreated */
1197    put_dword(pbuf, HdrInfo->DateCreated);
1198    pbuf += 4;
1199 
1200    /* 04 bytes ModCounter */
1201    put_dword(pbuf, HdrInfo->ModCounter);
1202    pbuf += 4;
1203 
1204    /* 04 bytes ActiveMsgs */
1205    put_dword(pbuf, HdrInfo->ActiveMsgs);
1206    pbuf += 4;
1207 
1208    /* 04 bytes PasswordCRC */
1209    put_dword(pbuf, HdrInfo->PasswordCRC);
1210    pbuf += 4;
1211 
1212    /* 04 bytes BaseMsgNum */
1213    put_dword(pbuf, HdrInfo->BaseMsgNum);
1214    pbuf += 4;
1215 
1216    /* 04 bytes highwater */
1217    put_dword(pbuf, HdrInfo->highwater);
1218    pbuf += 4;
1219 
1220    /* 996 bytes RSRVD */
1221    memmove(pbuf, HdrInfo->RSRVD, (size_t)996);
1222    pbuf += 996;
1223 
1224    assert(pbuf - buf == HDRINFO_SIZE);
1225 
1226    return (farwrite(handle, (byte far *)buf, HDRINFO_SIZE) == HDRINFO_SIZE);
1227 }
1228 
write_idx(int handle,JAMIDXREC * Idx)1229 int write_idx(int handle, JAMIDXREC *Idx)
1230 {
1231    byte buf[IDX_SIZE], *pbuf = buf;
1232 
1233    /* 04 bytes UserCRC */
1234    put_dword(pbuf, Idx->UserCRC);
1235    pbuf += 4;
1236 
1237    /* 04 bytes HdrOffset */
1238    put_dword(pbuf, Idx->HdrOffset);
1239    pbuf += 4;
1240 
1241    assert(pbuf - buf == IDX_SIZE);
1242 
1243    return (farwrite(handle, (byte far *)buf, IDX_SIZE) == IDX_SIZE);
1244 }
1245 
write_hdr(int handle,JAMHDR * Hdr)1246 int write_hdr(int handle, JAMHDR *Hdr)
1247 {
1248    byte buf[HDR_SIZE], *pbuf = buf;
1249 
1250    /* 04 bytes Signature */
1251    memmove(pbuf, Hdr->Signature, (size_t)4);
1252    pbuf += 4;
1253 
1254    /* 02 bytes Revision */
1255    put_word(pbuf, Hdr->Revision);
1256    pbuf += 2;
1257 
1258    /* 02 bytes ReservedWord */
1259    put_word(pbuf, Hdr->ReservedWord);
1260    pbuf += 2;
1261 
1262    /* 04 bytes SubfieldLen */
1263    put_dword(pbuf, Hdr->SubfieldLen);
1264    pbuf += 4;
1265 
1266    /* 04 bytes TimesRead */
1267    put_dword(pbuf, Hdr->TimesRead);
1268    pbuf += 4;
1269 
1270    /* 04 bytes MsgIdCRC */
1271    put_dword(pbuf, Hdr->MsgIdCRC);
1272    pbuf += 4;
1273 
1274    /* 04 bytes ReplyCRC */
1275    put_dword(pbuf, Hdr->ReplyCRC);
1276    pbuf += 4;
1277 
1278    /* 04 bytes ReplyTo */
1279    put_dword(pbuf, Hdr->ReplyTo);
1280    pbuf += 4;
1281 
1282    /* 04 bytes Reply1st */
1283    put_dword(pbuf, Hdr->Reply1st);
1284    pbuf += 4;
1285 
1286    /* 04 bytes ReplyNext */
1287    put_dword(pbuf, Hdr->ReplyNext);
1288    pbuf += 4;
1289 
1290    /* 04 bytes DateWritten */
1291    put_dword(pbuf, Hdr->DateWritten);
1292    pbuf += 4;
1293 
1294    /* 04 bytes DateReceived */
1295    put_dword(pbuf, Hdr->DateReceived);
1296    pbuf += 4;
1297 
1298    /* 04 bytes DateProcessed */
1299    put_dword(pbuf, Hdr->DateProcessed);
1300    pbuf += 4;
1301 
1302    /* 04 bytes MsgNum */
1303    put_dword(pbuf, Hdr->MsgNum);
1304    pbuf += 4;
1305 
1306    /* 04 bytes Attribute */
1307    put_dword(pbuf, Hdr->Attribute);
1308    pbuf += 4;
1309 
1310    /* 04 bytes Attribute2 */
1311    put_dword(pbuf, Hdr->Attribute2);
1312    pbuf += 4;
1313 
1314    /* 04 bytes TxtOffset */
1315    put_dword(pbuf, Hdr->TxtOffset);
1316    pbuf += 4;
1317 
1318    /* 04 bytes TxtLen */
1319    put_dword(pbuf, Hdr->TxtLen);
1320    pbuf += 4;
1321 
1322    /* 04 bytes PasswordCRC */
1323    put_dword(pbuf, Hdr->PasswordCRC);
1324    pbuf += 4;
1325 
1326    /* 04 bytes Cost */
1327    put_dword(pbuf, Hdr->Cost);
1328    pbuf += 4;
1329 
1330    assert(pbuf - buf == HDR_SIZE);
1331 
1332    return (farwrite(handle, (byte far *)buf, HDR_SIZE) == HDR_SIZE);
1333 }
1334 
write_subfield(int handle,JAMSUBFIELD2LISTptr * subfield,dword SubfieldLen)1335 int write_subfield(int handle, JAMSUBFIELD2LISTptr *subfield, dword SubfieldLen)
1336 {
1337    unsigned char *buf, *pbuf;
1338    dword datlen;
1339    int rc;
1340    dword i;
1341    JAMSUBFIELD2ptr subfieldNext;
1342 
1343    buf = (unsigned char*)palloc(SubfieldLen);
1344    pbuf = buf;
1345    subfieldNext = &(subfield[0]->subfield[0]);
1346    for (i=0; i<subfield[0]->subfieldCount; i++, subfieldNext++) {
1347       /* 02 bytes LoID */
1348       put_word(pbuf, subfieldNext->LoID);
1349       pbuf += 2;
1350       /* 02 bytes HiID */
1351       put_word(pbuf, subfieldNext->HiID);
1352       pbuf += 2;
1353       /* 04 bytes DatLen */
1354       put_dword(pbuf, subfieldNext->DatLen);
1355 
1356       datlen = subfieldNext->DatLen;
1357       pbuf += 4;
1358       /* DatLen bytes Buffer */
1359       memmove(pbuf, subfieldNext->Buffer, datlen);
1360       pbuf += datlen;
1361    } /* endwhile */
1362    rc =((dword)farwrite(handle, (byte far *)buf, SubfieldLen) == SubfieldLen);
1363 
1364    pfree(buf);
1365 
1366    return rc;
1367 }
1368