|
|
1.1 root 1: /* userdat.c */
2:
3: /* Synchronet user data-related routines (exported) */
4:
5: /* $Id: userdat.c,v 1.10 2000/12/05 19:06:41 rswindell Exp $ */
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: * *
11: * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html *
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: #include "sbbs.h"
39: #include "cmdshell.h"
40:
41: /* convenient space-saving global variables */
42: char* crlf="\r\n";
43: char* nulstr="";
44:
45: /****************************************************************************/
46: /* Looks for a perfect match amoung all usernames (not deleted users) */
47: /* Makes dots and underscores synomynous with spaces for comparisions */
48: /* Returns the number of the perfect matched username or 0 if no match */
49: /****************************************************************************/
50: uint DLLCALL matchuser(scfg_t* cfg, char *name)
51: {
52: int file;
53: char str[256],c;
54: ulong l,length;
55: FILE *stream;
56:
57: sprintf(str,"%suser/name.dat",cfg->data_dir);
58: if((file=nopen(str,O_RDONLY))==-1)
59: return(0);
60: length=filelength(file);
61: if((stream=fdopen(file,"rb"))==NULL)
62: return(0);
63: for(l=0;l<length;l+=LEN_ALIAS+2) {
64: fread(str,LEN_ALIAS+2,1,stream);
65: for(c=0;c<LEN_ALIAS;c++)
66: if(str[c]==ETX) break;
67: str[c]=0;
68: if(!stricmp(str,name))
69: break;
70: /* convert dots to spaces */
71: for(c=0;str[c];c++)
72: if(str[c]=='.')
73: str[c]=' ';
74: if(!stricmp(str,name))
75: break;
76: /* convert spaces to dots */
77: for(c=0;str[c];c++)
78: if(str[c]==' ')
79: str[c]='.';
80: if(!stricmp(str,name))
81: break;
82: /* convert dots to underscores */
83: for(c=0;str[c];c++)
84: if(str[c]=='.')
85: str[c]='_';
86: if(!stricmp(str,name))
87: break;
88: /* convert underscores to spaces */
89: for(c=0;str[c];c++)
90: if(str[c]=='_')
91: str[c]=' ';
92: if(!stricmp(str,name))
93: break;
94: }
95: fclose(stream);
96: if(l<length)
97: return((l/(LEN_ALIAS+2))+1);
98: return(0);
99: }
100:
101: /****************************************************************************/
102: /* Returns the number of the last user in user.dat (deleted ones too) */
103: /****************************************************************************/
104: uint DLLCALL lastuser(scfg_t* cfg)
105: {
106: char str[256];
107: long length;
108:
109: sprintf(str,"%suser/user.dat", cfg->data_dir);
110: if((length=flength(str))>0)
111: return((uint)(length/U_LEN));
112: return(0);
113: }
114:
115: /****************************************************************************/
116: /* Fills the structure 'user' with info for user.number from user.dat */
117: /* Called from functions useredit, waitforcall and main_sec */
118: /****************************************************************************/
119: int DLLCALL getuserdat(scfg_t* cfg, user_t *user)
120: {
121: char userdat[U_LEN+1],str[U_LEN+1],tmp[64];
122: int i,file;
123:
124: if(!user->number || user->number>lastuser(cfg)) {
125: memset(user,0,sizeof(user_t));
126: return(-1);
127: }
128: sprintf(userdat,"%suser/user.dat",cfg->data_dir);
129: if((file=nopen(userdat,O_RDONLY|O_DENYNONE))==-1) {
130: memset(user,0,sizeof(user_t));
131: return(errno);
132: }
133: lseek(file,(long)((long)(user->number-1)*U_LEN),SEEK_SET);
134: i=0;
135: while(i<LOOP_NODEDAB
136: && lock(file,(long)((long)(user->number-1)*U_LEN),U_LEN)==-1) {
137: if(i>10)
138: mswait(55);
139: i++;
140: }
141:
142: if(i>=LOOP_NODEDAB) {
143: close(file);
144: memset(user,0L,sizeof(user_t));
145: return(-2);
146: }
147:
148: if(read(file,userdat,U_LEN)!=U_LEN) {
149: unlock(file,(long)((long)(user->number-1)*U_LEN),U_LEN);
150: close(file);
151: memset(user,0L,sizeof(user_t));
152: return(-3);
153: }
154:
155: unlock(file,(long)((long)(user->number-1)*U_LEN),U_LEN);
156: close(file);
157: getrec(userdat,U_ALIAS,LEN_ALIAS,user->alias);
158: /* order of these function */
159: getrec(userdat,U_NAME,LEN_NAME,user->name);
160: /* calls is irrelevant */
161: getrec(userdat,U_HANDLE,LEN_HANDLE,user->handle);
162: getrec(userdat,U_NOTE,LEN_NOTE,user->note);
163: getrec(userdat,U_COMP,LEN_COMP,user->comp);
164: getrec(userdat,U_COMMENT,LEN_COMMENT,user->comment);
165: getrec(userdat,U_NETMAIL,LEN_NETMAIL,user->netmail);
166: getrec(userdat,U_ADDRESS,LEN_ADDRESS,user->address);
167: getrec(userdat,U_LOCATION,LEN_LOCATION,user->location);
168: getrec(userdat,U_ZIPCODE,LEN_ZIPCODE,user->zipcode);
169: getrec(userdat,U_PASS,LEN_PASS,user->pass);
170: getrec(userdat,U_PHONE,LEN_PHONE,user->phone);
171: getrec(userdat,U_BIRTH,LEN_BIRTH,user->birth);
172: getrec(userdat,U_MODEM,LEN_MODEM,user->modem);
173: getrec(userdat,U_LASTON,8,str); user->laston=ahtoul(str);
174: getrec(userdat,U_FIRSTON,8,str); user->firston=ahtoul(str);
175: getrec(userdat,U_EXPIRE,8,str); user->expire=ahtoul(str);
176: getrec(userdat,U_PWMOD,8,str); user->pwmod=ahtoul(str);
177: getrec(userdat,U_NS_TIME,8,str);
178: user->ns_time=ahtoul(str);
179: if(user->ns_time<0x20000000L)
180: user->ns_time=user->laston; /* Fix for v2.00->v2.10 */
181:
182: getrec(userdat,U_LOGONS,5,str); user->logons=atoi(str);
183: getrec(userdat,U_LTODAY,5,str); user->ltoday=atoi(str);
184: getrec(userdat,U_TIMEON,5,str); user->timeon=atoi(str);
185: getrec(userdat,U_TEXTRA,5,str); user->textra=atoi(str);
186: getrec(userdat,U_TTODAY,5,str); user->ttoday=atoi(str);
187: getrec(userdat,U_TLAST,5,str); user->tlast=atoi(str);
188: getrec(userdat,U_POSTS,5,str); user->posts=atoi(str);
189: getrec(userdat,U_EMAILS,5,str); user->emails=atoi(str);
190: getrec(userdat,U_FBACKS,5,str); user->fbacks=atoi(str);
191: getrec(userdat,U_ETODAY,5,str); user->etoday=atoi(str);
192: getrec(userdat,U_PTODAY,5,str); user->ptoday=atoi(str);
193: getrec(userdat,U_ULB,10,str); user->ulb=atol(str);
194: getrec(userdat,U_ULS,5,str); user->uls=atoi(str);
195: getrec(userdat,U_DLB,10,str); user->dlb=atol(str);
196: getrec(userdat,U_DLS,5,str); user->dls=atoi(str);
197: getrec(userdat,U_CDT,10,str); user->cdt=atol(str);
198: getrec(userdat,U_MIN,10,str); user->min=atol(str);
199: getrec(userdat,U_LEVEL,2,str); user->level=atoi(str);
200: getrec(userdat,U_FLAGS1,8,str); user->flags1=ahtoul(str); /***
201: getrec(userdat,U_TL,2,str); user->tl=atoi(str); ***/
202: getrec(userdat,U_FLAGS2,8,str); user->flags2=ahtoul(str);
203: getrec(userdat,U_FLAGS3,8,str); user->flags3=ahtoul(str);
204: getrec(userdat,U_FLAGS4,8,str); user->flags4=ahtoul(str);
205: getrec(userdat,U_EXEMPT,8,str); user->exempt=ahtoul(str);
206: getrec(userdat,U_REST,8,str); user->rest=ahtoul(str);
207: getrec(userdat,U_ROWS,2,str); user->rows=atoi(str);
208: if(user->rows && user->rows<10)
209: user->rows=10;
210: user->sex=userdat[U_SEX];
211: if(!user->sex)
212: user->sex=SP; /* fix for v1b04 that could save as 0 */
213: user->prot=userdat[U_PROT];
214: if(user->prot<SP)
215: user->prot=SP;
216: getrec(userdat,U_MISC,8,str); user->misc=ahtoul(str);
217: if(user->rest&FLAG('Q'))
218: user->misc&=~SPIN;
219:
220: getrec(userdat,U_LEECH,2,str);
221: user->leech=(uchar)ahtoul(str);
222: getrec(userdat,U_CURSUB,8,user->cursub); /* was useron.cursub (01/19/00) */
223: getrec(userdat,U_CURDIR,8,user->curdir); /* was useron.curdir (01/19/00) */
224:
225: getrec(userdat,U_FREECDT,10,str);
226: user->freecdt=atol(str);
227:
228: getrec(userdat,U_XEDIT,8,str);
229: for(i=0;i<cfg->total_xedits;i++)
230: if(!stricmp(str,cfg->xedit[i]->code) /* && chk_ar(cfg->xedit[i]->ar,user) */)
231: break;
232: user->xedit=i+1;
233: if(user->xedit>cfg->total_xedits)
234: user->xedit=0;
235:
236: getrec(userdat,U_SHELL,8,str);
237: for(i=0;i<cfg->total_shells;i++)
238: if(!stricmp(str,cfg->shell[i]->code))
239: break;
240: if(i==cfg->total_shells)
241: i=0;
242: user->shell=i;
243:
244: getrec(userdat,U_QWK,8,str);
245: if(str[0]<SP) { /* v1c, so set defaults */
246: if(user->rest&FLAG('Q'))
247: user->qwk=(QWK_RETCTLA);
248: else
249: user->qwk=(QWK_FILES|QWK_ATTACH|QWK_EMAIL|QWK_DELMAIL); }
250: else
251: user->qwk=ahtoul(str);
252:
253: getrec(userdat,U_TMPEXT,3,user->tmpext);
254: if((!user->tmpext[0] || !strcmp(user->tmpext,"0")) && cfg->total_fcomps)
255: strcpy(user->tmpext,cfg->fcomp[0]->ext); /* For v1x to v2x conversion */
256:
257: getrec(userdat,U_CHAT,8,str);
258: user->chat=ahtoul(str);
259:
260: unixtodstr(cfg, time(NULL),str);
261: unixtodstr(cfg, user->laston,tmp);
262: if(strcmp(str,tmp) && user->ltoday) {
263: user->ltoday=user->ttoday=user->ptoday=user->etoday=user->textra=0;
264: user->freecdt=cfg->level_freecdtperday[user->level];
265: }
266:
267:
268: #if 0 // removed 01/19/00
269: if(useron.number==user->number) {
270: if(user!=&useron)
271: useron=*user;
272:
273: if(online) {
274:
275: #if 0 /* legacy? */
276: getusrdirs();
277: getusrsubs();
278: #endif
279: if(user->misc&AUTOTERM) { // was useron.misc (01/19/00)
280: user->misc&=~(ANSI|RIP|WIP);
281: user->misc|=autoterm; }
282: } }
283: #endif
284: return(0);
285: }
286:
287: /****************************************************************************/
288: /* Writes into user.number's slot in user.dat data in structure 'user' */
289: /* Called from functions newuser, useredit and main */
290: /****************************************************************************/
291: int DLLCALL putuserdat(scfg_t* cfg, user_t* user)
292: {
293: int i,file;
294: char userdat[U_LEN+1],str[U_LEN+1];
295: node_t node;
296:
297: if(!user->number)
298: return(-1);
299:
300: memset(userdat,ETX,U_LEN);
301: putrec(userdat,U_ALIAS,LEN_ALIAS+5,user->alias);
302: putrec(userdat,U_NAME,LEN_NAME,user->name);
303: putrec(userdat,U_HANDLE,LEN_HANDLE,user->handle);
304: putrec(userdat,U_HANDLE+LEN_HANDLE,2,crlf);
305:
306: putrec(userdat,U_NOTE,LEN_NOTE,user->note);
307: putrec(userdat,U_COMP,LEN_COMP,user->comp);
308: putrec(userdat,U_COMP+LEN_COMP,2,crlf);
309:
310: putrec(userdat,U_COMMENT,LEN_COMMENT,user->comment);
311: putrec(userdat,U_COMMENT+LEN_COMMENT,2,crlf);
312:
313: putrec(userdat,U_NETMAIL,LEN_NETMAIL,user->netmail);
314: putrec(userdat,U_NETMAIL+LEN_NETMAIL,2,crlf);
315:
316: putrec(userdat,U_ADDRESS,LEN_ADDRESS,user->address);
317: putrec(userdat,U_LOCATION,LEN_LOCATION,user->location);
318: putrec(userdat,U_ZIPCODE,LEN_ZIPCODE,user->zipcode);
319: putrec(userdat,U_ZIPCODE+LEN_ZIPCODE,2,crlf);
320:
321: putrec(userdat,U_PASS,LEN_PASS,user->pass);
322: putrec(userdat,U_PHONE,LEN_PHONE,user->phone);
323: putrec(userdat,U_BIRTH,LEN_BIRTH,user->birth);
324: putrec(userdat,U_MODEM,LEN_MODEM,user->modem);
325: putrec(userdat,U_LASTON,8,ultoa(user->laston,str,16));
326: putrec(userdat,U_FIRSTON,8,ultoa(user->firston,str,16));
327: putrec(userdat,U_EXPIRE,8,ultoa(user->expire,str,16));
328: putrec(userdat,U_PWMOD,8,ultoa(user->pwmod,str,16));
329: putrec(userdat,U_PWMOD+8,2,crlf);
330:
331: putrec(userdat,U_LOGONS,5,ultoa(user->logons,str,10));
332: putrec(userdat,U_LTODAY,5,ultoa(user->ltoday,str,10));
333: putrec(userdat,U_TIMEON,5,ultoa(user->timeon,str,10));
334: putrec(userdat,U_TEXTRA,5,ultoa(user->textra,str,10));
335: putrec(userdat,U_TTODAY,5,ultoa(user->ttoday,str,10));
336: putrec(userdat,U_TLAST,5,ultoa(user->tlast,str,10));
337: putrec(userdat,U_POSTS,5,ultoa(user->posts,str,10));
338: putrec(userdat,U_EMAILS,5,ultoa(user->emails,str,10));
339: putrec(userdat,U_FBACKS,5,ultoa(user->fbacks,str,10));
340: putrec(userdat,U_ETODAY,5,ultoa(user->etoday,str,10));
341: putrec(userdat,U_PTODAY,5,ultoa(user->ptoday,str,10));
342: putrec(userdat,U_PTODAY+5,2,crlf);
343:
344: putrec(userdat,U_ULB,10,ultoa(user->ulb,str,10));
345: putrec(userdat,U_ULS,5,ultoa(user->uls,str,10));
346: putrec(userdat,U_DLB,10,ultoa(user->dlb,str,10));
347: putrec(userdat,U_DLS,5,ultoa(user->dls,str,10));
348: putrec(userdat,U_CDT,10,ultoa(user->cdt,str,10));
349: putrec(userdat,U_MIN,10,ultoa(user->min,str,10));
350: putrec(userdat,U_MIN+10,2,crlf);
351:
352: putrec(userdat,U_LEVEL,2,ultoa(user->level,str,10));
353: putrec(userdat,U_FLAGS1,8,ultoa(user->flags1,str,16));
354: putrec(userdat,U_TL,2,nulstr); /* unused */
355: putrec(userdat,U_FLAGS2,8,ultoa(user->flags2,str,16));
356: putrec(userdat,U_EXEMPT,8,ultoa(user->exempt,str,16));
357: putrec(userdat,U_REST,8,ultoa(user->rest,str,16));
358: putrec(userdat,U_REST+8,2,crlf);
359:
360: putrec(userdat,U_ROWS,2,ultoa(user->rows,str,10));
361: userdat[U_SEX]=user->sex;
362: userdat[U_PROT]=user->prot;
363: putrec(userdat,U_MISC,8,ultoa(user->misc,str,16));
364: putrec(userdat,U_LEECH,2,ultoa(user->leech,str,16));
365:
366: putrec(userdat,U_CURSUB,8,user->cursub);
367: putrec(userdat,U_CURDIR,8,user->curdir);
368:
369: // putrec(userdat,U_CMDSET,2,ultoa(user->cmdset,str,16)); /* Unused */
370: putrec(userdat,U_CMDSET+2,2,crlf);
371:
372: putrec(userdat,U_XFER_CMD+LEN_XFER_CMD,2,crlf);
373:
374: putrec(userdat,U_MAIL_CMD+LEN_MAIL_CMD,2,crlf);
375:
376: putrec(userdat,U_FREECDT,10,ultoa(user->freecdt,str,10));
377:
378: putrec(userdat,U_FLAGS3,8,ultoa(user->flags3,str,16));
379: putrec(userdat,U_FLAGS4,8,ultoa(user->flags4,str,16));
380:
381: if(user->xedit)
382: putrec(userdat,U_XEDIT,8,cfg->xedit[user->xedit-1]->code);
383: else
384: putrec(userdat,U_XEDIT,8,nulstr);
385:
386: putrec(userdat,U_SHELL,8,cfg->shell[user->shell]->code);
387:
388: putrec(userdat,U_QWK,8,ultoa(user->qwk,str,16));
389: putrec(userdat,U_TMPEXT,3,user->tmpext);
390: putrec(userdat,U_CHAT,8,ultoa(user->chat,str,16));
391: putrec(userdat,U_NS_TIME,8,ultoa(user->ns_time,str,16));
392:
393: putrec(userdat,U_UNUSED,29,crlf);
394: putrec(userdat,U_UNUSED+29,2,crlf);
395:
396: sprintf(str,"%suser/user.dat", cfg->data_dir);
397: if((file=nopen(str,O_WRONLY|O_CREAT|O_DENYNONE))==-1) {
398: return(errno);
399: }
400:
401: lseek(file,(long)((long)((long)user->number-1)*U_LEN),SEEK_SET);
402:
403: i=0;
404: while(i<LOOP_NODEDAB
405: && lock(file,(long)((long)(user->number-1)*U_LEN),U_LEN)==-1) {
406: if(i>10)
407: mswait(55);
408: i++;
409: }
410:
411: if(i>=LOOP_NODEDAB) {
412: close(file);
413: return(-2);
414: }
415:
416: if(write(file,userdat,U_LEN)!=U_LEN) {
417: unlock(file,(long)((long)(user->number-1)*U_LEN),U_LEN);
418: close(file);
419: return(-3);
420: }
421: unlock(file,(long)((long)(user->number-1)*U_LEN),U_LEN);
422: close(file);
423: for(i=1;i<=cfg->sys_nodes;i++) { /* instant user data update */
424: if(i==cfg->node_num)
425: continue;
426: getnodedat(cfg, i,&node,0);
427: if(node.useron==user->number && (node.status==NODE_INUSE
428: || node.status==NODE_QUIET)) {
429: getnodedat(cfg, i,&node,1);
430: node.misc|=NODE_UDAT;
431: putnodedat(cfg, i,&node);
432: break;
433: }
434: }
435: return(0);
436: }
437:
438:
439: /****************************************************************************/
440: /* Returns the username in 'str' that corresponds to the 'usernumber' */
441: /* Called from functions everywhere */
442: /****************************************************************************/
443: char* DLLCALL username(scfg_t* cfg, int usernumber,char *strin)
444: {
445: char str[256];
446: char c;
447: int file;
448:
449: if(usernumber<1) {
450: strin[0]=0;
451: return(strin); }
452: sprintf(str,"%suser/name.dat",cfg->data_dir);
453: if(flength(str)<1L) {
454: strin[0]=0;
455: return(strin); }
456: if((file=nopen(str,O_RDONLY))==-1) {
457: strin[0]=0;
458: return(strin); }
459: if(filelength(file)<(long)((long)usernumber*(LEN_ALIAS+2))) {
460: close(file);
461: strin[0]=0;
462: return(strin); }
463: lseek(file,(long)((long)(usernumber-1)*(LEN_ALIAS+2)),SEEK_SET);
464: read(file,strin,LEN_ALIAS);
465: close(file);
466: for(c=0;c<LEN_ALIAS;c++)
467: if(strin[c]==ETX) break;
468: strin[c]=0;
469: if(!c)
470: strcpy(strin,"DELETED USER");
471: return(strin);
472: }
473:
474: /****************************************************************************/
475: /* Places into 'strout' CR or ETX terminated string starting at */
476: /* 'start' and ending at 'start'+'length' or terminator from 'strin' */
477: /****************************************************************************/
478: void DLLCALL getrec(char *strin,int start,int length,char *strout)
479: {
480: int i=0,stop;
481:
482: stop=start+length;
483: while(start<stop) {
484: if(strin[start]==ETX || strin[start]==CR || strin[start]==LF)
485: break;
486: strout[i++]=strin[start++];
487: }
488: strout[i]=0;
489: }
490:
491: /****************************************************************************/
492: /* Places into 'strout', 'strin' starting at 'start' and ending at */
493: /* 'start'+'length' */
494: /****************************************************************************/
495: void DLLCALL putrec(char *strout,int start,int length,char *strin)
496: {
497: int i=0,j;
498:
499: j=strlen(strin);
500: while(i<j && i<length)
501: strout[start++]=strin[i++];
502: while(i++<length)
503: strout[start++]=ETX;
504: }
505:
506:
507: /****************************************************************************/
508: /* Returns the age derived from the string 'birth' in the format MM/DD/YY */
509: /* Called from functions statusline, main_sec, xfer_sec, useredit and */
510: /* text files */
511: /****************************************************************************/
512: char DLLCALL getage(scfg_t* cfg, char *birth)
513: {
514: char age;
515: struct tm * tm;
516: time_t now;
517:
518: if(!atoi(birth) || !atoi(birth+3)) /* Invalid */
519: return(0);
520:
521: now=time(NULL);
522: tm=gmtime(&now);
523: if(tm==NULL)
524: return(0);
525: age=(tm->tm_year)-(((birth[6]&0xf)*10)+(birth[7]&0xf));
526: if(age>105)
527: age-=105;
528: tm->tm_mon++; /* convert to 1 based */
529: if(cfg->sys_misc&SM_EURODATE) { /* DD/MM/YY format */
530: if(atoi(birth)>31 || atoi(birth+3)>12)
531: return(0);
532: if(((birth[3]&0xf)*10)+(birth[4]&0xf)>tm->tm_mon ||
533: (((birth[3]&0xf)*10)+(birth[4]&0xf)==tm->tm_mon &&
534: ((birth[0]&0xf)*10)+(birth[1]&0xf)>tm->tm_mday))
535: age--; }
536: else { /* MM/DD/YY format */
537: if(atoi(birth)>12 || atoi(birth+3)>31)
538: return(0);
539: if(((birth[0]&0xf)*10)+(birth[1]&0xf)>tm->tm_mon ||
540: (((birth[0]&0xf)*10)+(birth[1]&0xf)==tm->tm_mon &&
541: ((birth[3]&0xf)*10)+(birth[4]&0xf)>tm->tm_mday))
542: age--; }
543: if(age<0)
544: return(0);
545: return(age);
546: }
547:
548:
549: /****************************************************************************/
550: /* Reads the data for node number 'number' into the structure 'node' */
551: /* from node.dab */
552: /* if lockit is non-zero, locks this node's record. putnodedat() unlocks it */
553: /****************************************************************************/
554: int DLLCALL getnodedat(scfg_t* cfg, uint number, node_t *node, char lockit)
555: {
556: char str[256];
557: int count=0;
558: int file;
559:
560: if(!number || number>cfg->sys_nodes)
561: return(-1);
562:
563: sprintf(str,"%snode.dab",cfg->ctrl_dir);
564: if((file=nopen(str,O_RDONLY|O_DENYNONE))==-1) {
565: memset(node,0,sizeof(node_t));
566: return(errno);
567: }
568:
569: number--; /* make zero based */
570: while(count<LOOP_NODEDAB) {
571: if(count>10)
572: mswait(100);
573: lseek(file,(long)number*sizeof(node_t),SEEK_SET);
574: if(lockit
575: && lock(file,(long)number*sizeof(node_t),sizeof(node_t))==-1) {
576: count++;
577: continue; }
578: if(read(file,node,sizeof(node_t))==sizeof(node_t))
579: break;
580: count++; }
581:
582: close(file);
583: if(count==LOOP_NODEDAB)
584: return(-2);
585:
586: return(0);
587: }
588:
589: /****************************************************************************/
590: /* Write the data from the structure 'node' into node.dab */
591: /* getnodedat(num,&node,1); must have been called before calling this func */
592: /* NOTE: ------^ the indicates the node record has been locked */
593: /****************************************************************************/
594: int DLLCALL putnodedat(scfg_t* cfg, uint number, node_t* node)
595: {
596: char str[256];
597: int file;
598:
599: if(!number || number>cfg->sys_nodes)
600: return(-1);
601:
602: sprintf(str,"%snode.dab",cfg->ctrl_dir);
603: if((file=nopen(str,O_RDWR|O_CREAT|O_DENYNONE))==-1) {
604: memset(node,0,sizeof(node_t));
605: return(errno);
606: }
607:
608: number--; /* make zero based */
609: lseek(file,(long)number*sizeof(node_t),SEEK_SET);
610: if(write(file,node,sizeof(node_t))!=sizeof(node_t)) {
611: unlock(file,(long)number*sizeof(node_t),sizeof(node_t));
612: close(file);
613: return(-2);
614: }
615: unlock(file,(long)number*sizeof(node_t),sizeof(node_t));
616: close(file);
617:
618: return(0);
619: }
620:
621: /****************************************************************************/
622: uint DLLCALL userdatdupe(scfg_t* cfg, uint usernumber, uint offset, uint datlen, char *dat
623: ,BOOL del)
624: {
625: char str[256];
626: uint i;
627: int file;
628: long l,length;
629:
630: truncsp(dat);
631: sprintf(str,"%suser/user.dat", cfg->data_dir);
632: if((file=nopen(str,O_RDONLY|O_DENYNONE))==-1)
633: return(0);
634: length=filelength(file);
635: for(l=0;l<length;l+=U_LEN) {
636: if(usernumber && l/U_LEN==(long)usernumber-1)
637: continue;
638: lseek(file,l+offset,SEEK_SET);
639: i=0;
640: while(i<LOOP_NODEDAB && lock(file,l,U_LEN)==-1) {
641: if(i>10)
642: mswait(55);
643: i++; }
644:
645: if(i>=LOOP_NODEDAB) {
646: close(file);
647: return(0); }
648:
649: read(file,str,datlen);
650: for(i=0;i<datlen;i++)
651: if(str[i]==ETX) break;
652: str[i]=0;
653: truncsp(str);
654: if(!stricmp(str,dat)) {
655: if(!del) { /* Don't include deleted users in search */
656: lseek(file,l+U_MISC,SEEK_SET);
657: read(file,str,8);
658: getrec(str,0,8,str);
659: if(ahtoul(str)&(DELETED|INACTIVE)) {
660: unlock(file,l,U_LEN);
661: continue; } }
662: unlock(file,l,U_LEN);
663: close(file);
664: return((l/U_LEN)+1); }
665: else
666: unlock(file,l,U_LEN); }
667: close(file);
668: return(0);
669: }
670:
671: /****************************************************************************/
672: /* Creates a short message for 'usernumber' than contains 'strin' */
673: /****************************************************************************/
674: int DLLCALL putsmsg(scfg_t* cfg, int usernumber, char *strin)
675: {
676: char str[256];
677: int file,i;
678: node_t node;
679:
680: sprintf(str,"%smsgs/%4.4u.msg",cfg->data_dir,usernumber);
681: if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) {
682: return(errno);
683: }
684: i=strlen(strin);
685: if(write(file,strin,i)!=i) {
686: close(file);
687: return(errno);
688: }
689: close(file);
690: for(i=1;i<=cfg->sys_nodes;i++) { /* flag node if user on that msg waiting */
691: getnodedat(cfg,i,&node,0);
692: if(node.useron==usernumber
693: && (node.status==NODE_INUSE || node.status==NODE_QUIET)
694: && !(node.misc&NODE_MSGW)) {
695: getnodedat(cfg,i,&node,1);
696: node.misc|=NODE_MSGW;
697: putnodedat(cfg,i,&node);
698: }
699: }
700: return(0);
701: }
702:
703: static BOOL ar_exp(scfg_t* cfg, uchar **ptrptr, user_t* user)
704: {
705: BOOL result,not,or,equal;
706: uint i,n,artype=AR_LEVEL,age;
707: ulong l;
708: time_t now;
709: struct tm * tm;
710:
711: result = TRUE;
712:
713: for(;(**ptrptr);(*ptrptr)++) {
714:
715: if((**ptrptr)==AR_ENDNEST)
716: break;
717:
718: not=or=equal = FALSE;
719:
720: if((**ptrptr)==AR_OR) {
721: or=1;
722: (*ptrptr)++; }
723:
724: if((**ptrptr)==AR_NOT) {
725: not=1;
726: (*ptrptr)++; }
727:
728: if((**ptrptr)==AR_EQUAL) {
729: equal=1;
730: (*ptrptr)++; }
731:
732: if((result && or) || (!result && !or))
733: break;
734:
735: if((**ptrptr)==AR_BEGNEST) {
736: (*ptrptr)++;
737: if(ar_exp(cfg,ptrptr,user))
738: result=!not;
739: else
740: result=not;
741: while((**ptrptr)!=AR_ENDNEST && (**ptrptr)) /* in case of early exit */
742: (*ptrptr)++;
743: if(!(**ptrptr))
744: break;
745: continue; }
746:
747: artype=(**ptrptr);
748: switch(artype) {
749: case AR_ANSI: /* No arguments */
750: case AR_RIP:
751: case AR_WIP:
752: case AR_LOCAL:
753: case AR_EXPERT:
754: case AR_SYSOP:
755: case AR_QUIET:
756: case AR_OS2:
757: case AR_DOS:
758: break;
759: default:
760: (*ptrptr)++;
761: break; }
762:
763: n=(**ptrptr);
764: i=(*(short *)*ptrptr);
765: switch(artype) {
766: case AR_LEVEL:
767: if((equal && user->level!=n) || (!equal && user->level<n))
768: result=not;
769: else
770: result=!not;
771: break;
772: case AR_AGE:
773: age=getage(cfg,user->birth);
774: if((equal && age!=n) || (!equal && age<n))
775: result=not;
776: else
777: result=!not;
778: break;
779: case AR_BPS:
780: result=!not;
781: (*ptrptr)++;
782: break;
783: case AR_ANSI:
784: if(!(user->misc&ANSI))
785: result=not;
786: else result=!not;
787: break;
788: case AR_RIP:
789: if(!(user->misc&RIP))
790: result=not;
791: else result=!not;
792: break;
793: case AR_WIP:
794: if(!(user->misc&WIP))
795: result=not;
796: else result=!not;
797: break;
798: case AR_OS2:
799: #ifndef __OS2__
800: result=not;
801: #else
802: result=!not;
803: #endif
804: break;
805: case AR_DOS:
806: #ifdef __FLAT__
807: result=not;
808: #else
809: result=!not;
810: #endif
811: break;
812: case AR_WIN32:
813: #ifndef _WIN32
814: result=not;
815: #else
816: result=!not;
817: #endif
818: break;
819: case AR_UNIX:
820: #ifndef __unix__
821: result=not;
822: #else
823: result=!not;
824: #endif
825: break;
826: case AR_LINUX:
827: #ifndef __linux__
828: result=not;
829: #else
830: result=!not;
831: #endif
832: break;
833: case AR_EXPERT:
834: if(!(user->misc&EXPERT))
835: result=not;
836: else result=!not;
837: break;
838: case AR_SYSOP:
839: if(user->level<SYSOP_LEVEL)
840: result=not;
841: else result=!not;
842: break;
843: case AR_QUIET:
844: result=not;
845: break;
846: case AR_LOCAL:
847: result=not;
848: break;
849: case AR_DAY:
850: now=time(NULL);
851: tm=localtime(&now);
852: if(tm==NULL || (equal && tm->tm_wday!=(int)n)
853: || (!equal && tm->tm_wday<(int)n))
854: result=not;
855: else
856: result=!not;
857: break;
858: case AR_CREDIT:
859: l=(ulong)i*1024UL;
860: if((equal && user->cdt+user->freecdt!=l)
861: || (!equal && user->cdt+user->freecdt<l))
862: result=not;
863: else
864: result=!not;
865: (*ptrptr)++;
866: break;
867: case AR_NODE:
868: if((equal && cfg->node_num!=n) || (!equal && cfg->node_num<n))
869: result=not;
870: else
871: result=!not;
872: break;
873: case AR_USER:
874: if((equal && user->number!=i) || (!equal && user->number<i))
875: result=not;
876: else
877: result=!not;
878: (*ptrptr)++;
879: break;
880: case AR_GROUP:
881: result=not;
882: (*ptrptr)++;
883: break;
884: case AR_SUB:
885: result=not;
886: (*ptrptr)++;
887: break;
888: case AR_SUBCODE:
889: result=not;
890: while(*(*ptrptr))
891: (*ptrptr)++;
892: break;
893: case AR_LIB:
894: result=not;
895: (*ptrptr)++;
896: break;
897: case AR_DIR:
898: result=not;
899: (*ptrptr)++;
900: break;
901: case AR_DIRCODE:
902: result=not;
903: while(*(*ptrptr))
904: (*ptrptr)++;
905: break;
906: case AR_EXPIRE:
907: now=time(NULL);
908: if(!user->expire || now+((long)i*24L*60L*60L)>user->expire)
909: result=not;
910: else
911: result=!not;
912: (*ptrptr)++;
913: break;
914: case AR_RANDOM:
915: n=sbbs_random(i+1);
916: if((equal && n!=i) || (!equal && n<i))
917: result=not;
918: else
919: result=!not;
920: (*ptrptr)++;
921: break;
922: case AR_LASTON:
923: now=time(NULL);
924: if((now-user->laston)/(24L*60L*60L)<(long)i)
925: result=not;
926: else
927: result=!not;
928: (*ptrptr)++;
929: break;
930: case AR_LOGONS:
931: if((equal && user->logons!=i) || (!equal && user->logons<i))
932: result=not;
933: else
934: result=!not;
935: (*ptrptr)++;
936: break;
937: case AR_MAIN_CMDS:
938: result=not;
939: (*ptrptr)++;
940: break;
941: case AR_FILE_CMDS:
942: result=not;
943: (*ptrptr)++;
944: break;
945: case AR_TLEFT:
946: result=not;
947: break;
948: case AR_TUSED:
949: result=not;
950: break;
951: case AR_TIME:
952: now=time(NULL);
953: tm=gmtime(&now);
954: if(tm==NULL || (tm->tm_hour*60)+tm->tm_min<(int)i)
955: result=not;
956: else
957: result=!not;
958: (*ptrptr)++;
959: break;
960: case AR_PCR:
961: if(user->logons>user->posts
962: && (!user->posts || 100/(user->logons/user->posts)<(long)n))
963: result=not;
964: else
965: result=!not;
966: break;
967: case AR_UDR: /* up/download byte ratio */
968: l=user->dlb;
969: if(!l) l=1;
970: if(user->dlb>user->ulb
971: && (!user->ulb || 100/(l/user->ulb)<n))
972: result=not;
973: else
974: result=!not;
975: break;
976: case AR_UDFR: /* up/download file ratio */
977: i=user->dls;
978: if(!i) i=1;
979: if(user->dls>user->uls
980: && (!user->uls || 100/(i/user->uls)<n))
981: result=not;
982: else
983: result=!not;
984: break;
985: case AR_FLAG1:
986: if((!equal && !(user->flags1&FLAG(n)))
987: || (equal && user->flags1!=FLAG(n)))
988: result=not;
989: else
990: result=!not;
991: break;
992: case AR_FLAG2:
993: if((!equal && !(user->flags2&FLAG(n)))
994: || (equal && user->flags2!=FLAG(n)))
995: result=not;
996: else
997: result=!not;
998: break;
999: case AR_FLAG3:
1000: if((!equal && !(user->flags3&FLAG(n)))
1001: || (equal && user->flags3!=FLAG(n)))
1002: result=not;
1003: else
1004: result=!not;
1005: break;
1006: case AR_FLAG4:
1007: if((!equal && !(user->flags4&FLAG(n)))
1008: || (equal && user->flags4!=FLAG(n)))
1009: result=not;
1010: else
1011: result=!not;
1012: break;
1013: case AR_REST:
1014: if((!equal && !(user->rest&FLAG(n)))
1015: || (equal && user->rest!=FLAG(n)))
1016: result=not;
1017: else
1018: result=!not;
1019: break;
1020: case AR_EXEMPT:
1021: if((!equal && !(user->exempt&FLAG(n)))
1022: || (equal && user->exempt!=FLAG(n)))
1023: result=not;
1024: else
1025: result=!not;
1026: break;
1027: case AR_SEX:
1028: if(user->sex!=n)
1029: result=not;
1030: else
1031: result=!not;
1032: break; } }
1033: return(result);
1034: }
1035:
1036: BOOL DLLCALL chk_ar(scfg_t* cfg, uchar *ar, user_t* user)
1037: {
1038: uchar *p;
1039:
1040: if(ar==NULL)
1041: return(TRUE);
1042: p=ar;
1043: return(ar_exp(cfg,&p,user));
1044: }
1045:
1046: /****************************************************************************/
1047: /* Fills 'str' with record for usernumber starting at start for length bytes*/
1048: /* Called from function ??? */
1049: /****************************************************************************/
1050: int DLLCALL getuserrec(scfg_t* cfg, int usernumber,int start, int length, char *str)
1051: {
1052: char c,path[256];
1053: int i,file;
1054:
1055: if(!usernumber)
1056: return(-1);
1057: sprintf(path,"%suser/user.dat",cfg->data_dir);
1058: if((file=nopen(path,O_RDONLY|O_DENYNONE))==-1)
1059: return(errno);
1060: if(usernumber<1
1061: || filelength(file)<(long)((long)(usernumber-1L)*U_LEN)+(long)start) {
1062: close(file);
1063: return(-2);
1064: }
1065: lseek(file,(long)((long)(usernumber-1)*U_LEN)+start,SEEK_SET);
1066:
1067: i=0;
1068: while(i<LOOP_NODEDAB
1069: && lock(file,(long)((long)(usernumber-1)*U_LEN)+start,length)==-1) {
1070: if(i>10)
1071: mswait(55);
1072: i++; }
1073:
1074: if(i>=LOOP_NODEDAB) {
1075: close(file);
1076: return(-3);
1077: }
1078:
1079: if(read(file,str,length)!=length) {
1080: unlock(file,(long)((long)(usernumber-1)*U_LEN)+start,length);
1081: close(file);
1082: return(-4);
1083: }
1084:
1085: unlock(file,(long)((long)(usernumber-1)*U_LEN)+start,length);
1086: close(file);
1087: for(c=0;c<length;c++)
1088: if(str[c]==ETX || str[c]==CR) break;
1089: str[c]=0;
1090:
1091: return(0);
1092: }
1093:
1094: /****************************************************************************/
1095: /* Places into user.dat at the offset for usernumber+start for length bytes */
1096: /* Called from various locations */
1097: /****************************************************************************/
1098: int DLLCALL putuserrec(scfg_t* cfg, int usernumber,int start, uint length, char *str)
1099: {
1100: char str2[256];
1101: int file;
1102: uint c,i;
1103: node_t node;
1104:
1105: if(usernumber<1)
1106: return(-1);
1107:
1108: sprintf(str2,"%suser/user.dat",cfg->data_dir);
1109: if((file=nopen(str2,O_WRONLY|O_DENYNONE))==-1)
1110: return(errno);
1111:
1112: strcpy(str2,str);
1113: if(strlen(str2)<length) {
1114: for(c=strlen(str2);c<length;c++)
1115: str2[c]=ETX;
1116: str2[c]=0;
1117: }
1118: lseek(file,(long)((long)((long)((long)usernumber-1)*U_LEN)+start),SEEK_SET);
1119:
1120: i=0;
1121: while(i<LOOP_NODEDAB
1122: && lock(file,(long)((long)(usernumber-1)*U_LEN)+start,length)==-1) {
1123: if(i>10)
1124: mswait(55);
1125: i++; }
1126:
1127: if(i>=LOOP_NODEDAB)
1128: return(-3);
1129:
1130: write(file,str2,length);
1131: unlock(file,(long)((long)(usernumber-1)*U_LEN)+start,length);
1132: close(file);
1133: for(i=1;i<=cfg->sys_nodes;i++) { /* instant user data update */
1134: if(i==cfg->node_num)
1135: continue;
1136: getnodedat(cfg, i,&node,0);
1137: if(node.useron==usernumber && (node.status==NODE_INUSE
1138: || node.status==NODE_QUIET)) {
1139: getnodedat(cfg, i,&node,1);
1140: node.misc|=NODE_UDAT;
1141: putnodedat(cfg, i,&node);
1142: break;
1143: }
1144: }
1145:
1146: return(0);
1147: }
1148:
1149: /****************************************************************************/
1150: /* Updates user 'usernumber's record (numeric string) by adding 'adj' to it */
1151: /* returns the new value. */
1152: /****************************************************************************/
1153: ulong DLLCALL adjustuserrec(scfg_t* cfg, int usernumber, int start, int length, long adj)
1154: {
1155: char str[256],c,path[256];
1156: char tmp[32];
1157: int i,file;
1158: long val;
1159: node_t node;
1160:
1161: if(usernumber<1)
1162: return(0UL);
1163:
1164: sprintf(path,"%suser/user.dat",cfg->data_dir);
1165: if((file=nopen(path,O_RDWR|O_DENYNONE))==-1)
1166: return(0UL);
1167:
1168: lseek(file,(long)((long)(usernumber-1)*U_LEN)+start,SEEK_SET);
1169:
1170: i=0;
1171: while(i<LOOP_NODEDAB
1172: && lock(file,(long)((long)(usernumber-1)*U_LEN)+start,length)==-1) {
1173: if(i>10)
1174: mswait(55);
1175: i++; }
1176:
1177: if(i>=LOOP_NODEDAB) {
1178: close(file);
1179: return(0);
1180: }
1181:
1182: if(read(file,str,length)!=length) {
1183: unlock(file,(long)((long)(usernumber-1)*U_LEN)+start,length);
1184: close(file);
1185: return(0UL);
1186: }
1187: for(c=0;c<length;c++)
1188: if(str[c]==ETX || str[c]==CR) break;
1189: str[c]=0;
1190: val=atol(str);
1191: if(adj<0L && val<-adj) /* don't go negative */
1192: val=0UL;
1193: else val+=adj;
1194: lseek(file,(long)((long)(usernumber-1)*U_LEN)+start,SEEK_SET);
1195: putrec(str,0,length,ultoa(val,tmp,10));
1196: if(write(file,str,length)!=length) {
1197: unlock(file,(long)((long)(usernumber-1)*U_LEN)+start,length);
1198: close(file);
1199: return(val);
1200: }
1201: unlock(file,(long)((long)(usernumber-1)*U_LEN)+start,length);
1202: close(file);
1203: for(i=1;i<=cfg->sys_nodes;i++) { /* instant user data update */
1204: if(i==cfg->node_num)
1205: continue;
1206: getnodedat(cfg, i,&node,0);
1207: if(node.useron==usernumber && (node.status==NODE_INUSE
1208: || node.status==NODE_QUIET)) {
1209: getnodedat(cfg, i,&node,1);
1210: node.misc|=NODE_UDAT;
1211: putnodedat(cfg, i,&node);
1212: break;
1213: }
1214: }
1215: return(val);
1216: }
1217:
1218: /****************************************************************************/
1219: /* Subtract credits from the current user online, accounting for the new */
1220: /* "free credits" field. */
1221: /****************************************************************************/
1222: void DLLCALL subtract_cdt(scfg_t* cfg, user_t* user, long amt)
1223: {
1224: char tmp[64];
1225: long mod;
1226:
1227: if(!amt)
1228: return;
1229: if(user->freecdt) {
1230: if((ulong)amt>user->freecdt) { /* subtract both credits and */
1231: mod=amt-user->freecdt; /* free credits */
1232: putuserrec(cfg, user->number,U_FREECDT,10,"0");
1233: user->freecdt=0;
1234: user->cdt=adjustuserrec(cfg, user->number,U_CDT,10,-mod); }
1235: else { /* subtract just free credits */
1236: user->freecdt-=amt;
1237: putuserrec(cfg, user->number,U_FREECDT,10
1238: ,ultoa(user->freecdt,tmp,10)); } }
1239: else /* no free credits */
1240: user->cdt=adjustuserrec(cfg, user->number,U_CDT,10,-amt);
1241: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.