smbutil.c 40.2 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
/* smbutil.c */

/* Synchronet message base (SMB) utility */

/* $Id$ */

/****************************************************************************
 * @format.tab-size 4		(Plain Text/Source Code File Header)			*
 * @format.use-tabs true	(see http://www.synchro.net/ptsc_hdr.html)		*
 *																			*
11
 * Copyright 2004 Rob Swindell - http://www.synchro.net/copyright.html		*
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
 *																			*
 * This program is free software; you can redistribute it and/or			*
 * modify it under the terms of the GNU General Public License				*
 * as published by the Free Software Foundation; either version 2			*
 * of the License, or (at your option) any later version.					*
 * See the GNU General Public License for more details: gpl.txt or			*
 * http://www.fsf.org/copyleft/gpl.html										*
 *																			*
 * Anonymous FTP access to the most recent released source is available at	*
 * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net	*
 *																			*
 * Anonymous CVS access to the development source and modification history	*
 * is available at cvs.synchro.net:/cvsroot/sbbs, example:					*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs login			*
 *     (just hit return, no password is necessary)							*
 * cvs -d :pserver:anonymous@cvs.synchro.net:/cvsroot/sbbs checkout src		*
 *																			*
 * For Synchronet coding style and modification guidelines, see				*
 * http://www.synchro.net/source.html										*
 *																			*
 * You are encouraged to submit any modifications (preferably in Unix diff	*
 * format) via e-mail to mods@synchro.net									*
 *																			*
 * Note: If this box doesn't appear square, then you need to fix your tabs.	*
 ****************************************************************************/

38
#define SMBUTIL_VER "2.33"
39
40
char	revision[16];
char	compiler[32];
41
42

#define NOANALYSIS		(1L<<0)
43
#define NOCRC			(1L<<1)
44
45
46
47
48
49
50

#ifdef __WATCOMC__
	#define ffblk find_t
    #define findfirst(x,y,z) _dos_findfirst(x,z,y)
	#define findnext(x) _dos_findnext(x)
#endif

51
52
53
54
55
56
#if defined(_WIN32)
	#include <ctype.h>	/* isdigit() */
	#include <conio.h>	/* getch() */
#endif

/* ANSI */
57
#include <stdio.h>
rswindell's avatar
rswindell committed
58
59
60
61
#include <time.h>		/* time */
#include <errno.h>		/* errno */
#include <string.h>		/* strrchr */
#include <ctype.h>		/* toupper */
62

63
#include "sbbs.h"
64
#include "genwrap.h"	/* stricmp */
rswindell's avatar
rswindell committed
65
#include "dirwrap.h"	/* fexist */
rswindell's avatar
rswindell committed
66
#include "conwrap.h"	/* getch */
67
#include "filewrap.h"
68
#include "smblib.h"
69
#include "crc32.h"
70
#include "gen_defs.h"	/* MAX_PATH */
71
72
73
74
75

#ifdef __WATCOMC__
	#include <dos.h>
#endif

76
/* gets is dangerous */
77
#define gets(str)  fgets((str), sizeof(str), stdin)
78

79
80
#define CHSIZE_FP(fp,size)	if(chsize(fileno(fp),size)) printf("chsize failed!\n");

81
82
83
84
85
86
/********************/
/* Global variables */
/********************/

smb_t smb;
ulong mode=0L;
87
ushort tzone=0;
88
89
90
91
92
93

/************************/
/* Program usage/syntax */
/************************/

char *usage=
94
"usage: smbutil [-opts] cmd <filespec.shd>\n"
95
96
97
98
99
"\n"
"cmd:\n"
"       l[n] = list msgs starting at number n\n"
"       r[n] = read msgs starting at number n\n"
"       v[n] = view msg headers starting at number n\n"
100
101
102
"       i[f] = import msg from text file f (or use stdin)\n"
"       e[f] = import e-mail from text file f (or use stdin)\n"
"       n[f] = import netmail from text file f (or use stdin)\n"
103
104
"       s    = display msg base status\n"
"       c    = change msg base status\n"
105
"       d    = delete all msgs\n"
106
107
108
"       m    = maintain msg base - delete old msgs and msgs over max\n"
"       p[k] = pack msg base (k specifies minimum packable Kbytes)\n"
"opts:\n"
rswindell's avatar
rswindell committed
109
"       c    = create message base if it doesn't exist\n"
110
"       a    = always pack msg base (disable compression analysis)\n"
111
"       i    = ignore duplicate messages (do not store CRC)\n"
112
"       d    = use default values (no prompt) for to, from, and subject\n"
113
114
115
116
117
118
"       t<s> = set 'to' user name for imported message\n"
"       n<s> = set 'to' netmail address for imported message\n"
"       u<s> = set 'to' user number for imported message\n"
"       f<s> = set 'from' user name for imported message\n"
"       e<s> = set 'from' user number for imported message\n"
"       s<s> = set 'subject' for imported message\n"
119
"       z[n] = set time zone (n=min +/- from UT or 'EST','EDT','CST',etc)\n"
120
"       #    = set number of messages to view/list (e.g. -1)\n"
121
122
;

123
124
125
126
127
128
/*****************************************************************************/
// Expands Unix LF to CRLF
/*****************************************************************************/
ulong lf_expand(BYTE* inbuf, ulong inlen, BYTE* outbuf)
{
	ulong	i,j;
rswindell's avatar
rswindell committed
129

130
131
132
133
134
135
136
	for(i=j=0;i<inlen;i++) {
		if(inbuf[i]=='\n' && (!i || inbuf[i-1]!='\r'))
			outbuf[j++]='\r';
		outbuf[j++]=inbuf[i];
	}
	return(j);
}
rswindell's avatar
rswindell committed
137

138
139
140
/****************************************************************************/
/* Adds a new message to the message base									*/
/****************************************************************************/
141
142
void postmsg(char type, char* to, char* to_number, char* to_address, 
			 char* from, char* from_number, char* subject, FILE* fp)
