Annotation of sbbs/sbbs2/smb/smblib.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.