|
|
1.1 root 1: /* ALLUSERS.C */
2:
3: /* Developed 1990-1997 by Rob Swindell; PO Box 501, Yorba Linda, CA 92885 */
4:
5: /****************************************************************************/
6: /* Makes global changes to Synchronet user database (USER.DAT) */
7: /* Compatible with Version 2.1 of Synchronet BBS Software */
8: /****************************************************************************/
9:
10: #include <io.h>
11: #include <share.h>
12: #include <stdio.h>
13: #include <fcntl.h>
14: #include <errno.h>
15: #include <stdlib.h>
16: #include <sys/stat.h>
17:
18: #include "sbbsdefs.h"
19:
20: int min=0,max=99;
21: long reqflags[4]={0},reqrest=0,reqexempt=0;
22:
23: char *usage=
24: "\nusage: allusers [data\\user path] [[-require] [...]] "
25: "/modify [[/modify] [...]]\n"
26: "\nwhere require is one of:\n"
27: " L# set minimum level to # (default=0)\n"
28: " M# set maximum level to # (default=99)\n"
29: " F#<flags> set required flags from flag set #\n"
30: " E<flags> set required exemptions\n"
31: " R<flags> set required restrictions\n"
32: "\nwhere modify is one of:\n"
33: " L# change security level to #\n"
34: " F#[+|-]<flags> add or remove flags from flag set #\n"
35: " E[+|-]<flags> add or remove exemption flags\n"
36: " R[+|-]<flags> add or remove restriction flags\n"
37: "\nExamples:\n"
38: " ALLUSERS -L30 /FA add 'A' to flag set #1 for all level 30+ users\n"
39: " ALLUSERS /F3-G remove 'G' from flag set #3 for all users\n"
40: " ALLUSERS -F2B /E-P remove 'P' exemption for all users with FLAG '2B'\n"
41: " ALLUSERS /R+W add 'W' restriction for all users\n"
42: ;
43:
44: /****************************************************************************/
45: /* Attempts to lock a user record, retries for up to 10 seconds */
46: /* Returns 0 on success, -1 on failure */
47: /****************************************************************************/
48: int lockuser(FILE *stream, ulong offset)
49: {
50: time_t start;
51:
52: if(lock(fileno(stream),offset,U_LEN)==0)
53: return(0);
54: start=time(NULL);
55: while(1) {
56: if(lock(fileno(stream),offset,U_LEN)==0)
57: return(0);
58: if(time(NULL)-start>=10L)
59: break; }
60: return(-1);
61: }
62:
63: /****************************************************************************/
64: /* Converts an ASCII Hex string into an ulong */
65: /****************************************************************************/
66: ulong ahtoul(char *str)
67: {
68: ulong l,val=0;
69:
70: while((l=(*str++)|0x20)!=0x20)
71: val=(l&0xf)+(l>>6&1)*9+val*16;
72: return(val);
73: }
74:
75: /****************************************************************************/
76: /* Truncates white-space chars off end of 'str' and terminates at first tab */
77: /****************************************************************************/
78: void truncsp(char *str)
79: {
80: char c;
81:
82: str[strcspn(str,"\t")]=0;
83: c=strlen(str);
84: while(c && (uchar)str[c-1]<=SP) c--;
85: str[c]=0;
86: }
87:
88: /****************************************************************************/
89: /* Returns bytes offset into user record for flag set # 'set' */
90: /****************************************************************************/
91: long getflagoff(int set)
92: {
93: switch(set) {
94: default:
95: return(U_FLAGS1);
96: case 2:
97: return(U_FLAGS2);
98: case 3:
99: return(U_FLAGS3);
100: case 4:
101: return(U_FLAGS4); }
102: }
103:
104: /****************************************************************************/
105: /* Checks a user record against the requirements set on the command line */
106: /* Returns 1 if the user meets the requirements (or no requirements were */
107: /* specified) or 0 if the user does not meet any of the requirements. */
108: /****************************************************************************/
109: int chkuser(FILE *stream, long offset)
110: {
111: char str[128];
112: int i;
113:
114: if(min || max!=99) { /* Check security level */
115: fseek(stream,offset+U_LEVEL,SEEK_SET);
116: if(!fread(str,2,1,stream))
117: return(0);
118: str[2]=0;
119: i=atoi(str);
120: if(i<min || i>max) /* not within range */
121: return(0); } /* so skip this user */
122:
123: for(i=0;i<4;i++)
124: if(reqflags[i]) {
125: fseek(stream,offset+getflagoff(i+1),SEEK_SET);
126: if(!fread(str,8,1,stream))
127: return(0);
128: str[8]=0;
129: truncsp(str);
130: if((ahtoul(str)&reqflags[i])!=reqflags[i])
131: return(0); } /* doesn't have 'em all */
132:
133: if(reqrest) {
134: fseek(stream,offset+U_REST,SEEK_SET);
135: if(!fread(str,8,1,stream))
136: return(0);
137: str[8]=0;
138: truncsp(str);
139: if((ahtoul(str)&reqrest)!=reqrest)
140: return(0); }
141:
142: if(reqexempt) {
143: fseek(stream,offset+U_REST,SEEK_SET);
144: if(!fread(str,8,1,stream))
145: return(0);
146: str[8]=0;
147: truncsp(str);
148: if((ahtoul(str)&reqexempt)!=reqexempt)
149: return(0); }
150:
151: return(1);
152: }
153:
154: int main(int argc, char **argv)
155: {
156: char dir[128],str[128];
157: int i,j,k,file,set,sub,mod;
158: long l,f,flags,flagoff,length,offset;
159: FILE *stream;
160:
161: printf("\nALLUSERS v2.10 - Bulk User Editor for Synchronet User Database\n");
162:
163: if(argc<2) {
164: printf(usage);
165: exit(1); }
166: dir[0]=0;
167: for(i=1;i<argc;i++) {
168: flags=flagoff=sub=mod=0;
169: if(argv[i][0]=='-')
170: switch(toupper(argv[i][1])) {
171: case 'L': /* Set minimum sec level */
172: min=atoi(argv[i]+2);
173: break;
174: case 'M': /* Set maximum sec level */
175: max=atoi(argv[i]+2);
176: break;
177: case 'F': /* Set required flags */
178: j=3;
179: set=1;
180: if(isdigit(argv[i][2]))
181: set=argv[i][2]&0xf;
182: else
183: j=2;
184: for(;argv[i][j];j++)
185: if(isalpha(argv[i][j]))
186: reqflags[set-1]|=FLAG(toupper(argv[i][j]));
187: break;
188: case 'R': /* Set required restrictions */
189: for(j=2;argv[i][j];j++)
190: if(isalpha(argv[i][j]))
191: reqrest|=FLAG(toupper(argv[i][j]));
192: break;
193: case 'E': /* Set required exemptions */
194: for(j=2;argv[i][j];j++)
195: if(isalpha(argv[i][j]))
196: reqexempt|=FLAG(toupper(argv[i][j]));
197: break;
198: default: /* Unrecognized include */
199: printf(usage);
200: exit(1); }
201:
202: else if(argv[i][0]=='/')
203: switch(toupper(argv[i][1])) {
204: case 'F': /* flags */
205: j=3;
206: set=1;
207: if(isdigit(argv[i][2]))
208: set=argv[i][2]&0xf;
209: else
210: j=2;
211: if(argv[i][j]=='+')
212: j++;
213: else if(argv[i][j]=='-') {
214: j++;
215: sub=1; }
216: for(;argv[i][j];j++)
217: if(isalpha(argv[i][j]))
218: flags|=FLAG(toupper(argv[i][j]));
219: sprintf(str,"%sUSER.DAT",dir);
220: if((file=sopen(str,O_RDWR|O_BINARY,SH_DENYNO))==-1) {
221: printf("Error opening %s\n",str);
222: exit(1); }
223: if((stream=fdopen(file,"w+b"))==NULL) {
224: printf("Error opening %s\n",str);
225: exit(1); }
226: setvbuf(stream,NULL,_IOFBF,2048);
227: length=filelength(file);
228: printf("\n%s Flags %s Set #%d\n",sub ? "Removing":"Adding"
229: ,sub ? "from":"to",set);
230: for(offset=0;offset<length;offset+=U_LEN) {
231: printf("%lu of %lu (%u modified)\r"
232: ,(offset/U_LEN)+1,length/U_LEN,mod);
233: if(lockuser(stream,offset)) {
234: printf("Error locking offset %lu\n",offset);
235: continue; }
236: if(!chkuser(stream,offset)) {
237: unlock(fileno(stream),offset,U_LEN);
238: continue; }
239: flagoff=getflagoff(set);
240: fseek(stream,offset+flagoff,SEEK_SET);
241: fread(str,8,1,stream);
242: str[8]=0;
243: truncsp(str);
244: l=f=ahtoul(str);
245: if(sub)
246: l&=~flags;
247: else
248: l|=flags;
249: if(l==f) { /* no change */
250: unlock(fileno(stream),offset,U_LEN);
251: continue; }
252: mod++;
253: sprintf(str,"%lx",l);
254: while(strlen(str)<8)
255: strcat(str,"\3");
256: fseek(stream,offset+flagoff,SEEK_SET);
257: fwrite(str,8,1,stream);
258: unlock(fileno(stream),offset,U_LEN); }
259: fclose(stream);
260: printf("\n");
261: break;
262: case 'E': /* Exemptions */
263: flagoff=U_EXEMPT;
264: case 'R': /* Restrictions */
265: if(!flagoff)
266: flagoff=U_REST;
267: j=2;
268: if(argv[i][j]=='+')
269: j++;
270: else if(argv[i][j]=='-') {
271: j++;
272: sub=1; }
273: for(;argv[i][j];j++)
274: if(isalpha(argv[i][j]))
275: flags|=FLAG(toupper(argv[i][j]));
276: sprintf(str,"%sUSER.DAT",dir);
277: if((file=sopen(str,O_RDWR|O_BINARY,SH_DENYNO))==-1) {
278: printf("Error opening %s\n",str);
279: exit(1); }
280: if((stream=fdopen(file,"w+b"))==NULL) {
281: printf("Error opening %s\n",str);
282: exit(1); }
283: setvbuf(stream,NULL,_IOFBF,2048);
284: length=filelength(file);
285: printf("\n%s %s\n"
286: ,sub ? "Removing":"Adding"
287: ,flagoff==U_REST ? "Restrictions":"Exemptions");
288: for(offset=0;offset<length;offset+=U_LEN) {
289: printf("%lu of %lu (%u modified)\r"
290: ,(offset/U_LEN)+1,length/U_LEN,mod);
291: if(lockuser(stream,offset)) {
292: printf("Error locking offset %lu\n",offset);
293: continue; }
294: if(!chkuser(stream,offset)) {
295: unlock(fileno(stream),offset,U_LEN);
296: continue; }
297: fseek(stream,offset+flagoff,SEEK_SET);
298: fread(str,8,1,stream);
299: str[8]=0;
300: truncsp(str);
301: l=f=ahtoul(str);
302: if(sub)
303: l&=~flags;
304: else
305: l|=flags;
306: if(l==f) { /* no change */
307: unlock(fileno(stream),offset,U_LEN);
308: continue; }
309: mod++;
310: sprintf(str,"%lx",l);
311: while(strlen(str)<8)
312: strcat(str,"\3");
313: fseek(stream,offset+flagoff,SEEK_SET);
314: fwrite(str,8,1,stream);
315: unlock(fileno(stream),offset,U_LEN); }
316: fclose(stream);
317: printf("\n");
318: break;
319: case 'L': /* Level */
320: j=atoi(argv[i]+2);
321: if(j>99)
322: j=99;
323: if(j<0)
324: j=0;
325: sprintf(str,"%sUSER.DAT",dir);
326: if((file=sopen(str,O_RDWR|O_BINARY,SH_DENYNO))==-1) {
327: printf("Error opening %s\n",str);
328: exit(1); }
329: if((stream=fdopen(file,"w+b"))==NULL) {
330: printf("Error opening %s\n",str);
331: exit(1); }
332: setvbuf(stream,NULL,_IOFBF,2048);
333: length=filelength(file);
334: printf("\nChanging Levels\n");
335: for(offset=0;offset<length;offset+=U_LEN) {
336: printf("%lu of %lu (%u modified)\r"
337: ,(offset/U_LEN)+1,length/U_LEN,mod);
338: if(lockuser(stream,offset)) {
339: printf("Error locking offset %lu\n",offset);
340: continue; }
341: if(!chkuser(stream,offset)) {
342: unlock(fileno(stream),offset,U_LEN);
343: continue; }
344: fseek(stream,offset+U_LEVEL,SEEK_SET);
345: fread(str,2,1,stream);
346: str[2]=0;
347: truncsp(str);
348: if(atoi(str)==j) { /* no change */
349: unlock(fileno(stream),offset,U_LEN);
350: continue; }
351: sprintf(str,"%02u",j);
352: fseek(stream,offset+U_LEVEL,SEEK_SET);
353: fwrite(str,2,1,stream);
354: unlock(fileno(stream),offset,U_LEN);
355: mod++; }
356: fclose(stream);
357: printf("\n");
358: break;
359: default:
360: printf(usage);
361: exit(1); }
362: else {
363: strcpy(dir,argv[i]);
364: if(dir[strlen(dir)-1]!='\\' && dir[strlen(dir)-1]!=':')
365: strcat(dir,"\\"); } }
366: return(0);
367: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.