143
{
144
145
146
147
	char	str[128];
	char	buf[128];
	char	pad=0;
	char*	msgtxt=NULL;
148
	char*	newtxt;
149
	long	msgtxtlen;
150
	ushort	xlat,net;
151
152
153
	int 	i;
	long	l,length;
	ulong	offset,crc;
154
	ushort		agent=AGENT_SMBUTIL;
155
156
	smbmsg_t	msg;

157
158
159
160
161
162
163
	/* Read message text from stream (file or stdin) */
	msgtxtlen=0;
	while(!feof(fp)) {
		i=fread(buf,1,sizeof(buf),fp);
		if(i<1)
			break;
		if((msgtxt=(char*)realloc(msgtxt,msgtxtlen+i))==NULL) {
164
			fprintf(stderr,"\n\7malloc(%ld) failure\n",msgtxtlen+i);
165
166
167
168
169
170
			exit(1);
		}
		memcpy(msgtxt+msgtxtlen,buf,i);
		msgtxtlen+=i;
	}

171
172
173
174
175
176
177
178
179
180
	if((newtxt=(char*)malloc(msgtxtlen*2))==NULL) {
		fprintf(stderr,"\n\7malloc(%ld) failure\n",msgtxtlen*2);
		exit(1);
	}

	/* Expand LFs to CRLFs */
	msgtxtlen=lf_expand(msgtxt, msgtxtlen, newtxt);
	free(msgtxt);
	msgtxt=newtxt;

181
182
	/* Allocate space in message base */
	length=msgtxtlen+sizeof(xlat);	/* for translation string */
rswindell's avatar
rswindell committed
183
184
185
	if(!(smb.status.attr&SMB_HYPERALLOC)) {
		i=smb_open_da(&smb);
		if(i) {
186
			fprintf(stderr,"\n\7!smb_open_da returned %d: %s\n",i,smb.last_error);
187
188
			exit(1); 
		}
rswindell's avatar
rswindell committed
189
		offset=smb_allocdat(&smb,length,1);
190
191
		smb_close_da(&smb); 
	} else
rswindell's avatar
rswindell committed
192
193
194
195
		offset=smb_hallocdat(&smb);

	fseek(smb.sdt_fp,offset,SEEK_SET);
	xlat=XLAT_NONE;
196
197
	smb_fwrite(&smb,&xlat,sizeof(xlat),smb.sdt_fp);
	smb_fwrite(&smb,msgtxt,msgtxtlen,smb.sdt_fp);
198
	for(l=length;l%SDT_BLOCK_LEN;l++)
199
		smb_fwrite(&smb,&pad,sizeof(pad),smb.sdt_fp);
rswindell's avatar
rswindell committed
200
201
202
203
204
205
206
207
	fflush(smb.sdt_fp);

	memset(&msg,0,sizeof(smbmsg_t));
	msg.hdr.version=smb_ver();
	msg.hdr.when_written.time=time(NULL);
	msg.hdr.when_written.zone=tzone;
	msg.hdr.when_imported=msg.hdr.when_written;

208
	if(smb.status.max_crcs && !(mode&NOCRC)) {
209
210
211
212
		crc=0xffffffffUL;
		for(l=0;l<msgtxtlen;l++) 
			crc=ucrc32(msgtxt[l],crc);
		crc=~crc;
rswindell's avatar
rswindell committed
213
214
		i=smb_addcrc(&smb,crc);
		if(i) {
215
			fprintf(stderr,"\n\7!smb_addcrc returned %d: %s\n",i,smb.last_error);
rswindell's avatar
rswindell committed
216
			smb_freemsgdat(&smb,offset,length,1);
217
218
219
			exit(1); 
		} 
	}
rswindell's avatar
rswindell committed
220
221
222

	msg.hdr.offset=offset;

223
224
	if(to==NULL) {
		printf("To User Name: ");
225
		fgets(str,sizeof(str),stdin); 
226
	} else
227
		SAFECOPY(str,to);
228

rswindell's avatar
rswindell committed
229
	truncsp(str);
230
	i=smb_hfield_str(&msg,RECIPIENT,str);
231
	if(i) {
232
		fprintf(stderr,"\n\7!smb_hfield returned %d: %s\n",i,smb.last_error);
233
		smb_freemsgdat(&smb,offset,length,1);
rswindell's avatar
rswindell committed
234
235
		exit(1); 
	}
rswindell's avatar
rswindell committed
236
237
238
	if(type=='E' || type=='N')
		smb.status.attr|=SMB_EMAIL;
	if(smb.status.attr&SMB_EMAIL) {
239
240
241
242
		if(to_number==NULL) {
			printf("To User Number (0=QWKnet or Internet): ");
			gets(str);
		} else
243
			SAFECOPY(str,to_number);
rswindell's avatar
rswindell committed
244
		truncsp(str);
245
		i=smb_hfield_str(&msg,RECIPIENTEXT,str);
246
		if(i) {
247
			fprintf(stderr,"\n\7!smb_hfield returned %d: %s\n",i,smb.last_error);
248
			smb_freemsgdat(&smb,offset,length,1);
249
250
			exit(1); 
		}
rswindell's avatar
rswindell committed
251
252
		msg.idx.to=atoi(str); 
	}
rswindell's avatar
rswindell committed
253
254
	else {
		strlwr(str);
255
		msg.idx.to=crc16(str,0); 
256
	}
rswindell's avatar
rswindell committed
257
258

	if(smb.status.attr&SMB_EMAIL && (type=='N' || !msg.idx.to)) {
259
260
261
262
		if(to_address==NULL) {
			printf("To Address: ");
			gets(str);
		} else
263
			SAFECOPY(str,to_address);
rswindell's avatar
rswindell committed
264
265
266
267
268
269
270
271
		truncsp(str);
		if(*str) {
			if(strchr(str,'.'))
				net=NET_INTERNET;
			else
				net=NET_QWK;
			i=smb_hfield(&msg,RECIPIENTNETTYPE,sizeof(net),&net);
			if(i) {
272
				fprintf(stderr,"\n\7!smb_hfield returned %d: %s\n",i,smb.last_error);
rswindell's avatar
rswindell committed
273
				smb_freemsgdat(&smb,offset,length,1);
rswindell's avatar
rswindell committed
274
275
				exit(1); 
			}
276
			i=smb_hfield_str(&msg,RECIPIENTNETADDR,str);
rswindell's avatar
rswindell committed
277
			if(i) {
278
				fprintf(stderr,"\n\7!smb_hfield returned %d: %s\n",i,smb.last_error);
rswindell's avatar
rswindell committed
279
				smb_freemsgdat(&smb,offset,length,1);
280
281
282
283
				exit(1); 
			} 
		} 
	}
rswindell's avatar
rswindell committed
284

285
286
287
288
	if(from==NULL) {
		printf("From User Name: ");
		gets(str);
	} else
289
		SAFECOPY(str,from);
rswindell's avatar
rswindell committed
290
	truncsp(str);
291
	i=smb_hfield_str(&msg,SENDER,str);
rswindell's avatar
rswindell committed
292
	if(i) {
293
		fprintf(stderr,"\n\7!smb_hfield returned %d: %s\n",i,smb.last_error);
rswindell's avatar
rswindell committed
294
		smb_freemsgdat(&smb,offset,length,1);
rswindell's avatar
rswindell committed
295
296
		exit(1); 
	}
rswindell's avatar
rswindell committed
297
	if(smb.status.attr&SMB_EMAIL) {
298
299
300
301
		if(from_number==NULL) {
			printf("From User Number: ");
			gets(str);
		} else
302
			SAFECOPY(str,from_number);
rswindell's avatar
rswindell committed
303
		truncsp(str);
304
		i=smb_hfield_str(&msg,SENDEREXT,str);
305
		if(i) {
306
			fprintf(stderr,"\n\7!smb_hfield returned %d: %s\n",i,smb.last_error);
307
			smb_freemsgdat(&smb,offset,length,1);
308
309
310
311
			exit(1); 
		}
		msg.idx.from=atoi(str); 
	} else {
rswindell's avatar
rswindell committed
312
		strlwr(str);
313
		msg.idx.from=crc16(str,0); 
314
	}
315
	smb_hfield(&msg, SENDERAGENT, sizeof(agent), &agent);
rswindell's avatar
rswindell committed
316

317
318
319
320
	if(subject==NULL) {
		printf("Subject: ");
		gets(str);
	} else
321
		SAFECOPY(str,subject);
rswindell's avatar
rswindell committed
322
	truncsp(str);
323
	i=smb_hfield_str(&msg,SUBJECT,str);
324
	if(i) {
325
		fprintf(stderr,"\n\7!smb_hfield returned %d: %s\n",i,smb.last_error);
326
		smb_freemsgdat(&smb,offset,length,1);
327
328
		exit(1); 
	}
329
	msg.idx.subj=subject_crc(str);
rswindell's avatar
rswindell committed
330
331
332

	i=smb_dfield(&msg,TEXT_BODY,length);
	if(i) {
333
		fprintf(stderr,"\n\7!smb_dfield returned %d: %s\n",i,smb.last_error);
rswindell's avatar
rswindell committed
334
		smb_freemsgdat(&smb,offset,length,1);
rswindell's avatar
rswindell committed
335
336
		exit(1); 
	}
rswindell's avatar
rswindell committed
337

338
	sprintf(str,"SMBUTIL %s-%s r%s %s %s"
339
340
341
342
343
344
		,SMBUTIL_VER
		,PLATFORM_DESC
		,revision
		,__DATE__
		,compiler
		);
345
	smb_hfield_str(&msg,FIDOPID,str);
346

rswindell's avatar
rswindell committed
347
348
	i=smb_addmsghdr(&smb,&msg,smb.status.attr&SMB_HYPERALLOC);

349
	if(i!=SMB_SUCCESS) {
350
		fprintf(stderr,"\n\7!smb_addmsghdr returned %d: %s\n",i,smb.last_error);
351
		smb_freemsg_dfields(&smb,&msg,1);
rswindell's avatar
rswindell committed
352
353
		exit(1); 
	}
rswindell's avatar
rswindell committed
354
	smb_freemsgmem(&msg);
355

356
	free(msgtxt);
357
358
359
360
361
}

