Annotation of sbbs/src/sbbs3/userdat.c, revision 1.1

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

unix.superglobalmegacorp.com

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