Annotation of sbbs/sbbs3/userdat.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.