|
|
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 <stdio.h>
11: #include <fcntl.h>
12: #include <errno.h>
13: #include <stdlib.h>
14: #include <sys/stat.h>
15:
16: #include "dirwrap.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: /* Returns bytes offset into user record for flag set # 'set' */
65: /****************************************************************************/
66: long getflagoff(int set)
67: {
68: switch(set) {
69: default:
70: return(U_FLAGS1);
71: case 2:
72: return(U_FLAGS2);
73: case 3:
74: return(U_FLAGS3);
75: case 4:
76: return(U_FLAGS4); }
77: }
78:
79: /****************************************************************************/
80: /* Checks a user record against the requirements set on the command line */
81: /* Returns 1 if the user meets the requirements (or no requirements were */
82: /* specified) or 0 if the user does not meet any of the requirements. */
83: /****************************************************************************/
84: int chkuser(FILE *stream, long offset)
85: {
86: char str[128];
87: int i;
88:
89: if(min || max!=99) { /* Check security level */
90: fseek(stream,offset+U_LEVEL,SEEK_SET);
91: if(!fread(str,2,1,stream))
92: return(0);
93: str[2]=0;
94: i=atoi(str);
95: if(i<min || i>max) /* not within range */
96: return(0); } /* so skip this user */
97:
98: for(i=0;i<4;i++)
99: if(reqflags[i]) {
100: fseek(stream,offset+getflagoff(i+1),SEEK_SET);
101: if(!fread(str,8,1,stream))
102: return(0);
103: str[8]=0;
104: truncsp(str);
105: if((ahtoul(str)&reqflags[i])!=reqflags[i])
106: return(0); } /* doesn't have 'em all */
107:
108: if(reqrest) {
109: fseek(stream,offset+U_REST,SEEK_SET);
110: if(!fread(str,8,1,stream))
111: return(0);
112: str[8]=0;
113: truncsp(str);
114: if((ahtoul(str)&reqrest)!=reqrest)
115: return(0); }
116:
117: if(reqexempt) {
118: fseek(stream,offset+U_REST,SEEK_SET);
119: if(!fread(str,8,1,stream))
120: return(0);
121: str[8]=0;
122: truncsp(str);
123: if((ahtoul(str)&reqexempt)!=reqexempt)
124: return(0); }
125:
126: return(1);
127: }
128:
129: int main(int argc, char **argv)
130: {
131: char dir[128],str[128];
132: int i,j,k,file,set,sub,mod;
133: long l,f,flags,flagoff,length,offset;
134: FILE *stream;
135:
136: printf("\nALLUSERS v2.10 - Bulk User Editor for Synchronet User Database\n");
137:
138: if(argc<2) {
139: printf(usage);
140: exit(1); }
141: dir[0]=0;
142: for(i=1;i<argc;i++) {
143: flags=flagoff=sub=mod=0;
144: if(argv[i][0]=='-')
145: switch(toupper(argv[i][1])) {
146: case 'L': /* Set minimum sec level */
147: min=atoi(argv[i]+2);
148: break;
149: case 'M': /* Set maximum sec level */
150: max=atoi(argv[i]+2);
151: break;
152: case 'F': /* Set required flags */
153: j=3;
154: set=1;
155: if(isdigit(argv[i][2]))
156: set=argv[i][2]&0xf;
157: else
158: j=2;
159: for(;argv[i][j];j++)
160: if(isalpha(argv[i][j]))
161: reqflags[set-1]|=FLAG(toupper(argv[i][j]));
162: break;
163: case 'R': /* Set required restrictions */
164: for(j=2;argv[i][j];j++)
165: if(isalpha(argv[i][j]))
166: reqrest|=FLAG(toupper(argv[i][j]));
167: break;
168: case 'E': /* Set required exemptions */
169: for(j=2;argv[i][j];j++)
170: if(isalpha(argv[i][j]))
171: reqexempt|=FLAG(toupper(argv[i][j]));
172: break;
173: default: /* Unrecognized include */
174: printf(usage);
175: exit(1); }
176:
177: else if(argv[i][0]=='/')
178: switch(toupper(argv[i][1])) {
179: case 'F': /* flags */
180: j=3;
181: set=1;
182: if(isdigit(argv[i][2]))
183: set=argv[i][2]&0xf;
184: else
185: j=2;
186: if(argv[i][j]=='+')
187: j++;
188: else if(argv[i][j]=='-') {
189: j++;
190: sub=1; }
191: for(;argv[i][j];j++)
192: if(isalpha(argv[i][j]))
193: flags|=FLAG(toupper(argv[i][j]));
194: sprintf(str,"%suser.dat",dir);
195: if(!fexistcase(str) || (file=sopen(str,O_RDWR|O_BINARY,SH_DENYNO))==-1) {
196: printf("Error opening %s\n",str);
197: exit(1); }
198: if((stream=fdopen(file,"w+b"))==NULL) {
199: printf("Error opening %s\n",str);
200: exit(1); }
201: setvbuf(stream,NULL,_IOFBF,2048);
202: length=filelength(file);
203: printf("\n%s Flags %s Set #%d\n",sub ? "Removing":"Adding"
204: ,sub ? "from":"to",set);
205: for(offset=0;offset<length;offset+=U_LEN) {
206: printf("%lu of %lu (%u modified)\r"
207: ,(offset/U_LEN)+1,length/U_LEN,mod);
208: if(lockuser(stream,offset)) {
209: printf("Error locking offset %lu\n",offset);
210: continue; }
211: if(!chkuser(stream,offset)) {
212: unlock(fileno(stream),offset,U_LEN);
213: continue; }
214: flagoff=getflagoff(set);
215: fseek(stream,offset+flagoff,SEEK_SET);
216: fread(str,8,1,stream);
217: str[8]=0;
218: truncsp(str);
219: l=f=ahtoul(str);
220: if(sub)
221: l&=~flags;
222: else
223: l|=flags;
224: if(l==f) { /* no change */
225: unlock(fileno(stream),offset,U_LEN);
226: continue; }
227: mod++;
228: sprintf(str,"%lx",l);
229: while(strlen(str)<8)
230: strcat(str,"\3");
231: fseek(stream,offset+flagoff,SEEK_SET);
232: fwrite(str,8,1,stream);
233: unlock(fileno(stream),offset,U_LEN); }
234: fclose(stream);
235: printf("\n");
236: break;
237: case 'E': /* Exemptions */
238: flagoff=U_EXEMPT;
239: case 'R': /* Restrictions */
240: if(!flagoff)
241: flagoff=U_REST;
242: j=2;
243: if(argv[i][j]=='+')
244: j++;
245: else if(argv[i][j]=='-') {
246: j++;
247: sub=1; }
248: for(;argv[i][j];j++)
249: if(isalpha(argv[i][j]))
250: flags|=FLAG(toupper(argv[i][j]));
251: sprintf(str,"%suser.dat",dir);
252: if(!fexistcase(str) || (file=sopen(str,O_RDWR|O_BINARY,SH_DENYNO))==-1) {
253: printf("Error opening %s\n",str);
254: exit(1); }
255: if((stream=fdopen(file,"w+b"))==NULL) {
256: printf("Error opening %s\n",str);
257: exit(1); }
258: setvbuf(stream,NULL,_IOFBF,2048);
259: length=filelength(file);
260: printf("\n%s %s\n"
261: ,sub ? "Removing":"Adding"
262: ,flagoff==U_REST ? "Restrictions":"Exemptions");
263: for(offset=0;offset<length;offset+=U_LEN) {
264: printf("%lu of %lu (%u modified)\r"
265: ,(offset/U_LEN)+1,length/U_LEN,mod);
266: if(lockuser(stream,offset)) {
267: printf("Error locking offset %lu\n",offset);
268: continue; }
269: if(!chkuser(stream,offset)) {
270: unlock(fileno(stream),offset,U_LEN);
271: continue; }
272: fseek(stream,offset+flagoff,SEEK_SET);
273: fread(str,8,1,stream);
274: str[8]=0;
275: truncsp(str);
276: l=f=ahtoul(str);
277: if(sub)
278: l&=~flags;
279: else
280: l|=flags;
281: if(l==f) { /* no change */
282: unlock(fileno(stream),offset,U_LEN);
283: continue; }
284: mod++;
285: sprintf(str,"%lx",l);
286: while(strlen(str)<8)
287: strcat(str,"\3");
288: fseek(stream,offset+flagoff,SEEK_SET);
289: fwrite(str,8,1,stream);
290: unlock(fileno(stream),offset,U_LEN); }
291: fclose(stream);
292: printf("\n");
293: break;
294: case 'L': /* Level */
295: j=atoi(argv[i]+2);
296: if(j>99)
297: j=99;
298: if(j<0)
299: j=0;
300: sprintf(str,"%suser.dat",dir);
301: if(!fexistcase(str) || (file=sopen(str,O_RDWR|O_BINARY,SH_DENYNO))==-1) {
302: printf("Error opening %s\n",str);
303: exit(1); }
304: if((stream=fdopen(file,"w+b"))==NULL) {
305: printf("Error opening %s\n",str);
306: exit(1); }
307: setvbuf(stream,NULL,_IOFBF,2048);
308: length=filelength(file);
309: printf("\nChanging Levels\n");
310: for(offset=0;offset<length;offset+=U_LEN) {
311: printf("%lu of %lu (%u modified)\r"
312: ,(offset/U_LEN)+1,length/U_LEN,mod);
313: if(lockuser(stream,offset)) {
314: printf("Error locking offset %lu\n",offset);
315: continue; }
316: if(!chkuser(stream,offset)) {
317: unlock(fileno(stream),offset,U_LEN);
318: continue; }
319: fseek(stream,offset+U_LEVEL,SEEK_SET);
320: fread(str,2,1,stream);
321: str[2]=0;
322: truncsp(str);
323: if(atoi(str)==j) { /* no change */
324: unlock(fileno(stream),offset,U_LEN);
325: continue; }
326: sprintf(str,"%02u",j);
327: fseek(stream,offset+U_LEVEL,SEEK_SET);
328: fwrite(str,2,1,stream);
329: unlock(fileno(stream),offset,U_LEN);
330: mod++; }
331: fclose(stream);
332: printf("\n");
333: break;
334: default:
335: printf(usage);
336: exit(1); }
337: else {
338: strcpy(dir,argv[i]);
339: backslash(dir); } }
340: return(0);
341: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.