/****************************************************************************/
/* Shows the message base header											*/
/****************************************************************************/
362
void showstatus(void)
363
364
365
{
	int i;

rswindell's avatar
rswindell committed
366
367
	i=smb_locksmbhdr(&smb);
	if(i) {
368
		fprintf(stderr,"\n\7!smb_locksmbhdr returned %d: %s\n",i,smb.last_error);
rswindell's avatar
rswindell committed
369
370
		return; 
	}
rswindell's avatar
rswindell committed
371
372
373
	i=smb_getstatus(&smb);
	smb_unlocksmbhdr(&smb);
	if(i) {
374
		fprintf(stderr,"\n\7!smb_getstatus returned %d: %s\n",i,smb.last_error);
rswindell's avatar
rswindell committed
375
376
		return; 
	}
rswindell's avatar
rswindell committed
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
	printf("last_msg        =%lu\n"
		   "total_msgs      =%lu\n"
		   "header_offset   =%lu\n"
		   "max_crcs        =%lu\n"
		   "max_msgs        =%lu\n"
		   "max_age         =%u\n"
		   "attr            =%04Xh\n"
		   ,smb.status.last_msg
		   ,smb.status.total_msgs
		   ,smb.status.header_offset
		   ,smb.status.max_crcs
		   ,smb.status.max_msgs
		   ,smb.status.max_age
		   ,smb.status.attr
		   );
392
393
394
395
396
}

/****************************************************************************/
/* Configure message base header											*/
/****************************************************************************/
397
void config(void)
398
399
400
401
{
	char max_msgs[128],max_crcs[128],max_age[128],header_offset[128],attr[128];
	int i;

rswindell's avatar
rswindell committed
402
403
	i=smb_locksmbhdr(&smb);
	if(i) {
404
		fprintf(stderr,"\n\7!smb_locksmbhdr returned %d: %s\n",i,smb.last_error);
rswindell's avatar
rswindell committed
405
406
		return; 
	}
rswindell's avatar
rswindell committed
407
408
409
	i=smb_getstatus(&smb);
	smb_unlocksmbhdr(&smb);
	if(i) {
410
		fprintf(stderr,"\n\7!smb_getstatus returned %d: %s\n",i,smb.last_error);
rswindell's avatar
rswindell committed
411
412
		return; 
	}
rswindell's avatar
rswindell committed
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
	printf("Header offset =%-5lu  New value (CR=No Change): "
		,smb.status.header_offset);
	gets(header_offset);
	printf("Max msgs      =%-5lu  New value (CR=No Change): "
		,smb.status.max_msgs);
	gets(max_msgs);
	printf("Max crcs      =%-5lu  New value (CR=No Change): "
		,smb.status.max_crcs);
	gets(max_crcs);
	printf("Max age       =%-5u  New value (CR=No Change): "
		,smb.status.max_age);
	gets(max_age);
	printf("Attributes    =%-5u  New value (CR=No Change): "
		,smb.status.attr);
	gets(attr);
	i=smb_locksmbhdr(&smb);
	if(i) {
430
		fprintf(stderr,"\n\7!smb_locksmbhdr returned %d: %s\n",i,smb.last_error);
rswindell's avatar
rswindell committed
431
432
		return; 
	}
rswindell's avatar
rswindell committed
433
434
	i=smb_getstatus(&smb);
	if(i) {
435
		fprintf(stderr,"\n\7!smb_getstatus returned %d: %s\n",i,smb.last_error);
rswindell's avatar
rswindell committed
436
		smb_unlocksmbhdr(&smb);
rswindell's avatar
rswindell committed
437
438
		return; 
	}
rswindell's avatar
rswindell committed
439
440
441
442
443
444
445
446
447
448
449
	if(isdigit(max_msgs[0]))
		smb.status.max_msgs=atol(max_msgs);
	if(isdigit(max_crcs[0]))
		smb.status.max_crcs=atol(max_crcs);
	if(isdigit(max_age[0]))
		smb.status.max_age=atoi(max_age);
	if(isdigit(header_offset[0]))
		smb.status.header_offset=atol(header_offset);
	if(isdigit(attr[0]))
		smb.status.attr=atoi(attr);
	i=smb_putstatus(&smb);
450
	smb_unlocksmbhdr(&smb);
rswindell's avatar
rswindell committed
451
	if(i)
452
		fprintf(stderr,"\n\7!smb_putstatus returned %d: %s\n",i,smb.last_error);
453
454
455
456
457
458
459
460
461
462
463
}

