#include #include #include #include #include #include #define STUFF_SIZE 129 /* buffer size for fgets */ #define ASIZE 2499 /* determines # of conferences */ /* we can handle */ #define VERSION "3.00" long public = 0L; /* count of public messages */ long private = 0L; /* count of private messages */ struct hdr /* message header structure */ { char _private; /* first byte is privacy flag */ /* ' ' means mail has been read */ /* '-' means not read */ /* '+' means private message */ char _msg[7]; /* message number in ASCII */ char _date[8]; /* date in ASCII (mm-dd-yy) */ char _time[5]; /* time in ASCII (hh:mm) */ char _to[25]; /* name of receiver */ char _from[25]; /* name of sender */ char _subj[37]; /* message subject */ char _ref[8]; /* msg refers to this msg # */ char _count[6]; /* # of 128-byte blocks in msg */ char _junk2[6]; /* these 6 bytes are, in order: */ /* 1. killed msg flag */ /* 225 (0xE1) == active */ /* 226 (0xE2) == killed */ /* 2. conference number */ /* 3-6. Reserved for future use */ } header; struct conf /* conference header structure */ { int _num; /* conference number */ int _msgs; /* # of msgs in conference */ char _name[15]; /* conf. name (14 chars max) */ } confs[ASIZE]; /* prototypes for ANSI C */ void strip(char *s); char *byp(char *s); void main(void); int nummsg(int n); int readblk(FILE *fp, char *buff); int readhdr(FILE *fp); void strncp(char *d, char *s, int n); void sep(FILE *fp); void strip(char *s) /* strip trailing whitespace from string s */ { char *p; p = s; while (*p) p++; while (p > s && isspace(*--p)) *p = 0; } char *byp(char *s) /* bypass unwanted whitespace from string s */ { while (isspace(*s)) s++; return(s); } void main(void) { FILE *ifp, *ofp; int i = 0, j; int cn, Acc_confs; char *sp; char stuff[STUFF_SIZE]; char BBS_name[80]; char BBS_location[80]; char BBS_phone_number[25]; char Packet_date[12]; char Packet_time[9]; char User_name[25]; char temp[25]; char *unavailable = "Not provided."; printf("%c[2J",27); printf("QWK2TXT %s QWK -> TXT converter\n", VERSION); printf("Public Domain as of Feb. 10, 1991\n\n"); if ((ifp = fopen("control.dat", "r")) == NULL) /* open control.dat */ { printf("\n\tRequired file CONTROL.DAT not found."); exit(1); } if(fgets(stuff,STUFF_SIZE,ifp) != NULL) /* get BBS' name */ { strip(stuff); strcpy(BBS_name,stuff); } if(fgets(stuff,STUFF_SIZE,ifp) != NULL) /* get BBS' city/state */ { strip(stuff); if(stuff[0] == 0) strcpy(BBS_location,unavailable); else strcpy(BBS_location,stuff); } if(fgets(stuff,STUFF_SIZE,ifp) != NULL) /* get BBS' phone number */ { strip(stuff); strcpy(BBS_phone_number,stuff); } fgets(stuff, STUFF_SIZE, ifp); /* toss sysop name into bit-bucket */ fgets(stuff, STUFF_SIZE, ifp); /* toss door reg. # and BBS ID too */ if(fgets(stuff,STUFF_SIZE,ifp) != NULL) /* get packet date & time */ { strip(stuff); strcpy(temp,stuff); } for(i=0; i<10; i++) /* strip packet date from string */ Packet_date[i] = temp[i]; Packet_date[10] = '\0'; for(i=11; i<19; i++) /* strip packet time from string */ Packet_time[i-11] = temp[i]; Packet_time[8] = '\0'; if(fgets(stuff,STUFF_SIZE,ifp) != NULL) /* get user's name */ { strip(stuff); strcpy(User_name,stuff); } for (i=0; i < 3; i++) /* Skip over Qmail menu filename, */ fgets(stuff, STUFF_SIZE, ifp); /* and two ASCII 0's */ fgets(stuff, STUFF_SIZE, ifp); /* get ASCII value of # of */ strip(stuff); /* conferences available */ Acc_confs = atoi(stuff); /* and convert it to int */ cn = i = 0; for (;;) /* loop to identify all conferences */ { if (!fgets(stuff, STUFF_SIZE, ifp)) break; strip(stuff); if (stuff[0] == 0) break; if (sscanf(stuff, "%d", &i) != 1) /* get conference number */ { /* and convert to an int */ i = 1; break; } if (!fgets(stuff, STUFF_SIZE, ifp)) /* get conference name */ { printf("\n\tCorrupted conference name in CONTROL.DAT."); exit(1); } strip(stuff); confs[cn]._num = i; confs[cn]._msgs = 0; strcpy(confs[cn++]._name, byp(stuff)); } if ((ofp = fopen("messages.txt", "w")) == NULL) /* open output file */ { printf("\n\tUnable to open MESSAGES.TXT for output."); exit(1); } sep(ofp); /* separate areas */ fprintf(ofp, " BBS Name: %s\n", BBS_name); fprintf(ofp, " BBS Location: %s\n", BBS_location); fprintf(ofp, "BBS Phone Number: %s\n", BBS_phone_number); fprintf(ofp, " Packet Date: %s\n", Packet_date); fprintf(ofp, " Packet Time: %s\n", Packet_time); fprintf(ofp, " User Name: %s\n\n", User_name); fprintf(ofp, "You have access to %d conference%s.\n", Acc_confs, (Acc_confs == 1) ? "" : "s"); sep(ofp); /* separate info above from actual messages */ printf("Indexing conference: "); /* read *.NDX files and save that info */ for (i = 0; i < cn; i++) confs[i]._msgs = nummsg(confs[i]._num); putchar('\r'); for(i=0; i < 30; i++) /* get rid of "Indexing..." message */ putchar(' '); /* (only for aesthetics) */ fclose(ifp); /* finished with CONTROL.DAT so close it */ if ((ifp = fopen("messages.dat", "rb")) == NULL) /* open message packet */ { printf("Unable to open required file MESSAGES.DAT."); fclose(ofp); exit(1); } if (readblk(ifp, stuff)) /* read in 1st record with Sparky's copyright */ { /* abort if we can't read for some reason */ printf("\n\tCan't read Sparkware's copyright message in MESSAGES.DAT."); fclose(ofp); exit(1); } for (i = 0; i < cn; i++) /* main loop -- do for every conference */ { while (confs[i]._msgs--) /* as long as the conference has messages */ { if (readhdr(ifp)) /* read the message header or abort if not found */ { printf("\n\tCan't read message header in MESSAGES.DAT file."); printf("\n\t\tConference: %d [%s]", i, confs[i]._name); printf("\n\t\t Message #: %d", confs[i]._msgs); fclose(ofp); exit(1); } /* keep user's interest up by displaying useless info */ printf("\rWriting message: %ld", public + private); fprintf(ofp, "Conference: %s\n", confs[i]._name); strncp(stuff, header._msg, 7); fprintf(ofp, "Message: %u\t", atoi(stuff)); if(header._private == 43) { fprintf(ofp, "[PRIVATE]\n"); /* flag message as private */ private += 1; } else { fprintf(ofp, "[PUBLIC]\n"); /* flag message as public */ public += 1; } strncp(stuff, header._from, 25); strip(stuff); fprintf(ofp, "From: %s\n", stuff); strncp(stuff, header._to, 25); strip(stuff); fprintf(ofp, "To: %s\n", stuff); strncp(stuff, header._subj, 37); strip(stuff); fprintf(ofp, "Subject: %s\n", stuff); strncp(stuff, header._date, 8); strncp(&stuff[20], header._time, 5); fprintf(ofp, "Date: %s %s\n\n", stuff, &stuff[20]); strncp(stuff, header._count, 6); j = atoi(stuff); /* get # of 128-byte blocks in message */ while (--j) /* read in each block */ { if (readblk(ifp, stuff)) { fclose(ofp); exit(1); } stuff[128] = 0; if (j == 1) strip(stuff); for (sp = stuff; *sp; sp++) if((unsigned char)*sp == 0xE3) /* if ã found, output newline */ fprintf(ofp, "\n"); else putc(*sp, ofp); } sep(ofp); } } fclose(ofp); /* close text file messages.txt */ fclose(ifp); /* close binary file messages.dat */ if( (public + private) <= 0L) /* this shouldn't happen unless Sparky */ { /* changes the .QWK format (again!) */ printf("\n\tPacket error: no messages found [incompatible format?]\n"); unlink("MESSAGES.TXT"); /* clean up garbage in this case */ exit(1); } else { printf("\r Public Messages: %ld", public); printf("\nPrivate Messages: %ld", private); printf("\n Total Messages: %ld\n\n", public + private); } } int nummsg(int n) /* Read Index files and process them */ { FILE *ifp; int i, j, ch; char name[20]; char five[5]; sprintf(name, "%03d.ndx", n); i = 0; if ((ifp = fopen(name, "rb")) != NULL) { printf("%03d\b\b\b", n); /* only show conf # if file is found */ /* I can't explain this next routine */ /* because it isn't mine. I found it */ /* scrawled in an old MSC manual. */ /* It does work, however, for both */ /* TC and MSC. MSBIN is a damnable */ for (;;) /* choice for indexing... */ { for (j = 0; j < 5; j++) { if ((ch = getc(ifp)) == EOF) ch = 26; five[j] = ch; } for (j = 0; j < 5 && five[j] == 26; j++) ; if (j == 5) break; i++; } fclose(ifp); } return(i); } int readblk(FILE *fp, char *buff) { int i, ch; for (i = 0; i < 128; i++) if ((ch = getc(fp)) == EOF) return(1); else *buff++ = ch; return(0); } int readhdr(FILE *fp) { if ( fread(&header, 1, sizeof(struct hdr), fp) != sizeof(struct hdr) ) return(1); else return(0); } void strncp(char *d, char *s, int n) /* this was for the CP/M version */ { while (n-- && (*d++ = *s++)) ; *d = 0; } void sep(FILE *fp) { int i; putc('\n',fp); for (i = 0; i < 70; i++) putc('-',fp); putc('\n',fp); }