home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1998 September / PCO_0998.ISO / filesbbs / dos / sbbs_src.exe / SBBS / SMB / SMBLIB.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-04-26  |  38.4 KB  |  1,323 lines

  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 */
  1323.