|
|
1.1 root 1: /* userdat.c */
2:
3: /* Synchronet user data-related routines (exported) */
4:
1.1.1.2 ! root 5: /* $Id: userdat.c,v 1.89 2004/12/29 04:38:14 rswindell Exp $ */
1.1 root 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: * *
1.1.1.2 ! root 11: * Copyright 2003 Rob Swindell - http://www.synchro.net/copyright.html *
1.1 root 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"
1.1.1.2 ! root 40: #ifndef USHRT_MAX
! 41: #define USHRT_MAX ((unsigned short)~0)
! 42: #endif
1.1 root 43:
44: /* convenient space-saving global variables */
45: char* crlf="\r\n";
46: char* nulstr="";
47:
1.1.1.2 ! root 48: #define VALID_CFG(cfg) (cfg!=NULL && cfg->size==sizeof(scfg_t))
! 49:
1.1 root 50: /****************************************************************************/
51: /* Looks for a perfect match amoung all usernames (not deleted users) */
52: /* Makes dots and underscores synomynous with spaces for comparisions */
53: /* Returns the number of the perfect matched username or 0 if no match */
54: /****************************************************************************/
1.1.1.2 ! root 55: uint DLLCALL matchuser(scfg_t* cfg, char *name, BOOL sysop_alias)
1.1 root 56: {
1.1.1.2 ! root 57: int file,c;
! 58: char* p;
! 59: char dat[LEN_ALIAS+2];
! 60: char str[256];
! 61: ulong l,length;
! 62: FILE* stream;
! 63:
! 64: if(!VALID_CFG(cfg) || name==NULL)
! 65: return(0);
! 66:
! 67: if(sysop_alias &&
! 68: (!stricmp(name,"SYSOP") || !stricmp(name,"POSTMASTER") || !stricmp(name,cfg->sys_id)))
! 69: return(1);
1.1 root 70:
71: sprintf(str,"%suser/name.dat",cfg->data_dir);
72: if((file=nopen(str,O_RDONLY))==-1)
73: return(0);
74: length=filelength(file);
75: if((stream=fdopen(file,"rb"))==NULL)
76: return(0);
77: for(l=0;l<length;l+=LEN_ALIAS+2) {
1.1.1.2 ! root 78: fread(dat,sizeof(dat),1,stream);
1.1 root 79: for(c=0;c<LEN_ALIAS;c++)
1.1.1.2 ! root 80: if(dat[c]==ETX) break;
! 81: dat[c]=0;
! 82: if(!stricmp(dat,name))
1.1 root 83: break;
84: /* convert dots to spaces */
1.1.1.2 ! root 85: strcpy(str,dat);
! 86: REPLACE_CHARS(str,'.',' ',p);
1.1 root 87: if(!stricmp(str,name))
88: break;
89: /* convert spaces to dots */
1.1.1.2 ! root 90: strcpy(str,dat);
! 91: REPLACE_CHARS(str,' ','.',p);
1.1 root 92: if(!stricmp(str,name))
93: break;
94: /* convert dots to underscores */
1.1.1.2 ! root 95: strcpy(str,dat);
! 96: REPLACE_CHARS(str,'.','_',p);
! 97: if(!stricmp(str,name))
! 98: break;
! 99: /* convert underscores to dots */
! 100: strcpy(str,dat);
! 101: REPLACE_CHARS(str,'_','.',p);
! 102: if(!stricmp(str,name))
! 103: break;
! 104: /* convert spaces to underscores */
! 105: strcpy(str,dat);
! 106: REPLACE_CHARS(str,' ','_',p);
1.1 root 107: if(!stricmp(str,name))
108: break;
109: /* convert underscores to spaces */
1.1.1.2 ! root 110: strcpy(str,dat);
! 111: REPLACE_CHARS(str,'_',' ',p);
1.1 root 112: if(!stricmp(str,name))
113: break;
114: }
115: fclose(stream);
116: if(l<length)
117: return((l/(LEN_ALIAS+2))+1);
118: return(0);
119: }
120:
121: /****************************************************************************/
1.1.1.2 ! root 122: uint DLLCALL total_users(scfg_t* cfg)
! 123: {
! 124: char str[MAX_PATH+1];
! 125: uint total_users=0;
! 126: int file;
! 127: long l,length;
! 128:
! 129: if(!VALID_CFG(cfg))
! 130: return(0);
! 131:
! 132: sprintf(str,"%suser/user.dat", cfg->data_dir);
! 133: if((file=nopen(str,O_RDONLY|O_DENYNONE))==-1)
! 134: return(0);
! 135: length=filelength(file);
! 136: for(l=0;l<length;l+=U_LEN) {
! 137: lseek(file,l+U_MISC,SEEK_SET);
! 138: if(read(file,str,8)!=8)
! 139: continue;
! 140: getrec(str,0,8,str);
! 141: if(ahtoul(str)&(DELETED|INACTIVE))
! 142: continue;
! 143: total_users++;
! 144: }
! 145: close(file);
! 146: return(total_users);
! 147: }
! 148:
! 149:
! 150: /****************************************************************************/
1.1 root 151: /* Returns the number of the last user in user.dat (deleted ones too) */
152: /****************************************************************************/
153: uint DLLCALL lastuser(scfg_t* cfg)
154: {
155: char str[256];
156: long length;
157:
1.1.1.2 ! root 158: if(!VALID_CFG(cfg))
! 159: return(0);
! 160:
1.1 root 161: sprintf(str,"%suser/user.dat", cfg->data_dir);
162: if((length=flength(str))>0)
163: return((uint)(length/U_LEN));
164: return(0);
165: }
166:
167: /****************************************************************************/
1.1.1.2 ! root 168: /* Deletes last user record in user.dat */
! 169: /****************************************************************************/
! 170: BOOL DLLCALL del_lastuser(scfg_t* cfg)
! 171: {
! 172: char str[256];
! 173: int file;
! 174: long length;
! 175:
! 176: if(!VALID_CFG(cfg))
! 177: return(FALSE);
! 178:
! 179: sprintf(str,"%suser/user.dat", cfg->data_dir);
! 180: if((file=nopen(str,O_RDWR|O_DENYNONE))==-1)
! 181: return(FALSE);
! 182: length=filelength(file);
! 183: if(length<U_LEN) {
! 184: close(file);
! 185: return(FALSE);
! 186: }
! 187: chsize(file,length-U_LEN);
! 188: close(file);
! 189: return(TRUE);
! 190: }
! 191:
! 192:
! 193: /****************************************************************************/
1.1 root 194: /* Fills the structure 'user' with info for user.number from user.dat */
195: /* Called from functions useredit, waitforcall and main_sec */
196: /****************************************************************************/
197: int DLLCALL getuserdat(scfg_t* cfg, user_t *user)
198: {
199: char userdat[U_LEN+1],str[U_LEN+1],tmp[64];
200: int i,file;
201:
1.1.1.2 ! root 202: if(user==NULL)
! 203: return(-1);
! 204:
! 205: if(!VALID_CFG(cfg) || user->number<1) {
1.1 root 206: memset(user,0,sizeof(user_t));
207: return(-1);
208: }
209: sprintf(userdat,"%suser/user.dat",cfg->data_dir);
210: if((file=nopen(userdat,O_RDONLY|O_DENYNONE))==-1) {
211: memset(user,0,sizeof(user_t));
212: return(errno);
213: }
1.1.1.2 ! root 214: if(user->number > (filelength(file)/U_LEN)) {
! 215: close(file);
! 216: return(-1); /* no such user record */
! 217: }
1.1 root 218: lseek(file,(long)((long)(user->number-1)*U_LEN),SEEK_SET);
219: i=0;
220: while(i<LOOP_NODEDAB
221: && lock(file,(long)((long)(user->number-1)*U_LEN),U_LEN)==-1) {
1.1.1.2 ! root 222: if(i)
! 223: mswait(100);
1.1 root 224: i++;
225: }
226:
227: if(i>=LOOP_NODEDAB) {
228: close(file);
229: memset(user,0L,sizeof(user_t));
230: return(-2);
231: }
232:
233: if(read(file,userdat,U_LEN)!=U_LEN) {
234: unlock(file,(long)((long)(user->number-1)*U_LEN),U_LEN);
235: close(file);
236: memset(user,0L,sizeof(user_t));
237: return(-3);
238: }
239:
240: unlock(file,(long)((long)(user->number-1)*U_LEN),U_LEN);
241: close(file);
1.1.1.2 ! root 242: /* order of these function calls is irrelevant */
1.1 root 243: getrec(userdat,U_ALIAS,LEN_ALIAS,user->alias);
244: getrec(userdat,U_NAME,LEN_NAME,user->name);
245: getrec(userdat,U_HANDLE,LEN_HANDLE,user->handle);
246: getrec(userdat,U_NOTE,LEN_NOTE,user->note);
247: getrec(userdat,U_COMP,LEN_COMP,user->comp);
248: getrec(userdat,U_COMMENT,LEN_COMMENT,user->comment);
249: getrec(userdat,U_NETMAIL,LEN_NETMAIL,user->netmail);
250: getrec(userdat,U_ADDRESS,LEN_ADDRESS,user->address);
251: getrec(userdat,U_LOCATION,LEN_LOCATION,user->location);
252: getrec(userdat,U_ZIPCODE,LEN_ZIPCODE,user->zipcode);
253: getrec(userdat,U_PASS,LEN_PASS,user->pass);
254: getrec(userdat,U_PHONE,LEN_PHONE,user->phone);
255: getrec(userdat,U_BIRTH,LEN_BIRTH,user->birth);
256: getrec(userdat,U_MODEM,LEN_MODEM,user->modem);
257: getrec(userdat,U_LASTON,8,str); user->laston=ahtoul(str);
258: getrec(userdat,U_FIRSTON,8,str); user->firston=ahtoul(str);
259: getrec(userdat,U_EXPIRE,8,str); user->expire=ahtoul(str);
260: getrec(userdat,U_PWMOD,8,str); user->pwmod=ahtoul(str);
261: getrec(userdat,U_NS_TIME,8,str);
262: user->ns_time=ahtoul(str);
263: if(user->ns_time<0x20000000L)
264: user->ns_time=user->laston; /* Fix for v2.00->v2.10 */
1.1.1.2 ! root 265: getrec(userdat,U_LOGONTIME,8,str); user->logontime=ahtoul(str);
1.1 root 266:
267: getrec(userdat,U_LOGONS,5,str); user->logons=atoi(str);
268: getrec(userdat,U_LTODAY,5,str); user->ltoday=atoi(str);
269: getrec(userdat,U_TIMEON,5,str); user->timeon=atoi(str);
270: getrec(userdat,U_TEXTRA,5,str); user->textra=atoi(str);
271: getrec(userdat,U_TTODAY,5,str); user->ttoday=atoi(str);
272: getrec(userdat,U_TLAST,5,str); user->tlast=atoi(str);
273: getrec(userdat,U_POSTS,5,str); user->posts=atoi(str);
274: getrec(userdat,U_EMAILS,5,str); user->emails=atoi(str);
275: getrec(userdat,U_FBACKS,5,str); user->fbacks=atoi(str);
276: getrec(userdat,U_ETODAY,5,str); user->etoday=atoi(str);
277: getrec(userdat,U_PTODAY,5,str); user->ptoday=atoi(str);
278: getrec(userdat,U_ULB,10,str); user->ulb=atol(str);
279: getrec(userdat,U_ULS,5,str); user->uls=atoi(str);
280: getrec(userdat,U_DLB,10,str); user->dlb=atol(str);
281: getrec(userdat,U_DLS,5,str); user->dls=atoi(str);
282: getrec(userdat,U_CDT,10,str); user->cdt=atol(str);
283: getrec(userdat,U_MIN,10,str); user->min=atol(str);
284: getrec(userdat,U_LEVEL,2,str); user->level=atoi(str);
1.1.1.2 ! root 285: getrec(userdat,U_FLAGS1,8,str); user->flags1=ahtoul(str);
1.1 root 286: getrec(userdat,U_FLAGS2,8,str); user->flags2=ahtoul(str);
287: getrec(userdat,U_FLAGS3,8,str); user->flags3=ahtoul(str);
288: getrec(userdat,U_FLAGS4,8,str); user->flags4=ahtoul(str);
289: getrec(userdat,U_EXEMPT,8,str); user->exempt=ahtoul(str);
290: getrec(userdat,U_REST,8,str); user->rest=ahtoul(str);
291: getrec(userdat,U_ROWS,2,str); user->rows=atoi(str);
292: if(user->rows && user->rows<10)
293: user->rows=10;
294: user->sex=userdat[U_SEX];
295: if(!user->sex)
1.1.1.2 ! root 296: user->sex=' '; /* fix for v1b04 that could save as 0 */
1.1 root 297: user->prot=userdat[U_PROT];
1.1.1.2 ! root 298: if(user->prot<' ')
! 299: user->prot=' ';
1.1 root 300: getrec(userdat,U_MISC,8,str); user->misc=ahtoul(str);
301: if(user->rest&FLAG('Q'))
302: user->misc&=~SPIN;
303:
304: getrec(userdat,U_LEECH,2,str);
305: user->leech=(uchar)ahtoul(str);
1.1.1.2 ! root 306: getrec(userdat,U_CURSUB,sizeof(user->cursub)-1,user->cursub);
! 307: getrec(userdat,U_CURDIR,sizeof(user->curdir)-1,user->curdir);
! 308: getrec(userdat,U_CURXTRN,8,user->curxtrn);
1.1 root 309:
310: getrec(userdat,U_FREECDT,10,str);
311: user->freecdt=atol(str);
312:
313: getrec(userdat,U_XEDIT,8,str);
314: for(i=0;i<cfg->total_xedits;i++)
1.1.1.2 ! root 315: if(!stricmp(str,cfg->xedit[i]->code) && chk_ar(cfg,cfg->xedit[i]->ar,user))
1.1 root 316: break;
317: user->xedit=i+1;
318: if(user->xedit>cfg->total_xedits)
319: user->xedit=0;
320:
321: getrec(userdat,U_SHELL,8,str);
322: for(i=0;i<cfg->total_shells;i++)
323: if(!stricmp(str,cfg->shell[i]->code))
324: break;
325: if(i==cfg->total_shells)
326: i=0;
327: user->shell=i;
328:
329: getrec(userdat,U_QWK,8,str);
1.1.1.2 ! root 330: if(str[0]<' ') { /* v1c, so set defaults */
1.1 root 331: if(user->rest&FLAG('Q'))
1.1.1.2 ! root 332: user->qwk=QWK_DEFAULT|QWK_RETCTLA;
1.1 root 333: else
1.1.1.2 ! root 334: user->qwk=QWK_DEFAULT;
! 335: }
1.1 root 336: else
337: user->qwk=ahtoul(str);
338:
339: getrec(userdat,U_TMPEXT,3,user->tmpext);
340: if((!user->tmpext[0] || !strcmp(user->tmpext,"0")) && cfg->total_fcomps)
341: strcpy(user->tmpext,cfg->fcomp[0]->ext); /* For v1x to v2x conversion */
342:
343: getrec(userdat,U_CHAT,8,str);
344: user->chat=ahtoul(str);
345:
1.1.1.2 ! root 346: /* Reset daily stats if not logged on today */
1.1 root 347: unixtodstr(cfg, time(NULL),str);
348: unixtodstr(cfg, user->laston,tmp);
1.1.1.2 ! root 349: if(strcmp(str,tmp) && user->ltoday)
! 350: resetdailyuserdat(cfg,user);
1.1 root 351:
352: #if 0 // removed 01/19/00
353: if(useron.number==user->number) {
354: if(user!=&useron)
355: useron=*user;
356:
357: if(online) {
358:
359: #if 0 /* legacy? */
360: getusrdirs();
361: getusrsubs();
362: #endif
363: if(user->misc&AUTOTERM) { // was useron.misc (01/19/00)
1.1.1.2 ! root 364: user->misc&=~(ANSI|RIP|WIP|HTML);
! 365: user->misc|=autoterm;
! 366: }
! 367: }
! 368: }
1.1 root 369: #endif
370: return(0);
371: }
372:
373: /****************************************************************************/
374: /* Writes into user.number's slot in user.dat data in structure 'user' */
375: /* Called from functions newuser, useredit and main */
376: /****************************************************************************/
377: int DLLCALL putuserdat(scfg_t* cfg, user_t* user)
378: {
1.1.1.2 ! root 379: int i,file;
! 380: char userdat[U_LEN],str[MAX_PATH+1];
! 381: node_t node;
! 382:
! 383: if(user==NULL)
! 384: return(-1);
1.1 root 385:
1.1.1.2 ! root 386: if(!VALID_CFG(cfg) || user->number<1)
1.1 root 387: return(-1);
388:
389: memset(userdat,ETX,U_LEN);
390: putrec(userdat,U_ALIAS,LEN_ALIAS+5,user->alias);
391: putrec(userdat,U_NAME,LEN_NAME,user->name);
392: putrec(userdat,U_HANDLE,LEN_HANDLE,user->handle);
393: putrec(userdat,U_HANDLE+LEN_HANDLE,2,crlf);
394:
395: putrec(userdat,U_NOTE,LEN_NOTE,user->note);
396: putrec(userdat,U_COMP,LEN_COMP,user->comp);
397: putrec(userdat,U_COMP+LEN_COMP,2,crlf);
398:
399: putrec(userdat,U_COMMENT,LEN_COMMENT,user->comment);
400: putrec(userdat,U_COMMENT+LEN_COMMENT,2,crlf);
401:
402: putrec(userdat,U_NETMAIL,LEN_NETMAIL,user->netmail);
403: putrec(userdat,U_NETMAIL+LEN_NETMAIL,2,crlf);
404:
405: putrec(userdat,U_ADDRESS,LEN_ADDRESS,user->address);
406: putrec(userdat,U_LOCATION,LEN_LOCATION,user->location);
407: putrec(userdat,U_ZIPCODE,LEN_ZIPCODE,user->zipcode);
408: putrec(userdat,U_ZIPCODE+LEN_ZIPCODE,2,crlf);
409:
410: putrec(userdat,U_PASS,LEN_PASS,user->pass);
411: putrec(userdat,U_PHONE,LEN_PHONE,user->phone);
412: putrec(userdat,U_BIRTH,LEN_BIRTH,user->birth);
413: putrec(userdat,U_MODEM,LEN_MODEM,user->modem);
414: putrec(userdat,U_LASTON,8,ultoa(user->laston,str,16));
415: putrec(userdat,U_FIRSTON,8,ultoa(user->firston,str,16));
416: putrec(userdat,U_EXPIRE,8,ultoa(user->expire,str,16));
417: putrec(userdat,U_PWMOD,8,ultoa(user->pwmod,str,16));
418: putrec(userdat,U_PWMOD+8,2,crlf);
419:
420: putrec(userdat,U_LOGONS,5,ultoa(user->logons,str,10));
421: putrec(userdat,U_LTODAY,5,ultoa(user->ltoday,str,10));
422: putrec(userdat,U_TIMEON,5,ultoa(user->timeon,str,10));
423: putrec(userdat,U_TEXTRA,5,ultoa(user->textra,str,10));
424: putrec(userdat,U_TTODAY,5,ultoa(user->ttoday,str,10));
425: putrec(userdat,U_TLAST,5,ultoa(user->tlast,str,10));
426: putrec(userdat,U_POSTS,5,ultoa(user->posts,str,10));
427: putrec(userdat,U_EMAILS,5,ultoa(user->emails,str,10));
428: putrec(userdat,U_FBACKS,5,ultoa(user->fbacks,str,10));
429: putrec(userdat,U_ETODAY,5,ultoa(user->etoday,str,10));
430: putrec(userdat,U_PTODAY,5,ultoa(user->ptoday,str,10));
431: putrec(userdat,U_PTODAY+5,2,crlf);
432:
433: putrec(userdat,U_ULB,10,ultoa(user->ulb,str,10));
434: putrec(userdat,U_ULS,5,ultoa(user->uls,str,10));
435: putrec(userdat,U_DLB,10,ultoa(user->dlb,str,10));
436: putrec(userdat,U_DLS,5,ultoa(user->dls,str,10));
437: putrec(userdat,U_CDT,10,ultoa(user->cdt,str,10));
438: putrec(userdat,U_MIN,10,ultoa(user->min,str,10));
439: putrec(userdat,U_MIN+10,2,crlf);
440:
441: putrec(userdat,U_LEVEL,2,ultoa(user->level,str,10));
442: putrec(userdat,U_FLAGS1,8,ultoa(user->flags1,str,16));
443: putrec(userdat,U_TL,2,nulstr); /* unused */
444: putrec(userdat,U_FLAGS2,8,ultoa(user->flags2,str,16));
445: putrec(userdat,U_EXEMPT,8,ultoa(user->exempt,str,16));
446: putrec(userdat,U_REST,8,ultoa(user->rest,str,16));
447: putrec(userdat,U_REST+8,2,crlf);
448:
449: putrec(userdat,U_ROWS,2,ultoa(user->rows,str,10));
450: userdat[U_SEX]=user->sex;
451: userdat[U_PROT]=user->prot;
452: putrec(userdat,U_MISC,8,ultoa(user->misc,str,16));
453: putrec(userdat,U_LEECH,2,ultoa(user->leech,str,16));
454:
1.1.1.2 ! root 455: putrec(userdat,U_CURSUB,sizeof(user->cursub)-1,user->cursub);
! 456: putrec(userdat,U_CURDIR,sizeof(user->curdir)-1,user->curdir);
! 457: putrec(userdat,U_CURXTRN,8,user->curxtrn);
! 458: putrec(userdat,U_CURXTRN+8,2,crlf);
1.1 root 459:
460: putrec(userdat,U_XFER_CMD+LEN_XFER_CMD,2,crlf);
461:
462: putrec(userdat,U_MAIL_CMD+LEN_MAIL_CMD,2,crlf);
463:
464: putrec(userdat,U_FREECDT,10,ultoa(user->freecdt,str,10));
465:
466: putrec(userdat,U_FLAGS3,8,ultoa(user->flags3,str,16));
467: putrec(userdat,U_FLAGS4,8,ultoa(user->flags4,str,16));
468:
469: if(user->xedit)
470: putrec(userdat,U_XEDIT,8,cfg->xedit[user->xedit-1]->code);
471: else
472: putrec(userdat,U_XEDIT,8,nulstr);
473:
474: putrec(userdat,U_SHELL,8,cfg->shell[user->shell]->code);
475:
476: putrec(userdat,U_QWK,8,ultoa(user->qwk,str,16));
477: putrec(userdat,U_TMPEXT,3,user->tmpext);
478: putrec(userdat,U_CHAT,8,ultoa(user->chat,str,16));
479: putrec(userdat,U_NS_TIME,8,ultoa(user->ns_time,str,16));
1.1.1.2 ! root 480: putrec(userdat,U_LOGONTIME,8,ultoa(user->logontime,str,16));
1.1 root 481:
1.1.1.2 ! root 482: putrec(userdat,U_UNUSED,U_LEN-(U_UNUSED)-2,crlf);
! 483: putrec(userdat,U_UNUSED+(U_LEN-(U_UNUSED)-2),2,crlf);
1.1 root 484:
485: sprintf(str,"%suser/user.dat", cfg->data_dir);
1.1.1.2 ! root 486: if((file=nopen(str,O_RDWR|O_CREAT|O_DENYNONE))==-1) {
1.1 root 487: return(errno);
488: }
489:
1.1.1.2 ! root 490: if(filelength(file)<((long)user->number-1)*U_LEN) {
! 491: close(file);
! 492: return(-4);
! 493: }
! 494:
1.1 root 495: lseek(file,(long)((long)((long)user->number-1)*U_LEN),SEEK_SET);
496:
497: i=0;
498: while(i<LOOP_NODEDAB
499: && lock(file,(long)((long)(user->number-1)*U_LEN),U_LEN)==-1) {
1.1.1.2 ! root 500: if(i)
! 501: mswait(100);
1.1 root 502: i++;
503: }
504:
505: if(i>=LOOP_NODEDAB) {
506: close(file);
507: return(-2);
508: }
509:
510: if(write(file,userdat,U_LEN)!=U_LEN) {
511: unlock(file,(long)((long)(user->number-1)*U_LEN),U_LEN);
512: close(file);
513: return(-3);
514: }
515: unlock(file,(long)((long)(user->number-1)*U_LEN),U_LEN);
516: close(file);
517: for(i=1;i<=cfg->sys_nodes;i++) { /* instant user data update */
518: if(i==cfg->node_num)
519: continue;
1.1.1.2 ! root 520: getnodedat(cfg, i,&node,NULL);
1.1 root 521: if(node.useron==user->number && (node.status==NODE_INUSE
522: || node.status==NODE_QUIET)) {
1.1.1.2 ! root 523: getnodedat(cfg, i,&node,&file);
1.1 root 524: node.misc|=NODE_UDAT;
1.1.1.2 ! root 525: putnodedat(cfg, i,&node,file);
1.1 root 526: break;
527: }
528: }
529: return(0);
530: }
531:
532:
533: /****************************************************************************/
534: /* Returns the username in 'str' that corresponds to the 'usernumber' */
535: /* Called from functions everywhere */
536: /****************************************************************************/
1.1.1.2 ! root 537: char* DLLCALL username(scfg_t* cfg, int usernumber, char *name)
1.1 root 538: {
1.1.1.2 ! root 539: char str[256];
! 540: int c;
! 541: int file;
! 542:
! 543: if(name==NULL)
! 544: return(NULL);
1.1 root 545:
1.1.1.2 ! root 546: if(!VALID_CFG(cfg) || usernumber<1) {
! 547: name[0]=0;
! 548: return(name);
! 549: }
1.1 root 550: sprintf(str,"%suser/name.dat",cfg->data_dir);
551: if(flength(str)<1L) {
1.1.1.2 ! root 552: name[0]=0;
! 553: return(name);
! 554: }
1.1 root 555: if((file=nopen(str,O_RDONLY))==-1) {
1.1.1.2 ! root 556: name[0]=0;
! 557: return(name);
! 558: }
1.1 root 559: if(filelength(file)<(long)((long)usernumber*(LEN_ALIAS+2))) {
560: close(file);
1.1.1.2 ! root 561: name[0]=0;
! 562: return(name);
! 563: }
1.1 root 564: lseek(file,(long)((long)(usernumber-1)*(LEN_ALIAS+2)),SEEK_SET);
1.1.1.2 ! root 565: read(file,name,LEN_ALIAS);
1.1 root 566: close(file);
567: for(c=0;c<LEN_ALIAS;c++)
1.1.1.2 ! root 568: if(name[c]==ETX) break;
! 569: name[c]=0;
1.1 root 570: if(!c)
1.1.1.2 ! root 571: strcpy(name,"DELETED USER");
! 572: return(name);
1.1 root 573: }
574:
575: /****************************************************************************/
1.1.1.2 ! root 576: /* Puts 'name' into slot 'number' in user/name.dat */
1.1 root 577: /****************************************************************************/
1.1.1.2 ! root 578: int DLLCALL putusername(scfg_t* cfg, int number, char *name)
1.1 root 579: {
1.1.1.2 ! root 580: char str[256];
! 581: int file;
! 582: int wr;
! 583: long length;
! 584: uint total_users;
1.1 root 585:
1.1.1.2 ! root 586: if(!VALID_CFG(cfg) || name==NULL || number<1)
! 587: return(-1);
1.1 root 588:
1.1.1.2 ! root 589: sprintf(str,"%suser/name.dat", cfg->data_dir);
! 590: if((file=nopen(str,O_RDWR|O_CREAT))==-1)
! 591: return(errno);
! 592: length=filelength(file);
1.1 root 593:
1.1.1.2 ! root 594: /* Truncate corrupted name.dat */
! 595: total_users=lastuser(cfg);
! 596: if((uint)(length/(LEN_ALIAS+2))>total_users)
! 597: chsize(file,total_users*(LEN_ALIAS+2));
1.1 root 598:
1.1.1.2 ! root 599: if(length && length%(LEN_ALIAS+2)) {
! 600: close(file);
! 601: return(-3);
! 602: }
! 603: if(length<(((long)number-1)*(LEN_ALIAS+2))) {
! 604: sprintf(str,"%*s",LEN_ALIAS,nulstr);
! 605: memset(str,ETX,LEN_ALIAS);
! 606: strcat(str,crlf);
! 607: lseek(file,0L,SEEK_END);
! 608: while(filelength(file)<((long)number*(LEN_ALIAS+2)))
! 609: write(file,str,(LEN_ALIAS+2));
! 610: }
! 611: lseek(file,(long)(((long)number-1)*(LEN_ALIAS+2)),SEEK_SET);
! 612: putrec(str,0,LEN_ALIAS,name);
! 613: putrec(str,LEN_ALIAS,2,crlf);
! 614: wr=write(file,str,LEN_ALIAS+2);
! 615: close(file);
! 616:
! 617: if(wr!=LEN_ALIAS+2)
! 618: return(errno);
! 619: return(0);
! 620: }
1.1 root 621:
622: /****************************************************************************/
623: /* Returns the age derived from the string 'birth' in the format MM/DD/YY */
624: /****************************************************************************/
625: char DLLCALL getage(scfg_t* cfg, char *birth)
626: {
627: char age;
1.1.1.2 ! root 628: struct tm tm;
1.1 root 629: time_t now;
630:
1.1.1.2 ! root 631: if(!VALID_CFG(cfg) || birth==NULL)
! 632: return(0);
! 633:
1.1 root 634: if(!atoi(birth) || !atoi(birth+3)) /* Invalid */
635: return(0);
636:
637: now=time(NULL);
1.1.1.2 ! root 638: if(localtime_r(&now,&tm)==NULL)
1.1 root 639: return(0);
1.1.1.2 ! root 640: age=(tm.tm_year)-(((birth[6]&0xf)*10)+(birth[7]&0xf));
1.1 root 641: if(age>105)
642: age-=105;
1.1.1.2 ! root 643: tm.tm_mon++; /* convert to 1 based */
1.1 root 644: if(cfg->sys_misc&SM_EURODATE) { /* DD/MM/YY format */
645: if(atoi(birth)>31 || atoi(birth+3)>12)
646: return(0);
1.1.1.2 ! root 647: if(((birth[3]&0xf)*10)+(birth[4]&0xf)>tm.tm_mon ||
! 648: (((birth[3]&0xf)*10)+(birth[4]&0xf)==tm.tm_mon &&
! 649: ((birth[0]&0xf)*10)+(birth[1]&0xf)>tm.tm_mday))
! 650: age--;
! 651: } else { /* MM/DD/YY format */
1.1 root 652: if(atoi(birth)>12 || atoi(birth+3)>31)
653: return(0);
1.1.1.2 ! root 654: if(((birth[0]&0xf)*10)+(birth[1]&0xf)>tm.tm_mon ||
! 655: (((birth[0]&0xf)*10)+(birth[1]&0xf)==tm.tm_mon &&
! 656: ((birth[3]&0xf)*10)+(birth[4]&0xf)>tm.tm_mday))
! 657: age--;
! 658: }
1.1 root 659: if(age<0)
660: return(0);
661: return(age);
662: }
663:
664:
665: /****************************************************************************/
666: /* Reads the data for node number 'number' into the structure 'node' */
667: /* from node.dab */
668: /****************************************************************************/
1.1.1.2 ! root 669: int DLLCALL getnodedat(scfg_t* cfg, uint number, node_t *node, int* fdp)
1.1 root 670: {
1.1.1.2 ! root 671: char str[MAX_PATH+1];
! 672: int rd;
! 673: int count=0;
! 674: int file;
! 675:
! 676: if(fdp!=NULL)
! 677: *fdp=-1;
1.1 root 678:
1.1.1.2 ! root 679: if(!VALID_CFG(cfg)
! 680: || node==NULL || number<1 || number>cfg->sys_nodes)
1.1 root 681: return(-1);
682:
1.1.1.2 ! root 683: memset(node,0,sizeof(node_t));
1.1 root 684: sprintf(str,"%snode.dab",cfg->ctrl_dir);
1.1.1.2 ! root 685: if((file=nopen(str,O_RDWR|O_DENYNONE))==-1)
1.1 root 686: return(errno);
1.1.1.2 ! root 687:
! 688: if(filelength(file)>=(long)(number*sizeof(node_t))) {
! 689: number--; /* make zero based */
! 690: for(count=0;count<LOOP_NODEDAB;count++) {
! 691: if(count)
! 692: mswait(100);
! 693: lseek(file,(long)number*sizeof(node_t),SEEK_SET);
! 694: if(fdp!=NULL
! 695: && lock(file,(long)number*sizeof(node_t),sizeof(node_t))!=0)
! 696: continue;
! 697: rd=read(file,node,sizeof(node_t));
! 698: if(fdp==NULL || rd!=sizeof(node_t))
! 699: unlock(file,(long)number*sizeof(node_t),sizeof(node_t));
! 700: if(rd==sizeof(node_t))
! 701: break;
! 702: }
1.1 root 703: }
704:
1.1.1.2 ! root 705: if(fdp==NULL || count==LOOP_NODEDAB)
! 706: close(file);
! 707: else
! 708: *fdp=file;
1.1 root 709:
710: if(count==LOOP_NODEDAB)
711: return(-2);
712:
713: return(0);
714: }
715:
716: /****************************************************************************/
717: /* Write the data from the structure 'node' into node.dab */
718: /****************************************************************************/
1.1.1.2 ! root 719: int DLLCALL putnodedat(scfg_t* cfg, uint number, node_t* node, int file)
1.1 root 720: {
1.1.1.2 ! root 721: size_t wr=0;
! 722: int wrerr=0;
! 723: int attempts;
1.1 root 724:
1.1.1.2 ! root 725: if(!VALID_CFG(cfg)
! 726: || node==NULL || number<1 || number>cfg->sys_nodes || file<0) {
! 727: close(file);
1.1 root 728: return(-1);
729: }
730:
731: number--; /* make zero based */
1.1.1.2 ! root 732: for(attempts=0;attempts<10;attempts++) {
! 733: lseek(file,(long)number*sizeof(node_t),SEEK_SET);
! 734: if((wr=write(file,node,sizeof(node_t)))==sizeof(node_t))
! 735: break;
! 736: wrerr=errno; /* save write error */
! 737: mswait(100);
1.1 root 738: }
739: unlock(file,(long)number*sizeof(node_t),sizeof(node_t));
740: close(file);
741:
1.1.1.2 ! root 742: if(wr!=sizeof(node_t))
! 743: return(wrerr);
1.1 root 744: return(0);
745: }
746:
747: /****************************************************************************/
1.1.1.2 ! root 748: /* Packs the password 'pass' into 5bit ASCII inside node_t. 32bits in */
! 749: /* node.extaux, and the other 8bits in the upper byte of node.aux */
! 750: /****************************************************************************/
! 751: void DLLCALL packchatpass(char *pass, node_t *node)
1.1 root 752: {
1.1.1.2 ! root 753: char bits;
! 754: int i,j;
! 755:
! 756: if(pass==NULL || node==NULL)
! 757: return;
! 758:
! 759: node->aux&=~0xff00; /* clear the password */
! 760: node->extaux=0L;
! 761: if((j=strlen(pass))==0) /* there isn't a password */
! 762: return;
! 763: node->aux|=(int)((pass[0]-64)<<8); /* 1st char goes in low 5bits of aux */
! 764: if(j==1) /* password is only one char, we're done */
! 765: return;
! 766: node->aux|=(int)((pass[1]-64)<<13); /* low 3bits of 2nd char go in aux */
! 767: node->extaux|=(long)((pass[1]-64)>>3); /* high 2bits of 2nd char go extaux */
! 768: bits=2;
! 769: for(i=2;i<j;i++) { /* now process the 3rd char through the last */
! 770: node->extaux|=(long)((long)(pass[i]-64)<<bits);
! 771: bits+=5;
! 772: }
! 773: }
! 774:
! 775: /****************************************************************************/
! 776: /* Unpacks the password 'pass' from the 5bit ASCII inside node_t. 32bits in */
! 777: /* node.extaux, and the other 8bits in the upper byte of node.aux */
! 778: /****************************************************************************/
! 779: char* DLLCALL unpackchatpass(char *pass, node_t* node)
! 780: {
! 781: char bits;
! 782: int i;
! 783:
! 784: if(pass==NULL || node==NULL)
! 785: return(NULL);
! 786:
! 787: pass[0]=(node->aux&0x1f00)>>8;
! 788: pass[1]=(char)(((node->aux&0xe000)>>13)|((node->extaux&0x3)<<3));
! 789: bits=2;
! 790: for(i=2;i<8;i++) {
! 791: pass[i]=(char)((node->extaux>>bits)&0x1f);
! 792: bits+=5;
! 793: }
! 794: pass[8]=0;
! 795: for(i=0;i<8;i++)
! 796: if(pass[i])
! 797: pass[i]+=64;
! 798: return(pass);
! 799: }
! 800:
! 801: char* DLLCALL nodestatus(scfg_t* cfg, node_t* node, char* buf, size_t buflen)
! 802: {
! 803: char str[256];
! 804: char* mer;
! 805: int hour;
! 806:
! 807: if(node==NULL) {
! 808: strncpy(buf,"(null)",buflen);
! 809: return(buf);
! 810: }
! 811:
! 812: switch(node->status) {
! 813: case NODE_WFC:
! 814: strcpy(str,"Waiting for call");
! 815: break;
! 816: case NODE_OFFLINE:
! 817: strcpy(str,"Offline");
! 818: break;
! 819: case NODE_NETTING:
! 820: strcpy(str,"Networking");
! 821: break;
! 822: case NODE_LOGON:
! 823: strcpy(str,"At logon prompt");
! 824: break;
! 825: case NODE_EVENT_WAITING:
! 826: strcpy(str,"Waiting for all nodes to become inactive");
! 827: break;
! 828: case NODE_EVENT_LIMBO:
! 829: sprintf(str,"Waiting for node %d to finish external event"
! 830: ,node->aux);
! 831: break;
! 832: case NODE_EVENT_RUNNING:
! 833: strcpy(str,"Running external event");
! 834: break;
! 835: case NODE_NEWUSER:
! 836: strcpy(str,"New user applying for access ");
! 837: if(!node->connection)
! 838: strcat(str,"Locally");
! 839: else if(node->connection==0xffff) {
! 840: strcat(str,"via telnet");
! 841: } else
! 842: sprintf(str+strlen(str),"at %ubps",node->connection);
! 843: break;
! 844: case NODE_QUIET:
! 845: case NODE_INUSE:
! 846: username(cfg,node->useron,str);
! 847: strcat(str," ");
! 848: switch(node->action) {
! 849: case NODE_MAIN:
! 850: strcat(str,"at main menu");
! 851: break;
! 852: case NODE_RMSG:
! 853: strcat(str,"reading messages");
! 854: break;
! 855: case NODE_RMAL:
! 856: strcat(str,"reading mail");
! 857: break;
! 858: case NODE_RSML:
! 859: strcat(str,"reading sent mail");
! 860: break;
! 861: case NODE_RTXT:
! 862: strcat(str,"reading text files");
! 863: break;
! 864: case NODE_PMSG:
! 865: strcat(str,"posting message");
! 866: break;
! 867: case NODE_SMAL:
! 868: strcat(str,"sending mail");
! 869: break;
! 870: case NODE_AMSG:
! 871: strcat(str,"posting auto-message");
! 872: break;
! 873: case NODE_XTRN:
! 874: if(!node->aux)
! 875: strcat(str,"at external program menu");
! 876: else if(node->aux<=cfg->total_xtrns)
! 877: sprintf(str+strlen(str),"running %s"
! 878: ,cfg->xtrn[node->aux-1]->name);
! 879: else
! 880: sprintf(str+strlen(str),"running external program #%d"
! 881: ,node->aux);
! 882: break;
! 883: case NODE_DFLT:
! 884: strcat(str,"changing defaults");
! 885: break;
! 886: case NODE_XFER:
! 887: strcat(str,"at transfer menu");
! 888: break;
! 889: case NODE_RFSD:
! 890: sprintf(str+strlen(str),"retrieving from device #%d",node->aux);
! 891: break;
! 892: case NODE_DLNG:
! 893: strcat(str,"downloading");
! 894: break;
! 895: case NODE_ULNG:
! 896: strcat(str,"uploading");
! 897: break;
! 898: case NODE_BXFR:
! 899: strcat(str,"transferring bidirectional");
! 900: break;
! 901: case NODE_LFIL:
! 902: strcat(str,"listing files");
! 903: break;
! 904: case NODE_LOGN:
! 905: strcat(str,"logging on");
! 906: break;
! 907: case NODE_LCHT:
! 908: strcat(str,"in local chat with sysop");
! 909: break;
! 910: case NODE_MCHT:
! 911: if(node->aux) {
! 912: sprintf(str+strlen(str),"in multinode chat channel %d"
! 913: ,node->aux&0xff);
! 914: if(node->aux&0x1f00) { /* password */
! 915: strcat(str,"* ");
! 916: unpackchatpass(str+strlen(str),node);
! 917: }
! 918: }
! 919: else
! 920: strcat(str,"in multinode global chat channel");
! 921: break;
! 922: case NODE_PAGE:
! 923: sprintf(str+strlen(str)
! 924: ,"paging node %u for private chat",node->aux);
! 925: break;
! 926: case NODE_PCHT:
! 927: if(!node->aux)
! 928: strcat(str,"in local chat with sysop");
! 929: else
! 930: sprintf(str+strlen(str)
! 931: ,"in private chat with node %u"
! 932: ,node->aux);
! 933: break;
! 934: case NODE_GCHT:
! 935: strcat(str,"chatting with The Guru");
! 936: break;
! 937: case NODE_CHAT:
! 938: strcat(str,"in chat section");
! 939: break;
! 940: case NODE_TQWK:
! 941: strcat(str,"transferring QWK packet");
! 942: break;
! 943: case NODE_SYSP:
! 944: strcat(str,"performing sysop activities");
! 945: break;
! 946: default:
! 947: sprintf(str+strlen(str),"%d",node->action);
! 948: break;
! 949: }
! 950: if(!node->connection)
! 951: strcat(str," locally");
! 952: if(node->connection==0xffff) {
! 953: strcat(str," via telnet");
! 954: } else
! 955: sprintf(str+strlen(str)," at %ubps",node->connection);
! 956: if(node->action==NODE_DLNG) {
! 957: if((node->aux/60)>=12) {
! 958: if(node->aux/60==12)
! 959: hour=12;
! 960: else
! 961: hour=(node->aux/60)-12;
! 962: mer="pm";
! 963: } else {
! 964: if((node->aux/60)==0) /* 12 midnite */
! 965: hour=12;
! 966: else hour=node->aux/60;
! 967: mer="am";
! 968: }
! 969: sprintf(str+strlen(str), " ETA %02d:%02d %s"
! 970: ,hour,node->aux-((node->aux/60)*60),mer);
! 971: }
! 972: break;
! 973: }
! 974: if(node->misc&(NODE_LOCK|NODE_POFF|NODE_AOFF|NODE_MSGW|NODE_NMSG)) {
! 975: strcat(str," (");
! 976: if(node->misc&NODE_AOFF)
! 977: strcat(str,"A");
! 978: if(node->misc&NODE_LOCK)
! 979: strcat(str,"L");
! 980: if(node->misc&(NODE_MSGW|NODE_NMSG))
! 981: strcat(str,"M");
! 982: if(node->misc&NODE_POFF)
! 983: strcat(str,"P");
! 984: strcat(str,")");
! 985: }
! 986: if(((node->misc
! 987: &(NODE_ANON|NODE_UDAT|NODE_INTR|NODE_RRUN|NODE_EVENT|NODE_DOWN))
! 988: || node->status==NODE_QUIET)) {
! 989: strcat(str," [");
! 990: if(node->misc&NODE_ANON)
! 991: strcat(str,"A");
! 992: if(node->misc&NODE_INTR)
! 993: strcat(str,"I");
! 994: if(node->misc&NODE_RRUN)
! 995: strcat(str,"R");
! 996: if(node->misc&NODE_UDAT)
! 997: strcat(str,"U");
! 998: if(node->status==NODE_QUIET)
! 999: strcat(str,"Q");
! 1000: if(node->misc&NODE_EVENT)
! 1001: strcat(str,"E");
! 1002: if(node->misc&NODE_DOWN)
! 1003: strcat(str,"D");
! 1004: if(node->misc&NODE_LCHAT)
! 1005: strcat(str,"C");
! 1006: strcat(str,"]");
! 1007: }
! 1008: if(node->errors)
! 1009: sprintf(str+strlen(str)
! 1010: ," %d error%c",node->errors, node->errors>1 ? 's' : '\0' );
! 1011:
! 1012: strncpy(buf,str,buflen);
! 1013:
! 1014: return(buf);
! 1015: }
! 1016:
! 1017: /****************************************************************************/
! 1018: /* Displays the information for node number 'number' contained in 'node' */
! 1019: /****************************************************************************/
! 1020: void DLLCALL printnodedat(scfg_t* cfg, uint number, node_t* node)
! 1021: {
! 1022: char status[128];
! 1023:
! 1024: printf("Node %2d: %s\n",number,nodestatus(cfg,node,status,sizeof(status)));
! 1025: }
! 1026:
! 1027: /****************************************************************************/
! 1028: uint DLLCALL userdatdupe(scfg_t* cfg, uint usernumber, uint offset, uint datlen
! 1029: ,char *dat, BOOL del)
! 1030: {
! 1031: char str[MAX_PATH+1];
1.1 root 1032: uint i;
1033: int file;
1034: long l,length;
1035:
1.1.1.2 ! root 1036: if(!VALID_CFG(cfg) || dat==NULL)
! 1037: return(0);
! 1038:
1.1 root 1039: truncsp(dat);
1040: sprintf(str,"%suser/user.dat", cfg->data_dir);
1041: if((file=nopen(str,O_RDONLY|O_DENYNONE))==-1)
1042: return(0);
1043: length=filelength(file);
1044: for(l=0;l<length;l+=U_LEN) {
1045: if(usernumber && l/U_LEN==(long)usernumber-1)
1046: continue;
1047: lseek(file,l+offset,SEEK_SET);
1048: i=0;
1049: while(i<LOOP_NODEDAB && lock(file,l,U_LEN)==-1) {
1.1.1.2 ! root 1050: if(i)
! 1051: mswait(100);
! 1052: i++;
! 1053: }
1.1 root 1054:
1055: if(i>=LOOP_NODEDAB) {
1056: close(file);
1.1.1.2 ! root 1057: return(0);
! 1058: }
1.1 root 1059:
1060: read(file,str,datlen);
1061: for(i=0;i<datlen;i++)
1062: if(str[i]==ETX) break;
1063: str[i]=0;
1064: truncsp(str);
1065: if(!stricmp(str,dat)) {
1066: if(!del) { /* Don't include deleted users in search */
1067: lseek(file,l+U_MISC,SEEK_SET);
1068: read(file,str,8);
1069: getrec(str,0,8,str);
1070: if(ahtoul(str)&(DELETED|INACTIVE)) {
1071: unlock(file,l,U_LEN);
1.1.1.2 ! root 1072: continue;
! 1073: }
! 1074: }
1.1 root 1075: unlock(file,l,U_LEN);
1076: close(file);
1.1.1.2 ! root 1077: return((l/U_LEN)+1);
! 1078: } else
! 1079: unlock(file,l,U_LEN);
! 1080: }
1.1 root 1081: close(file);
1082: return(0);
1083: }
1084:
1085: /****************************************************************************/
1.1.1.2 ! root 1086: /* Creates a short message for 'usernumber' that contains 'strin' */
1.1 root 1087: /****************************************************************************/
1088: int DLLCALL putsmsg(scfg_t* cfg, int usernumber, char *strin)
1089: {
1090: char str[256];
1091: int file,i;
1092: node_t node;
1093:
1.1.1.2 ! root 1094: if(!VALID_CFG(cfg) || usernumber<1 || strin==NULL)
! 1095: return(-1);
! 1096:
! 1097: if(*strin==0)
! 1098: return(0);
! 1099:
1.1 root 1100: sprintf(str,"%smsgs/%4.4u.msg",cfg->data_dir,usernumber);
1101: if((file=nopen(str,O_WRONLY|O_CREAT|O_APPEND))==-1) {
1102: return(errno);
1103: }
1104: i=strlen(strin);
1105: if(write(file,strin,i)!=i) {
1106: close(file);
1107: return(errno);
1108: }
1109: close(file);
1110: for(i=1;i<=cfg->sys_nodes;i++) { /* flag node if user on that msg waiting */
1.1.1.2 ! root 1111: getnodedat(cfg,i,&node,NULL);
1.1 root 1112: if(node.useron==usernumber
1113: && (node.status==NODE_INUSE || node.status==NODE_QUIET)
1114: && !(node.misc&NODE_MSGW)) {
1.1.1.2 ! root 1115: getnodedat(cfg,i,&node,&file);
1.1 root 1116: node.misc|=NODE_MSGW;
1.1.1.2 ! root 1117: putnodedat(cfg,i,&node,file);
! 1118: }
! 1119: }
! 1120: return(0);
! 1121: }
! 1122:
! 1123: /****************************************************************************/
! 1124: /* Returns any short messages waiting for user number, buffer must be freed */
! 1125: /****************************************************************************/
! 1126: char* DLLCALL getsmsg(scfg_t* cfg, int usernumber)
! 1127: {
! 1128: char str[MAX_PATH+1], HUGE16 *buf;
! 1129: int i;
! 1130: int file;
! 1131: long length;
! 1132: node_t node;
! 1133:
! 1134: if(!VALID_CFG(cfg) || usernumber<1)
! 1135: return(NULL);
! 1136:
! 1137: sprintf(str,"%smsgs/%4.4u.msg",cfg->data_dir,usernumber);
! 1138: if(flength(str)<1L)
! 1139: return(NULL);
! 1140: if((file=nopen(str,O_RDWR))==-1)
! 1141: return(NULL);
! 1142: length=filelength(file);
! 1143: if((buf=(char *)malloc(length+1))==NULL) {
! 1144: close(file);
! 1145: return(NULL);
! 1146: }
! 1147: if(read(file,buf,length)!=length) {
! 1148: close(file);
! 1149: free(buf);
! 1150: return(NULL);
! 1151: }
! 1152: chsize(file,0L);
! 1153: close(file);
! 1154: buf[length]=0;
! 1155:
! 1156: for(i=1;i<=cfg->sys_nodes;i++) { /* clear msg waiting flag */
! 1157: getnodedat(cfg,i,&node,NULL);
! 1158: if(node.useron==usernumber
! 1159: && (node.status==NODE_INUSE || node.status==NODE_QUIET)
! 1160: && node.misc&NODE_MSGW) {
! 1161: getnodedat(cfg,i,&node,&file);
! 1162: node.misc&=~NODE_MSGW;
! 1163: putnodedat(cfg,i,&node,file);
1.1 root 1164: }
1165: }
1.1.1.2 ! root 1166:
! 1167: return(buf); /* caller must free */
! 1168: }
! 1169:
! 1170: char* DLLCALL getnmsg(scfg_t* cfg, int node_num)
! 1171: {
! 1172: char str[MAX_PATH+1];
! 1173: char* buf;
! 1174: int file;
! 1175: long length;
! 1176: node_t node;
! 1177:
! 1178: if(!VALID_CFG(cfg) || node_num<1)
! 1179: return(NULL);
! 1180:
! 1181: getnodedat(cfg,node_num,&node,&file);
! 1182: node.misc&=~NODE_NMSG; /* clear the NMSG flag */
! 1183: putnodedat(cfg,node_num,&node,file);
! 1184:
! 1185: sprintf(str,"%smsgs/n%3.3u.msg",cfg->data_dir,node_num);
! 1186: if(flength(str)<1L)
! 1187: return(NULL);
! 1188: if((file=nopen(str,O_RDWR))==-1)
! 1189: return(NULL);
! 1190: length=filelength(file);
! 1191: if(!length) {
! 1192: close(file);
! 1193: return(NULL);
! 1194: }
! 1195: if((buf=(char *)malloc(length+1))==NULL) {
! 1196: close(file);
! 1197: return(NULL);
! 1198: }
! 1199: if(read(file,buf,length)!=length) {
! 1200: close(file);
! 1201: free(buf);
! 1202: return(NULL);
! 1203: }
! 1204: chsize(file,0L);
! 1205: close(file);
! 1206: buf[length]=0;
! 1207:
! 1208: return(buf); /* caller must free */
! 1209: }
! 1210:
! 1211: /****************************************************************************/
! 1212: /* Creates a short message for node 'num' that contains 'strin' */
! 1213: /****************************************************************************/
! 1214: int DLLCALL putnmsg(scfg_t* cfg, int num, char *strin)
! 1215: {
! 1216: char str[256];
! 1217: int file,i;
! 1218: node_t node;
! 1219:
! 1220: if(!VALID_CFG(cfg) || num<1 || strin==NULL)
! 1221: return(-1);
! 1222:
! 1223: if(*strin==0)
! 1224: return(0);
! 1225:
! 1226: sprintf(str,"%smsgs/n%3.3u.msg",cfg->data_dir,num);
! 1227: if((file=nopen(str,O_WRONLY|O_CREAT))==-1)
! 1228: return(errno);
! 1229: lseek(file,0L,SEEK_END); // Instead of opening with O_APPEND
! 1230: i=strlen(strin);
! 1231: if(write(file,strin,i)!=i) {
! 1232: close(file);
! 1233: return(errno);
! 1234: }
! 1235: close(file);
! 1236: getnodedat(cfg,num,&node,NULL);
! 1237: if((node.status==NODE_INUSE || node.status==NODE_QUIET)
! 1238: && !(node.misc&NODE_NMSG)) {
! 1239: getnodedat(cfg,num,&node,&file);
! 1240: node.misc|=NODE_NMSG;
! 1241: putnodedat(cfg,num,&node,file);
! 1242: }
! 1243:
1.1 root 1244: return(0);
1245: }
1246:
1247: static BOOL ar_exp(scfg_t* cfg, uchar **ptrptr, user_t* user)
1248: {
1249: BOOL result,not,or,equal;
1250: uint i,n,artype=AR_LEVEL,age;
1251: ulong l;
1252: time_t now;
1.1.1.2 ! root 1253: struct tm tm;
1.1 root 1254:
1255: result = TRUE;
1256:
1257: for(;(**ptrptr);(*ptrptr)++) {
1258:
1259: if((**ptrptr)==AR_ENDNEST)
1260: break;
1261:
1262: not=or=equal = FALSE;
1263:
1264: if((**ptrptr)==AR_OR) {
1265: or=1;
1.1.1.2 ! root 1266: (*ptrptr)++;
! 1267: }
1.1 root 1268:
1269: if((**ptrptr)==AR_NOT) {
1270: not=1;
1.1.1.2 ! root 1271: (*ptrptr)++;
! 1272: }
1.1 root 1273:
1274: if((**ptrptr)==AR_EQUAL) {
1275: equal=1;
1.1.1.2 ! root 1276: (*ptrptr)++;
! 1277: }
1.1 root 1278:
1279: if((result && or) || (!result && !or))
1280: break;
1281:
1282: if((**ptrptr)==AR_BEGNEST) {
1283: (*ptrptr)++;
1284: if(ar_exp(cfg,ptrptr,user))
1285: result=!not;
1286: else
1287: result=not;
1288: while((**ptrptr)!=AR_ENDNEST && (**ptrptr)) /* in case of early exit */
1289: (*ptrptr)++;
1290: if(!(**ptrptr))
1291: break;
1.1.1.2 ! root 1292: continue;
! 1293: }
1.1 root 1294:
1295: artype=(**ptrptr);
1296: switch(artype) {
1297: case AR_ANSI: /* No arguments */
1298: case AR_RIP:
1299: case AR_WIP:
1300: case AR_LOCAL:
1301: case AR_EXPERT:
1302: case AR_SYSOP:
1303: case AR_QUIET:
1304: case AR_OS2:
1305: case AR_DOS:
1306: break;
1307: default:
1308: (*ptrptr)++;
1.1.1.2 ! root 1309: break;
! 1310: }
1.1 root 1311:
1312: n=(**ptrptr);
1313: i=(*(short *)*ptrptr);
1314: switch(artype) {
1315: case AR_LEVEL:
1.1.1.2 ! root 1316: if(user==NULL
! 1317: || (equal && user->level!=n)
! 1318: || (!equal && user->level<n))
1.1 root 1319: result=not;
1320: else
1321: result=!not;
1322: break;
1323: case AR_AGE:
1.1.1.2 ! root 1324: if(user==NULL)
1.1 root 1325: result=not;
1.1.1.2 ! root 1326: else {
! 1327: age=getage(cfg,user->birth);
! 1328: if((equal && age!=n) || (!equal && age<n))
! 1329: result=not;
! 1330: else
! 1331: result=!not;
! 1332: }
1.1 root 1333: break;
1334: case AR_BPS:
1335: result=!not;
1336: (*ptrptr)++;
1337: break;
1338: case AR_ANSI:
1.1.1.2 ! root 1339: if(user==NULL || !(user->misc&ANSI))
1.1 root 1340: result=not;
1341: else result=!not;
1342: break;
1343: case AR_RIP:
1.1.1.2 ! root 1344: if(user==NULL || !(user->misc&RIP))
1.1 root 1345: result=not;
1346: else result=!not;
1347: break;
1348: case AR_WIP:
1.1.1.2 ! root 1349: if(user==NULL || !(user->misc&WIP))
1.1 root 1350: result=not;
1351: else result=!not;
1352: break;
1353: case AR_OS2:
1354: #ifndef __OS2__
1355: result=not;
1356: #else
1357: result=!not;
1358: #endif
1359: break;
1360: case AR_DOS:
1361: #ifdef __FLAT__
1362: result=not;
1363: #else
1364: result=!not;
1365: #endif
1366: break;
1367: case AR_WIN32:
1368: #ifndef _WIN32
1369: result=not;
1370: #else
1371: result=!not;
1372: #endif
1373: break;
1374: case AR_UNIX:
1375: #ifndef __unix__
1376: result=not;
1377: #else
1378: result=!not;
1379: #endif
1380: break;
1381: case AR_LINUX:
1382: #ifndef __linux__
1383: result=not;
1384: #else
1385: result=!not;
1386: #endif
1387: break;
1388: case AR_EXPERT:
1.1.1.2 ! root 1389: if(user==NULL || !(user->misc&EXPERT))
1.1 root 1390: result=not;
1391: else result=!not;
1392: break;
1393: case AR_SYSOP:
1.1.1.2 ! root 1394: if(user==NULL || user->level<SYSOP_LEVEL)
1.1 root 1395: result=not;
1396: else result=!not;
1397: break;
1398: case AR_QUIET:
1399: result=not;
1400: break;
1401: case AR_LOCAL:
1402: result=not;
1403: break;
1404: case AR_DAY:
1405: now=time(NULL);
1.1.1.2 ! root 1406: localtime_r(&now,&tm);
! 1407: if((equal && tm.tm_wday!=(int)n)
! 1408: || (!equal && tm.tm_wday<(int)n))
1.1 root 1409: result=not;
1410: else
1411: result=!not;
1412: break;
1413: case AR_CREDIT:
1414: l=(ulong)i*1024UL;
1.1.1.2 ! root 1415: if(user==NULL
! 1416: || (equal && user->cdt+user->freecdt!=l)
1.1 root 1417: || (!equal && user->cdt+user->freecdt<l))
1418: result=not;
1419: else
1420: result=!not;
1421: (*ptrptr)++;
1422: break;
1423: case AR_NODE:
1424: if((equal && cfg->node_num!=n) || (!equal && cfg->node_num<n))
1425: result=not;
1426: else
1427: result=!not;
1428: break;
1429: case AR_USER:
1.1.1.2 ! root 1430: if(user==NULL
! 1431: || (equal && user->number!=i)
! 1432: || (!equal && user->number<i))
1.1 root 1433: result=not;
1434: else
1435: result=!not;
1436: (*ptrptr)++;
1437: break;
1438: case AR_GROUP:
1439: result=not;
1440: (*ptrptr)++;
1441: break;
1442: case AR_SUB:
1443: result=not;
1444: (*ptrptr)++;
1445: break;
1446: case AR_SUBCODE:
1447: result=not;
1448: while(*(*ptrptr))
1449: (*ptrptr)++;
1450: break;
1451: case AR_LIB:
1452: result=not;
1453: (*ptrptr)++;
1454: break;
1455: case AR_DIR:
1456: result=not;
1457: (*ptrptr)++;
1458: break;
1459: case AR_DIRCODE:
1460: result=not;
1461: while(*(*ptrptr))
1462: (*ptrptr)++;
1463: break;
1464: case AR_EXPIRE:
1465: now=time(NULL);
1.1.1.2 ! root 1466: if(user==NULL
! 1467: || user->expire==0
! 1468: || now+((long)i*24L*60L*60L)>user->expire)
1.1 root 1469: result=not;
1470: else
1471: result=!not;
1472: (*ptrptr)++;
1473: break;
1474: case AR_RANDOM:
1475: n=sbbs_random(i+1);
1476: if((equal && n!=i) || (!equal && n<i))
1477: result=not;
1478: else
1479: result=!not;
1480: (*ptrptr)++;
1481: break;
1482: case AR_LASTON:
1483: now=time(NULL);
1.1.1.2 ! root 1484: if(user==NULL || (now-user->laston)/(24L*60L*60L)<(long)i)
1.1 root 1485: result=not;
1486: else
1487: result=!not;
1488: (*ptrptr)++;
1489: break;
1490: case AR_LOGONS:
1.1.1.2 ! root 1491: if(user==NULL
! 1492: || (equal && user->logons!=i)
! 1493: || (!equal && user->logons<i))
1.1 root 1494: result=not;
1495: else
1496: result=!not;
1497: (*ptrptr)++;
1498: break;
1499: case AR_MAIN_CMDS:
1500: result=not;
1501: (*ptrptr)++;
1502: break;
1503: case AR_FILE_CMDS:
1504: result=not;
1505: (*ptrptr)++;
1506: break;
1507: case AR_TLEFT:
1508: result=not;
1509: break;
1510: case AR_TUSED:
1511: result=not;
1512: break;
1513: case AR_TIME:
1514: now=time(NULL);
1.1.1.2 ! root 1515: localtime_r(&now,&tm);
! 1516: if((tm.tm_hour*60)+tm.tm_min<(int)i)
1.1 root 1517: result=not;
1518: else
1519: result=!not;
1520: (*ptrptr)++;
1521: break;
1522: case AR_PCR:
1.1.1.2 ! root 1523: if(user==NULL)
! 1524: result=not;
! 1525: else if(user->logons>user->posts
! 1526: && (!user->posts || 100/((float)user->logons/user->posts)<(long)n))
1.1 root 1527: result=not;
1528: else
1529: result=!not;
1530: break;
1531: case AR_UDR: /* up/download byte ratio */
1.1.1.2 ! root 1532: if(user==NULL)
1.1 root 1533: result=not;
1.1.1.2 ! root 1534: else {
! 1535: l=user->dlb;
! 1536: if(!l) l=1;
! 1537: if(user->dlb>user->ulb
! 1538: && (!user->ulb || 100/((float)l/user->ulb)<n))
! 1539: result=not;
! 1540: else
! 1541: result=!not;
! 1542: }
1.1 root 1543: break;
1544: case AR_UDFR: /* up/download file ratio */
1.1.1.2 ! root 1545: if(user==NULL)
1.1 root 1546: result=not;
1.1.1.2 ! root 1547: else {
! 1548: i=user->dls;
! 1549: if(!i) i=1;
! 1550: if(user->dls>user->uls
! 1551: && (!user->uls || 100/((float)i/user->uls)<n))
! 1552: result=not;
! 1553: else
! 1554: result=!not;
! 1555: }
1.1 root 1556: break;
1557: case AR_FLAG1:
1.1.1.2 ! root 1558: if(user==NULL
! 1559: || (!equal && !(user->flags1&FLAG(n)))
1.1 root 1560: || (equal && user->flags1!=FLAG(n)))
1561: result=not;
1562: else
1563: result=!not;
1564: break;
1565: case AR_FLAG2:
1.1.1.2 ! root 1566: if(user==NULL
! 1567: || (!equal && !(user->flags2&FLAG(n)))
1.1 root 1568: || (equal && user->flags2!=FLAG(n)))
1569: result=not;
1570: else
1571: result=!not;
1572: break;
1573: case AR_FLAG3:
1.1.1.2 ! root 1574: if(user==NULL
! 1575: || (!equal && !(user->flags3&FLAG(n)))
1.1 root 1576: || (equal && user->flags3!=FLAG(n)))
1577: result=not;
1578: else
1579: result=!not;
1580: break;
1581: case AR_FLAG4:
1.1.1.2 ! root 1582: if(user==NULL
! 1583: || (!equal && !(user->flags4&FLAG(n)))
1.1 root 1584: || (equal && user->flags4!=FLAG(n)))
1585: result=not;
1586: else
1587: result=!not;
1588: break;
1589: case AR_REST:
1.1.1.2 ! root 1590: if(user==NULL
! 1591: || (!equal && !(user->rest&FLAG(n)))
1.1 root 1592: || (equal && user->rest!=FLAG(n)))
1593: result=not;
1594: else
1595: result=!not;
1596: break;
1597: case AR_EXEMPT:
1.1.1.2 ! root 1598: if(user==NULL
! 1599: || (!equal && !(user->exempt&FLAG(n)))
1.1 root 1600: || (equal && user->exempt!=FLAG(n)))
1601: result=not;
1602: else
1603: result=!not;
1604: break;
1605: case AR_SEX:
1.1.1.2 ! root 1606: if(user==NULL || user->sex!=n)
! 1607: result=not;
! 1608: else
! 1609: result=!not;
! 1610: break;
! 1611: case AR_SHELL:
! 1612: if(user==NULL
! 1613: || user->shell>=cfg->total_shells
! 1614: || stricmp(cfg->shell[user->shell]->code,(char*)*ptrptr))
1.1 root 1615: result=not;
1616: else
1617: result=!not;
1.1.1.2 ! root 1618: while(*(*ptrptr))
! 1619: (*ptrptr)++;
! 1620: break;
! 1621: case AR_PROT:
! 1622: if(user==NULL
! 1623: || stricmp(user->modem,(char*)*ptrptr)) /* should this be changed to client.prot? */
! 1624: result=not;
! 1625: else
! 1626: result=!not;
! 1627: while(*(*ptrptr))
! 1628: (*ptrptr)++;
! 1629: break;
! 1630: }
! 1631: }
1.1 root 1632: return(result);
1633: }
1634:
1635: BOOL DLLCALL chk_ar(scfg_t* cfg, uchar *ar, user_t* user)
1636: {
1637: uchar *p;
1638:
1639: if(ar==NULL)
1640: return(TRUE);
1.1.1.2 ! root 1641: if(!VALID_CFG(cfg))
! 1642: return(FALSE);
1.1 root 1643: p=ar;
1644: return(ar_exp(cfg,&p,user));
1645: }
1646:
1647: /****************************************************************************/
1648: /* Fills 'str' with record for usernumber starting at start for length bytes*/
1649: /* Called from function ??? */
1650: /****************************************************************************/
1651: int DLLCALL getuserrec(scfg_t* cfg, int usernumber,int start, int length, char *str)
1652: {
1.1.1.2 ! root 1653: char path[256];
! 1654: int i,c,file;
1.1 root 1655:
1.1.1.2 ! root 1656: if(!VALID_CFG(cfg) || usernumber<1 || str==NULL)
1.1 root 1657: return(-1);
1658: sprintf(path,"%suser/user.dat",cfg->data_dir);
1659: if((file=nopen(path,O_RDONLY|O_DENYNONE))==-1)
1660: return(errno);
1661: if(usernumber<1
1662: || filelength(file)<(long)((long)(usernumber-1L)*U_LEN)+(long)start) {
1663: close(file);
1664: return(-2);
1665: }
1666: lseek(file,(long)((long)(usernumber-1)*U_LEN)+start,SEEK_SET);
1667:
1.1.1.2 ! root 1668: if(length==0) /* auto-length */
! 1669: length=user_rec_len(start);
! 1670:
1.1 root 1671: i=0;
1672: while(i<LOOP_NODEDAB
1673: && lock(file,(long)((long)(usernumber-1)*U_LEN)+start,length)==-1) {
1.1.1.2 ! root 1674: if(i)
! 1675: mswait(100);
! 1676: i++;
! 1677: }
1.1 root 1678:
1679: if(i>=LOOP_NODEDAB) {
1680: close(file);
1681: return(-3);
1682: }
1683:
1684: if(read(file,str,length)!=length) {
1685: unlock(file,(long)((long)(usernumber-1)*U_LEN)+start,length);
1686: close(file);
1687: return(-4);
1688: }
1689:
1690: unlock(file,(long)((long)(usernumber-1)*U_LEN)+start,length);
1691: close(file);
1692: for(c=0;c<length;c++)
1693: if(str[c]==ETX || str[c]==CR) break;
1694: str[c]=0;
1695:
1696: return(0);
1697: }
1698:
1699: /****************************************************************************/
1700: /* Places into user.dat at the offset for usernumber+start for length bytes */
1701: /* Called from various locations */
1702: /****************************************************************************/
1703: int DLLCALL putuserrec(scfg_t* cfg, int usernumber,int start, uint length, char *str)
1704: {
1705: char str2[256];
1706: int file;
1707: uint c,i;
1708: node_t node;
1709:
1.1.1.2 ! root 1710: if(!VALID_CFG(cfg) || usernumber<1 || str==NULL)
1.1 root 1711: return(-1);
1712:
1713: sprintf(str2,"%suser/user.dat",cfg->data_dir);
1.1.1.2 ! root 1714: if((file=nopen(str2,O_RDWR|O_DENYNONE))==-1)
1.1 root 1715: return(errno);
1716:
1.1.1.2 ! root 1717: if(filelength(file)<((long)usernumber-1)*U_LEN) {
! 1718: close(file);
! 1719: return(-4);
! 1720: }
! 1721:
! 1722: if(length==0) /* auto-length */
! 1723: length=user_rec_len(start);
! 1724:
1.1 root 1725: strcpy(str2,str);
1726: if(strlen(str2)<length) {
1727: for(c=strlen(str2);c<length;c++)
1728: str2[c]=ETX;
1729: str2[c]=0;
1730: }
1731: lseek(file,(long)((long)((long)((long)usernumber-1)*U_LEN)+start),SEEK_SET);
1732:
1733: i=0;
1734: while(i<LOOP_NODEDAB
1735: && lock(file,(long)((long)(usernumber-1)*U_LEN)+start,length)==-1) {
1.1.1.2 ! root 1736: if(i)
! 1737: mswait(100);
! 1738: i++;
! 1739: }
1.1 root 1740:
1741: if(i>=LOOP_NODEDAB)
1742: return(-3);
1743:
1744: write(file,str2,length);
1745: unlock(file,(long)((long)(usernumber-1)*U_LEN)+start,length);
1746: close(file);
1747: for(i=1;i<=cfg->sys_nodes;i++) { /* instant user data update */
1748: if(i==cfg->node_num)
1749: continue;
1.1.1.2 ! root 1750: getnodedat(cfg, i,&node,NULL);
1.1 root 1751: if(node.useron==usernumber && (node.status==NODE_INUSE
1752: || node.status==NODE_QUIET)) {
1.1.1.2 ! root 1753: getnodedat(cfg, i,&node,&file);
1.1 root 1754: node.misc|=NODE_UDAT;
1.1.1.2 ! root 1755: putnodedat(cfg, i,&node,file);
1.1 root 1756: break;
1757: }
1758: }
1759:
1760: return(0);
1761: }
1762:
1763: /****************************************************************************/
1764: /* Updates user 'usernumber's record (numeric string) by adding 'adj' to it */
1765: /* returns the new value. */
1766: /****************************************************************************/
1767: ulong DLLCALL adjustuserrec(scfg_t* cfg, int usernumber, int start, int length, long adj)
1768: {
1.1.1.2 ! root 1769: char str[256],path[256];
1.1 root 1770: char tmp[32];
1.1.1.2 ! root 1771: int i,c,file;
1.1 root 1772: long val;
1773: node_t node;
1774:
1.1.1.2 ! root 1775: if(!VALID_CFG(cfg) || usernumber<1)
! 1776: return(0);
1.1 root 1777:
1778: sprintf(path,"%suser/user.dat",cfg->data_dir);
1779: if((file=nopen(path,O_RDWR|O_DENYNONE))==-1)
1.1.1.2 ! root 1780: return(0);
! 1781:
! 1782: if(filelength(file)<((long)usernumber-1)*U_LEN) {
! 1783: close(file);
! 1784: return(0);
! 1785: }
1.1 root 1786:
1787: lseek(file,(long)((long)(usernumber-1)*U_LEN)+start,SEEK_SET);
1788:
1.1.1.2 ! root 1789: if(length==0) /* auto-length */
! 1790: length=user_rec_len(start);
! 1791:
1.1 root 1792: i=0;
1793: while(i<LOOP_NODEDAB
1794: && lock(file,(long)((long)(usernumber-1)*U_LEN)+start,length)==-1) {
1.1.1.2 ! root 1795: if(i)
! 1796: mswait(100);
! 1797: i++;
! 1798: }
1.1 root 1799:
1800: if(i>=LOOP_NODEDAB) {
1801: close(file);
1802: return(0);
1803: }
1804:
1805: if(read(file,str,length)!=length) {
1806: unlock(file,(long)((long)(usernumber-1)*U_LEN)+start,length);
1807: close(file);
1.1.1.2 ! root 1808: return(0);
1.1 root 1809: }
1810: for(c=0;c<length;c++)
1811: if(str[c]==ETX || str[c]==CR) break;
1812: str[c]=0;
1813: val=atol(str);
1814: if(adj<0L && val<-adj) /* don't go negative */
1.1.1.2 ! root 1815: val=0;
1.1 root 1816: else val+=adj;
1817: lseek(file,(long)((long)(usernumber-1)*U_LEN)+start,SEEK_SET);
1818: putrec(str,0,length,ultoa(val,tmp,10));
1819: if(write(file,str,length)!=length) {
1820: unlock(file,(long)((long)(usernumber-1)*U_LEN)+start,length);
1821: close(file);
1822: return(val);
1823: }
1824: unlock(file,(long)((long)(usernumber-1)*U_LEN)+start,length);
1825: close(file);
1826: for(i=1;i<=cfg->sys_nodes;i++) { /* instant user data update */
1827: if(i==cfg->node_num)
1828: continue;
1.1.1.2 ! root 1829: getnodedat(cfg, i,&node,NULL);
1.1 root 1830: if(node.useron==usernumber && (node.status==NODE_INUSE
1831: || node.status==NODE_QUIET)) {
1.1.1.2 ! root 1832: getnodedat(cfg, i,&node,&file);
1.1 root 1833: node.misc|=NODE_UDAT;
1.1.1.2 ! root 1834: putnodedat(cfg, i,&node,file);
1.1 root 1835: break;
1836: }
1837: }
1838: return(val);
1839: }
1840:
1841: /****************************************************************************/
1842: /* Subtract credits from the current user online, accounting for the new */
1843: /* "free credits" field. */
1844: /****************************************************************************/
1845: void DLLCALL subtract_cdt(scfg_t* cfg, user_t* user, long amt)
1846: {
1847: char tmp[64];
1848: long mod;
1849:
1.1.1.2 ! root 1850: if(!amt || user==NULL)
1.1 root 1851: return;
1852: if(user->freecdt) {
1853: if((ulong)amt>user->freecdt) { /* subtract both credits and */
1854: mod=amt-user->freecdt; /* free credits */
1855: putuserrec(cfg, user->number,U_FREECDT,10,"0");
1856: user->freecdt=0;
1.1.1.2 ! root 1857: user->cdt=adjustuserrec(cfg, user->number,U_CDT,10,-mod);
! 1858: } else { /* subtract just free credits */
1.1 root 1859: user->freecdt-=amt;
1860: putuserrec(cfg, user->number,U_FREECDT,10
1.1.1.2 ! root 1861: ,ultoa(user->freecdt,tmp,10));
! 1862: }
! 1863: }
1.1 root 1864: else /* no free credits */
1865: user->cdt=adjustuserrec(cfg, user->number,U_CDT,10,-amt);
1866: }
1.1.1.2 ! root 1867:
! 1868: /****************************************************************************/
! 1869: /****************************************************************************/
! 1870: BOOL DLLCALL logoutuserdat(scfg_t* cfg, user_t* user, time_t now, time_t logontime)
! 1871: {
! 1872: char str[128];
! 1873: time_t tused;
! 1874: struct tm tm, tm_now;
! 1875:
! 1876: if(user==NULL)
! 1877: return(FALSE);
! 1878:
! 1879: if(now==0)
! 1880: now=time(NULL);
! 1881:
! 1882: tused=(now-logontime)/60;
! 1883: user->tlast=(ushort)(tused > USHRT_MAX ? USHRT_MAX : tused);
! 1884:
! 1885: putuserrec(cfg,user->number,U_LASTON,8,ultoa(now,str,16));
! 1886: putuserrec(cfg,user->number,U_TLAST,5,ultoa(user->tlast,str,10));
! 1887: adjustuserrec(cfg,user->number,U_TIMEON,5,user->tlast);
! 1888: adjustuserrec(cfg,user->number,U_TTODAY,5,user->tlast);
! 1889:
! 1890: /* Convert time_t to struct tm */
! 1891: if(localtime_r(&now,&tm_now)==NULL)
! 1892: return(FALSE);
! 1893:
! 1894: if(localtime_r(&logontime,&tm)==NULL)
! 1895: return(FALSE);
! 1896:
! 1897: /* Reset daily stats if new day */
! 1898: if(tm.tm_mday!=tm_now.tm_mday)
! 1899: resetdailyuserdat(cfg, user);
! 1900:
! 1901: return(TRUE);
! 1902: }
! 1903:
! 1904: /****************************************************************************/
! 1905: /****************************************************************************/
! 1906: void DLLCALL resetdailyuserdat(scfg_t* cfg, user_t* user)
! 1907: {
! 1908: char str[128];
! 1909:
! 1910: if(!VALID_CFG(cfg) || user==NULL)
! 1911: return;
! 1912:
! 1913: /* logons today */
! 1914: user->ltoday=0;
! 1915: putuserrec(cfg,user->number,U_LTODAY,5,"0");
! 1916: /* e-mails today */
! 1917: user->etoday=0;
! 1918: putuserrec(cfg,user->number,U_ETODAY,5,"0");
! 1919: /* posts today */
! 1920: user->ptoday=0;
! 1921: putuserrec(cfg,user->number,U_PTODAY,5,"0");
! 1922: /* free credits per day */
! 1923: user->freecdt=cfg->level_freecdtperday[user->level];
! 1924: putuserrec(cfg,user->number,U_FREECDT,10
! 1925: ,ultoa(user->freecdt,str,10));
! 1926: /* time used today */
! 1927: user->ttoday=0;
! 1928: putuserrec(cfg,user->number,U_TTODAY,5,"0");
! 1929: /* extra time today */
! 1930: user->textra=0;
! 1931: putuserrec(cfg,user->number,U_TEXTRA,5,"0");
! 1932: }
! 1933:
! 1934: /****************************************************************************/
! 1935: /****************************************************************************/
! 1936: char* DLLCALL usermailaddr(scfg_t* cfg, char* addr, char* name)
! 1937: {
! 1938: int i;
! 1939:
! 1940: if(!VALID_CFG(cfg) || addr==NULL || name==NULL)
! 1941: return(NULL);
! 1942:
! 1943: if(strchr(name,'@')!=NULL) { /* Avoid double-@ */
! 1944: strcpy(addr,name);
! 1945: return(addr);
! 1946: }
! 1947: if(strchr(name,'!') || (strchr(name,'.') && strchr(name,' ')))
! 1948: sprintf(addr,"\"%s\"@",name);
! 1949: else {
! 1950: sprintf(addr,"%s@",name);
! 1951: /* convert "first last@" to "first.last@" */
! 1952: for(i=0;addr[i];i++)
! 1953: if(addr[i]==' ' || addr[i]&0x80)
! 1954: addr[i]='.';
! 1955: strlwr(addr);
! 1956: }
! 1957: strcat(addr,cfg->sys_inetaddr);
! 1958: return(addr);
! 1959: }
! 1960:
! 1961: char* DLLCALL alias(scfg_t* cfg, char* name, char* buf)
! 1962: {
! 1963: int file;
! 1964: char line[128];
! 1965: char* p;
! 1966: char* np;
! 1967: char* tp;
! 1968: char fname[MAX_PATH+1];
! 1969: size_t namelen;
! 1970: size_t cmplen;
! 1971: FILE* fp;
! 1972:
! 1973: if(!VALID_CFG(cfg) || name==NULL || buf==NULL)
! 1974: return(NULL);
! 1975:
! 1976: p=name;
! 1977:
! 1978: sprintf(fname,"%salias.cfg",cfg->ctrl_dir);
! 1979: if((file=sopen(fname,O_RDONLY|O_BINARY,SH_DENYNO))==-1)
! 1980: return(name);
! 1981:
! 1982: if((fp=fdopen(file,"rb"))==NULL) {
! 1983: close(file);
! 1984: return(name);
! 1985: }
! 1986:
! 1987: while(!feof(fp)) {
! 1988: if(!fgets(line,sizeof(line),fp))
! 1989: break;
! 1990: np=line;
! 1991: SKIP_WHITESPACE(np);
! 1992: if(*np==';')
! 1993: continue;
! 1994: tp=np;
! 1995: FIND_WHITESPACE(tp);
! 1996: if(*tp) *tp=0;
! 1997: if(*np=='*') {
! 1998: np++;
! 1999: cmplen=strlen(np);
! 2000: namelen=strlen(name);
! 2001: if(namelen<cmplen)
! 2002: continue;
! 2003: if(strnicmp(np,name+(namelen-cmplen),cmplen))
! 2004: continue;
! 2005: np=tp+1;
! 2006: SKIP_WHITESPACE(np);
! 2007: truncsp(np);
! 2008: if(*np=='*')
! 2009: sprintf(buf,"%.*s%s",(int)(namelen-cmplen),name,np+1);
! 2010: else
! 2011: strcpy(buf,np);
! 2012: p=buf;
! 2013: break;
! 2014: }
! 2015: if(!stricmp(np,name)) {
! 2016: np=tp+1;
! 2017: SKIP_WHITESPACE(np);
! 2018: truncsp(np);
! 2019: strcpy(buf,np);
! 2020: p=buf;
! 2021: break;
! 2022: }
! 2023: }
! 2024: fclose(fp);
! 2025: return(p);
! 2026: }
! 2027:
! 2028: int DLLCALL newuserdat(scfg_t* cfg, user_t* user)
! 2029: {
! 2030: char str[MAX_PATH+1];
! 2031: char tmp[128];
! 2032: int c;
! 2033: int i;
! 2034: int err;
! 2035: int file;
! 2036: int unum=1;
! 2037: int last;
! 2038: long misc;
! 2039: FILE* stream;
! 2040: stats_t stats;
! 2041:
! 2042: if(!VALID_CFG(cfg) || user==NULL)
! 2043: return(-1);
! 2044:
! 2045: sprintf(str,"%suser/name.dat",cfg->data_dir);
! 2046: if(fexist(str)) {
! 2047: if((stream=fnopen(&file,str,O_RDONLY))==NULL) {
! 2048: return(errno);
! 2049: }
! 2050: last=filelength(file)/(LEN_ALIAS+2); /* total users */
! 2051: while(unum<=last) {
! 2052: fread(str,LEN_ALIAS+2,1,stream);
! 2053: for(c=0;c<LEN_ALIAS;c++)
! 2054: if(str[c]==ETX) break;
! 2055: str[c]=0;
! 2056: if(!c) { /* should be a deleted user */
! 2057: getuserrec(cfg,unum,U_MISC,8,str);
! 2058: misc=ahtoul(str);
! 2059: if(misc&DELETED) { /* deleted bit set too */
! 2060: getuserrec(cfg,unum,U_LASTON,8,str);
! 2061: if((time(NULL)-ahtoul(str))/86400>=cfg->sys_deldays)
! 2062: break; /* deleted long enough ? */
! 2063: }
! 2064: }
! 2065: unum++;
! 2066: }
! 2067: fclose(stream);
! 2068: }
! 2069:
! 2070: last=lastuser(cfg); /* Check against data file */
! 2071:
! 2072: if(unum>last+1) /* Corrupted name.dat? */
! 2073: unum=last+1;
! 2074: else if(unum<=last) { /* Overwriting existing user */
! 2075: getuserrec(cfg,unum,U_MISC,8,str);
! 2076: misc=ahtoul(str);
! 2077: if(!(misc&DELETED)) /* Not deleted? Set usernumber to end+1 */
! 2078: unum=last+1;
! 2079: }
! 2080:
! 2081: user->number=unum; /* store the new user number */
! 2082:
! 2083: if((err=putusername(cfg,user->number,user->alias))!=0)
! 2084: return(err);
! 2085:
! 2086: if((err=putuserdat(cfg,user))!=0)
! 2087: return(err);
! 2088:
! 2089: sprintf(str,"%sfile/%04u.in",cfg->data_dir,user->number); /* delete any files */
! 2090: delfiles(str,ALLFILES); /* waiting for user */
! 2091: rmdir(str);
! 2092: sprintf(tmp,"%04u.*",user->number);
! 2093: sprintf(str,"%sfile",cfg->data_dir);
! 2094: delfiles(str,tmp);
! 2095: sprintf(str,"%suser",cfg->data_dir);
! 2096: delfiles(str,tmp);
! 2097:
! 2098: sprintf(str,"%suser/ptrs/%04u.ixb",cfg->data_dir,user->number); /* msg ptrs */
! 2099: remove(str);
! 2100: sprintf(str,"%smsgs/%04u.msg",cfg->data_dir,user->number); /* delete short msg */
! 2101: remove(str);
! 2102:
! 2103: /* Update daily statistics database (for system and node) */
! 2104:
! 2105: for(i=0;i<2;i++) {
! 2106: sprintf(str,"%sdsts.dab",i ? cfg->ctrl_dir : cfg->node_dir);
! 2107: if((file=nopen(str,O_RDWR))==-1)
! 2108: continue;
! 2109: memset(&stats,0,sizeof(stats));
! 2110: lseek(file,4L,SEEK_SET); /* Skip timestamp */
! 2111: read(file,&stats,sizeof(stats));
! 2112: stats.nusers++;
! 2113: lseek(file,4L,SEEK_SET);
! 2114: write(file,&stats,sizeof(stats));
! 2115: close(file);
! 2116: }
! 2117:
! 2118: return(0);
! 2119: }
! 2120:
! 2121: /* Returns length of specified user record 'field', or -1 if invalid */
! 2122: int DLLCALL user_rec_len(int offset)
! 2123: {
! 2124: switch(offset) {
! 2125:
! 2126: /* Strings (of different lengths) */
! 2127: case U_ALIAS: return(LEN_ALIAS);
! 2128: case U_NAME: return(LEN_NAME);
! 2129: case U_HANDLE: return(LEN_HANDLE);
! 2130: case U_NOTE: return(LEN_NOTE);
! 2131: case U_COMP: return(LEN_COMP);
! 2132: case U_COMMENT: return(LEN_COMMENT);
! 2133: case U_NETMAIL: return(LEN_NETMAIL);
! 2134: case U_ADDRESS: return(LEN_ADDRESS);
! 2135: case U_LOCATION: return(LEN_LOCATION);
! 2136: case U_ZIPCODE: return(LEN_ZIPCODE);
! 2137: case U_PASS: return(LEN_PASS);
! 2138: case U_PHONE: return(LEN_PHONE);
! 2139: case U_BIRTH: return(LEN_BIRTH);
! 2140: case U_MODEM: return(LEN_MODEM);
! 2141:
! 2142: /* Internal codes (16 chars) */
! 2143: case U_CURSUB:
! 2144: case U_CURDIR:
! 2145: return (16);
! 2146:
! 2147: /* Dates in time_t format (8 hex digits) */
! 2148: case U_LASTON:
! 2149: case U_FIRSTON:
! 2150: case U_EXPIRE:
! 2151: case U_PWMOD:
! 2152: case U_NS_TIME:
! 2153: case U_LOGONTIME:
! 2154:
! 2155: /* 32-bit integers (8 hex digits) */
! 2156: case U_FLAGS1:
! 2157: case U_FLAGS2:
! 2158: case U_FLAGS3:
! 2159: case U_FLAGS4:
! 2160: case U_EXEMPT:
! 2161: case U_REST:
! 2162: case U_MISC:
! 2163: case U_QWK:
! 2164: case U_CHAT:
! 2165:
! 2166: /* Internal codes (8 chars) */
! 2167: case U_CURXTRN:
! 2168: case U_XEDIT:
! 2169: case U_SHELL:
! 2170: return(8);
! 2171:
! 2172: /* 16-bit integers (5 decimal digits) */
! 2173: case U_LOGONS:
! 2174: case U_LTODAY:
! 2175: case U_TIMEON:
! 2176: case U_TEXTRA:
! 2177: case U_TTODAY:
! 2178: case U_TLAST:
! 2179: case U_POSTS:
! 2180: case U_EMAILS:
! 2181: case U_FBACKS:
! 2182: case U_ETODAY:
! 2183: case U_PTODAY:
! 2184: case U_ULS:
! 2185: case U_DLS:
! 2186: return(5);
! 2187:
! 2188: /* 32-bit integers (10 decimal digits) */
! 2189: case U_ULB:
! 2190: case U_DLB:
! 2191: case U_CDT:
! 2192: case U_MIN:
! 2193: case U_FREECDT:
! 2194: return(10);
! 2195:
! 2196: /* 3 char strings */
! 2197: case U_TMPEXT:
! 2198: return(3);
! 2199:
! 2200: /* 2 digits integers (0-99) */
! 2201: case U_LEVEL:
! 2202: case U_TL:
! 2203: case U_ROWS:
! 2204: case U_LEECH: /* actually, 2 hex digits */
! 2205: return(2);
! 2206:
! 2207: /* Single digits chars */
! 2208: case U_SEX:
! 2209: case U_PROT:
! 2210: return(1);
! 2211: }
! 2212:
! 2213: return(-1);
! 2214: }
! 2215:
! 2216: BOOL DLLCALL is_download_free(scfg_t* cfg, uint dirnum, user_t* user)
! 2217: {
! 2218: if(!VALID_CFG(cfg))
! 2219: return(FALSE);
! 2220:
! 2221: if(dirnum>=cfg->total_dirs)
! 2222: return(FALSE);
! 2223:
! 2224: if(cfg->dir[dirnum]->misc&DIR_FREE)
! 2225: return(TRUE);
! 2226:
! 2227: if(user==NULL)
! 2228: return(FALSE);
! 2229:
! 2230: if(user->exempt&FLAG('D'))
! 2231: return(TRUE);
! 2232:
! 2233: if(cfg->dir[dirnum]->ex_ar[0]==0)
! 2234: return(FALSE);
! 2235:
! 2236: return(chk_ar(cfg,cfg->dir[dirnum]->ex_ar,user));
! 2237: }
! 2238:
! 2239: /****************************************************************************/
! 2240: /* Add an IP address (with comment) to the IP filter/trashcan file */
! 2241: /* ToDo: Move somewhere more appropriate (filter.c?) */
! 2242: /****************************************************************************/
! 2243: BOOL DLLCALL filter_ip(scfg_t* cfg, char* prot, char* reason, char* host
! 2244: ,char* ip_addr, char* username, char* fname)
! 2245: {
! 2246: char ip_can[MAX_PATH+1];
! 2247: char tstr[64];
! 2248: FILE* fp;
! 2249: time_t now=time(NULL);
! 2250:
! 2251: if(ip_addr==NULL)
! 2252: return(FALSE);
! 2253:
! 2254: sprintf(ip_can,"%sip.can",cfg->text_dir);
! 2255: if(fname==NULL)
! 2256: fname=ip_can;
! 2257:
! 2258: if((fp=fopen(fname,"a"))==NULL)
! 2259: return(FALSE);
! 2260:
! 2261: fprintf(fp,"\n; %s %s by %s on %s\n"
! 2262: ,prot,reason,username,timestr(cfg,&now,tstr));
! 2263:
! 2264: if(host!=NULL)
! 2265: fprintf(fp,"; Hostname: %s\n",host);
! 2266:
! 2267: fprintf(fp,"%s\n",ip_addr);
! 2268:
! 2269: fclose(fp);
! 2270: return(TRUE);
! 2271: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.