|
|
1.1 root 1: /* MLABELS.C */
2:
3: /* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
4:
5: /* Make mailing labels from Synchronet BBS user database */
6: /* Digital Dynamics - 03/16/93 v1.00 */
7: /* Digital Dynamics - 03/03/94 v2.00 */
8: /* Digital Dynamics - 04/13/95 v2.10 */
9: /* Digital Dynamics - 07/17/95 v2.20 */
10:
11: /* For compilation under Borland/Turbo C(++) */
12:
13: /* Set tabstops to 4 for viewing/printing */
14:
15: /* This program and source code are public domain. Modified versions may */
16: /* note be distributed without consent from Digital Dynamics. */
17:
18: #include <io.h>
19: #include <share.h>
20: #include <fcntl.h>
21: #include <errno.h>
22: #include <stdio.h>
23: #include <stdlib.h>
24: #include <sys\stat.h>
25: #include "sbbsdefs.h" /* Synchronet typedefs and macros header */
26:
27: #define DOUBLE_COLUMN (1<<0) /* Print double column labels */
28: #define ATTN_ALIAS (1<<1) /* Print ATTN: Alias/Real Name */
29:
30: char *nulstr="";
31: int min=0,max=99;
32: long reqflags[4]={0},reqrest=0,reqexempt=0;
33:
34: char *usage=
35: "\nusage: mlabels <data\\user path> [[-require] [...]] [/options] <outfile>\n"
36: "\nwhere require is one of:\n"
37: " L# set minimum level to # (default=0)\n"
38: " M# set maximum level to # (default=99)\n"
39: " F#<flags> set required flags from flag set #\n"
40: " E<flags> set required exemptions\n"
41: " R<flags> set required restrictions\n"
42: "\nwhere options is one or more of:\n"
43: " D double column labels\n"
44: " A include ATTN: alias/name on label\n"
45: "\nexample:\n"
46: "\nMLABELS \\SBBS\\DATA\\USER -L50 /D PRN\n";
47:
48:
49: /****************************************************************************/
50: /* Converts an ASCII Hex string into an ulong */
51: /****************************************************************************/
52: ulong ahtoul(char *str)
53: {
54: ulong l,val=0;
55:
56: while((l=(*str++)|0x20)!=0x20)
57: val=(l&0xf)+(l>>6&1)*9+val*16;
58: return(val);
59: }
60:
61: /****************************************************************************/
62: /* Truncates white-space chars off end of 'str' and terminates at first tab */
63: /****************************************************************************/
64: void truncsp(char *str)
65: {
66: char c;
67:
68: str[strcspn(str,"\t")]=0;
69: c=strlen(str);
70: while(c && (uchar)str[c-1]<=SP) c--;
71: str[c]=0;
72: }
73:
74: /****************************************************************************/
75: /* Returns bytes offset into user record for flag set # 'set' */
76: /****************************************************************************/
77: long getflagoff(int set)
78: {
79: switch(set) {
80: default:
81: return(U_FLAGS1);
82: case 2:
83: return(U_FLAGS2);
84: case 3:
85: return(U_FLAGS3);
86: case 4:
87: return(U_FLAGS4); }
88: }
89:
90: /****************************************************************************/
91: /* Checks a user record against the requirements set on the command line */
92: /* Returns 1 if the user meets the requirements (or no requirements were */
93: /* specified) or 0 if the user does not meet any of the requirements. */
94: /****************************************************************************/
95: int chkuser(FILE *stream, long offset)
96: {
97: char str[128];
98: int i;
99:
100: if(min || max!=99) { /* Check security level */
101: fseek(stream,offset+U_LEVEL,SEEK_SET);
102: fread(str,2,1,stream);
103: str[2]=0;
104: i=atoi(str);
105: if(i<min || i>max) /* not within range */
106: return(0); } /* so skip this user */
107:
108: for(i=0;i<4;i++)
109: if(reqflags[i]) {
110: fseek(stream,offset+getflagoff(i+1),SEEK_SET);
111: fread(str,8,1,stream);
112: str[8]=0;
113: truncsp(str);
114: if((ahtoul(str)&reqflags[i])!=reqflags[i])
115: return(0); } /* doesn't have 'em all */
116:
117: if(reqrest) {
118: fseek(stream,offset+U_REST,SEEK_SET);
119: fread(str,8,1,stream);
120: str[8]=0;
121: truncsp(str);
122: if((ahtoul(str)&reqrest)!=reqrest)
123: return(0); }
124:
125: if(reqexempt) {
126: fseek(stream,offset+U_REST,SEEK_SET);
127: fread(str,8,1,stream);
128: str[8]=0;
129: truncsp(str);
130: if((ahtoul(str)&reqexempt)!=reqexempt)
131: return(0); }
132:
133: return(1);
134: }
135:
136: /****************************************************************************/
137: /* Attempts to lock a user record, retries for up to 10 seconds */
138: /* Returns 0 on success, -1 on failure */
139: /****************************************************************************/
140: int lockuser(FILE *stream, ulong offset)
141: {
142: time_t start;
143:
144: if(lock(fileno(stream),offset,U_LEN)==0)
145: return(0);
146: start=time(NULL);
147: while(1) {
148: if(lock(fileno(stream),offset,U_LEN)==0)
149: return(0);
150: if(time(NULL)-start>=10L)
151: break; }
152: return(-1);
153: }
154:
155: /***************/
156: /* Entry point *
157: /***************/
158: int main(int argc, char **argv)
159: {
160: char str[256],buf1[U_LEN],buf2[U_LEN],infile[128]="",outfile[128]=""
161: ,mode=0; /* optional modes bits */
162: int i,j,k,file,printed=0;
163: long l,length,offset;
164: FILE *in,*out;
165:
166: printf("\nSynchronet Mailing Labels v2.10\n");
167: for(i=1;i<argc;i++) {
168: if(argv[i][0]=='-')
169: switch(toupper(argv[i][1])) {
170: case 'L': /* Set minimum sec level */
171: min=atoi(argv[i]+2);
172: break;
173: case 'M': /* Set maximum sec level */
174: max=atoi(argv[i]+2);
175: break;
176: case 'F': /* Set required flags */
177: j=3;
178: k=1;
179: if(isdigit(argv[i][2]))
180: k=argv[i][2]&0xf;
181: else
182: j=2;
183: for(;argv[i][j];j++)
184: if(isalpha(argv[i][j]))
185: reqflags[k-1]|=FLAG(toupper(argv[i][j]));
186: break;
187: case 'R': /* Set required restrictions */
188: for(j=2;argv[i][j];j++)
189: if(isalpha(argv[i][j]))
190: reqrest|=FLAG(toupper(argv[i][j]));
191: break;
192: case 'E': /* Set required exemptions */
193: for(j=2;argv[i][j];j++)
194: if(isalpha(argv[i][j]))
195: reqexempt|=FLAG(toupper(argv[i][j]));
196: break;
197: default: /* Unrecognized include */
198: printf(usage);
199: exit(1); }
200:
201: else if(argv[i][0]=='/') {
202: k=strlen(argv[i]);
203: for(j=1;j<k;j++)
204: switch(toupper(argv[i][j])) {
205: case 'D': /* Double column labels */
206: mode|=DOUBLE_COLUMN;
207: break;
208: case 'A': /* Attention Alias/Real Name */
209: mode|=ATTN_ALIAS;
210: break;
211: default:
212: printf("\nUnknown option\n");
213: case '?':
214: printf(usage);
215: exit(1); } }
216: else if(infile[0]) /* in filename already given */
217: strcpy(outfile,argv[i]);
218: else
219: strcpy(infile,argv[i]); }
220:
221: if(!infile[0] || !outfile[0]) {
222: printf("\nFilename not specified\n");
223: printf(usage);
224: exit(1); }
225:
226: if(infile[strlen(infile)-1]!='\\' && infile[strlen(infile)-1]!=':')
227: strcat(infile,"\\");
228: strcat(infile,"USER.DAT");
229: if((file=sopen(infile,O_RDONLY|O_BINARY,SH_DENYNO))==-1) {
230: printf("\nError opening %s\n",infile);
231: exit(1); }
232: if((in=fdopen(file,"rb"))==NULL) {
233: printf("\nError opening %s\n",infile);
234: exit(1); }
235: setvbuf(in,NULL,_IOFBF,2048);
236: length=filelength(file);
237:
238: if((file=open(outfile,O_WRONLY|O_TRUNC|O_CREAT|O_BINARY
239: ,S_IWRITE|S_IREAD))==-1) {
240: printf("\nError opening/creating %s\n",outfile);
241: exit(1); }
242: if((out=fdopen(file,"wb"))==NULL) {
243: printf("\nError opening %s\n",outfile);
244: exit(1); }
245: setvbuf(out,NULL,_IOFBF,2048);
246:
247: printf("\n");
248: for(offset=0;offset<length;offset+=U_LEN) {
249: printf("%lu of %lu (%u labels)\r"
250: ,(offset/U_LEN)+1,length/U_LEN,printed);
251: if(lockuser(in,offset)) {
252: printf("Error locking offset %lu\n",offset);
253: continue; }
254:
255: if(!chkuser(in,offset)) {
256: unlock(fileno(in),offset,U_LEN);
257: continue; }
258:
259: fseek(in,offset,SEEK_SET);
260: if(!fread(buf1,U_LEN,1,in)) {
261: printf("Couldn't read %lu bytes at %lu\n",U_LEN,offset);
262: break; }
263: unlock(fileno(in),offset,U_LEN);
264: for(i=0;i<U_LEN;i++) { /* Convert ETX (3) to NULL (0) */
265: if(buf1[i]==ETX)
266: buf1[i]=NULL; }
267:
268: buf1[U_MISC+8]=0;
269: l=ahtoul(buf1+U_MISC);
270: if(l&(DELETED|INACTIVE)) /* skip if deleted or inactive */
271: continue;
272:
273: while(mode&DOUBLE_COLUMN) { /* double wide - right column */
274: offset+=U_LEN;
275: printf("%lu of %lu (%u labels)\r"
276: ,(offset/U_LEN)+1,length/U_LEN,printed);
277: if(lockuser(in,offset)) {
278: printf("Error locking offset %lu\n",offset);
279: continue; }
280: fseek(in,offset,SEEK_SET);
281: if(!fread(buf2,U_LEN,1,in)) {
282: mode&=~DOUBLE_COLUMN;
283: unlock(fileno(in),offset,U_LEN); }
284: else {
285: if(!chkuser(in,offset)) {
286: unlock(fileno(in),offset,U_LEN);
287: continue; }
288: unlock(fileno(in),offset,U_LEN);
289: for(i=0;i<U_LEN;i++) { /* Convert ETX (3) to NULL (0) */
290: if(buf2[i]==ETX)
291: buf2[i]=NULL; }
292: buf2[U_MISC+8]=0;
293: l=ahtoul(buf2+U_MISC);
294: if(l&(DELETED|INACTIVE)) /* skip if deleted or inactive */
295: continue;
296: else
297: break; } }
298:
299: if(mode&DOUBLE_COLUMN) { /* print two columns */
300: fprintf(out," %-*.*s%*s%.*s\r\n"
301: ,LEN_NAME,LEN_NAME
302: ,buf1+U_NAME
303: ,41-LEN_NAME,nulstr
304: ,LEN_NAME
305: ,buf2+U_NAME);
306:
307: fprintf(out," %-*.*s%*s%.*s\r\n"
308: ,LEN_ADDRESS,LEN_ADDRESS
309: ,buf1+U_ADDRESS
310: ,41-LEN_ADDRESS,nulstr
311: ,LEN_ADDRESS
312: ,buf2+U_ADDRESS);
313:
314: sprintf(str,"%.*s %.*s"
315: ,LEN_LOCATION,buf1+U_LOCATION
316: ,LEN_ZIPCODE,buf1+U_ZIPCODE);
317:
318: fprintf(out," %-41s%.*s %.*s\r\n"
319: ,str
320: ,LEN_LOCATION,buf2+U_LOCATION
321: ,LEN_ZIPCODE,buf2+U_ZIPCODE);
322:
323: sprintf(str,"ATTN: %.*s",LEN_ALIAS,buf1+U_ALIAS);
324:
325: if(mode&ATTN_ALIAS)
326: fprintf(out," %-41sATTN: %.*s\r\n\r\n\r\n"
327: ,str,LEN_ALIAS,buf2+U_ALIAS);
328: else
329: fprintf(out,"\r\n\r\n\r\n");
330:
331: printed+=2; }
332:
333: else { /* single column labels */
334: fprintf(out," %.*s\r\n"
335: ,LEN_NAME
336: ,buf1+U_NAME);
337:
338: fprintf(out," %.*s\r\n"
339: ,LEN_ADDRESS
340: ,buf1+U_ADDRESS);
341:
342: fprintf(out," %.*s %.*s\r\n"
343: ,LEN_LOCATION
344: ,buf1+U_LOCATION
345: ,LEN_ZIPCODE
346: ,buf1+U_ZIPCODE);
347:
348: if(mode&ATTN_ALIAS)
349: fprintf(out," ATTN: %.*s\r\n\r\n\r\n"
350: ,LEN_ALIAS,buf1+U_ALIAS);
351: else
352: fprintf(out,"\r\n\r\n\r\n");
353:
354: printed++; } }
355: printf("\nDone.\n");
356: fclose(in);
357: fclose(out);
358: return(0);
359: }
360:
361: /* end of mlabels.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.