/****************************************************************************/
/* Lists messages' to, from, and subject                                    */
/****************************************************************************/
void listmsgs(ulong start, ulong count)
{
	int i;
	ulong l=0;
	smbmsg_t msg;

rswindell's avatar
rswindell committed
464
465
466
467
468
469
470
471
	if(!start)
		start=1;
	fseek(smb.sid_fp,(start-1L)*sizeof(idxrec_t),SEEK_SET);
	while(l<count) {
		if(!fread(&msg.idx,1,sizeof(idxrec_t),smb.sid_fp))
			break;
		i=smb_lockmsghdr(&smb,&msg);
		if(i) {
472
			fprintf(stderr,"\n\7!smb_lockmsghdr returned %d: %s\n",i,smb.last_error);
rswindell's avatar
rswindell committed
473
474
			break; 
		}
rswindell's avatar
rswindell committed
475
476
477
		i=smb_getmsghdr(&smb,&msg);
		smb_unlockmsghdr(&smb,&msg);
		if(i) {
478
			fprintf(stderr,"\n\7!smb_getmsghdr returned %d: %s\n",i,smb.last_error);
rswindell's avatar
rswindell committed
479
480
			break; 
		}
rswindell's avatar
rswindell committed
481
482
483
		printf("%4lu %-25.25s %-25.25s %.20s\n"
			,msg.hdr.number,msg.from,msg.to,msg.subj);
		smb_freemsgmem(&msg);
rswindell's avatar
rswindell committed
484
485
		l++; 
	}
486
487
488
489
490
491
492
493
494
495
}

char *binstr(uchar *buf, ushort length)
{
	static char str[512];
	char tmp[128];
	int i;

	str[0]=0;
	for(i=0;i<length;i++)
496
497
		if(buf[i] && (buf[i]<' ' || buf[i]>=0x7f) 
			&& buf[i]!='\r' && buf[i]!='\n' && buf[i]!='\t')
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
			break;
	if(i==length)		/* not binary */
		return(buf);
	for(i=0;i<length;i++) {
		sprintf(tmp,"%02X ",buf[i]);
		strcat(str,tmp); 
		if(i>=100) {
			strcat(str,"...");
			break;
		}
	}
	return(str);
}

/****************************************************************************/
/* Generates a 24 character ASCII string that represents the time_t pointer */
/* Used as a replacement for ctime()                                        */
/****************************************************************************/
516
char *my_timestr(time_t *intime)
517
518
519
520
521
{
    static char str[256];
    char mer[3],hour;
    struct tm *gm;

rswindell's avatar
rswindell committed
522
523
524
	gm=localtime(intime);
	if(gm==NULL) {
		strcpy(str,"Invalid Time");
rswindell's avatar
rswindell committed
525
526
		return(str); 
	}
rswindell's avatar
rswindell committed
527
528
529
530
531
	if(gm->tm_hour>=12) {
		if(gm->tm_hour==12)
			hour=12;
		else
			hour=gm->tm_hour-12;
rswindell's avatar
rswindell committed
532
533
		strcpy(mer,"pm"); 
	}
rswindell's avatar
rswindell committed
534
535
536
537
538
	else {
		if(gm->tm_hour==0)
			hour=12;
		else
			hour=gm->tm_hour;
rswindell's avatar
rswindell committed
539
540
		strcpy(mer,"am"); 
	}
rswindell's avatar
rswindell committed
541
542
543
544
	sprintf(str,"%s %s %02d %4d %02d:%02d %s"
		,wday[gm->tm_wday],mon[gm->tm_mon],gm->tm_mday,1900+gm->tm_year
		,hour,gm->tm_min,mer);
	return(str);
545
546
547
548
549
550
551
552
553
554
555
}

/****************************************************************************/
/* Displays message header information										*/
/****************************************************************************/
void viewmsgs(ulong start, ulong count)
{
	int i;
	ulong l=0;
	smbmsg_t msg;

rswindell's avatar
rswindell committed
556
557
558
559
560
561
562
563
	if(!start)
		start=1;
	fseek(smb.sid_fp,(start-1L)*sizeof(idxrec_t),SEEK_SET);
	while(l<count) {
		if(!fread(&msg.idx,1,sizeof(idxrec_t),smb.sid_fp))
			break;
		i=smb_lockmsghdr(&smb,&msg);
		if(i) {
564
			fprintf(stderr,"\n\7!smb_lockmsghdr returned %d: %s\n",i,smb.last_error);
rswindell's avatar
rswindell committed
565
566
			break; 
		}
rswindell's avatar
rswindell committed
567
568
569
		i=smb_getmsghdr(&smb,&msg);
		smb_unlockmsghdr(&smb,&msg);
		if(i) {
570
			fprintf(stderr,"\n\7!smb_getmsghdr returned %d: %s\n",i,smb.last_error);
rswindell's avatar
rswindell committed
571
572
			break; 
		}
573

574
575
576
		printf("--------------------\n");
		printf("%-20.20s %ld\n"		,"index record",ftell(smb.sid_fp)/sizeof(idxrec_t));
		smb_dump_msghdr(stdout,&msg);
rswindell's avatar
rswindell committed
577
578
		printf("\n");
		smb_freemsgmem(&msg);
rswindell's avatar
rswindell committed
579
580
		l++; 
	}
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
}

