|
|
1.1 root 1: /* smbutil.c */
2:
3: /* Synchronet message base (SMB) utility */
4:
5: /* $Id: smbutil.c,v 1.12 2000/11/28 02:46:10 rswindell Exp $ */
6:
7: /****************************************************************************
8: * @format.tab-size 4 (Plain Text/Source Code File Header) *
9: * @format.use-tabs true (see http://www.synchro.net/ptsc_hdr.html) *
10: * *
11: * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html *
12: * *
13: * This program is free software; you can redistribute it and/or *
14: * modify it under the terms of the GNU General Public License *
15: * as published by the Free Software Foundation; either version 2 *
16: * of the License, or (at your option) any later version. *
17: * See the GNU General Public License for more details: gpl.txt or *
18: * http://www.fsf.org/copyleft/gpl.html *
19: * *
20: * Anonymous FTP access to the most recent released source is available at *
21: * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net *
22: * *
23: * Anonymous CVS access to the development source and modification history *
24: * is available at cvs.synchro.net:/cvsroot/sbbs, example: *
25: * cvs -d :pserver:[email protected]:/cvsroot/sbbs login *
26: * (just hit return, no password is necessary) *
27: * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src *
28: * *
29: * For Synchronet coding style and modification guidelines, see *
30: * http://www.synchro.net/source.html *
31: * *
32: * You are encouraged to submit any modifications (preferably in Unix diff *
33: * format) via e-mail to [email protected] *
34: * *
35: * Note: If this box doesn't appear square, then you need to fix your tabs. *
36: ****************************************************************************/
37:
38: #define SMBUTIL_VER "2.20"
39:
40: #define NOANALYSIS (1L<<0)
41:
42: #ifdef __WATCOMC__
43: #define ffblk find_t
44: #define findfirst(x,y,z) _dos_findfirst(x,z,y)
45: #define findnext(x) _dos_findnext(x)
46: #endif
47:
48: #if defined(_WIN32)
49: #include <ctype.h> /* isdigit() */
50: #include <conio.h> /* getch() */
51: #endif
52:
53: /* ANSI */
54: #include <time.h> /* time */
55: #include <errno.h> /* errno */
56: #include <string.h> /* strrchr */
57:
58: #include "smblib.h"
59: #include "smbwrap.h"
60: #include "crc32.h"
61:
62: #ifdef __WATCOMC__
63: #include <dos.h>
64: #endif
65:
66: /* gets is dangerous */
67: #define gets(str) fgets((str), sizeof(str) - 1, stdin)
68:
69: /********************/
70: /* Global variables */
71: /********************/
72:
73: smb_t smb;
74: ulong mode=0L;
75: ushort tzone=PST;
76: char filein[128];
77: char attach[128];
78:
79: /************************/
80: /* Program usage/syntax */
81: /************************/
82:
83: char *usage=
84: "usage: smbutil [-opts] cmd <filespec.shd>\n"
85: "\n"
86: "cmd:\n"
87: " l[n] = list msgs starting at number n\n"
88: " r[n] = read msgs starting at number n\n"
89: " v[n] = view msg headers starting at number n\n"
90: " i<f> = import msg from text file f\n"
91: " e<f> = import e-mail from text file f\n"
92: " n<f> = import netmail from text file f\n"
93: " s = display msg base status\n"
94: " c = change msg base status\n"
95: " m = maintain msg base - delete old msgs and msgs over max\n"
96: " p[k] = pack msg base (k specifies minimum packable Kbytes)\n"
97: "opts:\n"
98: " c = create message base if it doesn't exist\n"
99: " a = always pack msg base (disable compression analysis)\n"
100: " z[n] = set time zone (n=min +/- from UT or 'EST','EDT','CST',etc)\n"
101: ;
102:
103: char *wday[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
104: char *mon[]={"Jan","Feb","Mar","Apr","May","Jun"
105: ,"Jul","Aug","Sep","Oct","Nov","Dec"};
106:
107: /****************************************************************************/
108: /* Updates 16-bit "rcrc" with character 'ch' */
109: /****************************************************************************/
110: void ucrc16(uchar ch, ushort *rcrc) {
111: ushort i, cy;
112: uchar nch=ch;
113:
114: for (i=0; i<8; i++) {
115: cy=*rcrc & 0x8000;
116: *rcrc<<=1;
117: if (nch & 0x80) *rcrc |= 1;
118: nch<<=1;
119: if (cy) *rcrc ^= 0x1021; }
120: }
121:
122: /****************************************************************************/
123: /* Returns CRC-16 of string (not including terminating NULL) */
124: /****************************************************************************/
125: ushort crc16(char *str)
126: {
127: int i=0;
128: ushort crc=0;
129:
130: ucrc16(0,&crc);
131: while(str[i])
132: ucrc16(str[i++],&crc);
133: ucrc16(0,&crc);
134: ucrc16(0,&crc);
135: return(crc);
136: }
137:
138: void remove_re(char *str)
139: {
140: while(!strnicmp(str,"RE:",3)) {
141: strcpy(str,str+3);
142: while(str[0]==SP)
143: strcpy(str,str+1);
144: }
145: }
146:
147: /************************************************/
148: /* Truncates white-space chars off end of 'str' */
149: /************************************************/
150: static void truncsp(char *str)
151: {
152: uint c;
153:
154: c=strlen(str);
155: while(c && (uchar)str[c-1]<=' ') c--;
156: str[c]=0;
157: }
158:
159:
160:
161: /****************************************************************************/
162: /* Adds a new message to the message base */
163: /****************************************************************************/
164: void postmsg(char type)
165: {
166: char str[128],buf[SDT_BLOCK_LEN];
167: ushort xlat,net;
168: int i,j,k,file;
169: long length;
170: ulong offset,crc=0xffffffffUL;
171: FILE *instream;
172: smbmsg_t msg;
173:
174: length=flength(filein);
175: if(length<1L) {
176: printf("\n\7!Invalid file size for '%s'\n",filein);
177: exit(1); }
178: length+=2; /* for translation string */
179: if(!(smb.status.attr&SMB_HYPERALLOC)) {
180: i=smb_open_da(&smb);
181: if(i) {
182: printf("\n\7!smb_open_da returned %d\n",i);
183: exit(1); }
184: offset=smb_allocdat(&smb,length,1);
185: smb_close_da(&smb); }
186: else
187: offset=smb_hallocdat(&smb);
188:
189: if((file=open(filein,O_RDONLY|O_BINARY))==-1
190: || (instream=fdopen(file,"rb"))==NULL) {
191: printf("\n\7!Error opening %s for read\n",filein);
192: smb_freemsgdat(&smb,offset,length,1);
193: exit(1); }
194: setvbuf(instream,NULL,_IOFBF,32*1024);
195: fseek(smb.sdt_fp,offset,SEEK_SET);
196: xlat=XLAT_NONE;
197: fwrite(&xlat,2,1,smb.sdt_fp);
198: k=SDT_BLOCK_LEN-2;
199: while(!feof(instream)) {
200: memset(buf,0,k);
201: j=fread(buf,1,k,instream);
202: if(smb.status.max_crcs)
203: for(i=0;i<j;i++)
204: crc=ucrc32(buf[i],crc);
205: fwrite(buf,k,1,smb.sdt_fp);
206: k=SDT_BLOCK_LEN; }
207: fflush(smb.sdt_fp);
208: fclose(instream);
209: crc=~crc;
210:
211: memset(&msg,0,sizeof(smbmsg_t));
212: memcpy(msg.hdr.id,"SHD\x1a",4);
213: msg.hdr.version=smb_ver();
214: msg.hdr.when_written.time=time(NULL);
215: msg.hdr.when_written.zone=tzone;
216: msg.hdr.when_imported=msg.hdr.when_written;
217:
218: if(smb.status.max_crcs) {
219: i=smb_addcrc(&smb,crc);
220: if(i) {
221: printf("\n\7!smb_addcrc returned %d\n",i);
222: smb_freemsgdat(&smb,offset,length,1);
223: exit(1); } }
224:
225: msg.hdr.offset=offset;
226:
227: printf("To User Name: ");
228: fgets(str,sizeof(str)-1,stdin);
229: truncsp(str);
230: i=smb_hfield(&msg,RECIPIENT,(ushort)strlen(str),str);
231: if(i) {
232: printf("\n\7!smb_hfield returned %d\n",i);
233: smb_freemsgdat(&smb,offset,length,1);
234: exit(1); }
235: if(type=='E' || type=='N')
236: smb.status.attr|=SMB_EMAIL;
237: if(smb.status.attr&SMB_EMAIL) {
238: printf("To User Number (0=QWKnet or Internet): ");
239: gets(str);
240: truncsp(str);
241: i=smb_hfield(&msg,RECIPIENTEXT,(ushort)strlen(str),str);
242: if(i) {
243: printf("\n\7!smb_hfield returned %d\n",i);
244: smb_freemsgdat(&smb,offset,length,1);
245: exit(1); }
246: msg.idx.to=atoi(str); }
247: else {
248: strlwr(str);
249: msg.idx.to=crc16(str); }
250:
251: if(smb.status.attr&SMB_EMAIL && (type=='N' || !msg.idx.to)) {
252: printf("To Address: ");
253: gets(str);
254: truncsp(str);
255: if(*str) {
256: if(strchr(str,'.'))
257: net=NET_INTERNET;
258: else
259: net=NET_QWK;
260: i=smb_hfield(&msg,RECIPIENTNETTYPE,sizeof(net),&net);
261: if(i) {
262: printf("\n\7!smb_hfield returned %d\n",i);
263: smb_freemsgdat(&smb,offset,length,1);
264: exit(1); }
265: i=smb_hfield(&msg,RECIPIENTNETADDR,(ushort)strlen(str),str);
266: if(i) {
267: printf("\n\7!smb_hfield returned %d\n",i);
268: smb_freemsgdat(&smb,offset,length,1);
269: exit(1); } } }
270:
271: printf("From User Name: ");
272: gets(str);
273: truncsp(str);
274: i=smb_hfield(&msg,SENDER,(ushort)strlen(str),str);
275: if(i) {
276: printf("\n\7!smb_hfield returned %d\n",i);
277: smb_freemsgdat(&smb,offset,length,1);
278: exit(1); }
279: if(smb.status.attr&SMB_EMAIL) {
280: printf("From User Number: ");
281: gets(str);
282: truncsp(str);
283: i=smb_hfield(&msg,SENDEREXT,(ushort)strlen(str),str);
284: if(i) {
285: printf("\n\7!smb_hfield returned %d\n",i);
286: smb_freemsgdat(&smb,offset,length,1);
287: exit(1); }
288: msg.idx.from=atoi(str); }
289: else {
290: strlwr(str);
291: msg.idx.from=crc16(str); }
292:
293: printf("Subject: ");
294: gets(str);
295: truncsp(str);
296: i=smb_hfield(&msg,SUBJECT,(ushort)strlen(str),str);
297: if(i) {
298: printf("\n\7!smb_hfield returned %d\n",i);
299: smb_freemsgdat(&smb,offset,length,1);
300: exit(1); }
301: remove_re(str);
302: strlwr(str);
303: msg.idx.subj=crc16(str);
304:
305: i=smb_dfield(&msg,TEXT_BODY,length);
306: if(i) {
307: printf("\n\7!smb_dfield returned %d\n",i);
308: smb_freemsgdat(&smb,offset,length,1);
309: exit(1); }
310:
311: i=smb_addmsghdr(&smb,&msg,smb.status.attr&SMB_HYPERALLOC);
312:
313: if(i) {
314: printf("\n\7!smb_addmsghdr returned %d\n",i);
315: smb_freemsgdat(&smb,offset,length,1);
316: exit(1); }
317: smb_freemsgmem(&msg);
318:
319: }
320:
321: /****************************************************************************/
322: /* Shows the message base header */
323: /****************************************************************************/
324: void showstatus(void)
325: {
326: int i;
327:
328: i=smb_locksmbhdr(&smb);
329: if(i) {
330: printf("\n\7!smb_locksmbhdr returned %d\n",i);
331: return; }
332: i=smb_getstatus(&smb);
333: smb_unlocksmbhdr(&smb);
334: if(i) {
335: printf("\n\7!smb_getstatus returned %d\n",i);
336: return; }
337: printf("last_msg =%lu\n"
338: "total_msgs =%lu\n"
339: "header_offset =%lu\n"
340: "max_crcs =%lu\n"
341: "max_msgs =%lu\n"
342: "max_age =%u\n"
343: "attr =%04Xh\n"
344: ,smb.status.last_msg
345: ,smb.status.total_msgs
346: ,smb.status.header_offset
347: ,smb.status.max_crcs
348: ,smb.status.max_msgs
349: ,smb.status.max_age
350: ,smb.status.attr
351: );
352: }
353:
354: /****************************************************************************/
355: /* Configure message base header */
356: /****************************************************************************/
357: void config(void)
358: {
359: char max_msgs[128],max_crcs[128],max_age[128],header_offset[128],attr[128];
360: int i;
361:
362: i=smb_locksmbhdr(&smb);
363: if(i) {
364: printf("\n\7!smb_locksmbhdr returned %d\n",i);
365: return; }
366: i=smb_getstatus(&smb);
367: smb_unlocksmbhdr(&smb);
368: if(i) {
369: printf("\n\7!smb_getstatus returned %d\n",i);
370: return; }
371: printf("Header offset =%-5lu New value (CR=No Change): "
372: ,smb.status.header_offset);
373: gets(header_offset);
374: printf("Max msgs =%-5lu New value (CR=No Change): "
375: ,smb.status.max_msgs);
376: gets(max_msgs);
377: printf("Max crcs =%-5lu New value (CR=No Change): "
378: ,smb.status.max_crcs);
379: gets(max_crcs);
380: printf("Max age =%-5u New value (CR=No Change): "
381: ,smb.status.max_age);
382: gets(max_age);
383: printf("Attributes =%-5u New value (CR=No Change): "
384: ,smb.status.attr);
385: gets(attr);
386: i=smb_locksmbhdr(&smb);
387: if(i) {
388: printf("\n\7!smb_locksmbhdr returned %d\n",i);
389: return; }
390: i=smb_getstatus(&smb);
391: if(i) {
392: printf("\n\7!smb_getstatus returned %d\n",i);
393: smb_unlocksmbhdr(&smb);
394: return; }
395: if(isdigit(max_msgs[0]))
396: smb.status.max_msgs=atol(max_msgs);
397: if(isdigit(max_crcs[0]))
398: smb.status.max_crcs=atol(max_crcs);
399: if(isdigit(max_age[0]))
400: smb.status.max_age=atoi(max_age);
401: if(isdigit(header_offset[0]))
402: smb.status.header_offset=atol(header_offset);
403: if(isdigit(attr[0]))
404: smb.status.attr=atoi(attr);
405: i=smb_putstatus(&smb);
406: smb_unlocksmbhdr(&smb);
407: if(i)
408: printf("\n\7!smb_putstatus returned %d\n",i);
409: }
410:
411: /****************************************************************************/
412: /* Lists messages' to, from, and subject */
413: /****************************************************************************/
414: void listmsgs(ulong start, ulong count)
415: {
416: int i;
417: ulong l=0;
418: smbmsg_t msg;
419:
420: if(!start)
421: start=1;
422: fseek(smb.sid_fp,(start-1L)*sizeof(idxrec_t),SEEK_SET);
423: while(l<count) {
424: if(!fread(&msg.idx,1,sizeof(idxrec_t),smb.sid_fp))
425: break;
426: i=smb_lockmsghdr(&smb,&msg);
427: if(i) {
428: printf("\n\7!smb_lockmsghdr returned %d\n",i);
429: break; }
430: i=smb_getmsghdr(&smb,&msg);
431: smb_unlockmsghdr(&smb,&msg);
432: if(i) {
433: printf("\n\7!smb_getmsghdr returned %d\n",i);
434: break; }
435: printf("%4lu %-25.25s %-25.25s %.20s\n"
436: ,msg.hdr.number,msg.from,msg.to,msg.subj);
437: smb_freemsgmem(&msg);
438: l++; }
439: }
440:
441: /****************************************************************************/
442: /* Returns an ASCII string for FidoNet address 'addr' */
443: /****************************************************************************/
444: char *faddrtoa(fidoaddr_t addr)
445: {
446: static char str[25];
447: char point[25];
448:
449: sprintf(str,"%u:%u/%u",addr.zone,addr.net,addr.node);
450: if(addr.point) {
451: sprintf(point,".%u",addr.point);
452: strcat(str,point); }
453: return(str);
454: }
455:
456: char *binstr(uchar *buf, ushort length)
457: {
458: static char str[512];
459: char tmp[128];
460: int i;
461:
462: str[0]=0;
463: for(i=0;i<length;i++)
464: if(buf[i] && (buf[i]<SP || buf[i]>=0x7f) && buf[i]!=CR && buf[i]!=LF)
465: break;
466: if(i==length) /* not binary */
467: return(buf);
468: for(i=0;i<length;i++) {
469: sprintf(tmp,"%02X ",buf[i]);
470: strcat(str,tmp);
471: if(i>=100) {
472: strcat(str,"...");
473: break;
474: }
475: }
476: return(str);
477: }
478:
479: /****************************************************************************/
480: /* Generates a 24 character ASCII string that represents the time_t pointer */
481: /* Used as a replacement for ctime() */
482: /****************************************************************************/
483: char *timestr(time_t *intime)
484: {
485: static char str[256];
486: char mer[3],hour;
487: struct tm *gm;
488:
489: gm=localtime(intime);
490: if(gm==NULL) {
491: strcpy(str,"Invalid Time");
492: return(str); }
493: if(gm->tm_hour>=12) {
494: if(gm->tm_hour==12)
495: hour=12;
496: else
497: hour=gm->tm_hour-12;
498: strcpy(mer,"pm"); }
499: else {
500: if(gm->tm_hour==0)
501: hour=12;
502: else
503: hour=gm->tm_hour;
504: strcpy(mer,"am"); }
505: sprintf(str,"%s %s %02d %4d %02d:%02d %s"
506: ,wday[gm->tm_wday],mon[gm->tm_mon],gm->tm_mday,1900+gm->tm_year
507: ,hour,gm->tm_min,mer);
508: return(str);
509: }
510:
511:
512: /****************************************************************************/
513: /* Converts when_t.zone into ASCII format */
514: /****************************************************************************/
515: char *zonestr(short zone)
516: {
517: static char str[32];
518:
519: switch((ushort)zone) {
520: case 0: return("UT");
521: case AST: return("AST");
522: case EST: return("EST");
523: case CST: return("CST");
524: case MST: return("MST");
525: case PST: return("PST");
526: case YST: return("YST");
527: case HST: return("HST");
528: case BST: return("BST");
529: case ADT: return("ADT");
530: case EDT: return("EDT");
531: case CDT: return("CDT");
532: case MDT: return("MDT");
533: case PDT: return("PDT");
534: case YDT: return("YDT");
535: case HDT: return("HDT");
536: case BDT: return("BDT");
537: case MID: return("MID");
538: case VAN: return("VAN");
539: case EDM: return("EDM");
540: case WIN: return("WIN");
541: case BOG: return("BOG");
542: case CAR: return("CAR");
543: case RIO: return("RIO");
544: case FER: return("FER");
545: case AZO: return("AZO");
546: case LON: return("LON");
547: case BER: return("BER");
548: case ATH: return("ATH");
549: case MOS: return("MOS");
550: case DUB: return("DUB");
551: case KAB: return("KAB");
552: case KAR: return("KAR");
553: case BOM: return("BOM");
554: case KAT: return("KAT");
555: case DHA: return("DHA");
556: case BAN: return("BAN");
557: case HON: return("HON");
558: case TOK: return("TOK");
559: case SYD: return("SYD");
560: case NOU: return("NOU");
561: case WEL: return("WEL");
562: }
563:
564: sprintf(str,"%02d:%02u",zone/60,zone<0 ? (-zone)%60 : zone%60);
565: return(str);
566: }
567:
568:
569: /****************************************************************************/
570: /* Displays message header information */
571: /****************************************************************************/
572: void viewmsgs(ulong start, ulong count)
573: {
574: char when_written[128]
575: ,when_imported[128];
576: int i;
577: ulong l=0;
578: smbmsg_t msg;
579:
580: if(!start)
581: start=1;
582: fseek(smb.sid_fp,(start-1L)*sizeof(idxrec_t),SEEK_SET);
583: while(l<count) {
584: if(!fread(&msg.idx,1,sizeof(idxrec_t),smb.sid_fp))
585: break;
586: i=smb_lockmsghdr(&smb,&msg);
587: if(i) {
588: printf("\n\7!smb_lockmsghdr returned %d\n",i);
589: break; }
590: i=smb_getmsghdr(&smb,&msg);
591: smb_unlockmsghdr(&smb,&msg);
592: if(i) {
593: printf("\n\7!smb_getmsghdr returned %d\n",i);
594: break; }
595:
596: sprintf(when_written,"%.24s %s"
597: ,timestr((time_t*)&msg.hdr.when_written.time)
598: ,zonestr(msg.hdr.when_written.zone));
599: sprintf(when_imported,"%.24s %s"
600: ,timestr((time_t*)&msg.hdr.when_imported.time)
601: ,zonestr(msg.hdr.when_imported.zone));
602:
603: printf( "%-20.20s %s\n"
604: "%-20.20s %s\n"
605: "%-20.20s %s\n"
606: "%-20.20s %04Xh\n"
607: "%-20.20s %04Xh\n"
608: "%-20.20s %u\n"
609: "%-20.20s %04Xh\n"
610: "%-20.20s %08lXh\n"
611: "%-20.20s %08lXh\n"
612: "%-20.20s %s\n"
613: "%-20.20s %s\n"
614: "%-20.20s %ld (%ld)\n"
615: "%-20.20s %ld\n"
616: "%-20.20s %ld\n"
617: "%-20.20s %ld\n"
618: "%-20.20s %s\n"
619: "%-20.20s %06lXh\n"
620: "%-20.20s %u\n",
621:
622: "subj",
623: msg.subj,
624:
625: "from",
626: msg.from,
627:
628: "to",
629: msg.to,
630:
631: "type",
632: msg.hdr.type,
633:
634: "version",
635: msg.hdr.version,
636:
637: "length",
638: msg.hdr.length,
639:
640: "attr",
641: msg.hdr.attr,
642:
643: "auxattr",
644: msg.hdr.auxattr,
645:
646: "netattr",
647: msg.hdr.netattr,
648:
649: "when_written",
650: when_written,
651:
652: "when_imported",
653: when_imported,
654:
655: "number",
656: msg.hdr.number,
657: ftell(smb.sid_fp)/sizeof(idxrec_t),
658:
659: "thread_orig",
660: msg.hdr.thread_orig,
661:
662: "thread_next",
663: msg.hdr.thread_next,
664:
665: "thread_first",
666: msg.hdr.thread_first,
667:
668: "reserved[16]",
669: binstr(msg.hdr.reserved,16),
670:
671: "offset",
672: msg.hdr.offset,
673:
674: "total_dfields",
675: msg.hdr.total_dfields
676: );
677: for(i=0;i<msg.hdr.total_dfields;i++)
678: printf("dfield[%02u].type %02Xh\n"
679: "dfield[%02u].offset %lu\n"
680: "dfield[%02u].length %lu\n"
681: ,i,msg.dfield[i].type
682: ,i,msg.dfield[i].offset
683: ,i,msg.dfield[i].length);
684:
685: for(i=0;i<msg.total_hfields;i++)
686: printf("hfield[%02u].type %02Xh\n"
687: "hfield[%02u].length %d\n"
688: "hfield[%02u]_dat %s\n"
689: ,i,msg.hfield[i].type
690: ,i,msg.hfield[i].length
691: ,i,binstr(msg.hfield_dat[i],msg.hfield[i].length));
692:
693: if(msg.from_net.type)
694: printf("from_net.type %02Xh\n"
695: "from_net.addr %s\n"
696: ,msg.from_net.type
697: ,msg.from_net.type==NET_FIDO
698: ? faddrtoa(*(fidoaddr_t *)msg.from_net.addr) : msg.from_net.addr);
699:
700: if(msg.to_net.type)
701: printf("to_net.type %02Xh\n"
702: "to_net.addr %s\n"
703: ,msg.to_net.type
704: ,msg.to_net.type==NET_FIDO
705: ? faddrtoa(*(fidoaddr_t *)msg.to_net.addr) : msg.to_net.addr);
706:
707: if(msg.replyto_net.type)
708: printf("replyto_net.type %02Xh\n"
709: "replyto_net.addr %s\n"
710: ,msg.replyto_net.type
711: ,msg.replyto_net.type==NET_FIDO
712: ? faddrtoa(*(fidoaddr_t *)msg.replyto_net.addr)
713: : msg.replyto_net.addr);
714:
715: printf("from_agent %02Xh\n"
716: "to_agent %02Xh\n"
717: "replyto_agent %02Xh\n"
718: ,msg.from_agent
719: ,msg.to_agent
720: ,msg.replyto_agent);
721:
722: printf("\n");
723: smb_freemsgmem(&msg);
724: l++; }
725: }
726:
727: /****************************************************************************/
728: /* Maintain message base - deletes messages older than max age (in days) */
729: /* or messages that exceed maximum */
730: /****************************************************************************/
731: void maint(void)
732: {
733: int i;
734: ulong l,m,n,f,flagged=0;
735: time_t now;
736: smbmsg_t msg;
737: idxrec_t HUGE16 *idx;
738:
739: printf("Maintaining %s\r\n",smb.file);
740: now=time(NULL);
741: i=smb_locksmbhdr(&smb);
742: if(i) {
743: printf("\n\7!smb_locksmbhdr returned %d\n",i);
744: return; }
745: i=smb_getstatus(&smb);
746: if(i) {
747: smb_unlocksmbhdr(&smb);
748: printf("\n\7!smb_getstatus returned %d\n",i);
749: return; }
750: if(!smb.status.total_msgs) {
751: smb_unlocksmbhdr(&smb);
752: printf("Empty\n");
753: return; }
754: printf("Loading index...\n");
755: if((idx=(idxrec_t *)LMALLOC(sizeof(idxrec_t)*smb.status.total_msgs))
756: ==NULL) {
757: smb_unlocksmbhdr(&smb);
758: printf("\n\7!Error allocating %lu bytes of memory\n"
759: ,sizeof(idxrec_t)*smb.status.total_msgs);
760: return; }
761: fseek(smb.sid_fp,0L,SEEK_SET);
762: for(l=0;l<smb.status.total_msgs;l++) {
763: printf("%lu of %lu\r"
764: ,l+1,smb.status.total_msgs);
765: if(!fread(&idx[l],1,sizeof(idxrec_t),smb.sid_fp))
766: break; }
767: printf("\nDone.\n\n");
768:
769: printf("Scanning for pre-flagged messages...\n");
770: for(m=0;m<l;m++) {
771: printf("\r%2u%%",m ? (long)(100.0/((float)l/m)) : 0);
772: if(idx[m].attr&MSG_DELETE)
773: flagged++; }
774: printf("\r100%% (%lu pre-flagged for deletion)\n",flagged);
775:
776: if(smb.status.max_age) {
777: printf("Scanning for messages more than %u days old...\n"
778: ,smb.status.max_age);
779: for(m=f=0;m<l;m++) {
780: printf("\r%2u%%",m ? (long)(100.0/((float)l/m)) : 0);
781: if(idx[m].attr&(MSG_PERMANENT|MSG_DELETE))
782: continue;
783: if((ulong)now>idx[m].time && (now-idx[m].time)/(24L*60L*60L)
784: >smb.status.max_age) {
785: f++;
786: flagged++;
787: idx[m].attr|=MSG_DELETE; } } /* mark for deletion */
788: printf("\r100%% (%lu flagged for deletion)\n",f); }
789:
790: printf("Scanning for read messages to be killed...\n");
791: for(m=f=0;m<l;m++) {
792: printf("\r%2u%%",m ? (long)(100.0/((float)l/m)) : 0);
793: if(idx[m].attr&(MSG_PERMANENT|MSG_DELETE))
794: continue;
795: if((idx[m].attr&(MSG_READ|MSG_KILLREAD))==(MSG_READ|MSG_KILLREAD)) {
796: f++;
797: flagged++;
798: idx[m].attr|=MSG_DELETE; } }
799: printf("\r100%% (%lu flagged for deletion)\n",f);
800:
801: if(l-flagged>smb.status.max_msgs) {
802: printf("Flagging excess messages for deletion...\n");
803: for(m=n=0,f=flagged;l-flagged>smb.status.max_msgs && m<l;m++) {
804: if(idx[m].attr&(MSG_PERMANENT|MSG_DELETE))
805: continue;
806: printf("%lu of %lu\r",++n,(l-f)-smb.status.max_msgs);
807: flagged++;
808: idx[m].attr|=MSG_DELETE; } /* mark for deletion */
809: printf("\nDone.\n\n"); }
810:
811: if(!flagged) { /* No messages to delete */
812: LFREE(idx);
813: smb_unlocksmbhdr(&smb);
814: return; }
815:
816: if(!(mode&NOANALYSIS)) {
817:
818: printf("Freeing allocated header and data blocks for deleted messages...\n");
819: if(!(smb.status.attr&SMB_HYPERALLOC)) {
820: i=smb_open_da(&smb);
821: if(i) {
822: smb_unlocksmbhdr(&smb);
823: printf("\n\7!smb_open_da returned %d\n",i);
824: exit(1); }
825: i=smb_open_ha(&smb);
826: if(i) {
827: smb_unlocksmbhdr(&smb);
828: printf("\n\7!smb_open_ha returned %d\n",i);
829: exit(1); } }
830:
831: for(m=n=0;m<l;m++) {
832: if(idx[m].attr&MSG_DELETE) {
833: printf("%lu of %lu\r",++n,flagged);
834: msg.idx=idx[m];
835: msg.hdr.number=msg.idx.number;
836: if((i=smb_getmsgidx(&smb,&msg))!=0) {
837: printf("\n\7!smb_getmsgidx returned %d\n",i);
838: continue; }
839: i=smb_lockmsghdr(&smb,&msg);
840: if(i) {
841: printf("\n\7!smb_lockmsghdr returned %d\n",i);
842: break; }
843: if((i=smb_getmsghdr(&smb,&msg))!=0) {
844: smb_unlockmsghdr(&smb,&msg);
845: printf("\n\7!smb_getmsghdr returned %d\n",i);
846: break; }
847: msg.hdr.attr|=MSG_DELETE; /* mark header as deleted */
848: if((i=smb_putmsg(&smb,&msg))!=0) {
849: smb_freemsgmem(&msg);
850: smb_unlockmsghdr(&smb,&msg);
851: printf("\n\7!smb_putmsg returned %d\n",i);
852: break; }
853: smb_unlockmsghdr(&smb,&msg);
854: if((i=smb_freemsg(&smb,&msg))!=0) {
855: smb_freemsgmem(&msg);
856: printf("\n\7!smb_freemsg returned %d\n",i);
857: break; }
858: smb_freemsgmem(&msg); } }
859: if(!(smb.status.attr&SMB_HYPERALLOC)) {
860: smb_close_ha(&smb);
861: smb_close_da(&smb); }
862: printf("\nDone.\n\n"); }
863:
864: printf("Re-writing index...\n");
865: rewind(smb.sid_fp);
866: if(chsize(fileno(smb.sid_fp),0L))
867: printf("chsize failed!\n");
868: for(m=n=0;m<l;m++) {
869: if(idx[m].attr&MSG_DELETE)
870: continue;
871: printf("%lu of %lu\r",++n,l-flagged);
872: fwrite(&idx[m],sizeof(idxrec_t),1,smb.sid_fp); }
873: printf("\nDone.\n\n");
874: fflush(smb.sid_fp);
875:
876: LFREE(idx);
877: smb.status.total_msgs-=flagged;
878: smb_putstatus(&smb);
879: smb_unlocksmbhdr(&smb);
880: }
881:
882:
883: typedef struct {
884: ulong old,new;
885: } datoffset_t;
886:
887: /****************************************************************************/
888: /* Removes all unused blocks from SDT and SHD files */
889: /****************************************************************************/
890: void packmsgs(ulong packable)
891: {
892: uchar str[128],buf[SDT_BLOCK_LEN],ch,fname[128],tmpfname[128];
893: int i,size;
894: ulong l,m,n,datoffsets=0,length,total,now;
895: FILE *tmp_sdt,*tmp_shd,*tmp_sid;
896: smbhdr_t hdr;
897: smbmsg_t msg;
898: datoffset_t *datoffset=NULL;
899:
900: now=time(NULL);
901: printf("Packing %s\n",smb.file);
902: i=smb_locksmbhdr(&smb);
903: if(i) {
904: printf("\n\7!smb_locksmbhdr returned %d\n",i);
905: return; }
906: i=smb_getstatus(&smb);
907: if(i) {
908: smb_unlocksmbhdr(&smb);
909: printf("\n\7!smb_getstatus returned %d\n",i);
910: return; }
911:
912: if(!(smb.status.attr&SMB_HYPERALLOC)) {
913: i=smb_open_ha(&smb);
914: if(i) {
915: smb_unlocksmbhdr(&smb);
916: printf("\n\7!smb_open_ha returned %d\n",i);
917: return; }
918: i=smb_open_da(&smb);
919: if(i) {
920: smb_unlocksmbhdr(&smb);
921: smb_close_ha(&smb);
922: printf("\n\7!smb_open_da returned %d\n",i);
923: return; } }
924:
925: if(!smb.status.total_msgs) {
926: printf("Empty\n");
927: rewind(smb.shd_fp);
928: chsize(fileno(smb.shd_fp),smb.status.header_offset);
929: rewind(smb.sdt_fp);
930: chsize(fileno(smb.sdt_fp),0L);
931: rewind(smb.sid_fp);
932: chsize(fileno(smb.sid_fp),0L);
933: if(!(smb.status.attr&SMB_HYPERALLOC)) {
934: rewind(smb.sha_fp);
935: chsize(fileno(smb.sha_fp),0L);
936: rewind(smb.sda_fp);
937: chsize(fileno(smb.sda_fp),0L);
938: smb_close_ha(&smb);
939: smb_close_da(&smb); }
940: smb_unlocksmbhdr(&smb);
941: return; }
942:
943:
944: if(!(smb.status.attr&SMB_HYPERALLOC) && !(mode&NOANALYSIS)) {
945: printf("Analyzing data blocks...\n");
946:
947: length=filelength(fileno(smb.sda_fp));
948:
949: fseek(smb.sda_fp,0L,SEEK_SET);
950: for(l=m=0;l<length;l+=2) {
951: printf("\r%2u%% ",l ? (long)(100.0/((float)length/l)) : 0);
952: i=0;
953: if(!fread(&i,2,1,smb.sda_fp))
954: break;
955: if(!i)
956: m++; }
957:
958: printf("\rAnalyzing header blocks...\n");
959:
960: length=filelength(fileno(smb.sha_fp));
961:
962: fseek(smb.sha_fp,0L,SEEK_SET);
963: for(l=n=0;l<length;l++) {
964: printf("\r%2u%% ",l ? (long)(100.0/((float)length/l)) : 0);
965: ch=0;
966: if(!fread(&ch,1,1,smb.sha_fp))
967: break;
968: if(!ch)
969: n++; }
970:
971: if(!m && !n) {
972: printf("\rAlready compressed.\n\n");
973: smb_close_ha(&smb);
974: smb_close_da(&smb);
975: smb_unlocksmbhdr(&smb);
976: return; }
977:
978: if(packable && (m*SDT_BLOCK_LEN)+(n*SHD_BLOCK_LEN)<packable*1024L) {
979: printf("\rLess than %luk compressable bytes.\n\n",packable);
980: smb_close_ha(&smb);
981: smb_close_da(&smb);
982: smb_unlocksmbhdr(&smb);
983: return; }
984:
985: printf("\rCompressing %lu data blocks (%lu bytes)\n"
986: " and %lu header blocks (%lu bytes)\n"
987: ,m,m*SDT_BLOCK_LEN,n,n*SHD_BLOCK_LEN); }
988:
989: if(!(smb.status.attr&SMB_HYPERALLOC)) {
990: rewind(smb.sha_fp);
991: chsize(fileno(smb.sha_fp),0L); /* Reset both allocation tables */
992: rewind(smb.sda_fp);
993: chsize(fileno(smb.sda_fp),0L); }
994:
995: if(smb.status.attr&SMB_HYPERALLOC && !(mode&NOANALYSIS)) {
996: printf("Analyzing %s\n",smb.file);
997:
998: length=filelength(fileno(smb.shd_fp));
999: m=n=0;
1000: for(l=smb.status.header_offset;l<length;l+=size) {
1001: printf("\r%2u%% ",(long)(100.0/((float)length/l)));
1002: msg.idx.offset=l;
1003: if((i=smb_lockmsghdr(&smb,&msg))!=0) {
1004: printf("\n(%06lX) smb_lockmsghdr returned %d\n",l,i);
1005: size=SHD_BLOCK_LEN;
1006: continue; }
1007: if((i=smb_getmsghdr(&smb,&msg))!=0) {
1008: smb_unlockmsghdr(&smb,&msg);
1009: m++;
1010: size=SHD_BLOCK_LEN;
1011: continue; }
1012: smb_unlockmsghdr(&smb,&msg);
1013: if(msg.hdr.attr&MSG_DELETE) {
1014: m+=smb_hdrblocks(msg.hdr.length);
1015: total=0;
1016: for(i=0;i<msg.hdr.total_dfields;i++)
1017: total+=msg.dfield[i].length;
1018: n+=smb_datblocks(total); }
1019: size=smb_getmsghdrlen(&msg);
1020: if(size<1) size=SHD_BLOCK_LEN;
1021: while(size%SHD_BLOCK_LEN)
1022: size++;
1023: smb_freemsgmem(&msg); }
1024:
1025:
1026: if(!m && !n) {
1027: printf("\rAlready compressed.\n\n");
1028: smb_unlocksmbhdr(&smb);
1029: return; }
1030:
1031: if(packable && (n*SDT_BLOCK_LEN)+(m*SHD_BLOCK_LEN)<packable*1024L) {
1032: printf("\rLess than %luk compressable bytes.\n\n",packable);
1033: smb_unlocksmbhdr(&smb);
1034: return; }
1035:
1036: printf("\rCompressing %lu data blocks (%lu bytes)\n"
1037: " and %lu header blocks (%lu bytes)\n"
1038: ,n,n*SDT_BLOCK_LEN,m,m*SHD_BLOCK_LEN); }
1039:
1040: sprintf(fname,"%s.sd$",smb.file);
1041: tmp_sdt=fopen(fname,"wb");
1042: sprintf(fname,"%s.sh$",smb.file);
1043: tmp_shd=fopen(fname,"wb");
1044: sprintf(fname,"%s.si$",smb.file);
1045: tmp_sid=fopen(fname,"wb");
1046: if(!tmp_sdt || !tmp_shd || !tmp_sid) {
1047: smb_unlocksmbhdr(&smb);
1048: if(!(smb.status.attr&SMB_HYPERALLOC)) {
1049: smb_close_ha(&smb);
1050: smb_close_da(&smb); }
1051: printf("\n\7!Error opening temp files\n");
1052: return; }
1053: setvbuf(tmp_sdt,NULL,_IOFBF,2*1024);
1054: setvbuf(tmp_shd,NULL,_IOFBF,2*1024);
1055: setvbuf(tmp_sid,NULL,_IOFBF,2*1024);
1056: if(!(smb.status.attr&SMB_HYPERALLOC)
1057: && (datoffset=(datoffset_t *)LMALLOC(sizeof(datoffset_t)*smb.status.total_msgs))
1058: ==NULL) {
1059: smb_unlocksmbhdr(&smb);
1060: smb_close_ha(&smb);
1061: smb_close_da(&smb);
1062: fclose(tmp_sdt);
1063: fclose(tmp_shd);
1064: fclose(tmp_sid);
1065: printf("\n\7!Error allocating memory\n");
1066: return; }
1067: fseek(smb.shd_fp,0L,SEEK_SET);
1068: fread(&hdr,1,sizeof(smbhdr_t),smb.shd_fp);
1069: fwrite(&hdr,1,sizeof(smbhdr_t),tmp_shd);
1070: fwrite(&(smb.status),1,sizeof(smbstatus_t),tmp_shd);
1071: for(l=sizeof(smbhdr_t)+sizeof(smbstatus_t);l<smb.status.header_offset;l++) {
1072: fread(&ch,1,1,smb.shd_fp); /* copy additional base header records */
1073: fwrite(&ch,1,1,tmp_shd); }
1074: fseek(smb.sid_fp,0L,SEEK_SET);
1075: total=0;
1076: for(l=0;l<smb.status.total_msgs;l++) {
1077: printf("%lu of %lu\r",l+1,smb.status.total_msgs);
1078: if(!fread(&msg.idx,1,sizeof(idxrec_t),smb.sid_fp))
1079: break;
1080: if(msg.idx.attr&MSG_DELETE) {
1081: printf("\nDeleted index.\n");
1082: continue; }
1083: i=smb_lockmsghdr(&smb,&msg);
1084: if(i) {
1085: printf("\n\7!smb_lockmsghdr returned %d\n",i);
1086: continue; }
1087: i=smb_getmsghdr(&smb,&msg);
1088: smb_unlockmsghdr(&smb,&msg);
1089: if(i) {
1090: printf("\n\7!smb_getmsghdr returned %d\n",i);
1091: continue; }
1092: if(msg.hdr.attr&MSG_DELETE) {
1093: printf("\nDeleted header.\n");
1094: smb_freemsgmem(&msg);
1095: continue; }
1096: if(msg.expiration.time && msg.expiration.time<=now) {
1097: printf("\nExpired message.\n");
1098: smb_freemsgmem(&msg);
1099: continue; }
1100: for(m=0;m<datoffsets;m++)
1101: if(msg.hdr.offset==datoffset[m].old)
1102: break;
1103: if(m<datoffsets) { /* another index pointed to this data */
1104: printf("duplicate index\n");
1105: msg.hdr.offset=datoffset[m].new;
1106: smb_incdat(&smb,datoffset[m].new,smb_getmsgdatlen(&msg),1); }
1107: else {
1108:
1109: if(!(smb.status.attr&SMB_HYPERALLOC))
1110: datoffset[datoffsets].old=msg.hdr.offset;
1111:
1112: fseek(smb.sdt_fp,msg.hdr.offset,SEEK_SET);
1113:
1114: m=smb_getmsgdatlen(&msg);
1115: if(m>16L*1024L*1024L) {
1116: printf("\n\7!Invalid data length (%lu)\n",m);
1117: continue; }
1118:
1119: if(!(smb.status.attr&SMB_HYPERALLOC)) {
1120: datoffset[datoffsets].new=msg.hdr.offset
1121: =smb_fallocdat(&smb,m,1);
1122: datoffsets++;
1123: fseek(tmp_sdt,msg.hdr.offset,SEEK_SET); }
1124: else {
1125: fseek(tmp_sdt,0L,SEEK_END);
1126: msg.hdr.offset=ftell(tmp_sdt); }
1127:
1128: /* Actually copy the data */
1129:
1130: n=smb_datblocks(m);
1131: for(m=0;m<n;m++) {
1132: fread(buf,1,SDT_BLOCK_LEN,smb.sdt_fp);
1133: if(!m && *(ushort *)buf!=XLAT_NONE && *(ushort *)buf!=XLAT_LZH) {
1134: printf("\nUnsupported translation type (%04X)\n"
1135: ,*(ushort *)buf);
1136: break; }
1137: fwrite(buf,1,SDT_BLOCK_LEN,tmp_sdt); }
1138: if(m<n)
1139: continue; }
1140:
1141: /* Write the new index entry */
1142: length=smb_getmsghdrlen(&msg);
1143: if(smb.status.attr&SMB_HYPERALLOC)
1144: msg.idx.offset=ftell(tmp_shd);
1145: else
1146: msg.idx.offset=smb_fallochdr(&smb,length)+smb.status.header_offset;
1147: msg.idx.number=msg.hdr.number;
1148: msg.idx.attr=msg.hdr.attr;
1149: msg.idx.time=msg.hdr.when_imported.time;
1150: sprintf(str,"%.128s",msg.subj);
1151: strlwr(str);
1152: remove_re(str);
1153: msg.idx.subj=crc16(str);
1154: if(smb.status.attr&SMB_EMAIL) {
1155: if(msg.to_ext)
1156: msg.idx.to=atoi(msg.to_ext);
1157: else
1158: msg.idx.to=0;
1159: if(msg.from_ext)
1160: msg.idx.from=atoi(msg.from_ext);
1161: else
1162: msg.idx.from=0; }
1163: else {
1164: sprintf(str,"%.128s",msg.to);
1165: strlwr(str);
1166: msg.idx.to=crc16(str);
1167: sprintf(str,"%.128s",msg.from);
1168: strlwr(str);
1169: msg.idx.from=crc16(str); }
1170: fwrite(&msg.idx,1,sizeof(idxrec_t),tmp_sid);
1171:
1172: /* Write the new header entry */
1173: fseek(tmp_shd,msg.idx.offset,SEEK_SET);
1174: fwrite(&msg.hdr,1,sizeof(msghdr_t),tmp_shd);
1175: for(n=0;n<msg.hdr.total_dfields;n++)
1176: fwrite(&msg.dfield[n],1,sizeof(dfield_t),tmp_shd);
1177: for(n=0;n<msg.total_hfields;n++) {
1178: fwrite(&msg.hfield[n],1,sizeof(hfield_t),tmp_shd);
1179: fwrite(msg.hfield_dat[n],1,msg.hfield[n].length,tmp_shd); }
1180: while(length%SHD_BLOCK_LEN) { /* pad with NULLs */
1181: fputc(0,tmp_shd);
1182: length++; }
1183: total++;
1184: smb_freemsgmem(&msg); }
1185:
1186: if(datoffset)
1187: LFREE(datoffset);
1188: if(!(smb.status.attr&SMB_HYPERALLOC)) {
1189: smb_close_ha(&smb);
1190: smb_close_da(&smb); }
1191:
1192: /* Change *.sh$ into *.shd */
1193: fclose(smb.shd_fp);
1194: fclose(tmp_shd);
1195: sprintf(fname,"%s.shd",smb.file);
1196: if(remove(fname)!=0)
1197: printf("\n\7!Error %d removing %s\n",errno,fname);
1198: sprintf(tmpfname,"%s.sh$",smb.file);
1199: if(rename(tmpfname,fname)!=0)
1200: printf("\n\7!Error %d renaming %s to %s\n",errno,tmpfname,fname);
1201:
1202:
1203: /* Change *.sd$ into *.sdt */
1204: fclose(smb.sdt_fp);
1205: fclose(tmp_sdt);
1206: sprintf(fname,"%s.sdt",smb.file);
1207: if(remove(fname)!=0)
1208: printf("\n\7!Error %d removing %s\n",errno,fname);
1209:
1210: sprintf(tmpfname,"%s.sd$",smb.file);
1211: if(rename(tmpfname,fname)!=0)
1212: printf("\n\7!Error %d renaming %s to %s\n",errno,tmpfname,fname);
1213:
1214: /* Change *.si$ into *.sid */
1215: fclose(smb.sid_fp);
1216: fclose(tmp_sid);
1217: sprintf(fname,"%s.sid",smb.file);
1218: if(remove(fname)!=0)
1219: printf("\n\7!Error %d removing %s\n",errno,fname);
1220:
1221: sprintf(tmpfname,"%s.si$",smb.file);
1222: if(rename(tmpfname,fname)!=0)
1223: printf("\n\7!Error %d renaming %s to %s\n",errno,tmpfname,fname);
1224:
1225: if((i=smb_open(&smb))!=0) {
1226: printf("\n\7!Error %d reopening %s\n",i,smb.file);
1227: return; }
1228:
1229: smb.status.total_msgs=total;
1230: if((i=smb_putstatus(&smb))!=0)
1231: printf("\n\7!smb_putstatus returned %d\n",i);
1232: printf("\nDone.\n\n");
1233: }
1234:
1235:
1236: /****************************************************************************/
1237: /* Read messages in message base */
1238: /****************************************************************************/
1239: void readmsgs(ulong start)
1240: {
1241: char HUGE16 *inbuf;
1242: int i,done=0,domsg=1;
1243: smbmsg_t msg;
1244:
1245: if(start)
1246: msg.offset=start-1;
1247: else
1248: msg.offset=0;
1249: while(!done) {
1250: if(domsg) {
1251: fseek(smb.sid_fp,msg.offset*sizeof(idxrec_t),SEEK_SET);
1252: if(!fread(&msg.idx,1,sizeof(idxrec_t),smb.sid_fp))
1253: break;
1254: i=smb_lockmsghdr(&smb,&msg);
1255: if(i) {
1256: printf("\n\7!smb_lockmsghdr returned %d\n",i);
1257: break; }
1258: i=smb_getmsghdr(&smb,&msg);
1259: if(i) {
1260: printf("\n\7!smb_getmsghdr returned %d\n",i);
1261: break; }
1262:
1263: printf("\n%lu (%lu)\n",msg.hdr.number,msg.offset+1);
1264: printf("Subj : %s\n",msg.subj);
1265: printf("To : %s",msg.to);
1266: if(msg.to_net.type)
1267: printf(" (%s)",msg.to_net.type==NET_FIDO
1268: ? faddrtoa(*(fidoaddr_t *)msg.to_net.addr) : msg.to_net.addr);
1269: printf("\nFrom : %s",msg.from);
1270: if(msg.from_net.type)
1271: printf(" (%s)",msg.from_net.type==NET_FIDO
1272: ? faddrtoa(*(fidoaddr_t *)msg.from_net.addr)
1273: : msg.from_net.addr);
1274: printf("\nDate : %.24s %s"
1275: ,timestr((time_t*)&msg.hdr.when_written.time)
1276: ,zonestr(msg.hdr.when_written.zone));
1277:
1278: printf("\n\n");
1279:
1280: if((inbuf=smb_getmsgtxt(&smb,&msg,GETMSGTXT_TAILS))!=NULL) {
1281: printf("%s",inbuf);
1282: FREE(inbuf); }
1283:
1284: i=smb_unlockmsghdr(&smb,&msg);
1285: if(i) {
1286: printf("\n\7!smb_unlockmsghdr returned %d\n",i);
1287: break; }
1288: smb_freemsgmem(&msg); }
1289: domsg=1;
1290: printf("\nReading %s (?=Menu): ",smb.file);
1291: switch(toupper(getch())) {
1292: case '?':
1293: printf("\n"
1294: "\n"
1295: "(R)e-read current message\n"
1296: "(L)ist messages\n"
1297: "(T)en more titles\n"
1298: "(V)iew message headers\n"
1299: "(Q)uit\n"
1300: "(+/-) Forward/Backward\n"
1301: "\n");
1302: domsg=0;
1303: break;
1304: case 'Q':
1305: printf("Quit\n");
1306: done=1;
1307: break;
1308: case 'R':
1309: printf("Re-read\n");
1310: break;
1311: case '-':
1312: printf("Backwards\n");
1313: if(msg.offset)
1314: msg.offset--;
1315: break;
1316: case 'T':
1317: printf("Ten titles\n");
1318: listmsgs(msg.offset+2,10);
1319: msg.offset+=10;
1320: domsg=0;
1321: break;
1322: case 'L':
1323: printf("List messages\n");
1324: listmsgs(1,-1);
1325: domsg=0;
1326: break;
1327: case 'V':
1328: printf("View message headers\n");
1329: viewmsgs(1,-1);
1330: domsg=0;
1331: break;
1332: case CR:
1333: case '+':
1334: printf("Next\n");
1335: msg.offset++;
1336: break; } }
1337: }
1338:
1339: time_t checktime(void)
1340: {
1341: struct tm tm;
1342:
1343: memset(&tm,0,sizeof(tm));
1344: tm.tm_year=94;
1345: tm.tm_mday=1;
1346: return(mktime(&tm)-0x2D24BD00L);
1347: }
1348:
1349: /***************/
1350: /* Entry point */
1351: /***************/
1352: int main(int argc, char **argv)
1353: {
1354: char cmd[128]="",*p,*s;
1355: int i,j,x,y;
1356: time_t t;
1357: BOOL create=FALSE;
1358:
1359: setvbuf(stdout,0,_IONBF,0);
1360:
1361: smb.file[0]=0;
1362: printf("\nSMBUTIL Version %s (%s) SMBLIB %s - Synchronet Message Base "\
1363: "Utility\n\n"
1364: ,SMBUTIL_VER
1365: #if defined(__linux__)
1366: ,"Linux"
1367: #elif defined(__unix__)
1368: ,"Unix"
1369: #elif defined(__OS2__)
1370: ,"OS/2"
1371: #elif defined(_WIN32)
1372: ,"Win32"
1373: #elif defined(__DOS4G__)
1374: ,"DOS4G"
1375: #elif defined(__FLAT__)
1376: ,"DOS32"
1377: #else
1378: ,"DOS16"
1379: #endif
1380: ,smb_lib_ver()
1381: );
1382:
1383: putenv("TZ=UCT0");
1384: tzset();
1385:
1386: if((t=checktime())!=0) {
1387: fprintf(stderr,"!TIME PROBLEM (%ld)\n",t);
1388: return(-1);
1389: }
1390:
1391: for(x=1;x<argc;x++) {
1392: if(
1393: #ifndef __unix__
1394: argv[x][0]=='/' || /* for backwards compatibilty */
1395: #endif
1396: argv[x][0]=='-') {
1397: for(j=1;argv[x][j];j++)
1398: switch(toupper(argv[x][j])) {
1399: case 'A':
1400: mode|=NOANALYSIS;
1401: break;
1402: case 'Z':
1403: if(isdigit(argv[x][j+1]))
1404: tzone=atoi(argv[x]+j+1);
1405: else if(!stricmp(argv[x]+j+1,"EST"))
1406: tzone=EST;
1407: else if(!stricmp(argv[x]+j+1,"EDT"))
1408: tzone=EDT;
1409: else if(!stricmp(argv[x]+j+1,"CST"))
1410: tzone=CST;
1411: else if(!stricmp(argv[x]+j+1,"CDT"))
1412: tzone=CDT;
1413: else if(!stricmp(argv[x]+j+1,"MST"))
1414: tzone=MST;
1415: else if(!stricmp(argv[x]+j+1,"MDT"))
1416: tzone=MDT;
1417: else if(!stricmp(argv[x]+j+1,"PST"))
1418: tzone=PST;
1419: else if(!stricmp(argv[x]+j+1,"PDT"))
1420: tzone=PDT;
1421: j=strlen(argv[x])-1;
1422: break;
1423: case 'C':
1424: create=TRUE;
1425: break;
1426: default:
1427: printf("\nUnknown opt '%c'\n",argv[x][j]);
1428: case '?':
1429: printf("%s",usage);
1430: exit(1);
1431: break; } }
1432: else {
1433: if(!cmd[0])
1434: strcpy(cmd,argv[x]);
1435: else {
1436: sprintf(smb.file,"%.64s",argv[x]);
1437: p=strrchr(smb.file,'.');
1438: s=strrchr(smb.file,'/');
1439: if(s==NULL)
1440: s=strrchr(smb.file,'\\');
1441: if(p>s) *p=0;
1442: smb.retry_time=30;
1443: printf("Opening %s\r\n",smb.file);
1444: if((i=smb_open(&smb))!=0) {
1445: printf("\n\7!Error %d opening %s message base\n",i,smb.file);
1446: exit(1); }
1447: if(!filelength(fileno(smb.shd_fp))) {
1448: if(!create) {
1449: printf("Empty\n");
1450: smb_close(&smb);
1451: continue; }
1452: smb.status.max_crcs=0;
1453: smb.status.max_age=0;
1454: smb.status.max_msgs=1000;
1455: smb.status.attr=0;
1456: if((i=smb_create(&smb))!=0) {
1457: smb_close(&smb);
1458: printf("!Error %d (%s) creating %s\n",i,smb.last_error,smb.file);
1459: continue;
1460: }
1461: }
1462: for(y=0;cmd[y];y++)
1463: switch(toupper(cmd[y])) {
1464: case 'I':
1465: case 'E':
1466: case 'N':
1467: strcpy(filein,cmd+1);
1468: i=smb_locksmbhdr(&smb);
1469: if(i) {
1470: printf("\n\7!smb_locksmbhdr returned %d\n",i);
1471: return(1); }
1472: postmsg((char)toupper(cmd[y]));
1473: y=strlen(cmd)-1;
1474: break;
1475: case 'S':
1476: showstatus();
1477: break;
1478: case 'C':
1479: config();
1480: break;
1481: case 'L':
1482: listmsgs(atol(cmd+1),-1L);
1483: y=strlen(cmd)-1;
1484: break;
1485: case 'P':
1486: packmsgs(atol(cmd+y+1));
1487: y=strlen(cmd)-1;
1488: break;
1489: case 'R':
1490: readmsgs(atol(cmd+1));
1491: y=strlen(cmd)-1;
1492: break;
1493: case 'V':
1494: viewmsgs(atol(cmd+1),-1L);
1495: y=strlen(cmd)-1;
1496: break;
1497: case 'M':
1498: maint();
1499: break;
1500: default:
1501: printf("%s",usage);
1502: break; }
1503: smb_close(&smb); } } }
1504: if(!cmd[0])
1505: printf("%s",usage);
1506: return(0);
1507: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.