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