/****************************************************************************/
/* Maintain message base - deletes messages older than max age (in days)	*/
/* or messages that exceed maximum											*/
/****************************************************************************/
void maint(void)
{
	int i;
	ulong l,m,n,f,flagged=0;
	time_t now;
	smbmsg_t msg;
	idxrec_t HUGE16 *idx;

	printf("Maintaining %s\r\n",smb.file);
	now=time(NULL);
	i=smb_locksmbhdr(&smb);
	if(i) {
599
		fprintf(stderr,"\n\7!smb_locksmbhdr returned %d: %s\n",i,smb.last_error);
rswindell's avatar
rswindell committed
600
601
		return; 
	}
602
603
604
	i=smb_getstatus(&smb);
	if(i) {
		smb_unlocksmbhdr(&smb);
605
		fprintf(stderr,"\n\7!smb_getstatus returned %d: %s\n",i,smb.last_error);
rswindell's avatar
rswindell committed
606
607
		return; 
	}
608
609
610
	if(!smb.status.total_msgs) {
		smb_unlocksmbhdr(&smb);
		printf("Empty\n");
rswindell's avatar
rswindell committed
611
612
		return; 
	}
613
614
615
616
	printf("Loading index...\n");
	if((idx=(idxrec_t *)LMALLOC(sizeof(idxrec_t)*smb.status.total_msgs))
		==NULL) {
		smb_unlocksmbhdr(&smb);
617
		fprintf(stderr,"\n\7!Error allocating %lu bytes of memory\n"
618
			,sizeof(idxrec_t)*smb.status.total_msgs);
rswindell's avatar
rswindell committed
619
620
		return; 
	}
621
622
623
624
625
	fseek(smb.sid_fp,0L,SEEK_SET);
	for(l=0;l<smb.status.total_msgs;l++) {
		printf("%lu of %lu\r"
			,l+1,smb.status.total_msgs);
		if(!fread(&idx[l],1,sizeof(idxrec_t),smb.sid_fp))
rswindell's avatar
rswindell committed
626
627
			break; 
	}
628
629
630
631
	printf("\nDone.\n\n");

	printf("Scanning for pre-flagged messages...\n");
	for(m=0;m<l;m++) {
rswindell's avatar
rswindell committed
632
		printf("\r%2lu%%",m ? (long)(100.0/((float)l/m)) : 0);
633
		if(idx[m].attr&MSG_DELETE)
rswindell's avatar
rswindell committed
634
635
			flagged++; 
	}
636
637
638
639
640
641
	printf("\r100%% (%lu pre-flagged for deletion)\n",flagged);

	if(smb.status.max_age) {
		printf("Scanning for messages more than %u days old...\n"
			,smb.status.max_age);
		for(m=f=0;m<l;m++) {
rswindell's avatar
rswindell committed
642
			printf("\r%2lu%%",m ? (long)(100.0/((float)l/m)) : 0);
643
644
645
646
647
648
			if(idx[m].attr&(MSG_PERMANENT|MSG_DELETE))
				continue;
			if((ulong)now>idx[m].time && (now-idx[m].time)/(24L*60L*60L)
				>smb.status.max_age) {
				f++;
				flagged++;
rswindell's avatar
rswindell committed
649
650
651
652
653
				idx[m].attr|=MSG_DELETE; 
			} 
		}  /* mark for deletion */
		printf("\r100%% (%lu flagged for deletion)\n",f); 
	}
654
655
656

	printf("Scanning for read messages to be killed...\n");
	for(m=f=0;m<l;m++) {
rswindell's avatar
rswindell committed
657
		printf("\r%2lu%%",m ? (long)(100.0/((float)l/m)) : 0);
658
659
660
661
662
		if(idx[m].attr&(MSG_PERMANENT|MSG_DELETE))
			continue;
		if((idx[m].attr&(MSG_READ|MSG_KILLREAD))==(MSG_READ|MSG_KILLREAD)) {
			f++;
			flagged++;
rswindell's avatar
rswindell committed
663
664
665
			idx[m].attr|=MSG_DELETE; 
		} 
	}
666
667
	printf("\r100%% (%lu flagged for deletion)\n",f);

668
	if(smb.status.max_msgs && l-flagged>smb.status.max_msgs) {
669
670
671
672
673
674
		printf("Flagging excess messages for deletion...\n");
		for(m=n=0,f=flagged;l-flagged>smb.status.max_msgs && m<l;m++) {
			if(idx[m].attr&(MSG_PERMANENT|MSG_DELETE))
				continue;
			printf("%lu of %lu\r",++n,(l-f)-smb.status.max_msgs);
			flagged++;
rswindell's avatar
rswindell committed
675
676
677
678
			idx[m].attr|=MSG_DELETE; 
		}			/* mark for deletion */
		printf("\nDone.\n\n"); 
	}
679
680
681
682

	if(!flagged) {				/* No messages to delete */
		LFREE(idx);
		smb_unlocksmbhdr(&smb);
rswindell's avatar
rswindell committed
683
684
		return; 
	}
685
686
687
688
689
690
691
692

	if(!(mode&NOANALYSIS)) {

		printf("Freeing allocated header and data blocks for deleted messages...\n");
		if(!(smb.status.attr&SMB_HYPERALLOC)) {
			i=smb_open_da(&smb);
			if(i) {
				smb_unlocksmbhdr(&smb);
693
				fprintf(stderr,"\n\7!smb_open_da returned %d: %s\n",i,smb.last_error);
rswindell's avatar
rswindell committed
694
695
				exit(1); 
			}
696
697
698
			i=smb_open_ha(&smb);
			if(i) {
				smb_unlocksmbhdr(&smb);
699
				fprintf(stderr,"\n\7!smb_open_ha returned %d: %s\n",i,smb.last_error);
rswindell's avatar
rswindell committed
700
701
702
				exit(1); 
			} 
		}
703
704
705
706
707
708
709

		for(m=n=0;m<l;m++) {
			if(idx[m].attr&MSG_DELETE) {
				printf("%lu of %lu\r",++n,flagged);
				msg.idx=idx[m];
				msg.hdr.number=msg.idx.number;
				if((i=smb_getmsgidx(&smb,&msg))!=0) {
710
					fprintf(stderr,"\n\7!smb_getmsgidx returned %d: %s\n",i,smb.last_error);
rswindell's avatar
rswindell committed
711
712
					continue; 
				}
713
714
				i=smb_lockmsghdr(&smb,&msg);
				if(i) {
715
					fprintf(stderr,"\n\7!smb_lockmsghdr returned %d: %s\n",i,smb.last_error);
rswindell's avatar
rswindell committed
716
717
					break; 
				}
718
719
				if((i=smb_getmsghdr(&smb,&msg))!=0) {
					smb_unlockmsghdr(&smb,&msg);
720
					fprintf(stderr,"\n\7!smb_getmsghdr returned %d: %s\n",i,smb.last_error);
rswindell's avatar
rswindell committed
721
722
					break; 
				}
723
724
725
726
				msg.hdr.attr|=MSG_DELETE;			/* mark header as deleted */
				if((i=smb_putmsg(&smb,&msg))!=0) {
					smb_freemsgmem(&msg);
					smb_unlockmsghdr(&smb,&msg);
727
					fprintf(stderr,"\n\7!smb_putmsg returned %d: %s\n",i,smb.last_error);
rswindell's avatar
rswindell committed
728
729
					break; 
				}
730
731
732
				smb_unlockmsghdr(&smb,&msg);
				if((i=smb_freemsg(&smb,&msg))!=0) {
					smb_freemsgmem(&msg);
733
					fprintf(stderr,"\n\7!smb_freemsg returned %d: %s\n",i,smb.last_error);
rswindell's avatar
rswindell committed
734
735
736
737
738
					break; 
				}
				smb_freemsgmem(&msg); 
			} 
		}
739
740
		if(!(smb.status.attr&SMB_HYPERALLOC)) {
			smb_close_ha(&smb);
rswindell's avatar
rswindell committed
741
742
743
744
			smb_close_da(&smb); 
		}
		printf("\nDone.\n\n"); 
	}
745
746
747

	printf("Re-writing index...\n");
	rewind(smb.sid_fp);
748
	CHSIZE_FP(smb.sid_fp,0);
749
750
751
752
	for(m=n=0;m<l;m++) {
		if(idx[m].attr&MSG_DELETE)
			continue;
		printf("%lu of %lu\r",++n,l-flagged);
rswindell's avatar
rswindell committed
753
754
		fwrite(&idx[m],sizeof(idxrec_t),1,smb.sid_fp); 
	}
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
	printf("\nDone.\n\n");
	fflush(smb.sid_fp);

	LFREE(idx);
	smb.status.total_msgs-=flagged;
	smb_putstatus(&smb);
	smb_unlocksmbhdr(&smb);
}


