Annotation of sbbs/sbbs2/smb/121a/fido2smb.c, revision 1.1.1.1

1.1       root        1: /* FIDO2SMB.C */
                      2: 
                      3: /* Converts FidoNet FTSC-1 (*.MSG) message base to SMB format */
                      4: 
                      5: /* The intention of this source code is an example of how to use the SMBLIB */
                      6: /* library functions to access an SMB format message base.                                     */
                      7: 
                      8: /* This program and source code are freeware. May be used in part or whole     */
                      9: /* for any purpose without consent or notification of Digital Dynamics.        */
                     10: 
                     11: /* Digital Dynamics does request that developers that release products that */
                     12: /* support the SMB format notify Digital Dynamics so the implementation        */
                     13: /* and contact chapters in the technical specification may be updated.         */
                     14: 
                     15: #include "smblib.h"
                     16: #include "crc32.h"
                     17: #include <dos.h>
                     18:                                                                        /* Attribute bits for fido msg header */
                     19: #define FIDO_PRIVATE   (1<<0)          /* Private message */
                     20: #define FIDO_CRASH             (1<<1)          /* Crash-mail (send immediately) */
                     21: #define FIDO_RECV              (1<<2)          /* Received successfully */
                     22: #define FIDO_SENT              (1<<3)          /* Sent successfully */
                     23: #define FIDO_FILE              (1<<4)          /* File attached */
                     24: #define FIDO_INTRANS   (1<<5)          /* In transit */
                     25: #define FIDO_ORPHAN    (1<<6)          /* Orphan */
                     26: #define FIDO_KILLSENT  (1<<7)          /* Kill it after sending it */
                     27: #define FIDO_LOCAL             (1<<8)          /* Created locally - on this system */
                     28: #define FIDO_HOLD              (1<<9)          /* Hold - don't send it yet */
                     29: #define FIDO_FREQ              (1<<11)         /* File request */
                     30: #define FIDO_RRREQ             (1<<12)         /* Return receipt request */
                     31: #define FIDO_RR                (1<<13)         /* This is a return receipt */
                     32: #define FIDO_AUDIT             (1<<14)         /* Audit request */
                     33: #define FIDO_FUPREQ     (1<<15)     /* File update request */
                     34: 
                     35: typedef struct {                                               /* FidoNet msg header */
                     36:        uchar   from[36],                                       /* From user */
                     37:                        to[36],                                         /* To user */
                     38:                        subj[72],                                       /* Message title */
                     39:                        time[20];                                       /* Time in goof-ball ASCII format */
                     40:        short   read,                                           /* Times read */
                     41:                        destnode,                                       /* Destination node */
                     42:                        orignode,                                       /* Origin node */
                     43:                        cost,                                           /* Cost in pennies */
                     44:                        orignet,                                        /* Origin net */
                     45:                        destnet,                                        /* Destination net */
                     46:                        destzone,                                       /* Destination zone */
                     47:                        origzone,                                       /* Origin zone */
                     48:                        destpoint,                                      /* Destination point */
                     49:                        origpoint,                                      /* Origin point */
                     50:                        re,                                             /* Message number regarding */
                     51:                        attr,                                           /* Attributes - see FIDO_* */
                     52:                        next;                                           /* Next message number in stream */
                     53:             } fmsghdr_t;
                     54: 
                     55: /******************************************/
                     56: /* CRC-16 routines required for SMB index */
                     57: /******************************************/
                     58: 
                     59: /****************************************************************************/
                     60: /* Updates 16-bit "rcrc" with character 'ch'                                */
                     61: /****************************************************************************/
                     62: void ucrc16(uchar ch, ushort *rcrc) {
                     63:        ushort i, cy;
                     64:     uchar nch=ch;
                     65:  
                     66: for (i=0; i<8; i++) {
                     67:     cy=*rcrc & 0x8000;
                     68:     *rcrc<<=1;
                     69:     if (nch & 0x80) *rcrc |= 1;
                     70:     nch<<=1;
                     71:     if (cy) *rcrc ^= 0x1021; }
                     72: }
                     73: 
                     74: /****************************************************************************/
                     75: /* Returns 16-crc of string (not counting terminating NULL)                            */
                     76: /****************************************************************************/
                     77: ushort crc16(char *str)
                     78: {
                     79:        int     i=0;
                     80:        ushort  crc=0;
                     81: 
                     82: ucrc16(0,&crc);
                     83: while(str[i])
                     84:        ucrc16(str[i++],&crc);
                     85: ucrc16(0,&crc);
                     86: ucrc16(0,&crc);
                     87: return(crc);
                     88: }
                     89: 
                     90: /****************************************************************************/
                     91: /* Truncates white-space chars off end of 'str' and terminates at first tab */
                     92: /****************************************************************************/
                     93: void truncsp(char *str)
                     94: {
                     95:        char c;
                     96: 
                     97: str[strcspn(str,"\t")]=0;
                     98: c=strlen(str);
                     99: while(c && (uchar)str[c-1]<=' ') c--;
                    100: str[c]=0;
                    101: }
                    102: 
                    103: /****************************************************************************/
                    104: /* Returns the length of the file in 'filespec'                             */
                    105: /****************************************************************************/
                    106: long flength(char *filespec)
                    107: {
                    108:     struct ffblk f;
                    109: 
                    110: if(findfirst(filespec,&f,0)==0)
                    111:     return(f.ff_fsize);
                    112: return(-1L);
                    113: }
                    114: 
                    115: /****************************************************************************/
                    116: /* Returns the FidoNet address kept in str as ASCII.                        */
                    117: /****************************************************************************/
                    118: fidoaddr_t atofaddr(char *str)
                    119: {
                    120:     char *p;
                    121:        fidoaddr_t addr;
                    122: 
                    123: addr.zone=addr.net=addr.node=addr.point=0;
                    124: if((p=strchr(str,':'))!=NULL) {
                    125:        addr.zone=atoi(str);
                    126:        addr.net=atoi(p+1); }
                    127: else {
                    128:        addr.zone=1;
                    129:        addr.net=atoi(str); }
                    130: if(!addr.zone)                         /* no such thing as zone 0 */
                    131:        addr.zone=1;
                    132: if((p=strchr(str,'/'))!=NULL)
                    133:     addr.node=atoi(p+1);
                    134: else {
                    135:        addr.net=1;
                    136:        addr.node=atoi(str); }
                    137: if((p=strchr(str,'.'))!=NULL)
                    138:     addr.point=atoi(p+1);
                    139: return(addr);
                    140: }
                    141: 
                    142: /****************************************************************************/
                    143: /* Converts goofy FidoNet time format into Unix format                                         */
                    144: /****************************************************************************/
                    145: time_t fmsgtime(char *str)
                    146: {
                    147:        char month[4];
                    148:        struct date date;
                    149:        struct time t;
                    150: 
                    151: if(isdigit(str[1])) {  /* Regular format: "01 Jan 86  02:34:56" */
                    152:        date.da_day=atoi(str);
                    153:        sprintf(month,"%3.3s",str+3);
                    154:        if(!stricmp(month,"jan"))
                    155:                date.da_mon=1;
                    156:        else if(!stricmp(month,"feb"))
                    157:                date.da_mon=2;
                    158:        else if(!stricmp(month,"mar"))
                    159:                date.da_mon=3;
                    160:        else if(!stricmp(month,"apr"))
                    161:                date.da_mon=4;
                    162:        else if(!stricmp(month,"may"))
                    163:                date.da_mon=5;
                    164:        else if(!stricmp(month,"jun"))
                    165:                date.da_mon=6;
                    166:        else if(!stricmp(month,"jul"))
                    167:                date.da_mon=7;
                    168:        else if(!stricmp(month,"aug"))
                    169:                date.da_mon=8;
                    170:        else if(!stricmp(month,"sep"))
                    171:                date.da_mon=9;
                    172:        else if(!stricmp(month,"oct"))
                    173:                date.da_mon=10;
                    174:        else if(!stricmp(month,"nov"))
                    175:                date.da_mon=11;
                    176:        else
                    177:                date.da_mon=12;
                    178:        date.da_year=1900+atoi(str+7);
                    179:        t.ti_hour=atoi(str+11);
                    180:        t.ti_min=atoi(str+14);
                    181:        t.ti_sec=atoi(str+17); }
                    182: 
                    183: else {                                 /* SEAdog  format: "Mon  1 Jan 86 02:34" */
                    184:        date.da_day=atoi(str+4);
                    185:        sprintf(month,"%3.3s",str+7);
                    186:        if(!stricmp(month,"jan"))
                    187:                date.da_mon=1;
                    188:        else if(!stricmp(month,"feb"))
                    189:                date.da_mon=2;
                    190:        else if(!stricmp(month,"mar"))
                    191:                date.da_mon=3;
                    192:        else if(!stricmp(month,"apr"))
                    193:                date.da_mon=4;
                    194:        else if(!stricmp(month,"may"))
                    195:                date.da_mon=5;
                    196:        else if(!stricmp(month,"jun"))
                    197:                date.da_mon=6;
                    198:        else if(!stricmp(month,"jul"))
                    199:                date.da_mon=7;
                    200:        else if(!stricmp(month,"aug"))
                    201:                date.da_mon=8;
                    202:        else if(!stricmp(month,"sep"))
                    203:                date.da_mon=9;
                    204:        else if(!stricmp(month,"oct"))
                    205:                date.da_mon=10;
                    206:        else if(!stricmp(month,"nov"))
                    207:                date.da_mon=11;
                    208:        else
                    209:                date.da_mon=12;
                    210:        date.da_year=1900+atoi(str+11);
                    211:        t.ti_hour=atoi(str+14);
                    212:        t.ti_min=atoi(str+17);
                    213:        t.ti_sec=0; }
                    214: return(dostounix(&date,&t));
                    215: }
                    216: 
                    217: /****************************************************************************/
                    218: /* Entry point - if you didn't know that, maybe you shouldn't be reading :) */
                    219: /****************************************************************************/
                    220: int main(int argc, char **argv)
                    221: {
                    222:        uchar   *p,str[128],*fbuf,*sbody,*stail,ch,done;
                    223:        ushort  xlat,net;
                    224:        int     i,j,file,col,cr,esc,orig,last,msgs,found;
                    225:        ulong   l,m,length,bodylen,taillen,crc;
                    226:        struct  ffblk ff;
                    227:        smbmsg_t        msg;
                    228:        smbstatus_t status;
                    229:        fmsghdr_t       fmsghdr;
                    230:        fidoaddr_t      destaddr,origaddr,faddr;
                    231: 
                    232: if(argc<3) {
                    233:        printf("usage: fido2smb <fido_dir> <smb_name>\r\n");
                    234:        exit(1); }
                    235: 
                    236: strcpy(smb_file,argv[2]);
                    237: strupr(smb_file);
                    238: 
                    239: smb_open(10);
                    240: if(!filelength(fileno(shd_fp)))
                    241:        smb_create(2000,2000,0,0,10);
                    242: 
                    243: smb_getstatus(&status);          // Initialized for first call to smb_addcrc()
                    244: 
                    245: /*********************************************/
                    246: /* Get the total number of .MSG files in dir */
                    247: /*********************************************/
                    248: printf("\nCounting messages...");
                    249: sprintf(str,"%s\\*.MSG",argv[1]);
                    250: last=findfirst(str,&ff,0);
                    251: for(msgs=0;!last;msgs++)
                    252:        last=findnext(&ff);
                    253: printf("\n%u messages.\n",msgs);
                    254: 
                    255: /******************************************/
                    256: /* Convert in sequence, starting at 1.MSG */
                    257: /******************************************/
                    258: for(i=1,found=0;found<msgs && i<2000;i++) {
                    259:        sprintf(str,"%s\\%u.MSG",argv[1],i);
                    260:        if((file=open(str,O_RDONLY|O_BINARY))==-1)
                    261:                continue;
                    262:        found++;
                    263:        strupr(str);
                    264:        printf("%s\n",str);
                    265:        read(file,&fmsghdr,sizeof(fmsghdr_t));
                    266:        memset(&msg,0,sizeof(smbmsg_t));
                    267:        memcpy(msg.hdr.id,"SHD\x1a",4);
                    268:        msg.hdr.version=SMB_VERSION;
                    269:        if(fmsghdr.attr&FIDO_PRIVATE)
                    270:                msg.idx.attr|=MSG_PRIVATE;
                    271:        msg.hdr.attr=msg.idx.attr;
                    272: 
                    273:        msg.hdr.when_imported.time=time(NULL);
                    274:        msg.hdr.when_written.time=fmsgtime(fmsghdr.time);
                    275: 
                    276:        origaddr.zone=fmsghdr.origzone;         /* only valid if NetMail */
                    277:        origaddr.net=fmsghdr.orignet;
                    278:        origaddr.node=fmsghdr.orignode;
                    279:        origaddr.point=fmsghdr.origpoint;
                    280: 
                    281:        destaddr.zone=fmsghdr.destzone;         /* only valid if NetMail */
                    282:        destaddr.net=fmsghdr.destnet;
                    283:        destaddr.node=fmsghdr.destnode;
                    284:        destaddr.point=fmsghdr.destpoint;
                    285: 
                    286:        smb_hfield(&msg,SENDER,strlen(fmsghdr.from),fmsghdr.from);
                    287:        strlwr(fmsghdr.from);
                    288:        msg.idx.from=crc16(fmsghdr.from);
                    289: 
                    290:        smb_hfield(&msg,RECIPIENT,strlen(fmsghdr.to),fmsghdr.to);
                    291:        strlwr(fmsghdr.to);
                    292:        msg.idx.to=crc16(fmsghdr.to);
                    293: 
                    294:        smb_hfield(&msg,SUBJECT,strlen(fmsghdr.subj),fmsghdr.subj);
                    295:        strlwr(fmsghdr.subj);
                    296:        msg.idx.subj=crc16(fmsghdr.subj);
                    297: 
                    298:        length=filelength(file)-sizeof(fmsghdr_t);
                    299:        if((fbuf=(char *)MALLOC(length))==NULL) {
                    300:                printf("alloc error\n");
                    301:                exit(1); }
                    302:        if((sbody=(char *)MALLOC(length*2L))==NULL) {
                    303:                printf("alloc error\n");
                    304:         exit(1); }
                    305:        if((stail=(char *)MALLOC(length))==NULL) {
                    306:                printf("alloc error\n");
                    307:         exit(1); }
                    308:        read(file,fbuf,length);
                    309:        close(file);
                    310: 
                    311:        for(col=l=esc=done=bodylen=taillen=orig=0,cr=1;l<length;l++) {
                    312:                ch=fbuf[l];
                    313:                if(ch==1 && cr) {       /* kludge line */
                    314: 
                    315:                        if(!strncmp(fbuf+l+1,"TOPT ",5))
                    316:                                destaddr.point=atoi(fbuf+l+6);
                    317: 
                    318:                        else if(!strncmp(fbuf+l+1,"FMPT ",5))
                    319:                                origaddr.point=atoi(fbuf+l+6);
                    320: 
                    321:                        else if(!strncmp(fbuf+l+1,"INTL ",5)) {
                    322:                                faddr=atofaddr(fbuf+l+6);
                    323:                                destaddr.zone=faddr.zone;
                    324:                                destaddr.net=faddr.net;
                    325:                                destaddr.node=faddr.node;
                    326:                                l+=6;
                    327:                                while(l<length && fbuf[l]!=SP) l++;
                    328:                                faddr=atofaddr(fbuf+l+1);
                    329:                                origaddr.zone=faddr.zone;
                    330:                                origaddr.net=faddr.net;
                    331:                                origaddr.node=faddr.node; }
                    332: 
                    333:                        else if(!strncmp(fbuf+l+1,"MSGID:",6)) {
                    334:                                l+=7;
                    335:                                while(l<length && fbuf[l]<=SP) l++;
                    336:                                m=l;
                    337:                                while(m<length && fbuf[m]!=CR) m++;
                    338:                                while(m && fbuf[m-1]<=SP) m--;
                    339:                                if(m>l)
                    340:                                        smb_hfield(&msg,FIDOMSGID,m-l,fbuf+l); }
                    341: 
                    342:                        else if(!strncmp(fbuf+l+1,"REPLY:",6)) {
                    343:                                l+=7;
                    344:                                while(l<length && fbuf[l]<=SP) l++;
                    345:                                m=l;
                    346:                                while(m<length && fbuf[m]!=CR) m++;
                    347:                                while(m && fbuf[m-1]<=SP) m--;
                    348:                                if(m>l)
                    349:                                        smb_hfield(&msg,FIDOREPLYID,m-l,fbuf+l); }
                    350: 
                    351:                        else if(!strncmp(fbuf+l+1,"FLAGS:",6)) {
                    352:                                l+=7;
                    353:                                while(l<length && fbuf[l]<=SP) l++;
                    354:                                m=l;
                    355:                                while(m<length && fbuf[m]!=CR) m++;
                    356:                                while(m && fbuf[m-1]<=SP) m--;
                    357:                                if(m>l)
                    358:                                        smb_hfield(&msg,FIDOFLAGS,m-l,fbuf+l); }
                    359: 
                    360:                        else if(!strncmp(fbuf+l+1,"PATH:",5)) {
                    361:                                l+=6;
                    362:                                while(l<length && fbuf[l]<=SP) l++;
                    363:                                m=l;
                    364:                                while(m<length && fbuf[m]!=CR) m++;
                    365:                                while(m && fbuf[m-1]<=SP) m--;
                    366:                                if(m>l)
                    367:                                        smb_hfield(&msg,FIDOPATH,m-l,fbuf+l); }
                    368: 
                    369:                        else if(!strncmp(fbuf+l+1,"PID:",4)) {
                    370:                                l+=5;
                    371:                                while(l<length && fbuf[l]<=SP) l++;
                    372:                                m=l;
                    373:                                while(m<length && fbuf[m]!=CR) m++;
                    374:                                while(m && fbuf[m-1]<=SP) m--;
                    375:                                if(m>l)
                    376:                                        smb_hfield(&msg,FIDOPID,m-l,fbuf+l); }
                    377: 
                    378:                        else {          /* Unknown kludge line */
                    379:                                while(l<length && fbuf[l]<=SP) l++;
                    380:                                m=l;
                    381:                                while(m<length && fbuf[m]!=CR) m++;
                    382:                                while(m && fbuf[m-1]<=SP) m--;
                    383:                                if(m>l)
                    384:                                        smb_hfield(&msg,FIDOCTRL,m-l,fbuf+l); }
                    385: 
                    386:                        while(l<length && fbuf[l]!=CR) l++;
                    387:                        continue; }
                    388: 
                    389:                if(ch!=LF && ch!=0x8d) {        /* ignore LF and soft CRs */
                    390:                        if(cr && (!strncmp((char *)fbuf+l,"--- ",4)
                    391:                                || !strncmp((char *)fbuf+l,"---\r",4)))
                    392:                                done=1;                         /* tear line and down go into tail */
                    393:                        if(done && cr && !strncmp(fbuf+l,"SEEN-BY:",8)) {
                    394:                                l+=8;
                    395:                                while(l<length && fbuf[l]<=SP) l++;
                    396:                                m=l;
                    397:                                while(m<length && fbuf[m]!=CR) m++;
                    398:                                while(m && fbuf[m-1]<=SP) m--;
                    399:                                if(m>l)
                    400:                                        smb_hfield(&msg,FIDOSEENBY,m-l,fbuf+l);
                    401:                                while(l<length && fbuf[l]!=CR) l++;
                    402:                                continue;  }  /* skip the CR */
                    403:                        if(done)
                    404:                                stail[taillen++]=ch;
                    405:                        else
                    406:                                sbody[bodylen++]=ch;
                    407:                        col++;
                    408:                        if(ch==CR) {
                    409:                                cr=1;
                    410:                                col=0;
                    411:                                if(done)
                    412:                                        stail[taillen++]=LF;
                    413:                                else
                    414:                                        sbody[bodylen++]=LF; }
                    415:                        else {
                    416:                                cr=0;
                    417:                                if(col==1 && !strncmp((char *)fbuf+l," * Origin: ",11)) {
                    418:                                        p=strchr(fbuf+l+11,CR);          /* find carriage return */
                    419:                                        while(p && *p!='(') p--;     /* rewind to '(' */
                    420:                                        if(p)
                    421:                                                origaddr=atofaddr(p+1);         /* get orig address */
                    422:                                        orig=done=1; }
                    423:                                if(done)
                    424:                                        continue;
                    425: 
                    426:                                if(ch==ESC) esc=1;              /* ANSI codes */
                    427:                                if(ch==SP && col>40 && !esc) {  /* word wrap */
                    428:                                        for(m=l+1;m<length;m++)         /* find next space */
                    429:                                                if(fbuf[m]<=SP)
                    430:                                                        break;
                    431:                                        if(m<length && m-l>80-col) {  /* if it's beyond the eol */
                    432:                                                sbody[bodylen++]=CR;
                    433:                                                sbody[bodylen++]=LF;
                    434:                                                col=0; } }
                    435:                                } } }
                    436: 
                    437:        if(bodylen>=2 && sbody[bodylen-2]==CR && sbody[bodylen-1]==LF)
                    438:                bodylen-=2;                                             /* remove last CRLF if present */
                    439: 
                    440:        for(l=0,crc=0xffffffff;l<bodylen;l++)
                    441:                crc=ucrc32(sbody[l],crc);
                    442:        crc=~crc;
                    443: 
                    444:        j=smb_addcrc(status.max_crcs,crc,10);
                    445:        if(j) {
                    446:                if(j==1) {
                    447:                        printf("\nDuplicate message\n");
                    448:                        smb_freemsgmem(msg);
                    449:                        FREE(fbuf);
                    450:                        FREE(sbody);
                    451:                        FREE(stail);
                    452:                        continue; }
                    453:                printf("smb_addcrc returned %d\n",j);
                    454:         exit(1); }
                    455: 
                    456:        while(taillen && stail[taillen-1]<=SP)  /* trim all garbage off the tail */
                    457:                taillen--;
                    458: 
                    459:        net=NET_FIDO;   /* Record origin address */
                    460:        smb_hfield(&msg,SENDERNETTYPE,sizeof(ushort),&net);
                    461:        smb_hfield(&msg,SENDERNETADDR,sizeof(fidoaddr_t),&origaddr);
                    462: 
                    463:        if(!orig) {     /* No origin line means NetMail, so add dest addr */
                    464:                smb_hfield(&msg,RECIPIENTNETTYPE,sizeof(ushort),&net);
                    465:                smb_hfield(&msg,RECIPIENTNETADDR,sizeof(fidoaddr_t),&destaddr); }
                    466: 
                    467:        if(smb_open_da(10)) {
                    468:                printf("error opening %s.SDA\n",smb_file);
                    469:         exit(1); }
                    470:        l=bodylen+2;
                    471:        if(taillen)
                    472:                l+=(taillen+2);
                    473:        msg.hdr.offset=smb_fallocdat(l,1);
                    474:        fclose(sda_fp);
                    475:        if(msg.hdr.offset && msg.hdr.offset<1L) {
                    476:                printf("error %ld allocating records\r\n",msg.hdr.offset);
                    477:         exit(1); }
                    478:        fseek(sdt_fp,msg.hdr.offset,SEEK_SET);
                    479:     xlat=XLAT_NONE;
                    480:        fwrite(&xlat,2,1,sdt_fp);
                    481:        l=ftell(sdt_fp);
                    482:        fwrite(sbody,SDT_BLOCK_LEN,smb_datblocks(bodylen),sdt_fp);
                    483:        if(taillen) {
                    484:                fseek(sdt_fp,l+bodylen,SEEK_SET);
                    485:                fwrite(&xlat,2,1,sdt_fp);
                    486:                fwrite(stail,SDT_BLOCK_LEN,smb_datblocks(taillen),sdt_fp); }
                    487:        fflush(sdt_fp);
                    488:        FREE(fbuf);
                    489:        FREE(sbody);
                    490:        FREE(stail);
                    491: 
                    492:        smb_dfield(&msg,TEXT_BODY,bodylen+2);
                    493:        if(taillen)
                    494:                smb_dfield(&msg,TEXT_TAIL,taillen+2);
                    495: 
                    496:        smb_addmsghdr(&msg,&status,1,10);
                    497:        smb_freemsgmem(msg); }
                    498: 
                    499: printf("\n%u messages converted.\n",found);
                    500: return(0);
                    501: }
                    502: 

unix.superglobalmegacorp.com

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