|
|
1.1 root 1: /* SMBLIB.C */
2:
3: /* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
4:
5: #include "smblib.h"
6: #include "lzh.h"
7:
8: int SMBCALL smb_ver(void)
9: {
10: return(SMB_VERSION);
11: }
12:
13: char * SMBCALL smb_lib_ver(void)
14: {
15: return(SMBLIB_VERSION);
16: }
17:
18: /****************************************************************************/
19: /* Open a message base of name 'smb->file' */
20: /* Opens files for READing messages or updating message indices only */
21: /****************************************************************************/
22: int SMBCALL smb_open(smb_t *smb)
23: {
24: int file;
25: char str[128];
26: smbhdr_t hdr;
27:
28: if(!smb->retry_time)
29: smb->retry_time=10;
30: smb->shd_fp=smb->sdt_fp=smb->sid_fp=NULL;
31: sprintf(str,"%s.SHD",smb->file);
32: if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYNO,S_IWRITE|S_IREAD))==-1
33: || (smb->shd_fp=fdopen(file,"r+b"))==NULL) {
34: if(file!=-1)
35: close(file);
36: return(2); }
37:
38: if(filelength(file)>=sizeof(smbhdr_t)) {
39: setvbuf(smb->shd_fp,smb->shd_buf,_IONBF,SHD_BLOCK_LEN);
40: if(smb_locksmbhdr(smb)) {
41: smb_close(smb);
42: return(-1); }
43: memset(&hdr,0,sizeof(smbhdr_t));
44: fread(&hdr,sizeof(smbhdr_t),1,smb->shd_fp);
45: if(memcmp(hdr.id,"SMB\x1a",4)) {
46: smb_close(smb);
47: return(-2); }
48: if(hdr.version<0x110) { /* Compatibility check */
49: smb_close(smb);
50: return(-3); }
51: if(fread(&(smb->status),1,sizeof(smbstatus_t),smb->shd_fp)
52: !=sizeof(smbstatus_t)) {
53: smb_close(smb);
54: return(-4); }
55: smb_unlocksmbhdr(smb);
56: rewind(smb->shd_fp); }
57:
58: setvbuf(smb->shd_fp,smb->shd_buf,_IOFBF,SHD_BLOCK_LEN);
59:
60: sprintf(str,"%s.SDT",smb->file);
61: if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYNO,S_IWRITE|S_IREAD))==-1
62: || (smb->sdt_fp=fdopen(file,"r+b"))==NULL) {
63: if(file!=-1)
64: close(file);
65: smb_close(smb);
66: return(1); }
67: setvbuf(smb->sdt_fp,NULL,_IOFBF,2*1024);
68:
69: sprintf(str,"%s.SID",smb->file);
70: if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYNO,S_IWRITE|S_IREAD))==-1
71: || (smb->sid_fp=fdopen(file,"r+b"))==NULL) {
72: if(file!=-1)
73: close(file);
74: smb_close(smb);
75: return(3); }
76: setvbuf(smb->sid_fp,NULL,_IOFBF,2*1024);
77:
78: return(0);
79: }
80:
81: /****************************************************************************/
82: /* Closes the currently open message base */
83: /****************************************************************************/
84: void SMBCALL smb_close(smb_t *smb)
85: {
86: if(smb->shd_fp!=NULL) {
87: smb_unlocksmbhdr(smb); /* In case it's been locked */
88: fclose(smb->shd_fp); }
89: if(smb->sid_fp!=NULL)
90: fclose(smb->sid_fp);
91: if(smb->sdt_fp!=NULL)
92: fclose(smb->sdt_fp);
93: smb->sid_fp=smb->shd_fp=smb->sdt_fp=NULL;
94: }
95:
96: /****************************************************************************/
97: /* Opens the data block allocation table message base 'smb->file' */
98: /* Retrys for retry_time number of seconds */
99: /* Return 0 on success, non-zero otherwise */
100: /****************************************************************************/
101: int SMBCALL smb_open_da(smb_t *smb)
102: {
103: int file;
104: char str[128];
105: ulong start=0;
106:
107: sprintf(str,"%s.SDA",smb->file);
108: while(1) {
109: if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYRW,S_IWRITE|S_IREAD))!=-1)
110: break;
111: if(errno!=EACCES)
112: return(-1);
113: if(!start)
114: start=time(NULL);
115: else
116: if(time(NULL)-start>=smb->retry_time)
117: return(-2); }
118: if((smb->sda_fp=fdopen(file,"r+b"))==NULL) {
119: close(file);
120: return(-3); }
121: setvbuf(smb->sda_fp,NULL,_IOFBF,2*1024);
122: return(0);
123: }
124:
125: void SMBCALL smb_close_da(smb_t *smb)
126: {
127: if(smb->sda_fp!=NULL)
128: fclose(smb->sda_fp);
129: smb->sda_fp=NULL;
130: }
131:
132: /****************************************************************************/
133: /* Opens the header block allocation table for message base 'smb.file' */
134: /* Retrys for smb.retry_time number of seconds */
135: /* Return 0 on success, non-zero otherwise */
136: /****************************************************************************/
137: int SMBCALL smb_open_ha(smb_t *smb)
138: {
139: int file;
140: char str[128];
141: ulong start=0;
142:
143: sprintf(str,"%s.SHA",smb->file);
144: while(1) {
145: if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYRW,S_IWRITE|S_IREAD))!=-1)
146: break;
147: if(errno!=EACCES)
148: return(-1);
149: if(!start)
150: start=time(NULL);
151: else
152: if(time(NULL)-start>=smb->retry_time)
153: return(-2); }
154: if((smb->sha_fp=fdopen(file,"r+b"))==NULL) {
155: close(file);
156: return(-3); }
157: setvbuf(smb->sha_fp,NULL,_IOFBF,2*1024);
158: return(0);
159: }
160:
161: void SMBCALL smb_close_ha(smb_t *smb)
162: {
163: if(smb->sha_fp!=NULL)
164: fclose(smb->sha_fp);
165: smb->sha_fp=NULL;
166: }
167:
168:
169: /****************************************************************************/
170: /* If the parameter 'push' is non-zero, this function stores the currently */
171: /* open message base to the "virtual" smb stack. Up to SMB_STACK_LEN */
172: /* message bases may be stored (defined in SMBDEFS.H). */
173: /* The parameter 'op' is the operation to perform on the stack. Either */
174: /* SMB_STACK_PUSH, SMB_STACK_POP, or SMB_STACK_XCHNG */
175: /* If the operation is SMB_STACK_POP, this function restores a message base */
176: /* previously saved with a SMB_STACK_PUSH call to this same function. */
177: /* If the operation is SMB_STACK_XCHNG, then the current message base is */
178: /* exchanged with the message base on the top of the stack (most recently */
179: /* pushed. */
180: /* If the current message base is not open, the SMB_STACK_PUSH and */
181: /* SMB_STACK_XCHNG operations do nothing */
182: /* Returns 0 on success, non-zero if stack full. */
183: /* If operation is SMB_STACK_POP or SMB_STACK_XCHNG, it always returns 0. */
184: /****************************************************************************/
185: int SMBCALL smb_stack(smb_t *smb, int op)
186: {
187: static char stack_file[SMB_STACK_LEN][128];
188: static FILE *stack_sdt[SMB_STACK_LEN],
189: *stack_shd[SMB_STACK_LEN],
190: *stack_sid[SMB_STACK_LEN],
191: *stack_sda[SMB_STACK_LEN],
192: *stack_sha[SMB_STACK_LEN];
193: static int stack_idx;
194: char tmp_file[128];
195: FILE *tmp_sdt,
196: *tmp_shd,
197: *tmp_sid,
198: *tmp_sda,
199: *tmp_sha;
200:
201: if(op==SMB_STACK_PUSH) {
202: if(stack_idx>=SMB_STACK_LEN)
203: return(1);
204: if(smb->shd_fp==NULL || smb->sdt_fp==NULL || smb->sid_fp==NULL)
205: return(0); /* Msg base not open */
206: memcpy(stack_file[stack_idx],smb->file,128);
207: stack_sdt[stack_idx]=smb->sdt_fp;
208: stack_shd[stack_idx]=smb->shd_fp;
209: stack_sid[stack_idx]=smb->sid_fp;
210: stack_sda[stack_idx]=smb->sda_fp;
211: stack_sha[stack_idx]=smb->sha_fp;
212: stack_idx++;
213: return(0); }
214: /* pop or xchng */
215: if(!stack_idx) /* Nothing on the stack, so do nothing */
216: return(0);
217: if(op==SMB_STACK_XCHNG) {
218: if(!smb->shd_fp)
219: return(0);
220: memcpy(tmp_file,smb->file,128);
221: tmp_sdt=smb->sdt_fp;
222: tmp_shd=smb->shd_fp;
223: tmp_sid=smb->sid_fp;
224: tmp_sda=smb->sda_fp;
225: tmp_sha=smb->sha_fp; }
226:
227: stack_idx--;
228: memcpy(smb->file,stack_file[stack_idx],128);
229: smb->sdt_fp=stack_sdt[stack_idx];
230: smb->shd_fp=stack_shd[stack_idx];
231: smb->sid_fp=stack_sid[stack_idx];
232: smb->sda_fp=stack_sda[stack_idx];
233: smb->sha_fp=stack_sha[stack_idx];
234: if(op==SMB_STACK_XCHNG) {
235: stack_idx++;
236: memcpy(stack_file[stack_idx-1],tmp_file,128);
237: stack_sdt[stack_idx-1]=tmp_sdt;
238: stack_shd[stack_idx-1]=tmp_shd;
239: stack_sid[stack_idx-1]=tmp_sid;
240: stack_sda[stack_idx-1]=tmp_sda;
241: stack_sha[stack_idx-1]=tmp_sha; }
242: return(0);
243: }
244:
245: /****************************************************************************/
246: /* Truncates header file */
247: /* Retrys for smb.retry_time number of seconds */
248: /* Return 0 on success, non-zero otherwise */
249: /****************************************************************************/
250: int SMBCALL smb_trunchdr(smb_t *smb)
251: {
252: ulong start=0;
253:
254: rewind(smb->shd_fp);
255: while(1) {
256: if(!chsize(fileno(smb->shd_fp),0L))
257: break;
258: if(errno!=EACCES)
259: return(-1);
260: if(!start)
261: start=time(NULL);
262: else
263: if(time(NULL)-start>=smb->retry_time) /* Time-out */
264: return(-2); }
265: return(0);
266: }
267:
268: /*********************************/
269: /* Message Base Header Functions */
270: /*********************************/
271:
272: /****************************************************************************/
273: /* Attempts for smb.retry_time number of seconds to lock the msg base hdr */
274: /****************************************************************************/
275: int SMBCALL smb_locksmbhdr(smb_t *smb)
276: {
277: ulong start=0;
278:
279: while(1) {
280: if(!lock(fileno(smb->shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t)))
281: return(0);
282: if(!start)
283: start=time(NULL);
284: else
285: if(time(NULL)-start>=smb->retry_time)
286: break; /* Incase we've already locked it */
287: unlock(fileno(smb->shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t)); }
288: return(-1);
289: }
290:
291: /****************************************************************************/
292: /* Read the SMB header from the header file and place into smb.status */
293: /****************************************************************************/
294: int SMBCALL smb_getstatus(smb_t *smb)
295: {
296: int i;
297:
298: setvbuf(smb->shd_fp,smb->shd_buf,_IONBF,SHD_BLOCK_LEN);
299: clearerr(smb->shd_fp);
300: fseek(smb->shd_fp,sizeof(smbhdr_t),SEEK_SET);
301: i=fread(&(smb->status),1,sizeof(smbstatus_t),smb->shd_fp);
302: setvbuf(smb->shd_fp,smb->shd_buf,_IOFBF,SHD_BLOCK_LEN);
303: if(i==sizeof(smbstatus_t))
304: return(0);
305: return(1);
306: }
307:
308: /****************************************************************************/
309: /* Writes message base header */
310: /****************************************************************************/
311: int SMBCALL smb_putstatus(smb_t *smb)
312: {
313: int i;
314:
315: clearerr(smb->shd_fp);
316: fseek(smb->shd_fp,sizeof(smbhdr_t),SEEK_SET);
317: i=fwrite(&(smb->status),1,sizeof(smbstatus_t),smb->shd_fp);
318: fflush(smb->shd_fp);
319: if(i==sizeof(smbstatus_t))
320: return(0);
321: return(1);
322: }
323:
324: /****************************************************************************/
325: /* Unlocks previously locks message base header */
326: /****************************************************************************/
327: int SMBCALL smb_unlocksmbhdr(smb_t *smb)
328: {
329: return(unlock(fileno(smb->shd_fp),0L,sizeof(smbhdr_t)+sizeof(smbstatus_t)));
330: }
331:
332: /********************************/
333: /* Individual Message Functions */
334: /********************************/
335:
336: /****************************************************************************/
337: /* Attempts for smb.retry_time number of seconds to lock the hdr for 'msg' */
338: /****************************************************************************/
339: int SMBCALL smb_lockmsghdr(smb_t *smb, smbmsg_t *msg)
340: {
341: ulong start=0;
342:
343: while(1) {
344: if(!lock(fileno(smb->shd_fp),msg->idx.offset,sizeof(msghdr_t)))
345: return(0);
346: if(!start)
347: start=time(NULL);
348: else
349: if(time(NULL)-start>=smb->retry_time)
350: break;
351: unlock(fileno(smb->shd_fp),msg->idx.offset,sizeof(msghdr_t)); }
352: return(-1);
353: }
354:
355: /****************************************************************************/
356: /* Fills msg->idx with message index based on msg->hdr.number */
357: /* OR if msg->hdr.number is 0, based on msg->offset (record offset). */
358: /* if msg.hdr.number does not equal 0, then msg->offset is filled too. */
359: /* Either msg->hdr.number or msg->offset must be initialized before */
360: /* calling this function */
361: /* Returns 1 if message number wasn't found, 0 if it was */
362: /****************************************************************************/
363: int SMBCALL smb_getmsgidx(smb_t *smb, smbmsg_t *msg)
364: {
365: idxrec_t idx;
366: ulong l,length,total,bot,top;
367:
368: clearerr(smb->sid_fp);
369: if(!msg->hdr.number) {
370: fseek(smb->sid_fp,msg->offset*sizeof(idxrec_t),SEEK_SET);
371: if(!fread(&msg->idx,sizeof(idxrec_t),1,smb->sid_fp))
372: return(1);
373: return(0); }
374:
375: length=filelength(fileno(smb->sid_fp));
376: if(!length)
377: return(1);
378: total=length/sizeof(idxrec_t);
379: if(!total)
380: return(1);
381:
382: bot=0;
383: top=total;
384: l=total/2; /* Start at middle index */
385: while(1) {
386: fseek(smb->sid_fp,l*sizeof(idxrec_t),SEEK_SET);
387: if(!fread(&idx,sizeof(idxrec_t),1,smb->sid_fp))
388: return(1);
389: if(bot==top-1 && idx.number!=msg->hdr.number)
390: return(1);
391: if(idx.number>msg->hdr.number) {
392: top=l;
393: l=bot+((top-bot)/2);
394: continue; }
395: if(idx.number<msg->hdr.number) {
396: bot=l;
397: l=top-((top-bot)/2);
398: continue; }
399: break; }
400: msg->idx=idx;
401: msg->offset=l;
402: return(0);
403: }
404:
405: /****************************************************************************/
406: /* Reads the last index record in the open message base */
407: /****************************************************************************/
408: int SMBCALL smb_getlastidx(smb_t *smb, idxrec_t *idx)
409: {
410: long length;
411:
412: clearerr(smb->sid_fp);
413: length=filelength(fileno(smb->sid_fp));
414: if(length<sizeof(idxrec_t))
415: return(-1);
416: fseek(smb->sid_fp,length-sizeof(idxrec_t),SEEK_SET);
417: if(!fread(idx,sizeof(idxrec_t),1,smb->sid_fp))
418: return(-2);
419: return(0);
420: }
421:
422: /****************************************************************************/
423: /* Figures out the total length of the header record for 'msg' */
424: /* Returns length */
425: /****************************************************************************/
426: uint SMBCALL smb_getmsghdrlen(smbmsg_t *msg)
427: {
428: int i;
429:
430: /* fixed portion */
431: msg->hdr.length=sizeof(msghdr_t);
432: /* data fields */
433: msg->hdr.length+=msg->hdr.total_dfields*sizeof(dfield_t);
434: /* header fields */
435: for(i=0;i<msg->total_hfields;i++) {
436: msg->hdr.length+=sizeof(hfield_t);
437: msg->hdr.length+=msg->hfield[i].length; }
438: return(msg->hdr.length);
439: }
440:
441: /****************************************************************************/
442: /* Figures out the total length of the data buffer for 'msg' */
443: /* Returns length */
444: /****************************************************************************/
445: ulong SMBCALL smb_getmsgdatlen(smbmsg_t *msg)
446: {
447: int i;
448: ulong length=0L;
449:
450: for(i=0;i<msg->hdr.total_dfields;i++)
451: length+=msg->dfield[i].length;
452: return(length);
453: }
454:
455: /****************************************************************************/
456: /* Read header information into 'msg' structure */
457: /* msg->idx.offset must be set before calling this function */
458: /* Must call smb_freemsgmem() to free memory allocated for var len strs */
459: /* Returns 0 on success, non-zero if error */
460: /****************************************************************************/
461: int SMBCALL smb_getmsghdr(smb_t *smb, smbmsg_t *msg)
462: {
463: void *vp,**vpp;
464: ushort i;
465: ulong l,offset;
466: idxrec_t idx;
467:
468: rewind(smb->shd_fp);
469: fseek(smb->shd_fp,msg->idx.offset,SEEK_SET);
470: idx=msg->idx;
471: offset=msg->offset;
472: memset(msg,0,sizeof(smbmsg_t));
473: msg->idx=idx;
474: msg->offset=offset;
475: if(!fread(&msg->hdr,sizeof(msghdr_t),1,smb->shd_fp))
476: return(-1);
477: if(memcmp(msg->hdr.id,"SHD\x1a",4))
478: return(-2);
479: if(msg->hdr.version<0x110)
480: return(-9);
481: l=sizeof(msghdr_t);
482: if(msg->hdr.total_dfields && (msg->dfield
483: =(dfield_t *)MALLOC(sizeof(dfield_t)*msg->hdr.total_dfields))==NULL) {
484: smb_freemsgmem(msg);
485: return(-3); }
486: i=0;
487: while(i<msg->hdr.total_dfields && l<msg->hdr.length) {
488: if(!fread(&msg->dfield[i],sizeof(dfield_t),1,smb->shd_fp)) {
489: smb_freemsgmem(msg);
490: return(-4); }
491: i++;
492: l+=sizeof(dfield_t); }
493: if(i<msg->hdr.total_dfields) {
494: smb_freemsgmem(msg);
495: return(-8); }
496:
497: while(l<msg->hdr.length) {
498: i=msg->total_hfields;
499: if((vpp=(void **)REALLOC(msg->hfield_dat,sizeof(void *)*(i+1)))==NULL) {
500: smb_freemsgmem(msg);
501: return(-3); }
502: msg->hfield_dat=vpp;
503: if((vp=(hfield_t *)REALLOC(msg->hfield,sizeof(hfield_t)*(i+1)))==NULL) {
504: smb_freemsgmem(msg);
505: return(-3); }
506: msg->hfield=vp;
507: msg->total_hfields++;
508: if(!fread(&msg->hfield[i],sizeof(hfield_t),1,smb->shd_fp)) {
509: smb_freemsgmem(msg);
510: return(-5); }
511: l+=sizeof(hfield_t);
512: if((msg->hfield_dat[i]=(char *)MALLOC(msg->hfield[i].length+1))
513: ==NULL) { /* Allocate 1 extra for NULL terminator */
514: smb_freemsgmem(msg); /* or 0 length field */
515: return(-3); }
516: memset(msg->hfield_dat[i],0,msg->hfield[i].length+1); /* init to NULL */
517: if(msg->hfield[i].length
518: && !fread(msg->hfield_dat[i],msg->hfield[i].length,1,smb->shd_fp)) {
519: smb_freemsgmem(msg);
520: return(-6); }
521:
522: switch(msg->hfield[i].type) { /* convenience variables */
523: case SENDER:
524: if(!msg->from) {
525: msg->from=msg->hfield_dat[i];
526: break; }
527: case FORWARDED: /* fall through */
528: msg->forwarded=1;
529: break;
530: case SENDERAGENT:
531: if(!msg->forwarded)
532: msg->from_agent=*(ushort *)msg->hfield_dat[i];
533: break;
534: case SENDEREXT:
535: if(!msg->forwarded)
536: msg->from_ext=msg->hfield_dat[i];
537: break;
538: case SENDERNETTYPE:
539: if(!msg->forwarded)
540: msg->from_net.type=*(ushort *)msg->hfield_dat[i];
541: break;
542: case SENDERNETADDR:
543: if(!msg->forwarded)
544: msg->from_net.addr=msg->hfield_dat[i];
545: break;
546: case REPLYTO:
547: msg->replyto=msg->hfield_dat[i];
548: break;
549: case REPLYTOEXT:
550: msg->replyto_ext=msg->hfield_dat[i];
551: break;
552: case REPLYTOAGENT:
553: msg->replyto_agent=*(ushort *)msg->hfield_dat[i];
554: break;
555: case REPLYTONETTYPE:
556: msg->replyto_net.type=*(ushort *)msg->hfield_dat[i];
557: break;
558: case REPLYTONETADDR:
559: msg->replyto_net.addr=msg->hfield_dat[i];
560: break;
561: case RECIPIENT:
562: msg->to=msg->hfield_dat[i];
563: break;
564: case RECIPIENTEXT:
565: msg->to_ext=msg->hfield_dat[i];
566: break;
567: case RECIPIENTAGENT:
568: msg->to_agent=*(ushort *)msg->hfield_dat[i];
569: break;
570: case RECIPIENTNETTYPE:
571: msg->to_net.type=*(ushort *)msg->hfield_dat[i];
572: break;
573: case RECIPIENTNETADDR:
574: msg->to_net.addr=msg->hfield_dat[i];
575: break;
576: case SUBJECT:
577: msg->subj=msg->hfield_dat[i];
578: break; }
579: l+=msg->hfield[i].length; }
580:
581: if(!msg->from || !msg->to || !msg->subj) {
582: smb_freemsgmem(msg);
583: return(-7); }
584: return(0);
585: }
586:
587: /****************************************************************************/
588: /* Frees memory allocated for 'msg' */
589: /****************************************************************************/
590: void SMBCALL smb_freemsgmem(smbmsg_t *msg)
591: {
592: ushort i;
593:
594: if(msg->dfield)
595: FREE(msg->dfield);
596: for(i=0;i<msg->total_hfields;i++)
597: if(msg->hfield_dat[i])
598: FREE(msg->hfield_dat[i]);
599: if(msg->hfield)
600: FREE(msg->hfield);
601: if(msg->hfield_dat)
602: FREE(msg->hfield_dat);
603: }
604:
605: /****************************************************************************/
606: /* Unlocks header for 'msg' */
607: /****************************************************************************/
608: int SMBCALL smb_unlockmsghdr(smb_t *smb, smbmsg_t *msg)
609: {
610: return(unlock(fileno(smb->shd_fp),msg->idx.offset,sizeof(msghdr_t)));
611: }
612:
613:
614: /****************************************************************************/
615: /* Adds a header field to the 'msg' structure (in memory only) */
616: /****************************************************************************/
617: int SMBCALL smb_hfield(smbmsg_t *msg, ushort type, ushort length, void *data)
618: {
619: void *vp,**vpp;
620: int i;
621:
622: i=msg->total_hfields;
623: if((vp=(hfield_t *)REALLOC(msg->hfield,sizeof(hfield_t)*(i+1)))==NULL)
624: return(1);
625: msg->hfield=vp;
626: if((vpp=(void **)REALLOC(msg->hfield_dat,sizeof(void *)*(i+1)))==NULL)
627: return(2);
628: msg->hfield_dat=vpp;
629: msg->total_hfields++;
630: msg->hfield[i].type=type;
631: msg->hfield[i].length=length;
632: if(length) {
633: if((msg->hfield_dat[i]=(void *)MALLOC(length))==NULL)
634: return(4);
635: memcpy(msg->hfield_dat[i],data,length); }
636: else
637: msg->hfield_dat[i]=NULL;
638: return(0);
639: }
640:
641: /****************************************************************************/
642: /* Adds a data field to the 'msg' structure (in memory only) */
643: /* Automatically figures out the offset into the data buffer from existing */
644: /* dfield lengths */
645: /****************************************************************************/
646: int SMBCALL smb_dfield(smbmsg_t *msg, ushort type, ulong length)
647: {
648: void *vp;
649: int i,j;
650:
651: i=msg->hdr.total_dfields;
652: if((vp=(dfield_t *)REALLOC(msg->dfield,sizeof(dfield_t)*(i+1)))==NULL)
653: return(1);
654: msg->dfield=vp;
655: msg->hdr.total_dfields++;
656: msg->dfield[i].type=type;
657: msg->dfield[i].length=length;
658: for(j=msg->dfield[i].offset=0;j<i;j++)
659: msg->dfield[i].offset+=msg->dfield[j].length;
660: return(0);
661: }
662:
663: /****************************************************************************/
664: /* Checks CRC history file for duplicate crc. If found, returns 1. */
665: /* If no dupe, adds to CRC history and returns 0, or negative if error. */
666: /****************************************************************************/
667: int SMBCALL smb_addcrc(smb_t *smb, ulong crc)
668: {
669: char str[128];
670: int file;
671: long length;
672: ulong l,*buf;
673: ulong start=0;
674:
675: if(!smb->status.max_crcs)
676: return(0);
677:
678: sprintf(str,"%s.SCH",smb->file);
679: while(1) {
680: if((file=sopen(str,O_RDWR|O_CREAT|O_BINARY,SH_DENYRW,S_IWRITE|S_IREAD))!=-1)
681: break;
682: if(errno!=EACCES)
683: return(-1);
684: if(!start)
685: start=time(NULL);
686: else
687: if(time(NULL)-start>=smb->retry_time)
688: return(-2); }
689:
690: length=filelength(file);
691: if(length<0L) {
692: close(file);
693: return(-4); }
694: if((buf=(ulong *)MALLOC(smb->status.max_crcs*4))==NULL) {
695: close(file);
696: return(-3); }
697: if(length>=smb->status.max_crcs*4) { /* Reached or exceeds max crcs */
698: read(file,buf,smb->status.max_crcs*4);
699: for(l=0;l<smb->status.max_crcs;l++)
700: if(crc==buf[l])
701: break;
702: if(l<smb->status.max_crcs) { /* Dupe CRC found */
703: close(file);
704: FREE(buf);
705: return(1); }
706: chsize(file,0L); /* truncate it */
707: lseek(file,0L,SEEK_SET);
708: write(file,buf+4,(smb->status.max_crcs-1)*4); }
709:
710: else if(length/4) { /* Less than max crcs */
711: read(file,buf,length);
712: for(l=0;l<length/4;l++)
713: if(crc==buf[l])
714: break;
715: if(l<length/4) { /* Dupe CRC found */
716: close(file);
717: FREE(buf);
718: return(1); } }
719:
720: lseek(file,0L,SEEK_END);
721: write(file,&crc,4); /* Write to the end */
722: FREE(buf);
723: close(file);
724: return(0);
725: }
726:
727:
728: /****************************************************************************/
729: /* Creates a new message header record in the header file. */
730: /* If storage is SMB_SELFPACK, self-packing conservative allocation is used */
731: /* If storage is SMB_FASTALLOC, fast allocation is used */
732: /* If storage is SMB_HYPERALLOC, no allocation tables are used (fastest) */
733: /****************************************************************************/
734: int SMBCALL smb_addmsghdr(smb_t *smb, smbmsg_t *msg, int storage)
735: {
736: int i;
737: long l;
738:
739: if(smb_locksmbhdr(smb))
740: return(1);
741: if(smb_getstatus(smb))
742: return(2);
743:
744: if(storage!=SMB_HYPERALLOC && (i=smb_open_ha(smb))!=0)
745: return(i);
746:
747: msg->hdr.length=smb_getmsghdrlen(msg);
748: if(storage==SMB_HYPERALLOC)
749: l=smb_hallochdr(smb);
750: else if(storage==SMB_FASTALLOC)
751: l=smb_fallochdr(smb,msg->hdr.length);
752: else
753: l=smb_allochdr(smb,msg->hdr.length);
754: if(l==-1L) {
755: smb_unlocksmbhdr(smb);
756: smb_close_ha(smb);
757: return(-1); }
758:
759: smb->status.last_msg++;
760: msg->idx.number=msg->hdr.number=smb->status.last_msg;
761: msg->idx.offset=smb->status.header_offset+l;
762: msg->idx.time=msg->hdr.when_imported.time;
763: msg->idx.attr=msg->hdr.attr;
764: msg->offset=smb->status.total_msgs;
765: smb->status.total_msgs++;
766: smb_putstatus(smb);
767:
768: if(storage!=SMB_HYPERALLOC)
769: smb_close_ha(smb);
770: i=smb_putmsg(smb,msg);
771: smb_unlocksmbhdr(smb);
772: return(i);
773: }
774:
775: /****************************************************************************/
776: /* Writes both header and index information for msg 'msg' */
777: /****************************************************************************/
778: int SMBCALL smb_putmsg(smb_t *smb, smbmsg_t *msg)
779: {
780: int i;
781:
782: i=smb_putmsghdr(smb,msg);
783: if(i)
784: return(i);
785: return(smb_putmsgidx(smb,msg));
786: }
787:
788: /****************************************************************************/
789: /* Writes index information for 'msg' */
790: /* msg->idx */
791: /* and msg->offset must be set prior to calling to this function */
792: /* Returns 0 if everything ok */
793: /****************************************************************************/
794: int SMBCALL smb_putmsgidx(smb_t *smb, smbmsg_t *msg)
795: {
796:
797: clearerr(smb->sid_fp);
798: fseek(smb->sid_fp,msg->offset*sizeof(idxrec_t),SEEK_SET);
799: if(!fwrite(&msg->idx,sizeof(idxrec_t),1,smb->sid_fp))
800: return(1);
801: fflush(smb->sid_fp);
802: return(0);
803: }
804:
805: /****************************************************************************/
806: /* Writes header information for 'msg' */
807: /* msg->hdr.length */
808: /* msg->idx.offset */
809: /* and msg->offset must be set prior to calling to this function */
810: /* Returns 0 if everything ok */
811: /****************************************************************************/
812: int SMBCALL smb_putmsghdr(smb_t *smb, smbmsg_t *msg)
813: {
814: ushort i;
815: ulong l;
816:
817: clearerr(smb->shd_fp);
818: if(fseek(smb->shd_fp,msg->idx.offset,SEEK_SET))
819: return(-1);
820:
821: /************************************************/
822: /* Write the fixed portion of the header record */
823: /************************************************/
824: if(!fwrite(&msg->hdr,sizeof(msghdr_t),1,smb->shd_fp))
825: return(-2);
826:
827: /************************************************/
828: /* Write the data fields (each is fixed length) */
829: /************************************************/
830: for(i=0;i<msg->hdr.total_dfields;i++)
831: if(!fwrite(&msg->dfield[i],sizeof(dfield_t),1,smb->shd_fp))
832: return(-3);
833:
834: /*******************************************/
835: /* Write the variable length header fields */
836: /*******************************************/
837: for(i=0;i<msg->total_hfields;i++) {
838: if(!fwrite(&msg->hfield[i],sizeof(hfield_t),1,smb->shd_fp))
839: return(-4);
840: if(msg->hfield[i].length /* more then 0 bytes long */
841: && !fwrite(msg->hfield_dat[i],msg->hfield[i].length,1,smb->shd_fp))
842: return(-5); }
843:
844: l=smb_getmsghdrlen(msg);
845: while(l%SHD_BLOCK_LEN) {
846: if(fputc(0,smb->shd_fp)==EOF)
847: return(-6); /* pad block with NULL */
848: l++; }
849: fflush(smb->shd_fp);
850: return(0);
851: }
852:
853: /****************************************************************************/
854: /* Creates a sub-board's initial header file */
855: /* Truncates and deletes other associated SMB files */
856: /****************************************************************************/
857: int SMBCALL smb_create(smb_t *smb)
858: {
859: char str[128];
860: smbhdr_t hdr;
861:
862: if(filelength(fileno(smb->shd_fp))>=sizeof(smbhdr_t)+sizeof(smbstatus_t)
863: && smb_locksmbhdr(smb)) /* header exists, so lock it */
864: return(1);
865: memset(&hdr,0,sizeof(smbhdr_t));
866: memcpy(hdr.id,"SMB\x1a",4); /* <S> <M> <B> <^Z> */
867: hdr.version=SMB_VERSION;
868: hdr.length=sizeof(smbhdr_t)+sizeof(smbstatus_t);
869: smb->status.last_msg=smb->status.total_msgs=0;
870: smb->status.header_offset=sizeof(smbhdr_t)+sizeof(smbstatus_t);
871: rewind(smb->shd_fp);
872: fwrite(&hdr,1,sizeof(smbhdr_t),smb->shd_fp);
873: fwrite(&(smb->status),1,sizeof(smbstatus_t),smb->shd_fp);
874: rewind(smb->shd_fp);
875: chsize(fileno(smb->shd_fp),sizeof(smbhdr_t)+sizeof(smbstatus_t));
876: fflush(smb->shd_fp);
877:
878: rewind(smb->sdt_fp);
879: chsize(fileno(smb->sdt_fp),0L);
880: rewind(smb->sid_fp);
881: chsize(fileno(smb->sid_fp),0L);
882:
883: sprintf(str,"%s.SDA",smb->file);
884: remove(str); /* if it exists, delete it */
885: sprintf(str,"%s.SHA",smb->file);
886: remove(str); /* if it exists, delete it */
887: sprintf(str,"%s.SCH",smb->file);
888: remove(str);
889: smb_unlocksmbhdr(smb);
890: return(0);
891: }
892:
893: /****************************************************************************/
894: /* Returns number of data blocks required to store "length" amount of data */
895: /****************************************************************************/
896: ulong SMBCALL smb_datblocks(ulong length)
897: {
898: ulong blocks;
899:
900: blocks=length/SDT_BLOCK_LEN;
901: if(length%SDT_BLOCK_LEN)
902: blocks++;
903: return(blocks);
904: }
905:
906: /****************************************************************************/
907: /* Returns number of header blocks required to store "length" size header */
908: /****************************************************************************/
909: ulong SMBCALL smb_hdrblocks(ulong length)
910: {
911: ulong blocks;
912:
913: blocks=length/SHD_BLOCK_LEN;
914: if(length%SHD_BLOCK_LEN)
915: blocks++;
916: return(blocks);
917: }
918:
919: /****************************************************************************/
920: /* Finds unused space in data file based on block allocation table and */
921: /* marks space as used in allocation table. */
922: /* File must be opened read/write DENY ALL */
923: /* Returns offset to beginning of data (in bytes, not blocks) */
924: /* Assumes smb_open_da() has been called */
925: /* smb_close_da() should be called after */
926: /* Returns negative on error */
927: /****************************************************************************/
928: long SMBCALL smb_allocdat(smb_t *smb, ulong length, ushort headers)
929: {
930: ushort i,j;
931: ulong l,blocks,offset=0L;
932:
933: blocks=smb_datblocks(length);
934: j=0; /* j is consecutive unused block counter */
935: fflush(smb->sda_fp);
936: rewind(smb->sda_fp);
937: while(!feof(smb->sda_fp)) {
938: if(!fread(&i,2,1,smb->sda_fp))
939: break;
940: offset+=SDT_BLOCK_LEN;
941: if(!i) j++;
942: else j=0;
943: if(j==blocks) {
944: offset-=(blocks*SDT_BLOCK_LEN);
945: break; } }
946: clearerr(smb->sda_fp);
947: fseek(smb->sda_fp,(offset/SDT_BLOCK_LEN)*2L,SEEK_SET);
948: for(l=0;l<blocks;l++)
949: if(!fwrite(&headers,2,1,smb->sda_fp))
950: return(-1);
951: fflush(smb->sda_fp);
952: return(offset);
953: }
954:
955: /****************************************************************************/
956: /* Allocates space for data, but doesn't search for unused blocks */
957: /* Returns negative on error */
958: /****************************************************************************/
959: long SMBCALL smb_fallocdat(smb_t *smb, ulong length, ushort headers)
960: {
961: ulong l,blocks,offset;
962:
963: fflush(smb->sda_fp);
964: clearerr(smb->sda_fp);
965: blocks=smb_datblocks(length);
966: fseek(smb->sda_fp,0L,SEEK_END);
967: offset=(ftell(smb->sda_fp)/2L)*SDT_BLOCK_LEN;
968: for(l=0;l<blocks;l++)
969: if(!fwrite(&headers,2,1,smb->sda_fp))
970: break;
971: fflush(smb->sda_fp);
972: if(l<blocks)
973: return(-1L);
974: return(offset);
975: }
976:
977: /****************************************************************************/
978: /* De-allocates space for data */
979: /* Returns non-zero on error */
980: /****************************************************************************/
981: int SMBCALL smb_freemsgdat(smb_t *smb, ulong offset, ulong length
982: , ushort headers)
983: {
984: ushort i;
985: ulong l,blocks;
986:
987: blocks=smb_datblocks(length);
988:
989: clearerr(smb->sda_fp);
990: for(l=0;l<blocks;l++) {
991: if(fseek(smb->sda_fp,((offset/SDT_BLOCK_LEN)+l)*2L,SEEK_SET))
992: return(1);
993: if(!fread(&i,2,1,smb->sda_fp))
994: return(2);
995: if(headers>i)
996: i=0; /* don't want to go negative */
997: else
998: i-=headers;
999: if(fseek(smb->sda_fp,-2L,SEEK_CUR))
1000: return(3);
1001: if(!fwrite(&i,2,1,smb->sda_fp))
1002: return(4); }
1003: fflush(smb->sda_fp);
1004: return(0);
1005: }
1006:
1007: /****************************************************************************/
1008: /* Adds to data allocation records for blocks starting at 'offset' */
1009: /* Returns non-zero on error */
1010: /****************************************************************************/
1011: int SMBCALL smb_incdat(smb_t *smb, ulong offset, ulong length, ushort headers)
1012: {
1013: ushort i;
1014: ulong l,blocks;
1015:
1016: clearerr(smb->sda_fp);
1017: blocks=smb_datblocks(length);
1018: for(l=0;l<blocks;l++) {
1019: fseek(smb->sda_fp,((offset/SDT_BLOCK_LEN)+l)*2L,SEEK_SET);
1020: if(!fread(&i,2,1,smb->sda_fp))
1021: return(1);
1022: i+=headers;
1023: fseek(smb->sda_fp,-2L,SEEK_CUR);
1024: if(!fwrite(&i,2,1,smb->sda_fp))
1025: return(2); }
1026: fflush(smb->sda_fp);
1027: return(0);
1028: }
1029:
1030: /****************************************************************************/
1031: /* De-allocates blocks for header record */
1032: /* Returns non-zero on error */
1033: /****************************************************************************/
1034: int SMBCALL smb_freemsghdr(smb_t *smb, ulong offset, ulong length)
1035: {
1036: uchar c=0;
1037: ulong l,blocks;
1038:
1039: clearerr(smb->sha_fp);
1040: blocks=smb_hdrblocks(length);
1041: fseek(smb->sha_fp,offset/SHD_BLOCK_LEN,SEEK_SET);
1042: for(l=0;l<blocks;l++)
1043: if(!fwrite(&c,1,1,smb->sha_fp))
1044: return(1);
1045: fflush(smb->sha_fp);
1046: return(0);
1047: }
1048:
1049: /****************************************************************************/
1050: /* Frees all allocated header and data blocks for 'msg' */
1051: /****************************************************************************/
1052: int SMBCALL smb_freemsg(smb_t *smb, smbmsg_t *msg)
1053: {
1054: int i;
1055: ushort x;
1056:
1057: if(smb->status.attr&SMB_HYPERALLOC) /* Nothing to do */
1058: return(0);
1059:
1060: for(x=0;x<msg->hdr.total_dfields;x++) {
1061: if((i=smb_freemsgdat(smb,msg->hdr.offset+msg->dfield[x].offset
1062: ,msg->dfield[x].length,1))!=0)
1063: return(i); }
1064: return(smb_freemsghdr(smb,msg->idx.offset-smb->status.header_offset
1065: ,msg->hdr.length));
1066: }
1067:
1068: /****************************************************************************/
1069: /* Finds unused space in header file based on block allocation table and */
1070: /* marks space as used in allocation table. */
1071: /* File must be opened read/write DENY ALL */
1072: /* Returns offset to beginning of header (in bytes, not blocks) */
1073: /* Assumes smb_open_ha() has been called */
1074: /* smb_close_ha() should be called after */
1075: /* Returns -1L on error */
1076: /****************************************************************************/
1077: long SMBCALL smb_allochdr(smb_t *smb, ulong length)
1078: {
1079: uchar c;
1080: ushort i;
1081: ulong l,blocks,offset=0;
1082:
1083: blocks=smb_hdrblocks(length);
1084: i=0; /* i is consecutive unused block counter */
1085: fflush(smb->sha_fp);
1086: rewind(smb->sha_fp);
1087: while(!feof(smb->sha_fp)) {
1088: if(!fread(&c,1,1,smb->sha_fp))
1089: break;
1090: offset+=SHD_BLOCK_LEN;
1091: if(!c) i++;
1092: else i=0;
1093: if(i==blocks) {
1094: offset-=(blocks*SHD_BLOCK_LEN);
1095: break; } }
1096: clearerr(smb->sha_fp);
1097: fseek(smb->sha_fp,offset/SHD_BLOCK_LEN,SEEK_SET);
1098: c=1;
1099: for(l=0;l<blocks;l++)
1100: if(!fwrite(&c,1,1,smb->sha_fp))
1101: return(-1L);
1102: fflush(smb->sha_fp);
1103: return(offset);
1104: }
1105:
1106: /****************************************************************************/
1107: /* Allocates space for index, but doesn't search for unused blocks */
1108: /* Returns -1L on error */
1109: /****************************************************************************/
1110: long SMBCALL smb_fallochdr(smb_t *smb, ulong length)
1111: {
1112: uchar c=1;
1113: ulong l,blocks,offset;
1114:
1115: blocks=smb_hdrblocks(length);
1116: fflush(smb->sha_fp);
1117: clearerr(smb->sha_fp);
1118: fseek(smb->sha_fp,0L,SEEK_END);
1119: offset=ftell(smb->sha_fp)*SHD_BLOCK_LEN;
1120: for(l=0;l<blocks;l++)
1121: if(!fwrite(&c,1,1,smb->sha_fp))
1122: return(-1L);
1123: fflush(smb->sha_fp);
1124: return(offset);
1125: }
1126:
1127: /************************************************************************/
1128: /* Allocate header blocks using Hyper Allocation */
1129: /* this function should be most likely not be called from anywhere but */
1130: /* smb_addmsghdr() */
1131: /************************************************************************/
1132: long SMBCALL smb_hallochdr(smb_t *smb)
1133: {
1134: long l;
1135:
1136: fflush(smb->shd_fp);
1137: fseek(smb->shd_fp,0L,SEEK_END);
1138: l=ftell(smb->shd_fp);
1139: if(l<smb->status.header_offset) /* Header file truncated?!? */
1140: return(smb->status.header_offset);
1141: while((l-smb->status.header_offset)%SHD_BLOCK_LEN) /* Even block boundry */
1142: l++;
1143: return(l-smb->status.header_offset);
1144: }
1145:
1146: /************************************************************************/
1147: /* Allocate data blocks using Hyper Allocation */
1148: /* smb_locksmbhdr() should be called before this function and not */
1149: /* unlocked until all data fields for this message have been written */
1150: /* to the SDT file */
1151: /************************************************************************/
1152: long SMBCALL smb_hallocdat(smb_t *smb)
1153: {
1154: long l;
1155:
1156: fflush(smb->sdt_fp);
1157: fseek(smb->sdt_fp,0L,SEEK_END);
1158: l=ftell(smb->sdt_fp);
1159: if(l<=0)
1160: return(l);
1161: while(l%SDT_BLOCK_LEN) /* Make sure even block boundry */
1162: l++;
1163: return(l);
1164: }
1165:
1166:
1167: int SMBCALL smb_feof(FILE *fp)
1168: {
1169: return(feof(fp));
1170: }
1171:
1172: int SMBCALL smb_ferror(FILE *fp)
1173: {
1174: return(ferror(fp));
1175: }
1176:
1177: int SMBCALL smb_fflush(FILE *fp)
1178: {
1179: return(fflush(fp));
1180: }
1181:
1182: int SMBCALL smb_fgetc(FILE *fp)
1183: {
1184: return(fgetc(fp));
1185: }
1186:
1187: int SMBCALL smb_fputc(int ch, FILE *fp)
1188: {
1189: return(fputc(ch,fp));
1190: }
1191:
1192: int SMBCALL smb_fseek(FILE *fp, long offset, int whence)
1193: {
1194: return(fseek(fp,offset,whence));
1195: }
1196:
1197: long SMBCALL smb_ftell(FILE *fp)
1198: {
1199: return(ftell(fp));
1200: }
1201:
1202: long SMBCALL smb_fgetlength(FILE *fp)
1203: {
1204: return(filelength(fileno(fp)));
1205: }
1206:
1207: int SMBCALL smb_fsetlength(FILE *fp, long length)
1208: {
1209: return(chsize(fileno(fp),length));
1210: }
1211:
1212: void SMBCALL smb_rewind(FILE *fp)
1213: {
1214: rewind(fp);
1215: }
1216:
1217: void SMBCALL smb_clearerr(FILE *fp)
1218: {
1219: clearerr(fp);
1220: }
1221:
1222: long SMBCALL smb_fread(char HUGE16 *buf, long bytes, FILE *fp)
1223: {
1224: #ifdef __FLAT__
1225: return(fread(buf,1,bytes,fp));
1226: #else
1227: long count;
1228:
1229: for(count=bytes;count>0x7fff;count-=0x7fff,buf+=0x7fff)
1230: if(fread((char *)buf,1,0x7fff,fp)!=0x7fff)
1231: return(bytes-count);
1232: if(fread((char *)buf,1,(int)count,fp)!=count)
1233: return(bytes-count);
1234: return(bytes);
1235: #endif
1236: }
1237:
1238: long SMBCALL smb_fwrite(char HUGE16 *buf, long bytes, FILE *fp)
1239: {
1240: #ifdef __FLAT__
1241: return(fwrite(buf,1,bytes,fp));
1242: #else
1243: long count;
1244:
1245: for(count=bytes;count>0x7fff;count-=0x7fff,buf+=0x7fff)
1246: if(fwrite((char *)buf,1,0x7fff,fp)!=0x7fff)
1247: return(bytes-count);
1248: if(fwrite((char *)buf,1,(int)count,fp)!=count)
1249: return(bytes-count);
1250: return(bytes);
1251: #endif
1252: }
1253:
1254: #ifdef SMB_GETMSGTXT
1255:
1256: char HUGE16 * SMBCALL smb_getmsgtxt(smb_t *smb, smbmsg_t *msg, ulong mode)
1257: {
1258: char HUGE16 *buf=NULL,HUGE16 *lzhbuf,HUGE16 *p;
1259: ushort xlat;
1260: int i,j,lzh;
1261: long l=0,lzo,lzhlen,length;
1262:
1263: for(i=0;i<msg->hdr.total_dfields;i++) {
1264: if(!(msg->dfield[i].type==TEXT_BODY
1265: || (mode&GETMSGTXT_TAILS && msg->dfield[i].type==TEXT_TAIL))
1266: || msg->dfield[i].length<=2L)
1267: continue;
1268: fseek(smb->sdt_fp,msg->hdr.offset+msg->dfield[i].offset
1269: ,SEEK_SET);
1270: fread(&xlat,2,1,smb->sdt_fp);
1271: lzh=0;
1272: if(xlat==XLAT_LZH) {
1273: lzh=1;
1274: fread(&xlat,2,1,smb->sdt_fp); }
1275: if(xlat!=XLAT_NONE) /* no other translations currently supported */
1276: continue;
1277:
1278: length=msg->dfield[i].length-2L;
1279: if(lzh) {
1280: length-=2;
1281: if(length<1)
1282: continue;
1283: if((lzhbuf=LMALLOC(length))==NULL)
1284: return(buf);
1285: smb_fread(lzhbuf,length,smb->sdt_fp);
1286: lzhlen=*(long *)lzhbuf;
1287: if((p=REALLOC(buf,l+lzhlen+3L))==NULL) {
1288: FREE(lzhbuf);
1289: return(buf); }
1290: buf=p;
1291: lzh_decode((char *)lzhbuf,length,(char *)buf+l);
1292: FREE(lzhbuf);
1293: l+=lzhlen; }
1294: else {
1295: if((p=REALLOC(buf,l+length+3L))==NULL)
1296: return(buf);
1297: buf=p;
1298: p=buf+l;
1299: l+=fread(p,1,length,smb->sdt_fp);
1300: }
1301: if(!l)
1302: continue;
1303: l--;
1304: while(l && buf[l]==0) l--;
1305: l++;
1306: *(buf+l)=CR;
1307: l++;
1308: *(buf+l)=LF;
1309: l++;
1310: *(buf+l)=0; }
1311: return(buf);
1312: }
1313:
1314: void SMBCALL smb_freemsgtxt(char HUGE16 *buf)
1315: {
1316: if(buf!=NULL)
1317: FREE(buf);
1318: }
1319:
1320: #endif
1321:
1322: /* End of SMBLIB.C */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.