typedef struct {
	ulong old,new;
	} datoffset_t;

/****************************************************************************/
/* Removes all unused blocks from SDT and SHD files 						*/
/****************************************************************************/
void packmsgs(ulong packable)
{
	uchar str[128],buf[SDT_BLOCK_LEN],ch,fname[128],tmpfname[128];
	int i,size;
	ulong l,m,n,datoffsets=0,length,total,now;
	FILE *tmp_sdt,*tmp_shd,*tmp_sid;
778
	BOOL		error=FALSE;
779
780
781
782
	smbhdr_t	hdr;
	smbmsg_t	msg;
	datoffset_t *datoffset=NULL;

rswindell's avatar
rswindell committed
783
784
785
	now=time(NULL);
	printf("Packing %s\n",smb.file);
	i=smb_locksmbhdr(&smb);
786
	if(i) {
787
		fprintf(stderr,"\n\7!smb_locksmbhdr returned %d: %s\n",i,smb.last_error);
rswindell's avatar
rswindell committed
788
789
		return; 
	}
rswindell's avatar
rswindell committed
790
	i=smb_getstatus(&smb);
791
792
	if(i) {
		smb_unlocksmbhdr(&smb);
793
		fprintf(stderr,"\n\7!smb_getstatus returned %d: %s\n",i,smb.last_error);
rswindell's avatar
rswindell committed
794
795
		return; 
	}
rswindell's avatar
rswindell committed
796

797
	if(!(smb.status.attr&SMB_HYPERALLOC)) {
rswindell's avatar
rswindell committed
798
799
800
		i=smb_open_ha(&smb);
		if(i) {
			smb_unlocksmbhdr(&smb);
801
			fprintf(stderr,"\n\7!smb_open_ha returned %d: %s\n",i,smb.last_error);
rswindell's avatar
rswindell committed
802
803
			return; 
		}
rswindell's avatar
rswindell committed
804
805
806
807
		i=smb_open_da(&smb);
		if(i) {
			smb_unlocksmbhdr(&smb);
			smb_close_ha(&smb);
808
			fprintf(stderr,"\n\7!smb_open_da returned %d: %s\n",i,smb.last_error);
rswindell's avatar
rswindell committed
809
810
811
			return; 
		} 
	}
812

rswindell's avatar
rswindell committed
813
814
815
	if(!smb.status.total_msgs) {
		printf("Empty\n");
		rewind(smb.shd_fp);
816
		CHSIZE_FP(smb.shd_fp,smb.status.header_offset);
rswindell's avatar
rswindell committed
817
		rewind(smb.sdt_fp);
818
		CHSIZE_FP(smb.sdt_fp,0);
rswindell's avatar
rswindell committed
819
		rewind(smb.sid_fp);
820
		CHSIZE_FP(smb.sid_fp,0);
rswindell's avatar
rswindell committed
821
822
		if(!(smb.status.attr&SMB_HYPERALLOC)) {
			rewind(smb.sha_fp);
823
			CHSIZE_FP(smb.sha_fp,0);
rswindell's avatar
rswindell committed
824
			rewind(smb.sda_fp);
825
			CHSIZE_FP(smb.sda_fp,0);
rswindell's avatar
rswindell committed
826
			smb_close_ha(&smb);
rswindell's avatar
rswindell committed
827
828
			smb_close_da(&smb); 
		}
rswindell's avatar
rswindell committed
829
		smb_unlocksmbhdr(&smb);
rswindell's avatar
rswindell committed
830
831
		return; 
	}
832
833


rswindell's avatar
rswindell committed
834
835
	if(!(smb.status.attr&SMB_HYPERALLOC) && !(mode&NOANALYSIS)) {
		printf("Analyzing data blocks...\n");
836

rswindell's avatar
rswindell committed
837
		length=filelength(fileno(smb.sda_fp));
838

rswindell's avatar
rswindell committed
839
840
		fseek(smb.sda_fp,0L,SEEK_SET);
		for(l=m=0;l<length;l+=2) {
rswindell's avatar
rswindell committed
841
			printf("\r%2lu%%  ",l ? (long)(100.0/((float)length/l)) : 0);
rswindell's avatar
rswindell committed
842
843
844
845
			i=0;
			if(!fread(&i,2,1,smb.sda_fp))
				break;
			if(!i)
rswindell's avatar
rswindell committed
846
847
				m++; 
		}
848

rswindell's avatar
rswindell committed
849
		printf("\rAnalyzing header blocks...\n");
850

rswindell's avatar
rswindell committed
851
		length=filelength(fileno(smb.sha_fp));
852

rswindell's avatar
rswindell committed
853
854
		fseek(smb.sha_fp,0L,SEEK_SET);
		for(l=n=0;l<length;l++) {
rswindell's avatar
rswindell committed
855
			printf("\r%2lu%%  ",l ? (long)(100.0/((float)length/l)) : 0);
rswindell's avatar
rswindell committed
856
857
858
859
			ch=0;
			if(!fread(&ch,1,1,smb.sha_fp))
				break;
			if(!ch)
rswindell's avatar
rswindell committed
860
861
				n++; 
		}
rswindell's avatar
rswindell committed
862
863
864
865
866
867

		if(!m && !n) {
			printf("\rAlready compressed.\n\n");
			smb_close_ha(&smb);
			smb_close_da(&smb);
			smb_unlocksmbhdr(&smb);
rswindell's avatar
rswindell committed
868
869
			return; 
		}
870

rswindell's avatar
rswindell committed
871
		if(packable && (m*SDT_BLOCK_LEN)+(n*SHD_BLOCK_LEN)<packable*1024L) {
872
			printf("\rLess than %luk compressible bytes.\n\n",packable);
rswindell's avatar
rswindell committed
873
874
875
			smb_close_ha(&smb);
			smb_close_da(&smb);
			smb_unlocksmbhdr(&smb);
rswindell's avatar
rswindell committed
876
877
			return; 
		}
rswindell's avatar
rswindell committed
878
879
880

		printf("\rCompressing %lu data blocks (%lu bytes)\n"
				 "        and %lu header blocks (%lu bytes)\n"
rswindell's avatar
rswindell committed
881
882
				  ,m,m*SDT_BLOCK_LEN,n,n*SHD_BLOCK_LEN); 
	}
rswindell's avatar
rswindell committed
883
884
885

	if(!(smb.status.attr&SMB_HYPERALLOC)) {
		rewind(smb.sha_fp);
886
		CHSIZE_FP(smb.sha_fp,0);		/* Reset both allocation tables */
rswindell's avatar
rswindell committed
887
		rewind(smb.sda_fp);
888
		CHSIZE_FP(smb.sda_fp,0); 
rswindell's avatar
rswindell committed
889
	}
rswindell's avatar
rswindell committed
890
891
892
893
894
895
896

	if(smb.status.attr&SMB_HYPERALLOC && !(mode&NOANALYSIS)) {
		printf("Analyzing %s\n",smb.file);

		length=filelength(fileno(smb.shd_fp));
		m=n=0;
		for(l=smb.status.header_offset;l<length;l+=size) {
rswindell's avatar
rswindell committed
897
			printf("\r%2lu%%  ",(long)(100.0/((float)length/l)));
rswindell's avatar
rswindell committed
898
899
900
901
			msg.idx.offset=l;
			if((i=smb_lockmsghdr(&smb,&msg))!=0) {
				printf("\n(%06lX) smb_lockmsghdr returned %d\n",l,i);
				size=SHD_BLOCK_LEN;
rswindell's avatar
rswindell committed
902
903
				continue; 
			}
rswindell's avatar
rswindell committed
904
905
906
907
			if((i=smb_getmsghdr(&smb,&msg))!=0) {
				smb_unlockmsghdr(&smb,&msg);
				m++;
				size=SHD_BLOCK_LEN;
rswindell's avatar
rswindell committed
908
909
				continue; 
			}
rswindell's avatar
rswindell committed
910
911
912
			smb_unlockmsghdr(&smb,&msg);
			if(msg.hdr.attr&MSG_DELETE) {
				m+=smb_hdrblocks(msg.hdr.length);
rswindell's avatar
rswindell committed
913
914
915
916
917
				n+=smb_datblocks(smb_getmsgdatlen(&msg)); 
			}
			size=smb_hdrblocks(smb_getmsghdrlen(&msg))*SHD_BLOCK_LEN;
			smb_freemsgmem(&msg); 
		}
rswindell's avatar
rswindell committed
918
919
920
921
922


		if(!m && !n) {
			printf("\rAlready compressed.\n\n");
			smb_unlocksmbhdr(&smb);
rswindell's avatar
rswindell committed
923
924
			return; 
		}
rswindell's avatar
rswindell committed
925
926

		if(packable && (n*SDT_BLOCK_LEN)+(m*SHD_BLOCK_LEN)<packable*1024L) {
927
			printf("\rLess than %luk compressible bytes.\n\n",packable);
rswindell's avatar
rswindell committed
928
			smb_unlocksmbhdr(&smb);
rswindell's avatar
rswindell committed
929
930
			return; 
		}
rswindell's avatar
rswindell committed
931
932
933

		printf("\rCompressing %lu data blocks (%lu bytes)\n"
				 "        and %lu header blocks (%lu bytes)\n"
rswindell's avatar
rswindell committed
934
935
				  ,n,n*SDT_BLOCK_LEN,m,m*SHD_BLOCK_LEN); 
	}
rswindell's avatar
rswindell committed
936
937
938
939
940
941
942
943
944
945
946

	sprintf(fname,"%s.sd$",smb.file);
	tmp_sdt=fopen(fname,"wb");
	sprintf(fname,"%s.sh$",smb.file);
	tmp_shd=fopen(fname,"wb");
	sprintf(fname,"%s.si$",smb.file);
	tmp_sid=fopen(fname,"wb");
	if(!tmp_sdt || !tmp_shd || !tmp_sid) {
		smb_unlocksmbhdr(&smb);
		if(!(smb.status.attr&SMB_HYPERALLOC)) {
			smb_close_ha(&smb);
rswindell's avatar
rswindell committed
947
948
			smb_close_da(&smb); 
		}
949
		fprintf(stderr,"\n\7!Error opening temp files\n");
rswindell's avatar
rswindell committed
950
951
		return; 
	}
rswindell's avatar
rswindell committed
952
953
954
955
956
957
958
	setvbuf(tmp_sdt,NULL,_IOFBF,2*1024);
	setvbuf(tmp_shd,NULL,_IOFBF,2*1024);
	setvbuf(tmp_sid,NULL,_IOFBF,2*1024);
	if(!(smb.status.attr&SMB_HYPERALLOC)
		&& (datoffset=(datoffset_t *)LMALLOC(sizeof(datoffset_t)*smb.status.total_msgs))
		==NULL) {
		smb_unlocksmbhdr(&smb);
959
960
		smb_close_ha(&smb);
		smb_close_da(&smb);
rswindell's avatar
rswindell committed
961
962
963
		fclose(tmp_sdt);
		fclose(tmp_shd);
		fclose(tmp_sid);
964
		fprintf(stderr,"\n\7!Error allocating memory\n");
rswindell's avatar
rswindell committed
965
966
		return; 
	}
rswindell's avatar
rswindell committed
967
968
969
970
971
972
	fseek(smb.shd_fp,0L,SEEK_SET);
	fread(&hdr,1,sizeof(smbhdr_t),smb.shd_fp);
	fwrite(&hdr,1,sizeof(smbhdr_t),tmp_shd);
	fwrite(&(smb.status),1,sizeof(smbstatus_t),tmp_shd);
	for(l=sizeof(smbhdr_t)+sizeof(smbstatus_t);l<smb.status.header_offset;l++) {
		fread(&ch,1,1,smb.shd_fp);			/* copy additional base header records */
rswindell's avatar
rswindell committed
973
974
		fwrite(&ch,1,1,tmp_shd); 
	}
rswindell's avatar
rswindell committed
975
976
977
978
979
980
981
982
	fseek(smb.sid_fp,0L,SEEK_SET);
	total=0;
	for(l=0;l<smb.status.total_msgs;l++) {
		printf("%lu of %lu\r",l+1,smb.status.total_msgs);
		if(!fread(&msg.idx,1,sizeof(idxrec_t),smb.sid_fp))
			break;
		if(msg.idx.attr&MSG_DELETE) {
			printf("\nDeleted index.\n");
rswindell's avatar
rswindell committed
983
984
			continue; 
		}
rswindell's avatar
rswindell committed
985
986
		i=smb_lockmsghdr(&smb,&msg);
		if(i) {
987
			fprintf(stderr,"\n\7!smb_lockmsghdr returned %d: %s\n",i,smb.last_error);
rswindell's avatar
rswindell committed
988
989
			continue; 
		}
rswindell's avatar
rswindell committed
990
		i=smb_getmsghdr(&smb,&msg);
991
		smb_unlockmsghdr(&smb,&msg);
rswindell's avatar
rswindell committed
992
		if(i) {
993
			fprintf(stderr,"\n\7!smb_getmsghdr returned %d: %s\n",i,smb.last_error);
rswindell's avatar
rswindell committed
994
995
			continue; 
		}
996
		if(msg.hdr.attr&MSG_DELETE) {
rswindell's avatar
rswindell committed
997
998
			printf("\nDeleted header.\n");
			smb_freemsgmem(&msg);
rswindell's avatar
rswindell committed
999
1000
			continue; 
		}
1001
		if(msg.expiration && msg.expiration<=now) {
rswindell's avatar
rswindell committed
1002
1003
			printf("\nExpired message.\n");
			smb_freemsgmem(&msg);
rswindell's avatar
rswindell committed
1004
1005
			continue; 
		}
rswindell's avatar
rswindell committed
1006
1007
1008
1009
1010
1011
		for(m=0;m<datoffsets;m++)
			if(msg.hdr.offset==datoffset[m].old)
				break;
		if(m<datoffsets) {				/* another index pointed to this data */
			printf("duplicate index\n");
			msg.hdr.offset=datoffset[m].new;
1012
			smb_incmsgdat(&smb,datoffset[m].new,smb_getmsgdatlen(&msg),1); 
rswindell's avatar
rswindell committed
1013
		} else {
1014

rswindell's avatar
rswindell committed
1015
1016
1017
1018
1019
1020
1021
			if(!(smb.status.attr&SMB_HYPERALLOC))
				datoffset[datoffsets].old=msg.hdr.offset;

			fseek(smb.sdt_fp,msg.hdr.offset,SEEK_SET);

			m=smb_getmsgdatlen(&msg);
			if(m>16L*1024L*1024L) {
1022
				fprintf(stderr,"\n\7!Invalid data length (%lu)\n",m);
rswindell's avatar
rswindell committed
1023
1024
				continue; 
			}
rswindell's avatar
rswindell committed
1025
1026
1027
1028
1029

			if(!(smb.status.attr&SMB_HYPERALLOC)) {
				datoffset[datoffsets].new=msg.hdr.offset
					=smb_fallocdat(&smb,m,1);
				datoffsets++;
rswindell's avatar
rswindell committed
1030
1031
				fseek(tmp_sdt,msg.hdr.offset,SEEK_SET); 
			}
rswindell's avatar
rswindell committed
1032
1033
			else {
				fseek(tmp_sdt,0L,SEEK_END);
rswindell's avatar
rswindell committed
1034
1035
				msg.hdr.offset=ftell(tmp_sdt); 
			}
rswindell's avatar
rswindell committed
1036
1037
1038
1039
1040
1041
1042
1043
1044

			/* Actually copy the data */

			n=smb_datblocks(m);
			for(m=0;m<n;m++) {
				fread(buf,1,SDT_BLOCK_LEN,smb.sdt_fp);
				if(!m && *(ushort *)buf!=XLAT_NONE && *(ushort *)buf!=XLAT_LZH) {
					printf("\nUnsupported translation type (%04X)\n"
						,*(ushort *)buf);
rswindell's avatar
rswindell committed
1045
1046
1047
1048
					break; 
				}
				fwrite(buf,1,SDT_BLOCK_LEN,tmp_sdt); 
			}
rswindell's avatar
rswindell committed
1049
			if(m<n)
rswindell's avatar
rswindell committed
1050
1051
				continue; 
		}
rswindell's avatar
rswindell committed
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061

		/* Write the new index entry */
		length=smb_getmsghdrlen(&msg);
		if(smb.status.attr&SMB_HYPERALLOC)
			msg.idx.offset=ftell(tmp_shd);
		else
			msg.idx.offset=smb_fallochdr(&smb,length)+smb.status.header_offset;
		msg.idx.number=msg.hdr.number;
		msg.idx.attr=msg.hdr.attr;
		msg.idx.time=msg.hdr.when_imported.time;
1062
		msg.idx.subj=subject_crc(msg.subj);
rswindell's avatar
rswindell committed
1063
1064
1065
1066
1067
1068
1069
1070
		if(smb.status.attr&SMB_EMAIL) {
			if(msg.to_ext)
				msg.idx.to=atoi(msg.to_ext);
			else
				msg.idx.to=0;
			if(msg.from_ext)
				msg.idx.from=atoi(msg.from_ext);
			else