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

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

unix.superglobalmegacorp.com

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