Annotation of sbbs/sbbs3/listfile.cpp, revision 1.1

1.1     ! root        1: /* listfile.cpp */
        !             2: 
        !             3: /* Synchronet file database listing functions */
        !             4: 
        !             5: /* $Id: listfile.cpp,v 1.8 2000/12/11 23:21:12 rswindell Exp $ */
        !             6: 
        !             7: /****************************************************************************
        !             8:  * @format.tab-size 4          (Plain Text/Source Code File Header)                    *
        !             9:  * @format.use-tabs true       (see http://www.synchro.net/ptsc_hdr.html)              *
        !            10:  *                                                                                                                                                     *
        !            11:  * Copyright 2000 Rob Swindell - http://www.synchro.net/copyright.html         *
        !            12:  *                                                                                                                                                     *
        !            13:  * This program is free software; you can redistribute it and/or                       *
        !            14:  * modify it under the terms of the GNU General Public License                         *
        !            15:  * as published by the Free Software Foundation; either version 2                      *
        !            16:  * of the License, or (at your option) any later version.                                      *
        !            17:  * See the GNU General Public License for more details: gpl.txt or                     *
        !            18:  * http://www.fsf.org/copyleft/gpl.html                                                                                *
        !            19:  *                                                                                                                                                     *
        !            20:  * Anonymous FTP access to the most recent released source is available at     *
        !            21:  * ftp://vert.synchro.net, ftp://cvs.synchro.net and ftp://ftp.synchro.net     *
        !            22:  *                                                                                                                                                     *
        !            23:  * Anonymous CVS access to the development source and modification history     *
        !            24:  * is available at cvs.synchro.net:/cvsroot/sbbs, example:                                     *
        !            25:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs login                       *
        !            26:  *     (just hit return, no password is necessary)                                                     *
        !            27:  * cvs -d :pserver:[email protected]:/cvsroot/sbbs checkout src                *
        !            28:  *                                                                                                                                                     *
        !            29:  * For Synchronet coding style and modification guidelines, see                                *
        !            30:  * http://www.synchro.net/source.html                                                                          *
        !            31:  *                                                                                                                                                     *
        !            32:  * You are encouraged to submit any modifications (preferably in Unix diff     *
        !            33:  * format) via e-mail to [email protected]                                                                      *
        !            34:  *                                                                                                                                                     *
        !            35:  * Note: If this box doesn't appear square, then you need to fix your tabs.    *
        !            36:  ****************************************************************************/
        !            37: 
        !            38: #include "sbbs.h"
        !            39: 
        !            40: #define BF_MAX 26      /* Batch Flag max: A-Z */       
        !            41: 
        !            42: int extdesclines(char *str);
        !            43: 
        !            44: /*****************************************************************************/
        !            45: /* List files in directory 'dir' that match 'filespec'. Filespec must be        */
        !            46: /* padded. ex: FILE*   .EXT, not FILE*.EXT. 'mode' determines other critiria */
        !            47: /* the files must meet before they'll be listed. 'mode' bit FL_NOHDR doesn't */
        !            48: /* list the directory header.                                                */
        !            49: /* Returns -1 if the listing was aborted, otherwise total files listed          */
        !            50: /*****************************************************************************/
        !            51: int sbbs_t::listfiles(uint dirnum, char *filespec, int tofile, long mode)
        !            52: {
        !            53:        char    str[256],hdr[256],c,d,letter='A',*p,*datbuf,ext[513];
        !            54:        char    tmp[512];
        !            55:        uchar*  ixbbuf;
        !            56:        uchar   flagprompt=0;
        !            57:        uint    i,j;
        !            58:        int             file,found=0,lastbat=0,disp;
        !            59:        long    l,m=0,n,anchor,next,datbuflen;
        !            60:        file_t  f,bf[26];       /* bf is batch flagged files */
        !            61: 
        !            62:        if(mode&FL_ULTIME) {
        !            63:                last_ns_time=now;
        !            64:                sprintf(str,"%s%s.dab",cfg.dir[dirnum]->data_dir,cfg.dir[dirnum]->code);
        !            65:                if((file=nopen(str,O_RDONLY))!=-1) {
        !            66:                        read(file,&l,4);
        !            67:                        close(file);
        !            68:                        if(ns_time>(time_t)l)
        !            69:                                return(0); } }
        !            70:        sprintf(str,"%s%s.ixb",cfg.dir[dirnum]->data_dir,cfg.dir[dirnum]->code);
        !            71:        if((file=nopen(str,O_RDONLY))==-1)
        !            72:                return(0);
        !            73:        l=filelength(file);
        !            74:        if(!l) {
        !            75:                close(file);
        !            76:                return(0); }
        !            77:        if((ixbbuf=(uchar *)MALLOC(l))==NULL) {
        !            78:                close(file);
        !            79:                errormsg(WHERE,ERR_ALLOC,str,l);
        !            80:                return(0); }
        !            81:        if(lread(file,ixbbuf,l)!=l) {
        !            82:                close(file);
        !            83:                errormsg(WHERE,ERR_READ,str,l);
        !            84:                FREE((char *)ixbbuf);
        !            85:                return(0); }
        !            86:        close(file);
        !            87:        sprintf(str,"%s%s.dat",cfg.dir[dirnum]->data_dir,cfg.dir[dirnum]->code);
        !            88:        if((file=nopen(str,O_RDONLY))==-1) {
        !            89:                errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
        !            90:                FREE((char *)ixbbuf);
        !            91:                return(0); }
        !            92:        datbuflen=filelength(file);
        !            93:        if((datbuf=(char *)MALLOC(datbuflen))==NULL) {
        !            94:                close(file);
        !            95:                errormsg(WHERE,ERR_ALLOC,str,datbuflen);
        !            96:                FREE((char *)ixbbuf);
        !            97:                return(0); }
        !            98:        if(lread(file,datbuf,datbuflen)!=datbuflen) {
        !            99:                close(file);
        !           100:                errormsg(WHERE,ERR_READ,str,datbuflen);
        !           101:                FREE((char *)datbuf);
        !           102:                FREE((char *)ixbbuf);
        !           103:                return(0); }
        !           104:        close(file);
        !           105:        if(!tofile) {
        !           106:                action=NODE_LFIL;
        !           107:                getnodedat(cfg.node_num,&thisnode,0);
        !           108:                if(thisnode.action!=NODE_LFIL) {        /* was a sync */
        !           109:                        getnodedat(cfg.node_num,&thisnode,1);
        !           110:                        thisnode.action=NODE_LFIL;
        !           111:                        putnodedat(cfg.node_num,&thisnode); } }
        !           112: 
        !           113:        while(online && found<MAX_FILES) {
        !           114:                if(found<0)
        !           115:                        found=0;
        !           116:                if(m>=l || flagprompt) {                  /* End of list */
        !           117:                        if(useron.misc&BATCHFLAG && !tofile && found && found!=lastbat
        !           118:                                && !(mode&(FL_EXFIND|FL_VIEW))) {
        !           119:                                flagprompt=0;
        !           120:                                lncntr=0;
        !           121:                                if((i=batchflagprompt(dirnum,bf,letter-'A',l/F_IXBSIZE))==2) {
        !           122:                                        m=anchor;
        !           123:                                        found-=letter-'A';
        !           124:                                        letter='A'; }
        !           125:                                else if(i==3) {
        !           126:                                        if((long)anchor-((letter-'A')*F_IXBSIZE)<0) {
        !           127:                                                m=0;
        !           128:                                                found=0; }
        !           129:                                        else {
        !           130:                                                m=anchor-((letter-'A')*F_IXBSIZE);
        !           131:                                                found-=letter-'A'; }
        !           132:                                        letter='A'; }
        !           133:                                else if((int)i==-1) {
        !           134:                                        FREE((char *)ixbbuf);
        !           135:                                        FREE((char *)datbuf);
        !           136:                                        return(-1); }
        !           137:                                else
        !           138:                                        break;
        !           139:                                getnodedat(cfg.node_num,&thisnode,0);
        !           140:                                nodesync(); }
        !           141:                        else
        !           142:                                break; }
        !           143: 
        !           144:                if(letter>'Z')
        !           145:                        letter='A';
        !           146:                if(letter=='A')
        !           147:                        anchor=m;
        !           148: 
        !           149:                if(msgabort()) {                 /* used to be !tofile && msgabort() */
        !           150:                        FREE((char *)ixbbuf);
        !           151:                        FREE((char *)datbuf);
        !           152:                        return(-1); }
        !           153:                for(j=0;j<12 && m<l;j++)
        !           154:                        if(j==8)
        !           155:                                str[j]='.';
        !           156:                        else
        !           157:                                str[j]=ixbbuf[m++];             /* Turns FILENAMEEXT into FILENAME.EXT */
        !           158:                str[j]=0;
        !           159:                if(!(mode&(FL_FINDDESC|FL_EXFIND)) && filespec[0]
        !           160:                        && !filematch(str,filespec)) {
        !           161:                        m+=11;
        !           162:                        continue; }
        !           163:                n=ixbbuf[m]|((long)ixbbuf[m+1]<<8)|((long)ixbbuf[m+2]<<16);
        !           164:                if(n>=datbuflen) {      /* out of bounds */
        !           165:                        m+=11;
        !           166:                        continue; }
        !           167:                if(mode&(FL_FINDDESC|FL_EXFIND)) {
        !           168:                        getrec((char *)&datbuf[n],F_DESC,LEN_FDESC,tmp);
        !           169:                        strupr(tmp);
        !           170:                        p=strstr(tmp,filespec);
        !           171:                        if(!(mode&FL_EXFIND) && p==NULL) {
        !           172:                                m+=11;
        !           173:                                continue; }
        !           174:                        getrec((char *)&datbuf[n],F_MISC,1,tmp);
        !           175:                        j=tmp[0];  /* misc bits */
        !           176:                        if(j) j-=SP;
        !           177:                        if(mode&FL_EXFIND && j&FM_EXTDESC) { /* search extended description */
        !           178:                                getextdesc(dirnum,n,ext);
        !           179:                                strupr(ext);
        !           180:                                if(!strstr(ext,filespec) && !p) {       /* not in description or */
        !           181:                                        m+=11;                                           /* extended description */
        !           182:                                        continue; } }
        !           183:                        else if(!p) {                    /* no extended description and not in desc */
        !           184:                                m+=11;
        !           185:                                continue; } }
        !           186:                if(mode&FL_ULTIME) {
        !           187:                        if(ns_time>(ixbbuf[m+3]|((long)ixbbuf[m+4]<<8)|((long)ixbbuf[m+5]<<16)
        !           188:                                |((long)ixbbuf[m+6]<<24))) {
        !           189:                                m+=11;
        !           190:                                continue; } }
        !           191:                if(useron.misc&BATCHFLAG && letter=='A' && found && !tofile
        !           192:                        && !(mode&(FL_EXFIND|FL_VIEW))
        !           193:                        && (!mode || !(useron.misc&EXPERT)))
        !           194:                        bputs(text[FileListBatchCommands]);
        !           195:                m+=11;
        !           196:                if(!found && !(mode&(FL_EXFIND|FL_VIEW))) {
        !           197:                        for(i=0;i<usrlibs;i++)
        !           198:                                if(usrlib[i]==cfg.dir[dirnum]->lib)
        !           199:                                        break;
        !           200:                        for(j=0;j<usrdirs[i];j++)
        !           201:                                if(usrdir[i][j]==dirnum)
        !           202:                                        break;                                          /* big header */
        !           203:                        if((!mode || !(useron.misc&EXPERT)) && !tofile && (!filespec[0]
        !           204:                                || (strchr(filespec,'*') || strchr(filespec,'?')))) {
        !           205:                                sprintf(hdr,"%s%s.hdr",cfg.dir[dirnum]->data_dir,cfg.dir[dirnum]->code);
        !           206:                                if(fexist(hdr))
        !           207:                                        printfile(hdr,0);       /* Use DATA\DIRS\<CODE>.HDR */
        !           208:                                else {
        !           209:                                        if(useron.misc&BATCHFLAG)
        !           210:                                                bputs(text[FileListBatchCommands]);
        !           211:                                        else {
        !           212:                                                CLS;
        !           213:                                                d=strlen(cfg.lib[usrlib[i]]->lname)>strlen(cfg.dir[dirnum]->lname) ?
        !           214:                                                        strlen(cfg.lib[usrlib[i]]->lname)+17
        !           215:                                                        : strlen(cfg.dir[dirnum]->lname)+17;
        !           216:                                                if(i>8 || j>8) d++;
        !           217:                                                attr(cfg.color[clr_filelsthdrbox]);
        !           218:                                                bputs("��");            /* use to start with \r\n */
        !           219:                                                for(c=0;c<d;c++)
        !           220:                                                        outchar('�');
        !           221:                                                bputs("�\r\n� ");
        !           222:                                                sprintf(hdr,text[BoxHdrLib],i+1,cfg.lib[usrlib[i]]->lname);
        !           223:                                                bputs(hdr);
        !           224:                                                for(c=bstrlen(hdr);c<d;c++)
        !           225:                                                        outchar(SP);
        !           226:                                                bputs("�\r\n� ");
        !           227:                                                sprintf(hdr,text[BoxHdrDir],j+1,cfg.dir[dirnum]->lname);
        !           228:                                                bputs(hdr);
        !           229:                                                for(c=bstrlen(hdr);c<d;c++)
        !           230:                                                        outchar(SP);
        !           231:                                                bputs("�\r\n� ");
        !           232:                                                sprintf(hdr,text[BoxHdrFiles],l/F_IXBSIZE);
        !           233:                                                bputs(hdr);
        !           234:                                                for(c=bstrlen(hdr);c<d;c++)
        !           235:                                                        outchar(SP);
        !           236:                                                bputs("�\r\n��");
        !           237:                                                for(c=0;c<d;c++)
        !           238:                                                        outchar('�');
        !           239:                                                bputs("�\r\n"); } } }
        !           240:                        else {                                  /* short header */
        !           241:                                if(tofile) {
        !           242:                                        sprintf(hdr,"(%u) %s ",i+1,cfg.lib[usrlib[i]]->sname);
        !           243:                                        write(tofile,crlf,2);
        !           244:                                        write(tofile,hdr,strlen(hdr)); }
        !           245:                                else {
        !           246:                                        sprintf(hdr,text[ShortHdrLib],i+1,cfg.lib[usrlib[i]]->sname);
        !           247:                                        bputs("\r\1>\r\n");
        !           248:                                        bputs(hdr); }
        !           249:                                c=bstrlen(hdr);
        !           250:                                if(tofile) {
        !           251:                                        sprintf(hdr,"(%u) %s",j+1,cfg.dir[dirnum]->lname);
        !           252:                                        write(tofile,hdr,strlen(hdr)); }
        !           253:                                else {
        !           254:                                        sprintf(hdr,text[ShortHdrDir],j+1,cfg.dir[dirnum]->lname);
        !           255:                                        bputs(hdr); }
        !           256:                                c+=bstrlen(hdr);
        !           257:                                if(tofile) {
        !           258:                                        write(tofile,crlf,2);
        !           259:                                        sprintf(hdr,"%*s",c,nulstr);
        !           260:                                        memset(hdr,'�',c);
        !           261:                                        strcat(hdr,crlf);
        !           262:                                        write(tofile,hdr,strlen(hdr)); }
        !           263:                                else {
        !           264:                                        CRLF;
        !           265:                                        attr(cfg.color[clr_filelstline]);
        !           266:                                        while(c--)
        !           267:                                                outchar('�');
        !           268:                                        CRLF; } } }
        !           269:                next=m;
        !           270:                disp=1;
        !           271:                if(mode&(FL_EXFIND|FL_VIEW)) {
        !           272:                        f.dir=dirnum;
        !           273:                        strcpy(f.name,str);
        !           274:                        m-=11;
        !           275:                        f.datoffset=n;
        !           276:                        f.dateuled=ixbbuf[m+3]|((long)ixbbuf[m+4]<<8)
        !           277:                                |((long)ixbbuf[m+5]<<16)|((long)ixbbuf[m+6]<<24);
        !           278:                        f.datedled=ixbbuf[m+7]|((long)ixbbuf[m+8]<<8)
        !           279:                                |((long)ixbbuf[m+9]<<16)|((long)ixbbuf[m+10]<<24);
        !           280:                        m+=11;
        !           281:                        f.size=0;
        !           282:                        getfiledat(&cfg,&f);
        !           283:                        if(!found)
        !           284:                                bputs("\r\1>");
        !           285:                        if(mode&FL_EXFIND) {
        !           286:                                if(!viewfile(&f,1)) {
        !           287:                                        FREE((char *)ixbbuf);
        !           288:                                        FREE((char *)datbuf);
        !           289:                                        return(-1); } }
        !           290:                        else {
        !           291:                                if(!viewfile(&f,0)) {
        !           292:                                        FREE((char *)ixbbuf);
        !           293:                                        FREE((char *)datbuf);
        !           294:                                        return(-1); } } }
        !           295: 
        !           296:                else if(tofile)
        !           297:                        listfiletofile(str,&datbuf[n],dirnum,tofile);
        !           298:                else if(mode&FL_FINDDESC)
        !           299:                        disp=listfile(str,&datbuf[n],dirnum,filespec,letter,n);
        !           300:                else
        !           301:                        disp=listfile(str,&datbuf[n],dirnum,nulstr,letter,n);
        !           302:                if(!disp && letter>'A') {
        !           303:                        next=m-F_IXBSIZE;
        !           304:                        letter--; }
        !           305:                else {
        !           306:                        disp=1;
        !           307:                        found++; }
        !           308:                if(sys_status&SS_ABORT) {
        !           309:                        FREE((char *)ixbbuf);
        !           310:                        FREE((char *)datbuf);
        !           311:                        return(-1); }
        !           312:                if(mode&(FL_EXFIND|FL_VIEW))
        !           313:                        continue;
        !           314:                if(useron.misc&BATCHFLAG && !tofile) {
        !           315:                        if(disp) {
        !           316:                                strcpy(bf[letter-'A'].name,str);
        !           317:                                m-=11;
        !           318:                                bf[letter-'A'].datoffset=n;
        !           319:                                bf[letter-'A'].dateuled=ixbbuf[m+3]|((long)ixbbuf[m+4]<<8)
        !           320:                                        |((long)ixbbuf[m+5]<<16)|((long)ixbbuf[m+6]<<24);
        !           321:                                bf[letter-'A'].datedled=ixbbuf[m+7]|((long)ixbbuf[m+8]<<8)
        !           322:                                        |((long)ixbbuf[m+9]<<16)|((long)ixbbuf[m+10]<<24); }
        !           323:                        m+=11;
        !           324:                        if(flagprompt || letter=='Z' || !disp ||
        !           325:                                (filespec[0] && !strchr(filespec,'*') && !strchr(filespec,'?')
        !           326:                                && !(mode&FL_FINDDESC))
        !           327:                                || (useron.misc&BATCHFLAG && !tofile && lncntr>=rows-2)
        !           328:                                ) {
        !           329:                                flagprompt=0;
        !           330:                                lncntr=0;
        !           331:                                lastbat=found;
        !           332:                                if((int)(i=batchflagprompt(dirnum,bf,letter-'A'+1,l/F_IXBSIZE))<1) {
        !           333:                                        FREE((char *)ixbbuf);
        !           334:                                        FREE((char *)datbuf);
        !           335:                                        if(i==-1)
        !           336:                                                return(-1);
        !           337:                                        else
        !           338:                                                return(found); }
        !           339:                                if(i==2) {
        !           340:                                        next=anchor;
        !           341:                                        found-=(letter-'A')+1; }
        !           342:                                else if(i==3) {
        !           343:                                        if((long)anchor-((letter-'A'+1)*F_IXBSIZE)<0) {
        !           344:                                                next=0;
        !           345:                                                found=0; }
        !           346:                                        else {
        !           347:                                                next=anchor-((letter-'A'+1)*F_IXBSIZE);
        !           348:                                                found-=letter-'A'+1; } }
        !           349:                                getnodedat(cfg.node_num,&thisnode,0);
        !           350:                                nodesync();
        !           351:                                letter='A';     }
        !           352:                        else letter++; }
        !           353:                if(useron.misc&BATCHFLAG && !tofile
        !           354:                        && lncntr>=rows-2) {
        !           355:                        lncntr=0;               /* defeat pause() */
        !           356:                        flagprompt=1; }
        !           357:                m=next;
        !           358:                if(mode&FL_FINDDESC) continue;
        !           359:                if(filespec[0] && !strchr(filespec,'*') && !strchr(filespec,'?') && m)
        !           360:                        break; }
        !           361: 
        !           362:        FREE((char *)ixbbuf);
        !           363:        FREE((char *)datbuf);
        !           364:        return(found);
        !           365: }
        !           366: 
        !           367: /****************************************************************************/
        !           368: /* Prints one file's information on a single line                           */
        !           369: /* Return 1 if displayed, 0 otherwise                                                                          */
        !           370: /****************************************************************************/
        !           371: bool sbbs_t::listfile(char *fname, char HUGE16 *buf, uint dirnum
        !           372:        , char *search, char letter, ulong datoffset)
        !           373: {
        !           374:        char    str[256],ext[513]="",*ptr,*cr,*lf,exist=1;
        !           375:        char    tmp[512];
        !           376:     uchar      alt;
        !           377:     int                i,j;
        !           378:     ulong      cdt;
        !           379: 
        !           380:        if(buf[F_MISC]!=ETX && (buf[F_MISC]-SP)&FM_EXTDESC && useron.misc&EXTDESC) {
        !           381:                getextdesc(dirnum,datoffset,ext);
        !           382:                if(useron.misc&BATCHFLAG && lncntr+extdesclines(ext)>=rows-2 && letter!='A')
        !           383:                        return(false); }
        !           384:        attr(cfg.color[clr_filename]);
        !           385:        bputs(fname);
        !           386:        if(buf[F_MISC]!=ETX && (buf[F_MISC]-SP)&FM_EXTDESC) {
        !           387:                if(!(useron.misc&EXTDESC))
        !           388:                        outchar('+');
        !           389:                else
        !           390:                        outchar(SP); }
        !           391:        else
        !           392:                outchar(SP);
        !           393:        if(useron.misc&BATCHFLAG) {
        !           394:                attr(cfg.color[clr_filedesc]);
        !           395:                bprintf("%c",letter); }
        !           396:        getrec((char *)buf,F_ALTPATH,2,str);
        !           397:        alt=(uchar)ahtoul(str);
        !           398:        sprintf(str,"%s%s",alt>0 && alt<=cfg.altpaths ? cfg.altpath[alt-1]:cfg.dir[dirnum]->path
        !           399:                ,unpadfname(fname,tmp));
        !           400:        if(cfg.dir[dirnum]->misc&DIR_FCHK && !fexist(str)) {
        !           401:                exist=0;
        !           402:                attr(cfg.color[clr_err]); }
        !           403:        else
        !           404:                attr(cfg.color[clr_filecdt]);
        !           405:        getrec((char *)buf,F_CDT,LEN_FCDT,str);
        !           406:        cdt=atol(str);
        !           407:        if(useron.misc&BATCHFLAG) {
        !           408:                if(!cdt) {
        !           409:                        attr(curatr^(HIGH|BLINK));
        !           410:                        bputs("  FREE"); }
        !           411:                else {
        !           412:                        if(cdt<1024)    /* 1k is smallest size */
        !           413:                                cdt=1024;
        !           414:                        bprintf("%5luk",cdt/1024L); } }
        !           415:        else {
        !           416:                if(!cdt) {  /* FREE file */
        !           417:                        attr(curatr^(HIGH|BLINK));
        !           418:                        bputs("   FREE"); }
        !           419:                else if(cdt>9999999L)
        !           420:                        bprintf("%6luk",cdt/1024L);
        !           421:                else
        !           422:                        bprintf("%7lu",cdt); }
        !           423:        if(exist)
        !           424:                outchar(SP);
        !           425:        else
        !           426:                outchar('-');
        !           427:        getrec((char *)buf,F_DESC,LEN_FDESC,str);
        !           428:        attr(cfg.color[clr_filedesc]);
        !           429:        if(!ext[0]) {
        !           430:                if(search[0]) { /* high-light string in string */
        !           431:                        strcpy(tmp,str);
        !           432:                        strupr(tmp);
        !           433:                        ptr=strstr(tmp,search);
        !           434:                        i=strlen(search);
        !           435:                        j=ptr-tmp;
        !           436:                        bprintf("%.*s",j,str);
        !           437:                        attr(cfg.color[clr_filedesc]^HIGH);
        !           438:                        bprintf("%.*s",i,str+j);
        !           439:                        attr(cfg.color[clr_filedesc]);
        !           440:                        bprintf("%.*s",strlen(str)-(j+i),str+j+i); }
        !           441:                else
        !           442:                        bputs(str);
        !           443:                CRLF; }
        !           444:        ptr=ext;
        !           445:        while(*ptr && ptr<ext+512 && !msgabort()) {
        !           446:                cr=strchr(ptr,CR);
        !           447:                lf=strchr(ptr,LF);
        !           448:                if(lf && (lf<cr || !cr)) cr=lf;
        !           449:                if(cr>ptr+LEN_FDESC)
        !           450:                        cr=ptr+LEN_FDESC;
        !           451:                else if(cr)
        !           452:                        *cr=0;
        !           453:        //        bprintf("%.*s\r\n",LEN_FDESC,ptr);
        !           454:                sprintf(str,"%.*s\r\n",LEN_FDESC,ptr);
        !           455:                putmsg(str,P_NOATCODES|P_SAVEATR);
        !           456:                if(!cr) {
        !           457:                        if(strlen(ptr)>LEN_FDESC)
        !           458:                                cr=ptr+LEN_FDESC;
        !           459:                        else
        !           460:                                break; }
        !           461:                if(!(*(cr+1)) || !(*(cr+2)))
        !           462:                        break;
        !           463:                bprintf("%21s",nulstr);
        !           464:                ptr=cr;
        !           465:                if(!(*ptr)) ptr++;
        !           466:                while(*ptr==LF || *ptr==CR) ptr++; }
        !           467:        return(true);
        !           468: }
        !           469: 
        !           470: void sbbs_t::clearline(void)
        !           471: {
        !           472:        int i;
        !           473: 
        !           474:        outchar(CR);
        !           475:        if(useron.misc&ANSI)
        !           476:                bputs("\x1b[K");
        !           477:        else {
        !           478:                for(i=0;i<79;i++)
        !           479:                        outchar(SP);
        !           480:                outchar(CR); }
        !           481: }
        !           482: 
        !           483: /****************************************************************************/
        !           484: /* Remove credits from uploader of file 'f'                                 */
        !           485: /****************************************************************************/
        !           486: bool sbbs_t::removefcdt(file_t* f)
        !           487: {
        !           488:        char    str[128];
        !           489:        char    tmp[512];
        !           490:        int             u;
        !           491:        long    cdt;
        !           492: 
        !           493:        if((u=matchuser(&cfg,f->uler))==0) {
        !           494:           bputs(text[UnknownUser]);
        !           495:           return(false); }
        !           496:        cdt=0L;
        !           497:        if(cfg.dir[f->dir]->misc&DIR_CDTMIN && cur_cps) {
        !           498:                if(cfg.dir[f->dir]->misc&DIR_CDTUL)
        !           499:                        cdt=((ulong)(f->cdt*(cfg.dir[f->dir]->up_pct/100.0))/cur_cps)/60;
        !           500:                if(cfg.dir[f->dir]->misc&DIR_CDTDL
        !           501:                        && f->timesdled)  /* all downloads */
        !           502:                        cdt+=((ulong)((long)f->timesdled
        !           503:                                *f->cdt*(cfg.dir[f->dir]->dn_pct/100.0))/cur_cps)/60;
        !           504:                adjustuserrec(&cfg,u,U_MIN,10,-cdt);
        !           505:                sprintf(str,"%lu minute",cdt);
        !           506:                sprintf(tmp,text[FileRemovedUserMsg]
        !           507:                        ,f->name,cdt ? str : text[No]);
        !           508:                putsmsg(&cfg,u,tmp); }
        !           509:        else {
        !           510:                if(cfg.dir[f->dir]->misc&DIR_CDTUL)
        !           511:                        cdt=(ulong)(f->cdt*(cfg.dir[f->dir]->up_pct/100.0));
        !           512:                if(cfg.dir[f->dir]->misc&DIR_CDTDL
        !           513:                        && f->timesdled)  /* all downloads */
        !           514:                        cdt+=(ulong)((long)f->timesdled
        !           515:                                *f->cdt*(cfg.dir[f->dir]->dn_pct/100.0));
        !           516:                adjustuserrec(&cfg,u,U_CDT,10,-cdt);
        !           517:                sprintf(tmp,text[FileRemovedUserMsg]
        !           518:                        ,f->name,cdt ? ultoac(cdt,str) : text[No]);
        !           519:                putsmsg(&cfg,u,tmp); }
        !           520: 
        !           521:        adjustuserrec(&cfg,u,U_ULB,10,-f->size);
        !           522:        adjustuserrec(&cfg,u,U_ULS,5,-1);
        !           523:        return(true);
        !           524: }
        !           525: 
        !           526: /****************************************************************************/
        !           527: /* Move file 'f' from f.dir to newdir                                       */
        !           528: /****************************************************************************/
        !           529: bool sbbs_t::movefile(file_t* f, int newdir)
        !           530: {
        !           531:        char str[256],path[256],fname[128],ext[1024];
        !           532:        int olddir=f->dir;
        !           533: 
        !           534:        if(findfile(&cfg,newdir,f->name)) {
        !           535:                bprintf(text[FileAlreadyThere],f->name);
        !           536:                return(false); }
        !           537:        getextdesc(olddir,f->datoffset,ext);
        !           538:        if(cfg.dir[olddir]->misc&DIR_MOVENEW)
        !           539:                f->dateuled=time(NULL);
        !           540:        unpadfname(f->name,fname);
        !           541:        removefiledat(&cfg,f);
        !           542:        f->dir=newdir;
        !           543:        addfiledat(&cfg,f);
        !           544:        bprintf(text[MovedFile],f->name
        !           545:                ,cfg.lib[cfg.dir[f->dir]->lib]->sname,cfg.dir[f->dir]->sname);
        !           546:        sprintf(str,"Moved %s to %s %s",f->name
        !           547:                ,cfg.lib[cfg.dir[f->dir]->lib]->sname,cfg.dir[f->dir]->sname);
        !           548:        logline(nulstr,str);
        !           549:        if(!f->altpath) {       /* move actual file */
        !           550:                sprintf(str,"%s%s",cfg.dir[olddir]->path,fname);
        !           551:                if(fexist(str)) {
        !           552:                        sprintf(path,"%s%s",cfg.dir[f->dir]->path,fname);
        !           553:                        mv(str,path,0); } }
        !           554:        if(f->misc&FM_EXTDESC)
        !           555:                putextdesc(f->dir,f->datoffset,ext);
        !           556:        return(true);
        !           557: }
        !           558: 
        !           559: /****************************************************************************/
        !           560: /* Batch flagging prompt for download, extended info, and archive viewing      */
        !           561: /* Returns -1 if 'Q' or Ctrl-C, 0 if skip, 1 if [Enter], 2 otherwise        */
        !           562: /* or 3, backwards.                                                                                                            */
        !           563: /****************************************************************************/
        !           564: int sbbs_t::batchflagprompt(uint dirnum, file_t* bf, uint total
        !           565:                                                        ,long totalfiles)
        !           566: {
        !           567:        char    ch,c,d,str[256],fname[128],*p,remcdt,remfile;
        !           568:        char    tmp[512];
        !           569:        uint    i,j,ml,md,udir,ulib;
        !           570:        file_t  f;
        !           571: 
        !           572:        for(ulib=0;ulib<usrlibs;ulib++)
        !           573:                if(usrlib[ulib]==cfg.dir[dirnum]->lib)
        !           574:                        break;
        !           575:        for(udir=0;udir<usrdirs[ulib];udir++)
        !           576:                if(usrdir[ulib][udir]==dirnum)
        !           577:                        break;
        !           578: 
        !           579:        CRLF;
        !           580:        while(online) {
        !           581:                bprintf(text[BatchFlagPrompt]
        !           582:                        ,ulib+1
        !           583:                        ,cfg.lib[cfg.dir[dirnum]->lib]->sname
        !           584:                        ,udir+1
        !           585:                        ,cfg.dir[dirnum]->sname
        !           586:                        ,totalfiles);
        !           587:                ch=getkey(K_UPPER);
        !           588:                clearline();
        !           589:                if(ch=='?') {
        !           590:                        menu("batflag");
        !           591:                        if(lncntr)
        !           592:                                pause();
        !           593:                        return(2); }
        !           594:                if(ch=='Q' || sys_status&SS_ABORT)
        !           595:                        return(-1);
        !           596:                if(ch=='S')
        !           597:                        return(0);
        !           598:                if(ch=='P' || ch=='-')
        !           599:                        return(3);
        !           600:                if(ch=='B') {    /* Flag for batch download */
        !           601:                        if(useron.rest&FLAG('D')) {
        !           602:                                bputs(text[R_Download]);
        !           603:                                return(2); }
        !           604:                        if(total==1) {
        !           605:                                f.dir=dirnum;
        !           606:                                strcpy(f.name,bf[0].name);
        !           607:                                f.datoffset=bf[0].datoffset;
        !           608:                                f.size=0;
        !           609:                                getfiledat(&cfg,&f);
        !           610:                                addtobatdl(&f);
        !           611:                                CRLF;
        !           612:                                return(2); }
        !           613:                        bputs(text[BatchDlFlags]);
        !           614:                        d=getstr(str,BF_MAX,K_UPPER|K_LOWPRIO|K_NOCRLF);
        !           615:                        lncntr=0;
        !           616:                        if(sys_status&SS_ABORT)
        !           617:                                return(-1);
        !           618:                        if(d) {         /* d is string length */
        !           619:                                CRLF;
        !           620:                                lncntr=0;
        !           621:                                for(c=0;c<d;c++) {
        !           622:                                        if(batdn_total>=cfg.max_batdn) {
        !           623:                                                bprintf(text[BatchDlQueueIsFull],str+c);
        !           624:                                                break; }
        !           625:                                        if(strchr(str+c,'.')) {     /* filename or spec given */
        !           626:                                                f.dir=dirnum;
        !           627:                                                p=strchr(str+c,SP);
        !           628:                                                if(!p) p=strchr(str+c,',');
        !           629:                                                if(p) *p=0;
        !           630:                                                for(i=0;i<total;i++) {
        !           631:                                                        if(batdn_total>=cfg.max_batdn) {
        !           632:                                                                bprintf(text[BatchDlQueueIsFull],str+c);
        !           633:                                                                break; }
        !           634:                                                        padfname(str+c,tmp);
        !           635:                                                        if(filematch(bf[i].name,tmp)) {
        !           636:                                                                strcpy(f.name,bf[i].name);
        !           637:                                                                f.datoffset=bf[i].datoffset;
        !           638:                                                                f.size=0;
        !           639:                                                                getfiledat(&cfg,&f);
        !           640:                                                                addtobatdl(&f); } } }
        !           641:                                        if(strchr(str+c,'.'))
        !           642:                                                c+=strlen(str+c);
        !           643:                                        else if(str[c]<'A'+(char)total && str[c]>='A') {
        !           644:                                                f.dir=dirnum;
        !           645:                                                strcpy(f.name,bf[str[c]-'A'].name);
        !           646:                                                f.datoffset=bf[str[c]-'A'].datoffset;
        !           647:                                                f.size=0;
        !           648:                                                getfiledat(&cfg,&f);
        !           649:                                                addtobatdl(&f); } }
        !           650:                                CRLF;
        !           651:                                return(2); }
        !           652:                        clearline();
        !           653:                        continue; }
        !           654: 
        !           655:                if(ch=='E' || ch=='V') {    /* Extended Info */
        !           656:                        if(total==1) {
        !           657:                                f.dir=dirnum;
        !           658:                                strcpy(f.name,bf[0].name);
        !           659:                                f.datoffset=bf[0].datoffset;
        !           660:                                f.dateuled=bf[0].dateuled;
        !           661:                                f.datedled=bf[0].datedled;
        !           662:                                f.size=0;
        !           663:                                getfiledat(&cfg,&f);
        !           664:                                if(!viewfile(&f,ch=='E'))
        !           665:                                        return(-1);
        !           666:                                return(2); }
        !           667:                        bputs(text[BatchDlFlags]);
        !           668:                        d=getstr(str,BF_MAX,K_UPPER|K_LOWPRIO|K_NOCRLF);
        !           669:                        lncntr=0;
        !           670:                        if(sys_status&SS_ABORT)
        !           671:                                return(-1);
        !           672:                        if(d) {         /* d is string length */
        !           673:                                CRLF;
        !           674:                                lncntr=0;
        !           675:                                for(c=0;c<d;c++) {
        !           676:                                        if(strchr(str+c,'.')) {     /* filename or spec given */
        !           677:                                                f.dir=dirnum;
        !           678:                                                p=strchr(str+c,SP);
        !           679:                                                if(!p) p=strchr(str+c,',');
        !           680:                                                if(p) *p=0;
        !           681:                                                for(i=0;i<total;i++) {
        !           682:                                                        padfname(str+c,tmp);
        !           683:                                                        if(filematch(bf[i].name,tmp)) {
        !           684:                                                                strcpy(f.name,bf[i].name);
        !           685:                                                                f.datoffset=bf[i].datoffset;
        !           686:                                                                f.dateuled=bf[i].dateuled;
        !           687:                                                                f.datedled=bf[i].datedled;
        !           688:                                                                f.size=0;
        !           689:                                                                getfiledat(&cfg,&f);
        !           690:                                                                if(!viewfile(&f,ch=='E'))
        !           691:                                                                        return(-1); } } }
        !           692:                                        if(strchr(str+c,'.'))
        !           693:                                                c+=strlen(str+c);
        !           694:                                        else if(str[c]<'A'+(char)total && str[c]>='A') {
        !           695:                                                f.dir=dirnum;
        !           696:                                                strcpy(f.name,bf[str[c]-'A'].name);
        !           697:                                                f.datoffset=bf[str[c]-'A'].datoffset;
        !           698:                                                f.dateuled=bf[str[c]-'A'].dateuled;
        !           699:                                                f.datedled=bf[str[c]-'A'].datedled;
        !           700:                                                f.size=0;
        !           701:                                                getfiledat(&cfg,&f);
        !           702:                                                if(!viewfile(&f,ch=='E'))
        !           703:                                                        return(-1); } }
        !           704:                                return(2); }
        !           705:                        clearline();
        !           706:                        continue; }
        !           707: 
        !           708:                if((ch=='D' || ch=='M')     /* Delete or Move */
        !           709:                        && !(useron.rest&FLAG('R'))
        !           710:                        && (dir_op(dirnum) || useron.exempt&FLAG('R'))) {
        !           711:                        if(total==1) {
        !           712:                                strcpy(str,"A");
        !           713:                                d=1; }
        !           714:                        else {
        !           715:                                bputs(text[BatchDlFlags]);
        !           716:                                d=getstr(str,BF_MAX,K_UPPER|K_LOWPRIO|K_NOCRLF); }
        !           717:                        lncntr=0;
        !           718:                        if(sys_status&SS_ABORT)
        !           719:                                return(-1);
        !           720:                        if(d) {         /* d is string length */
        !           721:                                CRLF;
        !           722:                                if(ch=='D') {
        !           723:                                        if(noyes(text[AreYouSureQ]))
        !           724:                                                return(2);
        !           725:                                        remcdt=remfile=1;
        !           726:                                        if(dir_op(dirnum)) {
        !           727:                                                remcdt=!noyes(text[RemoveCreditsQ]);
        !           728:                                                remfile=!noyes(text[DeleteFileQ]); } }
        !           729:                                else if(ch=='M') {
        !           730:                                        CRLF;
        !           731:                                        for(i=0;i<usrlibs;i++)
        !           732:                                                bprintf(text[MoveToLibLstFmt],i+1,cfg.lib[usrlib[i]]->lname);
        !           733:                                        SYNC;
        !           734:                                        bprintf(text[MoveToLibPrompt],cfg.dir[dirnum]->lib+1);
        !           735:                                        if((ml=getnum(usrlibs))==-1)
        !           736:                                                return(2);
        !           737:                                        if(!ml)
        !           738:                                                ml=cfg.dir[dirnum]->lib;
        !           739:                                        else
        !           740:                                                ml--;
        !           741:                                        CRLF;
        !           742:                                        for(j=0;j<usrdirs[ml];j++)
        !           743:                                                bprintf(text[MoveToDirLstFmt]
        !           744:                                                        ,j+1,cfg.dir[usrdir[ml][j]]->lname);
        !           745:                                        SYNC;
        !           746:                                        bprintf(text[MoveToDirPrompt],usrdirs[ml]);
        !           747:                                        if((md=getnum(usrdirs[ml]))==-1)
        !           748:                                                return(2);
        !           749:                                        if(!md)
        !           750:                                                md=usrdirs[ml]-1;
        !           751:                                        else md--;
        !           752:                                        CRLF; }
        !           753:                                lncntr=0;
        !           754:                                for(c=0;c<d;c++) {
        !           755:                                        if(strchr(str+c,'.')) {     /* filename or spec given */
        !           756:                                                f.dir=dirnum;
        !           757:                                                p=strchr(str+c,SP);
        !           758:                                                if(!p) p=strchr(str+c,',');
        !           759:                                                if(p) *p=0;
        !           760:                                                for(i=0;i<total;i++) {
        !           761:                                                        padfname(str+c,tmp);
        !           762:                                                        if(filematch(bf[i].name,tmp)) {
        !           763:                                                                strcpy(f.name,bf[i].name);
        !           764:                                                                unpadfname(f.name,fname);
        !           765:                                                                f.datoffset=bf[i].datoffset;
        !           766:                                                                f.dateuled=bf[i].dateuled;
        !           767:                                                                f.datedled=bf[i].datedled;
        !           768:                                                                f.size=0;
        !           769:                                                                getfiledat(&cfg,&f);
        !           770:                                                                if(f.opencount) {
        !           771:                                                                        bprintf(text[FileIsOpen]
        !           772:                                                                                ,f.opencount,f.opencount>1 ? "s":nulstr);
        !           773:                                                                        continue; }
        !           774:                                                                if(ch=='D') {
        !           775:                                                                        removefiledat(&cfg,&f);
        !           776:                                                                        if(remfile) {
        !           777:                                                                                sprintf(tmp,"%s%s",cfg.dir[f.dir]->path,fname);
        !           778:                                                                                remove(tmp); }
        !           779:                                                                        if(remcdt)
        !           780:                                                                                removefcdt(&f); }
        !           781:                                                                else if(ch=='M')
        !           782:                                                                        movefile(&f,usrdir[ml][md]); } } }
        !           783:                                        if(strchr(str+c,'.'))
        !           784:                                                c+=strlen(str+c);
        !           785:                                        else if(str[c]<'A'+(char)total && str[c]>='A') {
        !           786:                                                f.dir=dirnum;
        !           787:                                                strcpy(f.name,bf[str[c]-'A'].name);
        !           788:                                                unpadfname(f.name,fname);
        !           789:                                                f.datoffset=bf[str[c]-'A'].datoffset;
        !           790:                                                f.dateuled=bf[str[c]-'A'].dateuled;
        !           791:                                                f.datedled=bf[str[c]-'A'].datedled;
        !           792:                                                f.size=0;
        !           793:                                                getfiledat(&cfg,&f);
        !           794:                                                if(f.opencount) {
        !           795:                                                        bprintf(text[FileIsOpen]
        !           796:                                                                ,f.opencount,f.opencount>1 ? "s":nulstr);
        !           797:                                                        continue; }
        !           798:                                                if(ch=='D') {
        !           799:                                                        removefiledat(&cfg,&f);
        !           800:                                                        if(remfile) {
        !           801:                                                                sprintf(tmp,"%s%s",cfg.dir[f.dir]->path,fname);
        !           802:                                                                remove(tmp); }
        !           803:                                                        if(remcdt)
        !           804:                                                                removefcdt(&f); }
        !           805:                                                else if(ch=='M')
        !           806:                                                        movefile(&f,usrdir[ml][md]); } }
        !           807:                                return(2); }
        !           808:                        clearline();
        !           809:                        continue; }
        !           810: 
        !           811:                return(1); }
        !           812: 
        !           813:        return(-1);
        !           814: }
        !           815: 
        !           816: /****************************************************************************/
        !           817: /* List detailed information about the files in 'filespec'. Prompts for     */
        !           818: /* action depending on 'mode.'                                              */
        !           819: /* Returns number of files matching filespec that were found                */
        !           820: /****************************************************************************/
        !           821: int sbbs_t::listfileinfo(uint dirnum, char *filespec, long mode)
        !           822: {
        !           823:        char    str[258],path[258],dirpath[256],done=0,ch,fname[13],ext[513];
        !           824:        char    tmp[512];
        !           825:        uchar   *ixbbuf,*usrxfrbuf=NULL,*p;
        !           826:        int             file;
        !           827:        int             found=0;
        !           828:     uint       i,j;
        !           829:        long    usrxfrlen;
        !           830:     long       m,l;
        !           831:        long    usrcdt;
        !           832:     time_t     start,end,t;
        !           833:     file_t     f;
        !           834:        struct  tm * tm;
        !           835: 
        !           836:        sprintf(str,"%sxfer.ixt",cfg.data_dir);
        !           837:        if(mode==FI_USERXFER && flength(str)>0L) {
        !           838:                if((file=nopen(str,O_RDONLY))==-1) {
        !           839:                        errormsg(WHERE,ERR_OPEN,str,O_RDONLY);
        !           840:                        return(0); }
        !           841:                usrxfrlen=filelength(file);
        !           842:                if((usrxfrbuf=(uchar *)MALLOC(usrxfrlen))==NULL) {
        !           843:                        close(file);
        !           844:                        errormsg(WHERE,ERR_ALLOC,str,usrxfrlen);
        !           845:                        return(0); }
        !           846:                if(read(file,usrxfrbuf,usrxfrlen)!=usrxfrlen) {
        !           847:                        close(file);
        !           848:                        FREE(usrxfrbuf);
        !           849:                        errormsg(WHERE,ERR_READ,str,usrxfrlen);
        !           850:                        return(0); }
        !           851:                close(file); }
        !           852:        sprintf(str,"%s%s.ixb",cfg.dir[dirnum]->data_dir,cfg.dir[dirnum]->code);
        !           853:        if((file=nopen(str,O_RDONLY))==-1)
        !           854:                return(0);
        !           855:        l=filelength(file);
        !           856:        if(!l) {
        !           857:                close(file);
        !           858:                return(0); }
        !           859:        if((ixbbuf=(uchar *)MALLOC(l))==NULL) {
        !           860:                close(file);
        !           861:                errormsg(WHERE,ERR_ALLOC,str,l);
        !           862:                return(0); }
        !           863:        if(lread(file,ixbbuf,l)!=l) {
        !           864:                close(file);
        !           865:                errormsg(WHERE,ERR_READ,str,l);
        !           866:                FREE((char *)ixbbuf);
        !           867:                if(usrxfrbuf)
        !           868:                        FREE(usrxfrbuf);
        !           869:                return(0); }
        !           870:        close(file);
        !           871:        sprintf(str,"%s%s.dat",cfg.dir[dirnum]->data_dir,cfg.dir[dirnum]->code);
        !           872:        if((file=nopen(str,O_RDONLY))==-1) {
        !           873:                errormsg(WHERE,ERR_READ,str,O_RDONLY);
        !           874:                FREE((char *)ixbbuf);
        !           875:                if(usrxfrbuf)
        !           876:                        FREE(usrxfrbuf);
        !           877:                return(0); }
        !           878:        close(file);
        !           879:        m=0;
        !           880:        while(online && !done && m<l) {
        !           881:                if(mode==FI_REMOVE && dir_op(dirnum))
        !           882:                        action=NODE_SYSP;
        !           883:                else action=NODE_LFIL;
        !           884:                if(msgabort()) {
        !           885:                        found=-1;
        !           886:                        break; }
        !           887:                for(i=0;i<12 && m<l;i++)
        !           888:                        if(i==8)
        !           889:                                str[i]='.';
        !           890:                        else
        !           891:                                str[i]=ixbbuf[m++];     /* Turns FILENAMEEXT into FILENAME.EXT */
        !           892:                str[i]=0;
        !           893:                unpadfname(str,fname);
        !           894:                if(filespec[0] && !filematch(str,filespec)) {
        !           895:                        m+=11;
        !           896:                        continue; }
        !           897:                f.datoffset=ixbbuf[m]|((long)ixbbuf[m+1]<<8)|((long)ixbbuf[m+2]<<16);
        !           898:                f.dateuled=ixbbuf[m+3]|((long)ixbbuf[m+4]<<8)
        !           899:                        |((long)ixbbuf[m+5]<<16)|((long)ixbbuf[m+6]<<24);
        !           900:                f.datedled=ixbbuf[m+7]|((long)ixbbuf[m+8]<<8)
        !           901:                        |((long)ixbbuf[m+9]<<16)|((long)ixbbuf[m+10]<<24);
        !           902:                m+=11;
        !           903:                if(mode==FI_OLD && f.datedled>ns_time)
        !           904:                        continue;
        !           905:                if((mode==FI_OLDUL || mode==FI_OLD) && f.dateuled>ns_time)
        !           906:                        continue;
        !           907:                f.dir=curdirnum=dirnum;
        !           908:                strcpy(f.name,str);
        !           909:                f.size=0;
        !           910:                getfiledat(&cfg,&f);
        !           911:                if(mode==FI_OFFLINE && f.size>=0)
        !           912:                        continue;
        !           913:                if(f.altpath>0 && f.altpath<=cfg.altpaths)
        !           914:                        strcpy(dirpath,cfg.altpath[f.altpath-1]);
        !           915:                else
        !           916:                        strcpy(dirpath,cfg.dir[f.dir]->path);
        !           917:                if(mode==FI_CLOSE && !f.opencount)
        !           918:                        continue;
        !           919:                if(mode==FI_USERXFER) {
        !           920:                        for(p=usrxfrbuf;p<usrxfrbuf+usrxfrlen;p+=24) {
        !           921:                                sprintf(str,"%17.17s",p);   /* %4.4u %12.12s */
        !           922:                                if(!strcmp(str+5,f.name) && useron.number==atoi(str))
        !           923:                                        break; }
        !           924:                        if(p>=usrxfrbuf+usrxfrlen) /* file wasn't found */
        !           925:                                continue; }
        !           926:                if((mode==FI_REMOVE) && (!dir_op(dirnum) && stricmp(f.uler
        !           927:                        ,useron.alias) && !(useron.exempt&FLAG('R'))))
        !           928:                        continue;
        !           929:                found++;
        !           930:                if(mode==FI_INFO) {
        !           931:                        if(!viewfile(&f,1)) {
        !           932:                                done=1;
        !           933:                                found=-1; } }
        !           934:                else
        !           935:                        fileinfo(&f);
        !           936:                if(mode==FI_CLOSE) {
        !           937:                        if(!noyes(text[CloseFileRecordQ])) {
        !           938:                                f.opencount=0;
        !           939:                                putfiledat(&cfg,&f); } }
        !           940:                else if(mode==FI_REMOVE || mode==FI_OLD || mode==FI_OLDUL
        !           941:                        || mode==FI_OFFLINE) {
        !           942:                        SYNC;
        !           943:                        CRLF;
        !           944:                        if(f.opencount) {
        !           945:                                mnemonics(text[QuitOrNext]);
        !           946:                                strcpy(str,"Q\r"); }
        !           947:                        else if(dir_op(dirnum)) {
        !           948:                                mnemonics(text[SysopRemoveFilePrompt]);
        !           949:                                strcpy(str,"VEFMCQR\r"); }
        !           950:                        else if(useron.exempt&FLAG('R')) {
        !           951:                                mnemonics(text[RExemptRemoveFilePrompt]);
        !           952:                                strcpy(str,"VEMQR\r"); }
        !           953:                        else {
        !           954:                                mnemonics(text[UserRemoveFilePrompt]);
        !           955:                                strcpy(str,"VEQR\r"); }
        !           956:                        switch(getkeys(str,0)) {
        !           957:                                case 'V':
        !           958:                                        viewfilecontents(&f);
        !           959:                                        CRLF;
        !           960:                                        ASYNC;
        !           961:                                        pause();
        !           962:                                        m-=F_IXBSIZE;
        !           963:                                        continue;
        !           964:                                case 'E':   /* edit file information */
        !           965:                                        if(dir_op(dirnum)) {
        !           966:                                                bputs(text[EditFilename]);
        !           967:                                                strcpy(str,fname);
        !           968:                                                getstr(str,12,K_EDIT|K_AUTODEL|K_UPPER);
        !           969:                                                if(strcmp(str,fname)) { /* rename */
        !           970:                                                        padfname(str,path);
        !           971:                                                        if(findfile(&cfg,f.dir,path))
        !           972:                                                                bprintf(text[FileAlreadyThere],path);
        !           973:                                                        else {
        !           974:                                                                sprintf(path,"%s%s",dirpath,fname);
        !           975:                                                                sprintf(tmp,"%s%s",dirpath,str);
        !           976:                                                                if(rename(path,tmp))
        !           977:                                                                        bprintf(text[CouldntRenameFile],path,tmp);
        !           978:                                                                else {
        !           979:                                                                        bprintf(text[FileRenamed],path,tmp);
        !           980:                                                                        strcpy(fname,str);
        !           981:                                                                        removefiledat(&cfg,&f);
        !           982:                                                                        strcpy(f.name,padfname(str,tmp));
        !           983:                                                                        addfiledat(&cfg,&f); } } } }
        !           984:                                        bputs(text[EditDescription]);
        !           985:                                        getstr(f.desc,LEN_FDESC,K_LINE|K_EDIT|K_AUTODEL);
        !           986:                                        if(f.misc&FM_EXTDESC) {
        !           987:                                                if(!noyes(text[DeleteExtDescriptionQ])) {
        !           988:                                                        remove(str);
        !           989:                                                        f.misc&=~FM_EXTDESC; } }
        !           990:                                        if(!dir_op(dirnum)) {
        !           991:                                                putfiledat(&cfg,&f);
        !           992:                                                break; }
        !           993:                                        bputs(text[EditUploader]);
        !           994:                                        getstr(f.uler,LEN_ALIAS,K_UPRLWR|K_EDIT|K_AUTODEL);
        !           995:                                        ultoa(f.cdt,str,10);
        !           996:                                        bputs(text[EditCreditValue]);
        !           997:                                        getstr(str,7,K_NUMBER|K_EDIT|K_AUTODEL);
        !           998:                                        f.cdt=atol(str);
        !           999:                                        ultoa(f.timesdled,str,10);
        !          1000:                                        bputs(text[EditTimesDownloaded]);
        !          1001:                                        getstr(str,5,K_NUMBER|K_EDIT|K_AUTODEL);
        !          1002:                                        f.timesdled=atoi(str);
        !          1003:                                        if(f.opencount) {
        !          1004:                                                ultoa(f.opencount,str,10);
        !          1005:                                                bputs(text[EditOpenCount]);
        !          1006:                                                getstr(str,3,K_NUMBER|K_EDIT|K_AUTODEL);
        !          1007:                                                f.opencount=atoi(str); }
        !          1008:                                        if(cfg.altpaths || f.altpath) {
        !          1009:                                                ultoa(f.altpath,str,10);
        !          1010:                                                bputs(text[EditAltPath]);
        !          1011:                                                getstr(str,3,K_NUMBER|K_EDIT|K_AUTODEL);
        !          1012:                                                f.altpath=atoi(str);
        !          1013:                                                if(f.altpath>cfg.altpaths)
        !          1014:                                                        f.altpath=0; }
        !          1015:                                        putfiledat(&cfg,&f);
        !          1016:                                        inputnstime(&f.dateuled);
        !          1017:                                        update_uldate(&f);
        !          1018:                                        break;
        !          1019:                                case 'F':   /* delete file only */
        !          1020:                                        sprintf(str,"%s%s",dirpath,fname);
        !          1021:                                        if(!fexist(str))
        !          1022:                                                bputs(text[FileNotThere]);
        !          1023:                                        else {
        !          1024:                                                if(!noyes(text[AreYouSureQ])) {
        !          1025:                                                        if(remove(str))
        !          1026:                                                                bprintf(text[CouldntRemoveFile],str);
        !          1027:                                                        else {
        !          1028:                                                                sprintf(tmp,"Deleted %s",str);
        !          1029:                                                                logline(nulstr,tmp); } } }
        !          1030:                                        break;
        !          1031:                                case 'R':   /* remove file from database */
        !          1032:                                        if(noyes(text[AreYouSureQ]))
        !          1033:                                                break;
        !          1034:                                        removefiledat(&cfg,&f);
        !          1035:                                        sprintf(str,"Removed %s from %s %s",f.name
        !          1036:                                                ,cfg.lib[cfg.dir[f.dir]->lib]->sname,cfg.dir[f.dir]->sname);
        !          1037:                                        logline("U-",str);
        !          1038:                                        sprintf(str,"%s%s",dirpath,fname);
        !          1039:                                        if(fexist(str)) {
        !          1040:                                                if(dir_op(dirnum)) {
        !          1041:                                                        if(!noyes(text[DeleteFileQ])) {
        !          1042:                                                                if(remove(str))
        !          1043:                                                                        bprintf(text[CouldntRemoveFile],str);
        !          1044:                                                                else {
        !          1045:                                                                        sprintf(tmp,"Deleted %s",str);
        !          1046:                                                                        logline(nulstr,tmp); } } }
        !          1047:                                                else if(remove(str))    /* always remove if not sysop */
        !          1048:                                                        bprintf(text[CouldntRemoveFile],str); }
        !          1049:                                        if(dir_op(dirnum) || useron.exempt&FLAG('R')) {
        !          1050:                                                i=cfg.lib[cfg.dir[f.dir]->lib]->offline_dir;
        !          1051:                                                if(i!=dirnum && i!=INVALID_DIR
        !          1052:                                                        && !findfile(&cfg,i,f.name)) {
        !          1053:                                                        sprintf(str,text[AddToOfflineDirQ]
        !          1054:                                                                ,fname,cfg.lib[cfg.dir[i]->lib]->sname,cfg.dir[i]->sname);
        !          1055:                                                        if(yesno(str)) {
        !          1056:                                                                getextdesc(f.dir,f.datoffset,ext);
        !          1057:                                                                f.dir=i;
        !          1058:                                                                addfiledat(&cfg,&f);
        !          1059:                                                                if(f.misc&FM_EXTDESC)
        !          1060:                                                                        putextdesc(f.dir,f.datoffset,ext); } } }
        !          1061:                                        if(dir_op(dirnum) || stricmp(f.uler,useron.alias)) {
        !          1062:                                                if(noyes(text[RemoveCreditsQ]))
        !          1063:        /* Fall through */      break; }
        !          1064:                                case 'C':   /* remove credits only */
        !          1065:                                        if((i=matchuser(&cfg,f.uler))==0) {
        !          1066:                                                bputs(text[UnknownUser]);
        !          1067:                                                break; }
        !          1068:                                        if(dir_op(dirnum)) {
        !          1069:                                                usrcdt=(ulong)(f.cdt*(cfg.dir[f.dir]->up_pct/100.0));
        !          1070:                                                if(f.timesdled)     /* all downloads */
        !          1071:                                                        usrcdt+=(ulong)((long)f.timesdled
        !          1072:                                                                *f.cdt*(cfg.dir[f.dir]->dn_pct/100.0));
        !          1073:                                                ultoa(usrcdt,str,10);
        !          1074:                                                bputs(text[CreditsToRemove]);
        !          1075:                                                getstr(str,10,K_NUMBER|K_LINE|K_EDIT|K_AUTODEL);
        !          1076:                                                f.cdt=atol(str); }
        !          1077:                                        usrcdt=adjustuserrec(&cfg,i,U_CDT,10,-(long)f.cdt);
        !          1078:                                        if(i==useron.number)
        !          1079:                                                useron.cdt=usrcdt;
        !          1080:                                        sprintf(str,text[FileRemovedUserMsg]
        !          1081:                                                ,f.name,f.cdt ? ultoac(f.cdt,tmp) : text[No]);
        !          1082:                                        putsmsg(&cfg,i,str);
        !          1083:                                        usrcdt=adjustuserrec(&cfg,i,U_ULB,10,-f.size);
        !          1084:                                        if(i==useron.number)
        !          1085:                                                useron.ulb=usrcdt;
        !          1086:                                        usrcdt=adjustuserrec(&cfg,i,U_ULS,5,-1);
        !          1087:                                        if(i==useron.number)
        !          1088:                                                useron.uls=(ushort)usrcdt;
        !          1089:                                        break;
        !          1090:                                case 'M':   /* move the file to another dir */
        !          1091:                                        CRLF;
        !          1092:                                        for(i=0;i<usrlibs;i++)
        !          1093:                                                bprintf(text[MoveToLibLstFmt],i+1,cfg.lib[usrlib[i]]->lname);
        !          1094:                                        SYNC;
        !          1095:                                        bprintf(text[MoveToLibPrompt],cfg.dir[dirnum]->lib+1);
        !          1096:                                        if((i=getnum(usrlibs))==-1)
        !          1097:                                                continue;
        !          1098:                                        if(!i)
        !          1099:                                                i=cfg.dir[dirnum]->lib;
        !          1100:                                        else
        !          1101:                                                i--;
        !          1102:                                        CRLF;
        !          1103:                                        for(j=0;j<usrdirs[i];j++)
        !          1104:                                                bprintf(text[MoveToDirLstFmt]
        !          1105:                                                        ,j+1,cfg.dir[usrdir[i][j]]->lname);
        !          1106:                                        SYNC;
        !          1107:                                        bprintf(text[MoveToDirPrompt],usrdirs[i]);
        !          1108:                                        if((j=getnum(usrdirs[i]))==-1)
        !          1109:                                                continue;
        !          1110:                                        if(!j)
        !          1111:                                                j=usrdirs[i]-1;
        !          1112:                                        else j--;
        !          1113:                                        CRLF;
        !          1114:                                        if(findfile(&cfg,usrdir[i][j],f.name)) {
        !          1115:                                                bprintf(text[FileAlreadyThere],f.name);
        !          1116:                                                break; }
        !          1117:                                        getextdesc(f.dir,f.datoffset,ext);
        !          1118:                                        removefiledat(&cfg,&f);
        !          1119:                                        if(f.dir==cfg.upload_dir || f.dir==cfg.sysop_dir)
        !          1120:                                                f.dateuled=time(NULL);
        !          1121:                                        f.dir=usrdir[i][j];
        !          1122:                                        addfiledat(&cfg,&f);
        !          1123:                                        bprintf(text[MovedFile],f.name
        !          1124:                                                ,cfg.lib[cfg.dir[f.dir]->lib]->sname,cfg.dir[f.dir]->sname);
        !          1125:                                        sprintf(str,"Moved %s to %s %s",f.name
        !          1126:                                                ,cfg.lib[cfg.dir[f.dir]->lib]->sname,cfg.dir[f.dir]->sname);
        !          1127:                                        logline(nulstr,str);
        !          1128:                                        if(!f.altpath) {    /* move actual file */
        !          1129:                                                sprintf(str,"%s%s",cfg.dir[dirnum]->path,fname);
        !          1130:                                                if(fexist(str)) {
        !          1131:                                                        sprintf(path,"%s%s",cfg.dir[f.dir]->path,fname);
        !          1132:                                                        mv(str,path,0); } }
        !          1133:                                        if(f.misc&FM_EXTDESC)
        !          1134:                                                putextdesc(f.dir,f.datoffset,ext);
        !          1135:                                        break;
        !          1136:                                case 'Q':   /* quit */
        !          1137:                                        found=-1;
        !          1138:                                        done=1;
        !          1139:                                        break; } }
        !          1140:                else if(mode==FI_DOWNLOAD || mode==FI_USERXFER) {
        !          1141:                        sprintf(path,"%s%s",dirpath,fname);
        !          1142:                        if(f.size<1L) { /* getfiledat will set this to -1 if non-existant */
        !          1143:                                SYNC;       /* and 0 byte files shouldn't be d/led */
        !          1144:                                mnemonics(text[QuitOrNext]);
        !          1145:                                if(getkeys("\rQ",0)=='Q') {
        !          1146:                                        found=-1;
        !          1147:                                        break; }
        !          1148:                                continue; }
        !          1149:                        if(!(cfg.dir[f.dir]->misc&DIR_FREE) && !(useron.exempt&FLAG('D'))
        !          1150:                                && f.cdt>(useron.cdt+useron.freecdt)) {
        !          1151:                                SYNC;
        !          1152:                                bprintf(text[YouOnlyHaveNCredits]
        !          1153:                                        ,ultoac(useron.cdt+useron.freecdt,tmp));
        !          1154:                                mnemonics(text[QuitOrNext]);
        !          1155:                                if(getkeys("\rQ",0)=='Q') {
        !          1156:                                        found=-1;
        !          1157:                                        break; }
        !          1158:                                continue; }
        !          1159:                        if(!chk_ar(cfg.dir[f.dir]->dl_ar,&useron)) {
        !          1160:                                SYNC;
        !          1161:                                bputs(text[CantDownloadFromDir]);
        !          1162:                                mnemonics(text[QuitOrNext]);
        !          1163:                                if(getkeys("\rQ",0)=='Q') {
        !          1164:                                        found=-1;
        !          1165:                                        break; }
        !          1166:                                continue; }
        !          1167:                        if(!(cfg.dir[f.dir]->misc&DIR_TFREE) && f.timetodl>timeleft && !dir_op(dirnum)
        !          1168:                                && !(useron.exempt&FLAG('T'))) {
        !          1169:                                SYNC;
        !          1170:                                bputs(text[NotEnoughTimeToDl]);
        !          1171:                                mnemonics(text[QuitOrNext]);
        !          1172:                                if(getkeys("\rQ",0)=='Q') {
        !          1173:                                        found=-1;
        !          1174:                                        break; }
        !          1175:                                continue; }
        !          1176:                        menu("dlprot");
        !          1177:                        openfile(&f);
        !          1178:                        SYNC;
        !          1179:                        mnemonics(text[ProtocolBatchQuitOrNext]);
        !          1180:                        strcpy(str,"BQ\r");
        !          1181:                        for(i=0;i<cfg.total_prots;i++)
        !          1182:                                if(cfg.prot[i]->dlcmd[0]
        !          1183:                                        && chk_ar(cfg.prot[i]->ar,&useron)) {
        !          1184:                                        sprintf(tmp,"%c",cfg.prot[i]->mnemonic);
        !          1185:                                        strcat(str,tmp); }
        !          1186:        //                ungetkey(useron.prot);
        !          1187:                        ch=(char)getkeys(str,0);
        !          1188:                        if(ch=='Q') {
        !          1189:                                found=-1;
        !          1190:                                done=1; }
        !          1191:                        else if(ch=='B') {
        !          1192:                                if(!addtobatdl(&f)) {
        !          1193:                                        closefile(&f);
        !          1194:                                        break; } }
        !          1195:                        else if(ch!=CR) {
        !          1196:                                for(i=0;i<cfg.total_prots;i++)
        !          1197:                                        if(cfg.prot[i]->dlcmd[0] && cfg.prot[i]->mnemonic==ch
        !          1198:                                                && chk_ar(cfg.prot[i]->ar,&useron))
        !          1199:                                                break;
        !          1200:                                if(i<cfg.total_prots) {
        !          1201:                                        if(online==ON_LOCAL) {
        !          1202:                                                bputs(text[EnterPath]);
        !          1203:                                                if(getstr(path,60,K_UPPER|K_LINE)) {
        !          1204:                                                        backslash(path);
        !          1205:                                                        strcat(path,fname);
        !          1206:                                                        sprintf(str,"%s%s",dirpath,fname);
        !          1207:                                                        if(!mv(str,path,1))
        !          1208:                                                                downloadfile(&f);
        !          1209:                                                        for(j=0;j<cfg.total_dlevents;j++)
        !          1210:                                                                if(!stricmp(cfg.dlevent[j]->ext,f.name+9)
        !          1211:                                                                        && chk_ar(cfg.dlevent[j]->ar,&useron)) {
        !          1212:                                                                        bputs(cfg.dlevent[j]->workstr);
        !          1213:                                                                        external(cmdstr(cfg.dlevent[j]->cmd,path,nulstr
        !          1214:                                                                                ,NULL)
        !          1215:                                                                                ,EX_OUTL);
        !          1216:                                                                        CRLF; }
        !          1217:                                                                } }
        !          1218:                                        else {
        !          1219:                                                delfiles(cfg.temp_dir,ALLFILES);
        !          1220:                                                if(cfg.dir[f.dir]->seqdev) {
        !          1221:                                                        lncntr=0;
        !          1222:                                                        seqwait(cfg.dir[f.dir]->seqdev);
        !          1223:                                                        bprintf(text[RetrievingFile],fname);
        !          1224:                                                        sprintf(str,"%s%s",dirpath,fname);
        !          1225:                                                        sprintf(path,"%s%s",cfg.temp_dir,fname);
        !          1226:                                                        mv(str,path,1); /* copy the file to temp dir */
        !          1227:                                                        getnodedat(cfg.node_num,&thisnode,1);
        !          1228:                                                        thisnode.aux=0xf0;
        !          1229:                                                        putnodedat(cfg.node_num,&thisnode);
        !          1230:                                                        CRLF; }
        !          1231:                                                for(j=0;j<cfg.total_dlevents;j++)
        !          1232:                                                        if(!stricmp(cfg.dlevent[j]->ext,f.name+9)
        !          1233:                                                                && chk_ar(cfg.dlevent[j]->ar,&useron)) {
        !          1234:                                                                bputs(cfg.dlevent[j]->workstr);
        !          1235:                                                                external(cmdstr(cfg.dlevent[j]->cmd,path,nulstr,NULL)
        !          1236:                                                                        ,EX_OUTL);
        !          1237:                                                                CRLF; }
        !          1238:                                                getnodedat(cfg.node_num,&thisnode,1);
        !          1239:                                                action=NODE_DLNG;
        !          1240:                                                t=now+f.timetodl;
        !          1241:                                                tm=gmtime(&t);
        !          1242:                                                if(tm==NULL)
        !          1243:                                                        break;
        !          1244:                                                thisnode.aux=(tm->tm_hour*60)+tm->tm_min;
        !          1245:                                                putnodedat(cfg.node_num,&thisnode); /* calculate ETA */
        !          1246:                                                start=time(NULL);
        !          1247:                                                j=protocol(cmdstr(cfg.prot[i]->dlcmd,path,nulstr,NULL),0);
        !          1248:                                                end=time(NULL);
        !          1249:                                                if(cfg.dir[f.dir]->misc&DIR_TFREE)
        !          1250:                                                        starttime+=end-start;
        !          1251:                                                if(cfg.prot[i]->misc&PROT_DSZLOG) {
        !          1252:                                                        if(checkprotlog(&f))
        !          1253:                                                                downloadfile(&f);
        !          1254:                                                        else
        !          1255:                                                                notdownloaded(f.size,start,end); }
        !          1256:                                                else {
        !          1257:                                                        if(!j)
        !          1258:                                                                downloadfile(&f);
        !          1259:                                                        else {
        !          1260:                                                                bprintf(text[FileNotSent],f.name);
        !          1261:                                                                notdownloaded(f.size,start,end); } }
        !          1262:                                                delfiles(cfg.temp_dir,ALLFILES);
        !          1263:                                                autohangup(); } } }
        !          1264:                        closefile(&f); }
        !          1265:                if(filespec[0] && !strchr(filespec,'*') && !strchr(filespec,'?')) 
        !          1266:                        break; 
        !          1267:        }
        !          1268:        FREE((char *)ixbbuf);
        !          1269:        if(usrxfrbuf)
        !          1270:                FREE(usrxfrbuf);
        !          1271:        return(found);
        !          1272: }
        !          1273: 
        !          1274: /****************************************************************************/
        !          1275: /* Prints one file's information on a single line to a file 'file'          */
        !          1276: /****************************************************************************/
        !          1277: void sbbs_t::listfiletofile(char *fname, char HUGE16 *buf, uint dirnum, int file)
        !          1278: {
        !          1279:     char       str[256];
        !          1280:        char    tmp[512];
        !          1281:     uchar      alt;
        !          1282:     ulong      cdt;
        !          1283:        bool    exist=true;
        !          1284: 
        !          1285:        strcpy(str,fname);
        !          1286:        if(buf[F_MISC]!=ETX && (buf[F_MISC]-SP)&FM_EXTDESC)
        !          1287:                strcat(str,"+");
        !          1288:        else
        !          1289:                strcat(str," ");
        !          1290:        write(file,str,13);
        !          1291:        getrec((char *)buf,F_ALTPATH,2,str);
        !          1292:        alt=(uchar)ahtoul(str);
        !          1293:        sprintf(str,"%s%s",alt>0 && alt<=cfg.altpaths ? cfg.altpath[alt-1]
        !          1294:                : cfg.dir[dirnum]->path,unpadfname(fname,tmp));
        !          1295:        if(cfg.dir[dirnum]->misc&DIR_FCHK && !fexist(str))
        !          1296:                exist=false;
        !          1297:        getrec((char *)buf,F_CDT,LEN_FCDT,str);
        !          1298:        cdt=atol(str);
        !          1299:        if(!cdt)
        !          1300:                strcpy(str,"   FREE");
        !          1301:        else
        !          1302:                sprintf(str,"%7lu",cdt);
        !          1303:        if(exist)
        !          1304:                strcat(str," ");
        !          1305:        else
        !          1306:                strcat(str,"-");
        !          1307:        write(file,str,8);
        !          1308:        getrec((char *)buf,F_DESC,LEN_FDESC,str);
        !          1309:        write(file,str,strlen(str));
        !          1310:        write(file,crlf,2);
        !          1311: }
        !          1312: 
        !          1313: int extdesclines(char *str)
        !          1314: {
        !          1315:        int i,lc,last;
        !          1316: 
        !          1317:        for(i=lc=last=0;str[i];i++)
        !          1318:                if(str[i]==LF || i-last>LEN_FDESC) {
        !          1319:                        lc++;
        !          1320:                        last=i; }
        !          1321:        return(lc);
        !          1322: }

unix.superglobalmegacorp.com

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