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

1.1       root        1: /* userdat.c */
                      2: 
                      3: /* Synchronet user data-related routines (exported) */
                      4: 
                      5: /* $Id: userdat.c,v 1.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.