|
|
1.1 root 1: /* smbutil.c */
2:
3: /* Synchronet message base (SMB) utility */
4:
1.1.1.2 ! root 5: /* $Id: smbutil.c,v 1.100 2011/03/21 01:29:53 sbbs Exp $ */
1.1 root 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: * *
1.1.1.2 ! root 11: * Copyright 2009 Rob Swindell - http://www.synchro.net/copyright.html *
1.1 root 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.33"
39: char revision[16];
40: char compiler[32];
41:
42: const char *wday[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
43: const char *mon[]={"Jan","Feb","Mar","Apr","May","Jun"
44: ,"Jul","Aug","Sep","Oct","Nov","Dec"};
45:
46:
47: #define NOANALYSIS (1L<<0)
48: #define NOCRC (1L<<1)
49:
50: #ifdef __WATCOMC__
51: #define ffblk find_t
52: #define findfirst(x,y,z) _dos_findfirst(x,z,y)
53: #define findnext(x) _dos_findnext(x)
54: #endif
55:
56: #if defined(_WIN32)
57: #include <ctype.h> /* isdigit() */
58: #include <conio.h> /* getch() */
59: #endif
60:
61: /* ANSI */
62: #include <stdio.h>
63: #include <time.h> /* time */
64: #include <errno.h> /* errno */
65: #include <string.h> /* strrchr */
66: #include <ctype.h> /* toupper */
67:
68: #include "genwrap.h" /* stricmp */
69: #include "dirwrap.h" /* fexist */
70: #include "conwrap.h" /* getch */
71: #include "filewrap.h"
72: #include "smblib.h"
73: #include "crc16.h"
74: #include "crc32.h"
75: #include "gen_defs.h" /* MAX_PATH */
76:
77: #ifdef __WATCOMC__
78: #include <dos.h>
79: #endif
80:
81: /* gets is dangerous */
82: #define gets(str) fgets((str), sizeof(str), stdin)
83:
84: #define CHSIZE_FP(fp,size) if(chsize(fileno(fp),size)) printf("chsize failed!\n");
85:
86: /********************/
87: /* Global variables */
88: /********************/
89:
90: smb_t smb;
91: ulong mode=0L;
92: ushort tzone=0;
93: ushort xlat=XLAT_NONE;
94: FILE* nulfp;
95: FILE* errfp;
96: FILE* statfp;
97: BOOL pause_on_exit=FALSE;
98: BOOL pause_on_error=FALSE;
99: char* beep="";
100:
101: /************************/
102: /* Program usage/syntax */
103: /************************/
104:
105: char *usage=
106: "usage: smbutil [-opts] cmd <filespec.shd>\n"
107: "\n"
108: "cmd:\n"
109: " l[n] = list msgs starting at number n\n"
110: " r[n] = read msgs starting at number n\n"
111: " x[n] = dump msg index at number n\n"
112: " v[n] = view msg headers starting at number n\n"
113: " i[f] = import msg from text file f (or use stdin)\n"
114: " e[f] = import e-mail from text file f (or use stdin)\n"
115: " n[f] = import netmail from text file f (or use stdin)\n"
116: " h = dump hash file\n"
117: " s = display msg base status\n"
118: " c = change msg base status\n"
119: " d = delete all msgs\n"
120: " m = maintain msg base - delete old msgs and msgs over max\n"
121: " p[k] = pack msg base (k specifies minimum packable Kbytes)\n"
122: "opts:\n"
123: " c[m] = create message base if it doesn't exist (m=max msgs)\n"
124: " a = always pack msg base (disable compression analysis)\n"
125: " i = ignore dupes (do not store CRCs or search for duplicate hashes)\n"
126: " d = use default values (no prompt) for to, from, and subject\n"
127: " l = LZH-compress message text\n"
128: " o = print errors on stdout (instead of stderr)\n"
129: " p = wait for keypress (pause) on exit\n"
130: " ! = wait for keypress (pause) on error\n"
131: " b = beep on error\n"
132: " t<s> = set 'to' user name for imported message\n"
133: " n<s> = set 'to' netmail address for imported message\n"
134: " u<s> = set 'to' user number for imported message\n"
135: " f<s> = set 'from' user name for imported message\n"
136: " e<s> = set 'from' user number for imported message\n"
137: " s<s> = set 'subject' for imported message\n"
138: " z[n] = set time zone (n=min +/- from UT or 'EST','EDT','CST',etc)\n"
139: " # = set number of messages to view/list (e.g. -1)\n"
140: ;
141:
142: void bail(int code)
143: {
144:
145: if(pause_on_exit || (code && pause_on_error)) {
146: fprintf(statfp,"\nHit enter to continue...");
147: getchar();
148: }
149:
150: if(code)
151: fprintf(statfp,"\nReturning error code: %d\n",code);
152: exit(code);
153: }
154:
155: /*****************************************************************************/
156: /* Expands Unix LF to CRLF */
157: /*****************************************************************************/
158: ulong lf_expand(BYTE* inbuf, BYTE* outbuf)
159: {
160: ulong i,j;
161:
162: for(i=j=0;inbuf[i];i++) {
163: if(inbuf[i]=='\n' && (!i || inbuf[i-1]!='\r'))
164: outbuf[j++]='\r';
165: outbuf[j++]=inbuf[i];
166: }
167: outbuf[j]=0;
168: return(j);
169: }
170:
171: /****************************************************************************/
172: /* Adds a new message to the message base */
173: /****************************************************************************/
174: void postmsg(char type, char* to, char* to_number, char* to_address,
175: char* from, char* from_number, char* subject, FILE* fp)
176: {
177: char str[128];
178: char buf[1024];
179: char* msgtxt=NULL;
180: char* newtxt;
181: long msgtxtlen;
182: ushort net;
183: int i;
184: ushort agent=AGENT_SMBUTIL;
185: smbmsg_t msg;
1.1.1.2 ! root 186: long dupechk_hashes=SMB_HASH_SOURCE_DUPE;
1.1 root 187:
188: /* Read message text from stream (file or stdin) */
189: msgtxtlen=0;
190: while(!feof(fp)) {
191: i=fread(buf,1,sizeof(buf),fp);
192: if(i<1)
193: break;
194: if((msgtxt=(char*)realloc(msgtxt,msgtxtlen+i+1))==NULL) {
195: fprintf(errfp,"\n%s!realloc(%ld) failure\n",beep,msgtxtlen+i+1);
196: bail(1);
197: }
198: memcpy(msgtxt+msgtxtlen,buf,i);
199: msgtxtlen+=i;
200: }
201:
202: if(msgtxt!=NULL) {
203:
204: msgtxt[msgtxtlen]=0; /* Must be NULL-terminated */
205:
206: if((newtxt=(char*)malloc((msgtxtlen*2)+1))==NULL) {
207: fprintf(errfp,"\n%s!malloc(%ld) failure\n",beep,(msgtxtlen*2)+1);
208: bail(1);
209: }
210:
211: /* Expand LFs to CRLFs */
212: msgtxtlen=lf_expand(msgtxt, newtxt);
213: free(msgtxt);
214: msgtxt=newtxt;
215: }
216:
217: memset(&msg,0,sizeof(smbmsg_t));
218: msg.hdr.when_written.time=time(NULL);
219: msg.hdr.when_written.zone=tzone;
220: msg.hdr.when_imported=msg.hdr.when_written;
221:
222: if((to==NULL || stricmp(to,"All")==0) && to_address!=NULL)
223: to=to_address;
224: if(to==NULL) {
225: printf("To User Name: ");
226: fgets(str,sizeof(str),stdin);
227: } else
228: SAFECOPY(str,to);
229: truncsp(str);
230:
231: if((i=smb_hfield_str(&msg,RECIPIENT,str))!=SMB_SUCCESS) {
232: fprintf(errfp,"\n%s!smb_hfield_str(0x%02X) returned %d: %s\n"
233: ,beep,RECIPIENT,i,smb.last_error);
234: bail(1);
235: }
236: if(type=='E' || type=='N')
237: smb.status.attr|=SMB_EMAIL;
238: if(smb.status.attr&SMB_EMAIL) {
239: if(to_address==NULL) {
240: if(to_number==NULL) {
241: printf("To User Number: ");
242: gets(str);
243: } else
244: SAFECOPY(str,to_number);
245: truncsp(str);
246: if((i=smb_hfield_str(&msg,RECIPIENTEXT,str))!=SMB_SUCCESS) {
247: fprintf(errfp,"\n%s!smb_hfield_str(0x%02X) returned %d: %s\n"
248: ,beep,RECIPIENTEXT,i,smb.last_error);
249: bail(1);
250: }
251: }
252: }
253:
254: if(smb.status.attr&SMB_EMAIL && (type=='N' || to_address!=NULL)) {
255: if(to_address==NULL) {
256: printf("To Address (e.g. user@host): ");
257: gets(str);
258: } else
259: SAFECOPY(str,to_address);
260: truncsp(str);
261: if(*str) {
262: net=smb_netaddr_type(str);
263: if((i=smb_hfield(&msg,RECIPIENTNETTYPE,sizeof(net),&net))!=SMB_SUCCESS) {
264: fprintf(errfp,"\n%s!smb_hfield(0x%02X) returned %d: %s\n"
265: ,beep,RECIPIENTNETTYPE,i,smb.last_error);
266: bail(1);
267: }
268: if((i=smb_hfield_str(&msg,RECIPIENTNETADDR,str))!=SMB_SUCCESS) {
269: fprintf(errfp,"\n%s!smb_hfield_str(0x%02X) returned %d: %s\n"
270: ,beep,RECIPIENTNETADDR,i,smb.last_error);
271: bail(1);
272: }
273: }
274: }
275:
276: if(from==NULL) {
277: printf("From User Name: ");
278: gets(str);
279: } else
280: SAFECOPY(str,from);
281: truncsp(str);
282: if((i=smb_hfield_str(&msg,SENDER,str))!=SMB_SUCCESS) {
283: fprintf(errfp,"\n%s!smb_hfield_str(0x%02X) returned %d: %s\n"
284: ,beep,SENDER,i,smb.last_error);
285: bail(1);
286: }
287: if(smb.status.attr&SMB_EMAIL) {
288: if(from_number==NULL) {
289: printf("From User Number: ");
290: gets(str);
291: } else
292: SAFECOPY(str,from_number);
293: truncsp(str);
294: if((i=smb_hfield_str(&msg,SENDEREXT,str))!=SMB_SUCCESS) {
295: fprintf(errfp,"\n%s!smb_hfield_str(0x%02X) returned %d: %s\n"
296: ,beep,SENDEREXT,i,smb.last_error);
297: bail(1);
298: }
299: }
300: if((i=smb_hfield(&msg, SENDERAGENT, sizeof(agent), &agent))!=SMB_SUCCESS) {
301: fprintf(errfp,"\n%s!smb_hfield(0x%02X) returned %d: %s\n"
302: ,beep,SENDERAGENT,i,smb.last_error);
303: bail(1);
304: }
305:
306: if(subject==NULL) {
307: printf("Subject: ");
308: gets(str);
309: } else
310: SAFECOPY(str,subject);
311: truncsp(str);
312: if((i=smb_hfield_str(&msg,SUBJECT,str))!=SMB_SUCCESS) {
313: fprintf(errfp,"\n%s!smb_hfield_str(0x%02X) returned %d: %s\n"
314: ,beep,SUBJECT,i,smb.last_error);
315: bail(1);
316: }
317:
318: safe_snprintf(str,sizeof(str),"SMBUTIL %s-%s r%s %s %s"
319: ,SMBUTIL_VER
320: ,PLATFORM_DESC
321: ,revision
322: ,__DATE__
323: ,compiler
324: );
325: if((i=smb_hfield_str(&msg,FIDOPID,str))!=SMB_SUCCESS) {
326: fprintf(errfp,"\n%s!smb_hfield_str(0x%02X) returned %d: %s\n"
327: ,beep,FIDOPID,i,smb.last_error);
328: bail(1);
329: }
330:
331: if(mode&NOCRC || smb.status.max_crcs==0) /* no CRC checking means no body text dupe checking */
332: dupechk_hashes&=~(1<<SMB_HASH_SOURCE_BODY);
333:
334: if((i=smb_addmsg(&smb,&msg,smb.status.attr&SMB_HYPERALLOC
335: ,dupechk_hashes,xlat,msgtxt,NULL))!=SMB_SUCCESS) {
336: fprintf(errfp,"\n%s!smb_addmsg returned %d: %s\n"
337: ,beep,i,smb.last_error);
338: bail(1);
339: }
340: smb_freemsgmem(&msg);
341:
342: FREE_AND_NULL(msgtxt);
343: }
344:
345: /****************************************************************************/
346: /* Shows the message base header */
347: /****************************************************************************/
348: void showstatus(void)
349: {
350: int i;
351:
352: i=smb_locksmbhdr(&smb);
353: if(i) {
354: fprintf(errfp,"\n%s!smb_locksmbhdr returned %d: %s\n"
355: ,beep,i,smb.last_error);
356: return;
357: }
358: i=smb_getstatus(&smb);
359: smb_unlocksmbhdr(&smb);
360: if(i) {
361: fprintf(errfp,"\n%s!smb_getstatus returned %d: %s\n"
362: ,beep,i,smb.last_error);
363: return;
364: }
365: printf("last_msg =%lu\n"
366: "total_msgs =%lu\n"
367: "header_offset =%lu\n"
368: "max_crcs =%lu\n"
369: "max_msgs =%lu\n"
370: "max_age =%u\n"
371: "attr =%04Xh\n"
372: ,smb.status.last_msg
373: ,smb.status.total_msgs
374: ,smb.status.header_offset
375: ,smb.status.max_crcs
376: ,smb.status.max_msgs
377: ,smb.status.max_age
378: ,smb.status.attr
379: );
380: }
381:
382: /****************************************************************************/
383: /* Configure message base header */
384: /****************************************************************************/
385: void config(void)
386: {
387: char max_msgs[128],max_crcs[128],max_age[128],header_offset[128],attr[128];
388: int i;
389:
390: i=smb_locksmbhdr(&smb);
391: if(i) {
392: fprintf(errfp,"\n%s!smb_locksmbhdr returned %d: %s\n"
393: ,beep,i,smb.last_error);
394: return;
395: }
396: i=smb_getstatus(&smb);
397: smb_unlocksmbhdr(&smb);
398: if(i) {
399: fprintf(errfp,"\n%s!smb_getstatus returned %d: %s\n"
400: ,beep,i,smb.last_error);
401: return;
402: }
403: printf("Header offset =%-5lu New value (CR=No Change): "
404: ,smb.status.header_offset);
405: gets(header_offset);
406: printf("Max msgs =%-5lu New value (CR=No Change): "
407: ,smb.status.max_msgs);
408: gets(max_msgs);
409: printf("Max crcs =%-5lu New value (CR=No Change): "
410: ,smb.status.max_crcs);
411: gets(max_crcs);
412: printf("Max age =%-5u New value (CR=No Change): "
413: ,smb.status.max_age);
414: gets(max_age);
415: printf("Attributes =%-5u New value (CR=No Change): "
416: ,smb.status.attr);
417: gets(attr);
418: i=smb_locksmbhdr(&smb);
419: if(i) {
420: fprintf(errfp,"\n%s!smb_locksmbhdr returned %d: %s\n"
421: ,beep,i,smb.last_error);
422: return;
423: }
424: i=smb_getstatus(&smb);
425: if(i) {
426: fprintf(errfp,"\n%s!smb_getstatus returned %d: %s\n"
427: ,beep,i,smb.last_error);
428: smb_unlocksmbhdr(&smb);
429: return;
430: }
431: if(isdigit(max_msgs[0]))
432: smb.status.max_msgs=atol(max_msgs);
433: if(isdigit(max_crcs[0]))
434: smb.status.max_crcs=atol(max_crcs);
435: if(isdigit(max_age[0]))
436: smb.status.max_age=atoi(max_age);
437: if(isdigit(header_offset[0]))
438: smb.status.header_offset=atol(header_offset);
439: if(isdigit(attr[0]))
440: smb.status.attr=atoi(attr);
441: i=smb_putstatus(&smb);
442: smb_unlocksmbhdr(&smb);
443: if(i)
444: fprintf(errfp,"\n%s!smb_putstatus returned %d: %s\n"
445: ,beep,i,smb.last_error);
446: }
447:
448: /****************************************************************************/
449: /* Lists messages' to, from, and subject */
450: /****************************************************************************/
451: void listmsgs(ulong start, ulong count)
452: {
453: int i;
454: ulong l=0;
455: smbmsg_t msg;
456:
457: if(!start)
458: start=1;
459: if(!count)
460: count=~0;
461: fseek(smb.sid_fp,(start-1L)*sizeof(idxrec_t),SEEK_SET);
462: while(l<count) {
463: if(!fread(&msg.idx,1,sizeof(idxrec_t),smb.sid_fp))
464: break;
465: i=smb_lockmsghdr(&smb,&msg);
466: if(i) {
467: fprintf(errfp,"\n%s!smb_lockmsghdr returned %d: %s\n"
468: ,beep,i,smb.last_error);
469: break;
470: }
471: i=smb_getmsghdr(&smb,&msg);
472: smb_unlockmsghdr(&smb,&msg);
473: if(i) {
474: fprintf(errfp,"\n%s!smb_getmsghdr returned %d: %s\n"
475: ,beep,i,smb.last_error);
476: break;
477: }
1.1.1.2 ! root 478: printf("%4lu %-25.25s %-25.25s %s\n"
1.1 root 479: ,msg.hdr.number,msg.from,msg.to,msg.subj);
480: smb_freemsgmem(&msg);
481: l++;
482: }
483: }
484:
485: /****************************************************************************/
486: /* Generates a 24 character ASCII string that represents the time_t pointer */
487: /* Used as a replacement for ctime() */
488: /****************************************************************************/
1.1.1.2 ! root 489: char *my_timestr(time_t intime)
1.1 root 490: {
491: static char str[256];
492: char mer[3],hour;
493: struct tm *gm;
494:
1.1.1.2 ! root 495: gm=localtime(&intime);
1.1 root 496: if(gm==NULL) {
497: strcpy(str,"Invalid Time");
498: return(str);
499: }
500: if(gm->tm_hour>=12) {
501: if(gm->tm_hour==12)
502: hour=12;
503: else
504: hour=gm->tm_hour-12;
505: strcpy(mer,"pm");
506: }
507: else {
508: if(gm->tm_hour==0)
509: hour=12;
510: else
511: hour=gm->tm_hour;
512: strcpy(mer,"am");
513: }
514: sprintf(str,"%s %s %02d %4d %02d:%02d %s"
515: ,wday[gm->tm_wday],mon[gm->tm_mon],gm->tm_mday,1900+gm->tm_year
516: ,hour,gm->tm_min,mer);
517: return(str);
518: }
519:
520: /****************************************************************************/
521: /****************************************************************************/
522: void dumpindex(ulong start, ulong count)
523: {
524: ulong l=0;
525: idxrec_t idx;
526:
527: if(!start)
528: start=1;
529: if(!count)
530: count=~0;
531: fseek(smb.sid_fp,(start-1L)*sizeof(idxrec_t),SEEK_SET);
532: while(l<count) {
533: if(!fread(&idx,1,sizeof(idx),smb.sid_fp))
534: break;
535:
536: printf("%4lu %04hX %04hX %04Xh %04Xh %06X %s\n"
537: ,idx.number,idx.from,idx.to,idx.subj,idx.attr
1.1.1.2 ! root 538: ,idx.offset,my_timestr(idx.time));
1.1 root 539: l++;
540: }
541: }
542:
543: /****************************************************************************/
544: /* Displays message header information */
545: /****************************************************************************/
546: void viewmsgs(ulong start, ulong count)
547: {
548: int i;
549: ulong l=0;
550: smbmsg_t msg;
551:
552: if(!start)
553: start=1;
554: if(!count)
555: count=~0;
556: fseek(smb.sid_fp,(start-1L)*sizeof(idxrec_t),SEEK_SET);
557: while(l<count) {
558: if(!fread(&msg.idx,1,sizeof(idxrec_t),smb.sid_fp))
559: break;
560: i=smb_lockmsghdr(&smb,&msg);
561: if(i) {
562: fprintf(errfp,"\n%s!smb_lockmsghdr returned %d: %s\n"
563: ,beep,i,smb.last_error);
564: break;
565: }
566: i=smb_getmsghdr(&smb,&msg);
567: smb_unlockmsghdr(&smb,&msg);
568: if(i) {
569: fprintf(errfp,"\n%s!smb_getmsghdr returned %d: %s\n"
570: ,beep,i,smb.last_error);
571: break;
572: }
573:
574: printf("--------------------\n");
575: printf("%-20.20s %ld\n" ,"index record",ftell(smb.sid_fp)/sizeof(idxrec_t));
576: smb_dump_msghdr(stdout,&msg);
577: printf("\n");
578: smb_freemsgmem(&msg);
579: l++;
580: }
581: }
582:
583: /****************************************************************************/
584: /****************************************************************************/
585: void dump_hashes(void)
586: {
587: char tmp[128];
588: int retval;
589: hash_t hash;
590:
591: if((retval=smb_open_hash(&smb))!=SMB_SUCCESS) {
592: fprintf(errfp,"\n%s!smb_open_hash returned %d: %s\n"
593: ,beep, retval, smb.last_error);
594: return;
595: }
596:
597: while(!smb_feof(smb.hash_fp)) {
598: if(smb_fread(&smb,&hash,sizeof(hash),smb.hash_fp)!=sizeof(hash))
599: break;
600: printf("\n");
601: printf("%-10s: %lu\n", "Number", hash.number);
602: printf("%-10s: %s\n", "Source", smb_hashsourcetype(hash.source));
603: printf("%-10s: %lu\n", "Length", hash.length);
1.1.1.2 ! root 604: printf("%-10s: %s\n", "Time", my_timestr(hash.time));
! 605: printf("%-10s: %02x\n", "Flags", hash.flags);
1.1 root 606: if(hash.flags&SMB_HASH_CRC16)
607: printf("%-10s: %04x\n", "CRC-16", hash.crc16);
608: if(hash.flags&SMB_HASH_CRC32)
609: printf("%-10s: %08lx\n","CRC-32", hash.crc32);
610: if(hash.flags&SMB_HASH_MD5)
611: printf("%-10s: %s\n", "MD5", MD5_hex(tmp,hash.md5));
612: }
613:
614: smb_close_hash(&smb);
615: }
616:
617: /****************************************************************************/
618: /* Maintain message base - deletes messages older than max age (in days) */
619: /* or messages that exceed maximum */
620: /****************************************************************************/
621: void maint(void)
622: {
623: int i;
624: ulong l,m,n,f,flagged=0;
625: time_t now;
626: smbmsg_t msg;
627: idxrec_t *idx;
628:
629: printf("Maintaining %s\r\n",smb.file);
630: now=time(NULL);
631: i=smb_locksmbhdr(&smb);
632: if(i) {
633: fprintf(errfp,"\n%s!smb_locksmbhdr returned %d: %s\n"
634: ,beep,i,smb.last_error);
635: return;
636: }
637: i=smb_getstatus(&smb);
638: if(i) {
639: smb_unlocksmbhdr(&smb);
640: fprintf(errfp,"\n%s!smb_getstatus returned %d: %s\n"
641: ,beep,i,smb.last_error);
642: return;
643: }
644: if(!smb.status.total_msgs) {
645: smb_unlocksmbhdr(&smb);
646: printf("Empty\n");
647: return;
648: }
649: printf("Loading index...\n");
650: if((idx=(idxrec_t *)malloc(sizeof(idxrec_t)*smb.status.total_msgs))
651: ==NULL) {
652: smb_unlocksmbhdr(&smb);
653: fprintf(errfp,"\n%s!Error allocating %lu bytes of memory\n"
654: ,beep,sizeof(idxrec_t)*smb.status.total_msgs);
655: return;
656: }
657: fseek(smb.sid_fp,0L,SEEK_SET);
658: for(l=0;l<smb.status.total_msgs;l++) {
659: printf("%lu of %lu\r"
660: ,l+1,smb.status.total_msgs);
661: if(!fread(&idx[l],1,sizeof(idxrec_t),smb.sid_fp))
662: break;
663: }
664: printf("\nDone.\n\n");
665:
666: printf("Scanning for pre-flagged messages...\n");
667: for(m=0;m<l;m++) {
668: printf("\r%2lu%%",m ? (long)(100.0/((float)l/m)) : 0);
669: if(idx[m].attr&MSG_DELETE)
670: flagged++;
671: }
672: printf("\r100%% (%lu pre-flagged for deletion)\n",flagged);
673:
674: if(smb.status.max_age) {
675: printf("Scanning for messages more than %u days old...\n"
676: ,smb.status.max_age);
677: for(m=f=0;m<l;m++) {
678: printf("\r%2lu%%",m ? (long)(100.0/((float)l/m)) : 0);
679: if(idx[m].attr&(MSG_PERMANENT|MSG_DELETE))
680: continue;
681: if((ulong)now>idx[m].time && (now-idx[m].time)/(24L*60L*60L)
682: >smb.status.max_age) {
683: f++;
684: flagged++;
685: idx[m].attr|=MSG_DELETE;
686: }
687: } /* mark for deletion */
688: printf("\r100%% (%lu flagged for deletion)\n",f);
689: }
690:
691: printf("Scanning for read messages to be killed...\n");
692: for(m=f=0;m<l;m++) {
693: printf("\r%2lu%%",m ? (long)(100.0/((float)l/m)) : 0);
694: if(idx[m].attr&(MSG_PERMANENT|MSG_DELETE))
695: continue;
696: if((idx[m].attr&(MSG_READ|MSG_KILLREAD))==(MSG_READ|MSG_KILLREAD)) {
697: f++;
698: flagged++;
699: idx[m].attr|=MSG_DELETE;
700: }
701: }
702: printf("\r100%% (%lu flagged for deletion)\n",f);
703:
704: if(smb.status.max_msgs && l-flagged>smb.status.max_msgs) {
705: printf("Flagging excess messages for deletion...\n");
706: for(m=n=0,f=flagged;l-flagged>smb.status.max_msgs && m<l;m++) {
707: if(idx[m].attr&(MSG_PERMANENT|MSG_DELETE))
708: continue;
709: printf("%lu of %lu\r",++n,(l-f)-smb.status.max_msgs);
710: flagged++;
711: idx[m].attr|=MSG_DELETE;
712: } /* mark for deletion */
713: printf("\nDone.\n\n");
714: }
715:
716: if(!flagged) { /* No messages to delete */
717: free(idx);
718: smb_unlocksmbhdr(&smb);
719: return;
720: }
721:
722: if(!(mode&NOANALYSIS)) {
723:
724: printf("Freeing allocated header and data blocks for deleted messages...\n");
725: if(!(smb.status.attr&SMB_HYPERALLOC)) {
726: i=smb_open_da(&smb);
727: if(i) {
728: smb_unlocksmbhdr(&smb);
729: fprintf(errfp,"\n%s!smb_open_da returned %d: %s\n"
730: ,beep,i,smb.last_error);
731: bail(1);
732: }
733: i=smb_open_ha(&smb);
734: if(i) {
735: smb_unlocksmbhdr(&smb);
736: fprintf(errfp,"\n%s!smb_open_ha returned %d: %s\n"
737: ,beep,i,smb.last_error);
738: bail(1);
739: }
740: }
741:
742: for(m=n=0;m<l;m++) {
743: if(idx[m].attr&MSG_DELETE) {
744: printf("%lu of %lu\r",++n,flagged);
745: msg.idx=idx[m];
746: msg.hdr.number=msg.idx.number;
747: if((i=smb_getmsgidx(&smb,&msg))!=0) {
748: fprintf(errfp,"\n%s!smb_getmsgidx returned %d: %s\n"
749: ,beep,i,smb.last_error);
750: continue;
751: }
752: i=smb_lockmsghdr(&smb,&msg);
753: if(i) {
754: fprintf(errfp,"\n%s!smb_lockmsghdr returned %d: %s\n"
755: ,beep,i,smb.last_error);
756: break;
757: }
758: if((i=smb_getmsghdr(&smb,&msg))!=0) {
759: smb_unlockmsghdr(&smb,&msg);
760: fprintf(errfp,"\n%s!smb_getmsghdr returned %d: %s\n"
761: ,beep,i,smb.last_error);
762: break;
763: }
764: msg.hdr.attr|=MSG_DELETE; /* mark header as deleted */
765: if((i=smb_putmsg(&smb,&msg))!=0) {
766: smb_freemsgmem(&msg);
767: smb_unlockmsghdr(&smb,&msg);
768: fprintf(errfp,"\n%s!smb_putmsg returned %d: %s\n"
769: ,beep,i,smb.last_error);
770: break;
771: }
772: smb_unlockmsghdr(&smb,&msg);
773: if((i=smb_freemsg(&smb,&msg))!=0) {
774: smb_freemsgmem(&msg);
775: fprintf(errfp,"\n%s!smb_freemsg returned %d: %s\n"
776: ,beep,i,smb.last_error);
777: break;
778: }
779: smb_freemsgmem(&msg);
780: }
781: }
782: if(!(smb.status.attr&SMB_HYPERALLOC)) {
783: smb_close_ha(&smb);
784: smb_close_da(&smb);
785: }
786: printf("\nDone.\n\n");
787: }
788:
789: printf("Re-writing index...\n");
790: rewind(smb.sid_fp);
791: CHSIZE_FP(smb.sid_fp,0);
792: for(m=n=0;m<l;m++) {
793: if(idx[m].attr&MSG_DELETE)
794: continue;
795: printf("%lu of %lu\r",++n,l-flagged);
796: fwrite(&idx[m],sizeof(idxrec_t),1,smb.sid_fp);
797: }
798: printf("\nDone.\n\n");
799: fflush(smb.sid_fp);
800:
801: free(idx);
802: smb.status.total_msgs-=flagged;
803: smb_putstatus(&smb);
804: smb_unlocksmbhdr(&smb);
805: }
806:
807:
808: typedef struct {
809: ulong old,new;
810: } datoffset_t;
811:
812: /****************************************************************************/
813: /* Removes all unused blocks from SDT and SHD files */
814: /****************************************************************************/
815: void packmsgs(ulong packable)
816: {
817: uchar str[128],buf[SDT_BLOCK_LEN],ch,fname[128],tmpfname[128];
818: int i,size;
819: ulong l,m,n,datoffsets=0,length,total,now;
820: FILE *tmp_sdt,*tmp_shd,*tmp_sid;
821: BOOL error=FALSE;
822: smbhdr_t hdr;
823: smbmsg_t msg;
824: datoffset_t *datoffset=NULL;
825:
826: now=time(NULL);
827: printf("Packing %s\n",smb.file);
828: i=smb_locksmbhdr(&smb);
829: if(i) {
830: fprintf(errfp,"\n%s!smb_locksmbhdr returned %d: %s\n"
831: ,beep,i,smb.last_error);
832: return;
833: }
834: i=smb_getstatus(&smb);
835: if(i) {
836: smb_unlocksmbhdr(&smb);
837: fprintf(errfp,"\n%s!smb_getstatus returned %d: %s\n"
838: ,beep,i,smb.last_error);
839: return;
840: }
841:
842: if(!(smb.status.attr&SMB_HYPERALLOC)) {
843: i=smb_open_ha(&smb);
844: if(i) {
845: smb_unlocksmbhdr(&smb);
846: fprintf(errfp,"\n%s!smb_open_ha returned %d: %s\n"
847: ,beep,i,smb.last_error);
848: return;
849: }
850: i=smb_open_da(&smb);
851: if(i) {
852: smb_unlocksmbhdr(&smb);
853: smb_close_ha(&smb);
854: fprintf(errfp,"\n%s!smb_open_da returned %d: %s\n"
855: ,beep,i,smb.last_error);
856: return;
857: }
858: }
859:
860: if(!smb.status.total_msgs) {
861: printf("Empty\n");
862: rewind(smb.shd_fp);
863: CHSIZE_FP(smb.shd_fp,smb.status.header_offset);
864: rewind(smb.sdt_fp);
865: CHSIZE_FP(smb.sdt_fp,0);
866: rewind(smb.sid_fp);
867: CHSIZE_FP(smb.sid_fp,0);
868: if(!(smb.status.attr&SMB_HYPERALLOC)) {
869: rewind(smb.sha_fp);
870: CHSIZE_FP(smb.sha_fp,0);
871: rewind(smb.sda_fp);
872: CHSIZE_FP(smb.sda_fp,0);
873: smb_close_ha(&smb);
874: smb_close_da(&smb);
875: }
876: smb_unlocksmbhdr(&smb);
877: return;
878: }
879:
880:
881: if(!(smb.status.attr&SMB_HYPERALLOC) && !(mode&NOANALYSIS)) {
882: printf("Analyzing data blocks...\n");
883:
884: length=filelength(fileno(smb.sda_fp));
885:
886: fseek(smb.sda_fp,0L,SEEK_SET);
887: for(l=m=0;l<length;l+=2) {
888: printf("\r%2lu%% ",l ? (long)(100.0/((float)length/l)) : 0);
1.1.1.2 ! root 889: /* TODO: Only works on LE (size mismatch) */
1.1 root 890: i=0;
891: if(!fread(&i,2,1,smb.sda_fp))
892: break;
893: if(!i)
894: m++;
895: }
896:
897: printf("\rAnalyzing header blocks...\n");
898:
899: length=filelength(fileno(smb.sha_fp));
900:
901: fseek(smb.sha_fp,0L,SEEK_SET);
902: for(l=n=0;l<length;l++) {
903: printf("\r%2lu%% ",l ? (long)(100.0/((float)length/l)) : 0);
904: ch=0;
905: if(!fread(&ch,1,1,smb.sha_fp))
906: break;
907: if(!ch)
908: n++;
909: }
910:
911: if(!m && !n) {
912: printf("\rAlready compressed.\n\n");
913: smb_close_ha(&smb);
914: smb_close_da(&smb);
915: smb_unlocksmbhdr(&smb);
916: return;
917: }
918:
919: if(packable && (m*SDT_BLOCK_LEN)+(n*SHD_BLOCK_LEN)<packable*1024L) {
920: printf("\rLess than %luk compressible bytes.\n\n",packable);
921: smb_close_ha(&smb);
922: smb_close_da(&smb);
923: smb_unlocksmbhdr(&smb);
924: return;
925: }
926:
927: printf("\rCompressing %lu data blocks (%lu bytes)\n"
928: " and %lu header blocks (%lu bytes)\n"
929: ,m,m*SDT_BLOCK_LEN,n,n*SHD_BLOCK_LEN);
930: }
931:
932: if(!(smb.status.attr&SMB_HYPERALLOC)) {
933: rewind(smb.sha_fp);
934: CHSIZE_FP(smb.sha_fp,0); /* Reset both allocation tables */
935: rewind(smb.sda_fp);
936: CHSIZE_FP(smb.sda_fp,0);
937: }
938:
939: if(smb.status.attr&SMB_HYPERALLOC && !(mode&NOANALYSIS)) {
940: printf("Analyzing %s\n",smb.file);
941:
942: length=filelength(fileno(smb.shd_fp));
943: m=n=0;
944: for(l=smb.status.header_offset;l<length;l+=size) {
945: printf("\r%2lu%% ",(long)(100.0/((float)length/l)));
946: msg.idx.offset=l;
947: if((i=smb_lockmsghdr(&smb,&msg))!=0) {
948: printf("\n(%06lX) smb_lockmsghdr returned %d\n",l,i);
949: size=SHD_BLOCK_LEN;
950: continue;
951: }
952: if((i=smb_getmsghdr(&smb,&msg))!=0) {
953: smb_unlockmsghdr(&smb,&msg);
954: m++;
955: size=SHD_BLOCK_LEN;
956: continue;
957: }
958: smb_unlockmsghdr(&smb,&msg);
959: if(msg.hdr.attr&MSG_DELETE) {
960: m+=smb_hdrblocks(msg.hdr.length);
961: n+=smb_datblocks(smb_getmsgdatlen(&msg));
962: }
963: size=smb_hdrblocks(smb_getmsghdrlen(&msg))*SHD_BLOCK_LEN;
964: smb_freemsgmem(&msg);
965: }
966:
967:
968: if(!m && !n) {
969: printf("\rAlready compressed.\n\n");
970: smb_unlocksmbhdr(&smb);
971: return;
972: }
973:
974: if(packable && (n*SDT_BLOCK_LEN)+(m*SHD_BLOCK_LEN)<packable*1024L) {
975: printf("\rLess than %luk compressible bytes.\n\n",packable);
976: smb_unlocksmbhdr(&smb);
977: return;
978: }
979:
980: printf("\rCompressing %lu data blocks (%lu bytes)\n"
981: " and %lu header blocks (%lu bytes)\n"
982: ,n,n*SDT_BLOCK_LEN,m,m*SHD_BLOCK_LEN);
983: }
984:
985: sprintf(fname,"%s.sd$",smb.file);
986: tmp_sdt=fopen(fname,"wb");
987: sprintf(fname,"%s.sh$",smb.file);
988: tmp_shd=fopen(fname,"wb");
989: sprintf(fname,"%s.si$",smb.file);
990: tmp_sid=fopen(fname,"wb");
991: if(!tmp_sdt || !tmp_shd || !tmp_sid) {
992: smb_unlocksmbhdr(&smb);
993: if(!(smb.status.attr&SMB_HYPERALLOC)) {
994: smb_close_ha(&smb);
995: smb_close_da(&smb);
996: }
997: fprintf(errfp,"\n%s!Error opening temp files\n",beep);
998: return;
999: }
1000: setvbuf(tmp_sdt,NULL,_IOFBF,2*1024);
1001: setvbuf(tmp_shd,NULL,_IOFBF,2*1024);
1002: setvbuf(tmp_sid,NULL,_IOFBF,2*1024);
1003: if(!(smb.status.attr&SMB_HYPERALLOC)
1004: && (datoffset=(datoffset_t *)malloc(sizeof(datoffset_t)*smb.status.total_msgs))
1005: ==NULL) {
1006: smb_unlocksmbhdr(&smb);
1007: smb_close_ha(&smb);
1008: smb_close_da(&smb);
1009: fclose(tmp_sdt);
1010: fclose(tmp_shd);
1011: fclose(tmp_sid);
1012: fprintf(errfp,"\n%s!Error allocating memory\n",beep);
1013: return;
1014: }
1015: fseek(smb.shd_fp,0L,SEEK_SET);
1016: fread(&hdr,1,sizeof(smbhdr_t),smb.shd_fp);
1017: fwrite(&hdr,1,sizeof(smbhdr_t),tmp_shd);
1018: fwrite(&(smb.status),1,sizeof(smbstatus_t),tmp_shd);
1019: for(l=sizeof(smbhdr_t)+sizeof(smbstatus_t);l<smb.status.header_offset;l++) {
1020: fread(&ch,1,1,smb.shd_fp); /* copy additional base header records */
1021: fwrite(&ch,1,1,tmp_shd);
1022: }
1023: fseek(smb.sid_fp,0L,SEEK_SET);
1024: total=0;
1025: for(l=0;l<smb.status.total_msgs;l++) {
1026: printf("%lu of %lu\r",l+1,smb.status.total_msgs);
1027: if(!fread(&msg.idx,1,sizeof(idxrec_t),smb.sid_fp))
1028: break;
1029: if(msg.idx.attr&MSG_DELETE) {
1030: printf("\nDeleted index.\n");
1031: continue;
1032: }
1033: i=smb_lockmsghdr(&smb,&msg);
1034: if(i) {
1035: fprintf(errfp,"\n%s!smb_lockmsghdr returned %d: %s\n"
1036: ,beep,i,smb.last_error);
1037: continue;
1038: }
1039: i=smb_getmsghdr(&smb,&msg);
1040: smb_unlockmsghdr(&smb,&msg);
1041: if(i) {
1042: fprintf(errfp,"\n%s!smb_getmsghdr returned %d: %s\n"
1043: ,beep,i,smb.last_error);
1044: continue;
1045: }
1046: if(msg.hdr.attr&MSG_DELETE) {
1047: printf("\nDeleted header.\n");
1048: smb_freemsgmem(&msg);
1049: continue;
1050: }
1051: if(msg.expiration && msg.expiration<=now) {
1052: printf("\nExpired message.\n");
1053: smb_freemsgmem(&msg);
1054: continue;
1055: }
1056: for(m=0;m<datoffsets;m++)
1057: if(msg.hdr.offset==datoffset[m].old)
1058: break;
1059: if(m<datoffsets) { /* another index pointed to this data */
1060: printf("duplicate index\n");
1061: msg.hdr.offset=datoffset[m].new;
1062: smb_incmsgdat(&smb,datoffset[m].new,smb_getmsgdatlen(&msg),1);
1063: } else {
1064:
1065: if(!(smb.status.attr&SMB_HYPERALLOC))
1066: datoffset[datoffsets].old=msg.hdr.offset;
1067:
1068: fseek(smb.sdt_fp,msg.hdr.offset,SEEK_SET);
1069:
1070: m=smb_getmsgdatlen(&msg);
1071: if(m>16L*1024L*1024L) {
1072: fprintf(errfp,"\n%s!Invalid data length (%lu)\n",beep,m);
1073: continue;
1074: }
1075:
1076: if(!(smb.status.attr&SMB_HYPERALLOC)) {
1077: datoffset[datoffsets].new=msg.hdr.offset
1078: =smb_fallocdat(&smb,m,1);
1079: datoffsets++;
1080: fseek(tmp_sdt,msg.hdr.offset,SEEK_SET);
1081: }
1082: else {
1083: fseek(tmp_sdt,0L,SEEK_END);
1084: msg.hdr.offset=ftell(tmp_sdt);
1085: }
1086:
1087: /* Actually copy the data */
1088:
1089: n=smb_datblocks(m);
1090: for(m=0;m<n;m++) {
1091: fread(buf,1,SDT_BLOCK_LEN,smb.sdt_fp);
1092: if(!m && *(ushort *)buf!=XLAT_NONE && *(ushort *)buf!=XLAT_LZH) {
1093: printf("\nUnsupported translation type (%04X)\n"
1094: ,*(ushort *)buf);
1095: break;
1096: }
1097: fwrite(buf,1,SDT_BLOCK_LEN,tmp_sdt);
1098: }
1099: if(m<n)
1100: continue;
1101: }
1102:
1103: /* Write the new index entry */
1104: length=smb_getmsghdrlen(&msg);
1105: if(smb.status.attr&SMB_HYPERALLOC)
1106: msg.idx.offset=ftell(tmp_shd);
1107: else
1108: msg.idx.offset=smb_fallochdr(&smb,length)+smb.status.header_offset;
1109: msg.idx.number=msg.hdr.number;
1110: msg.idx.attr=msg.hdr.attr;
1111: msg.idx.time=msg.hdr.when_imported.time;
1112: msg.idx.subj=smb_subject_crc(msg.subj);
1113: if(smb.status.attr&SMB_EMAIL) {
1114: if(msg.to_ext)
1115: msg.idx.to=atoi(msg.to_ext);
1116: else
1117: msg.idx.to=0;
1118: if(msg.from_ext)
1119: msg.idx.from=atoi(msg.from_ext);
1120: else
1121: msg.idx.from=0;
1122: }
1123: else {
1124: SAFECOPY(str,msg.to);
1125: strlwr(str);
1126: msg.idx.to=crc16(str,0);
1127: SAFECOPY(str,msg.from);
1128: strlwr(str);
1129: msg.idx.from=crc16(str,0);
1130: }
1131: fwrite(&msg.idx,1,sizeof(idxrec_t),tmp_sid);
1132:
1133: /* Write the new header entry */
1134: fseek(tmp_shd,msg.idx.offset,SEEK_SET);
1135: fwrite(&msg.hdr,1,sizeof(msghdr_t),tmp_shd);
1136: for(n=0;n<msg.hdr.total_dfields;n++)
1137: fwrite(&msg.dfield[n],1,sizeof(dfield_t),tmp_shd);
1138: for(n=0;n<msg.total_hfields;n++) {
1139: fwrite(&msg.hfield[n],1,sizeof(hfield_t),tmp_shd);
1140: fwrite(msg.hfield_dat[n],1,msg.hfield[n].length,tmp_shd);
1141: }
1142: while(length%SHD_BLOCK_LEN) { /* pad with NULLs */
1143: fputc(0,tmp_shd);
1144: length++;
1145: }
1146: total++;
1147: smb_freemsgmem(&msg);
1148: }
1149:
1150: if(datoffset)
1151: free(datoffset);
1152: if(!(smb.status.attr&SMB_HYPERALLOC)) {
1153: smb_close_ha(&smb);
1154: smb_close_da(&smb);
1155: }
1156:
1157: /* Change *.sh$ into *.shd */
1158: fclose(smb.shd_fp), smb.shd_fp=NULL;
1159: fclose(tmp_shd);
1160: sprintf(fname,"%s.shd",smb.file);
1161: if(remove(fname)!=0) {
1162: error=TRUE;
1163: fprintf(errfp,"\n%s!Error %d removing %s\n",beep,errno,fname);
1164: }
1165: sprintf(tmpfname,"%s.sh$",smb.file);
1166: if(!error && rename(tmpfname,fname)!=0) {
1167: error=TRUE;
1168: fprintf(errfp,"\n%s!Error %d renaming %s to %s\n",beep,errno,tmpfname,fname);
1169: }
1170:
1171:
1172: /* Change *.sd$ into *.sdt */
1173: fclose(smb.sdt_fp), smb.sdt_fp=NULL;
1174: fclose(tmp_sdt);
1175: sprintf(fname,"%s.sdt",smb.file);
1176: if(!error && remove(fname)!=0) {
1177: error=TRUE;
1178: fprintf(errfp,"\n%s!Error %d removing %s\n",beep,errno,fname);
1179: }
1180:
1181: sprintf(tmpfname,"%s.sd$",smb.file);
1182: if(!error && rename(tmpfname,fname)!=0) {
1183: error=TRUE;
1184: fprintf(errfp,"\n%s!Error %d renaming %s to %s\n",beep,errno,tmpfname,fname);
1185: }
1186:
1187: /* Change *.si$ into *.sid */
1188: fclose(smb.sid_fp), smb.sid_fp=NULL;
1189: fclose(tmp_sid);
1190: sprintf(fname,"%s.sid",smb.file);
1191: if(!error && remove(fname)!=0) {
1192: error=TRUE;
1193: fprintf(errfp,"\n%s!Error %d removing %s\n",beep,errno,fname);
1194: }
1195:
1196: sprintf(tmpfname,"%s.si$",smb.file);
1197: if(!error && rename(tmpfname,fname)!=0) {
1198: error=TRUE;
1199: fprintf(errfp,"\n%s!Error %d renaming %s to %s\n",beep,errno,tmpfname,fname);
1200: }
1201:
1202: if((i=smb_unlock(&smb))!=0)
1203: fprintf(errfp,"\n%s!ERROR %d (%s) unlocking %s\n"
1204: ,beep,i,smb.last_error,smb.file);
1205:
1206: if((i=smb_open(&smb))!=0) {
1207: fprintf(errfp,"\n%s!Error %d (%s) reopening %s\n"
1208: ,beep,i,smb.last_error,smb.file);
1209: return;
1210: }
1211: if((i=smb_locksmbhdr(&smb))!=0)
1212: fprintf(errfp,"\n%s!smb_locksmbhdr returned %d: %s\n"
1213: ,beep,i,smb.last_error);
1214: smb.status.total_msgs=total;
1215: if((i=smb_putstatus(&smb))!=0)
1216: fprintf(errfp,"\n%s!smb_putstatus returned %d: %s\n"
1217: ,beep,i,smb.last_error);
1218: smb_unlocksmbhdr(&smb);
1219: printf("\nDone.\n\n");
1220: }
1221:
1222: void delmsgs(void)
1223: {
1224: int i;
1225:
1226: printf("Deleting %s\n",smb.file);
1227:
1228: i=smb_locksmbhdr(&smb);
1229: if(i) {
1230: fprintf(errfp,"\n%s!smb_locksmbhdr returned %d: %s\n"
1231: ,beep,i,smb.last_error);
1232: return;
1233: }
1234: i=smb_getstatus(&smb);
1235: if(i) {
1236: smb_unlocksmbhdr(&smb);
1237: fprintf(errfp,"\n%s!smb_getstatus returned %d: %s\n"
1238: ,beep,i,smb.last_error);
1239: return;
1240: }
1241: if(!(smb.status.attr&SMB_HYPERALLOC)) {
1242: i=smb_open_da(&smb);
1243: if(i) {
1244: smb_unlocksmbhdr(&smb);
1245: fprintf(errfp,"\n%s!smb_open_da returned %d: %s\n"
1246: ,beep,i,smb.last_error);
1247: bail(1);
1248: }
1249: i=smb_open_ha(&smb);
1250: if(i) {
1251: smb_unlocksmbhdr(&smb);
1252: fprintf(errfp,"\n%s!smb_open_ha returned %d: %s\n"
1253: ,beep,i,smb.last_error);
1254: bail(1);
1255: }
1256: /* Reset both allocation tables */
1257: CHSIZE_FP(smb.sha_fp,0);
1258: CHSIZE_FP(smb.sda_fp,0);
1259: smb_close_ha(&smb);
1260: smb_close_da(&smb);
1261: }
1262:
1263: CHSIZE_FP(smb.sid_fp,0);
1264: CHSIZE_FP(smb.shd_fp,smb.status.header_offset);
1265: CHSIZE_FP(smb.sdt_fp,0);
1266:
1267: /* re-write status header */
1268: smb.status.total_msgs=0;
1269: if((i=smb_putstatus(&smb))!=0)
1270: fprintf(errfp,"\n%s!smb_putstatus returned %d: %s\n"
1271: ,beep,i,smb.last_error);
1272: smb_unlocksmbhdr(&smb);
1273: printf("\nDone.\n\n");
1274: }
1275:
1276: /****************************************************************************/
1277: /* Read messages in message base */
1278: /****************************************************************************/
1279: void readmsgs(ulong start)
1280: {
1281: char *inbuf;
1282: int i,done=0,domsg=1;
1283: smbmsg_t msg;
1284:
1285: if(start)
1286: msg.offset=start-1;
1287: else
1288: msg.offset=0;
1289: while(!done) {
1290: if(domsg) {
1291: fseek(smb.sid_fp,msg.offset*sizeof(idxrec_t),SEEK_SET);
1292: if(!fread(&msg.idx,1,sizeof(idxrec_t),smb.sid_fp))
1293: break;
1294: i=smb_lockmsghdr(&smb,&msg);
1295: if(i) {
1296: fprintf(errfp,"\n%s!smb_lockmsghdr returned %d: %s\n"
1297: ,beep,i,smb.last_error);
1298: break;
1299: }
1300: i=smb_getmsghdr(&smb,&msg);
1301: if(i) {
1302: fprintf(errfp,"\n%s!smb_getmsghdr returned %d: %s\n"
1303: ,beep,i,smb.last_error);
1304: break;
1305: }
1306:
1307: printf("\n%lu (%lu)\n",msg.hdr.number,msg.offset+1);
1308: printf("Subj : %s\n",msg.subj);
1309: printf("To : %s",msg.to);
1310: if(msg.to_net.type)
1311: printf(" (%s)",smb_netaddr(&msg.to_net));
1312: printf("\nFrom : %s",msg.from);
1313: if(msg.from_net.type)
1314: printf(" (%s)",smb_netaddr(&msg.from_net));
1315: printf("\nDate : %.24s %s"
1.1.1.2 ! root 1316: ,my_timestr(msg.hdr.when_written.time)
1.1 root 1317: ,smb_zonestr(msg.hdr.when_written.zone,NULL));
1318:
1319: printf("\n\n");
1320:
1321: if((inbuf=smb_getmsgtxt(&smb,&msg,GETMSGTXT_ALL))!=NULL) {
1322: printf("%s",inbuf);
1323: free(inbuf);
1324: }
1325:
1326: i=smb_unlockmsghdr(&smb,&msg);
1327: if(i) {
1328: fprintf(errfp,"\n%s!smb_unlockmsghdr returned %d: %s\n"
1329: ,beep,i,smb.last_error);
1330: break;
1331: }
1332: smb_freemsgmem(&msg);
1333: }
1334: domsg=1;
1335: printf("\nReading %s (?=Menu): ",smb.file);
1336: switch(toupper(getch())) {
1337: case '?':
1338: printf("\n"
1339: "\n"
1340: "(R)e-read current message\n"
1341: "(L)ist messages\n"
1342: "(T)en more titles\n"
1343: "(V)iew message headers\n"
1344: "(Q)uit\n"
1345: "(+/-) Forward/Backward\n"
1346: "\n");
1347: domsg=0;
1348: break;
1349: case 'Q':
1350: printf("Quit\n");
1351: done=1;
1352: break;
1353: case 'R':
1354: printf("Re-read\n");
1355: break;
1356: case '-':
1357: printf("Backwards\n");
1358: if(msg.offset)
1359: msg.offset--;
1360: break;
1361: case 'T':
1362: printf("Ten titles\n");
1363: listmsgs(msg.offset+2,10);
1364: msg.offset+=10;
1365: domsg=0;
1366: break;
1367: case 'L':
1368: printf("List messages\n");
1369: listmsgs(1,-1);
1370: domsg=0;
1371: break;
1372: case 'V':
1373: printf("View message headers\n");
1374: viewmsgs(1,-1);
1375: domsg=0;
1376: break;
1377: case CR:
1378: case '+':
1379: printf("Next\n");
1380: msg.offset++;
1381: break;
1382: }
1383: }
1384: }
1385:
1386: short str2tzone(const char* str)
1387: {
1388: char tmp[32];
1389: short zone;
1390:
1391: if(isdigit(*str) || *str=='-' || *str=='+') { /* [+|-]HHMM format */
1392: if(*str=='+') str++;
1393: sprintf(tmp,"%.*s",*str=='-'? 3:2,str);
1394: zone=atoi(tmp)*60;
1395: str+=(*str=='-') ? 3:2;
1396: if(zone<0)
1397: zone-=atoi(str);
1398: else
1399: zone+=atoi(str);
1400: return zone;
1401: }
1402: if(!stricmp(str,"EST") || !stricmp(str,"Eastern Standard Time"))
1403: return (short)EST;
1404: if(!stricmp(str,"EDT") || !stricmp(str,"Eastern Daylight Time"))
1405: return (short)EDT;
1406: if(!stricmp(str,"CST") || !stricmp(str,"Central Standard Time"))
1407: return (short)CST;
1408: if(!stricmp(str,"CDT") || !stricmp(str,"Central Daylight Time"))
1409: return (short)CDT;
1410: if(!stricmp(str,"MST") || !stricmp(str,"Mountain Standard Time"))
1411: return (short)MST;
1412: if(!stricmp(str,"MDT") || !stricmp(str,"Mountain Daylight Time"))
1413: return (short)MDT;
1414: if(!stricmp(str,"PST") || !stricmp(str,"Pacific Standard Time"))
1415: return (short)PST;
1416: if(!stricmp(str,"PDT") || !stricmp(str,"Pacific Daylight Time"))
1417: return (short)PDT;
1418:
1419: return 0; /* UTC */
1420: }
1421:
1422: /***************/
1423: /* Entry point */
1424: /***************/
1425: int main(int argc, char **argv)
1426: {
1427: char cmd[128]="",*p;
1428: char path[MAX_PATH+1];
1429: char* to=NULL;
1430: char* to_number=NULL;
1431: char* to_address=NULL;
1432: char* from=NULL;
1433: char* from_number=NULL;
1434: char* subj=NULL;
1435: FILE* fp;
1436: int i,j,x,y;
1437: long count=0;
1438: BOOL create=FALSE;
1439: time_t now;
1440: struct tm* tm;
1441:
1442: setvbuf(stdout,0,_IONBF,0);
1443:
1444: errfp=stderr;
1445: if((nulfp=fopen(_PATH_DEVNULL,"w+"))==NULL) {
1446: perror(_PATH_DEVNULL);
1447: bail(-1);
1448: }
1449: if(isatty(fileno(stderr)))
1450: statfp=stderr;
1451: else /* if redirected, don't send status messages to stderr */
1452: statfp=nulfp;
1453:
1.1.1.2 ! root 1454: sscanf("$Revision: 1.100 $", "%*s %s", revision);
1.1 root 1455:
1456: DESCRIBE_COMPILER(compiler);
1457:
1458: smb.file[0]=0;
1459: fprintf(statfp,"\nSMBUTIL v%s-%s (rev %s) SMBLIB %s - Synchronet Message Base "\
1460: "Utility\n\n"
1461: ,SMBUTIL_VER
1462: ,PLATFORM_DESC
1463: ,revision
1464: ,smb_lib_ver()
1465: );
1466:
1467: /* Automatically detect the system time zone (if possible) */
1468: tzset();
1469: now=time(NULL);
1470: if((tm=localtime(&now))!=NULL) {
1471: if(tm->tm_isdst<=0)
1472: tzone=str2tzone(tzname[0]);
1473: else
1474: tzone=str2tzone(tzname[1]);
1475: }
1476:
1477: for(x=1;x<argc && x>0;x++) {
1478: if(
1479: #ifndef __unix__
1480: argv[x][0]=='/' || /* for backwards compatibilty */
1481: #endif
1482: argv[x][0]=='-') {
1483: if(isdigit(argv[x][1])) {
1484: count=strtol(argv[x]+1,NULL,10);
1485: continue;
1486: }
1487: for(j=1;argv[x][j];j++)
1488: switch(toupper(argv[x][j])) {
1489: case 'A':
1490: mode|=NOANALYSIS;
1491: break;
1492: case 'I':
1493: mode|=NOCRC;
1494: break;
1495: case 'D':
1496: to="All";
1497: to_number="1";
1498: from="Sysop";
1499: from_number="1";
1500: subj="Announcement";
1501: break;
1502: case 'Z':
1503: tzone=str2tzone(argv[x]+j+1);
1504: j=strlen(argv[x])-1;
1505: break;
1506: case 'C':
1507: create=TRUE;
1508: break;
1509: case 'T':
1510: to=argv[x]+j+1;
1511: j=strlen(argv[x])-1;
1512: break;
1513: case 'U':
1514: to_number=argv[x]+j+1;
1515: j=strlen(argv[x])-1;
1516: break;
1517: case 'N':
1518: to_address=argv[x]+j+1;
1519: j=strlen(argv[x])-1;
1520: break;
1521: case 'F':
1522: from=argv[x]+j+1;
1523: j=strlen(argv[x])-1;
1524: break;
1525: case 'E':
1526: from_number=argv[x]+j+1;
1527: j=strlen(argv[x])-1;
1528: break;
1529: case 'S':
1530: subj=argv[x]+j+1;
1531: j=strlen(argv[x])-1;
1532: break;
1533: case 'O':
1534: errfp=stdout;
1535: break;
1536: case 'L':
1537: xlat=XLAT_LZH;
1538: break;
1539: case 'P':
1540: pause_on_exit=TRUE;
1541: break;
1542: case '!':
1543: pause_on_error=TRUE;
1544: break;
1545: case 'B':
1546: beep="\a";
1547: break;
1548: default:
1549: printf("\nUnknown opt '%c'\n",argv[x][j]);
1550: case '?':
1551: printf("%s",usage);
1552: bail(1);
1553: break;
1554: }
1555: }
1556: else {
1557: if(!cmd[0])
1558: SAFECOPY(cmd,argv[x]);
1559: else {
1560: SAFECOPY(smb.file,argv[x]);
1561: if((p=getfext(smb.file))!=NULL && stricmp(p,".shd")==0)
1562: *p=0; /* Chop off .shd extension, if supplied on command-line */
1563:
1564: sprintf(path,"%s.shd",smb.file);
1565: if(!fexistcase(path) && !create) {
1566: fprintf(errfp,"\n%s doesn't exist (use -c to create)\n",path);
1567: bail(1);
1568: }
1569: smb.retry_time=30;
1570: fprintf(statfp,"Opening %s\r\n",smb.file);
1571: if((i=smb_open(&smb))!=0) {
1572: fprintf(errfp,"\n%s!Error %d (%s) opening %s message base\n"
1573: ,beep,i,smb.last_error,smb.file);
1574: bail(1);
1575: }
1576: if(!filelength(fileno(smb.shd_fp))) {
1577: if(!create) {
1578: printf("Empty\n");
1579: smb_close(&smb);
1580: continue;
1581: }
1582: smb.status.max_msgs=strtoul(cmd+1,NULL,0);
1583: smb.status.max_crcs=count;
1584: if((i=smb_create(&smb))!=0) {
1585: smb_close(&smb);
1586: printf("!Error %d (%s) creating %s\n",i,smb.last_error,smb.file);
1587: continue;
1588: }
1589: }
1590: for(y=0;cmd[y];y++)
1591: switch(toupper(cmd[y])) {
1592: case 'I':
1593: case 'E':
1594: case 'N':
1595: if(cmd[1]!=0) {
1596: if((fp=fopen(cmd+1,"r"))==NULL) {
1597: fprintf(errfp,"\n%s!Error %d opening %s\n"
1598: ,beep,errno,cmd+1);
1599: bail(1);
1600: }
1601: } else
1602: fp=stdin;
1603: i=smb_locksmbhdr(&smb);
1604: if(i) {
1605: fprintf(errfp,"\n%s!smb_locksmbhdr returned %d: %s\n"
1606: ,beep,i,smb.last_error);
1607: return(1);
1608: }
1609: postmsg((char)toupper(cmd[y]),to,to_number,to_address,from,from_number,subj,fp);
1610: fclose(fp);
1611: y=strlen(cmd)-1;
1612: break;
1613: case 'S':
1614: showstatus();
1615: break;
1616: case 'C':
1617: config();
1618: break;
1619: case 'L':
1620: listmsgs(atol(cmd+1),count);
1621: y=strlen(cmd)-1;
1622: break;
1623: case 'X':
1624: dumpindex(atol(cmd+1),count);
1625: y=strlen(cmd)-1;
1626: break;
1627: case 'P':
1628: case 'D':
1629: if((i=smb_lock(&smb))!=0) {
1630: fprintf(errfp,"\n%s!smb_lock returned %d: %s\n"
1631: ,beep,i,smb.last_error);
1632: return(i);
1633: }
1634: switch(toupper(cmd[y])) {
1635: case 'P':
1636: packmsgs(atol(cmd+y+1));
1637: break;
1638: case 'D':
1639: delmsgs();
1640: break;
1641: }
1642: smb_unlock(&smb);
1643: y=strlen(cmd)-1;
1644: break;
1645: case 'R':
1646: readmsgs(atol(cmd+1));
1647: y=strlen(cmd)-1;
1648: break;
1649: case 'V':
1650: viewmsgs(atol(cmd+1),count);
1651: y=strlen(cmd)-1;
1652: break;
1653: case 'H':
1654: dump_hashes();
1655: break;
1656: case 'M':
1657: maint();
1658: break;
1659: default:
1660: printf("%s",usage);
1661: break;
1662: }
1663: smb_close(&smb);
1664: }
1665: }
1666: }
1667: if(!cmd[0])
1668: printf("%s",usage);
1669:
1670: bail(0);
1671:
1672: return(-1); /* never gets here */
1673: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.