Annotation of researchv9/jtools/src/sam/mesg.c, revision 1.1

1.1     ! root        1: #include "sam.h"
        !             2: 
        !             3: Header h;
        !             4: uchar  indata[DATASIZE];
        !             5: uchar  outdata[DATASIZE+3];
        !             6: short  outcount;
        !             7: long   inlong();
        !             8: Posn   cmdpt;
        !             9: Posn   cmdptadv;
        !            10: Buffer *snarfbuf;
        !            11: 
        !            12: log(out, s)
        !            13:        char *s;
        !            14: {
        !            15:        static fd=0;
        !            16:        if(fd<=0)
        !            17:                fd=creat("/usr/rob/sam.out", 0666);
        !            18:        fprint(fd, "%s%s\n", out? "out: " : "in:  ", s);
        !            19: }
        !            20: logn(out, n)
        !            21:        int n;
        !            22: {
        !            23:        char buf[32];
        !            24:        sprint(buf, "%d", n);
        !            25:        log(out, buf);
        !            26: }
        !            27: #ifdef DIST
        !            28: #define        log(a, b)
        !            29: #define logn(a, b)
        !            30: #endif
        !            31: rcvchar(){
        !            32:        static uchar buf[64];
        !            33:        static i, nleft=0;
        !            34:        if(nleft<=0){
        !            35:                nleft=read(0, (char *)buf, sizeof buf);
        !            36:                if(nleft<=0)
        !            37:                        return -1;
        !            38:                i=0;
        !            39:        }
        !            40:        --nleft;
        !            41:        return buf[i++];
        !            42: }
        !            43: rcv(){
        !            44:        register c;
        !            45:        static state=0;
        !            46:        static count=0;
        !            47:        static i=0;
        !            48:        while((c=rcvchar())!=-1)
        !            49:                switch(state){
        !            50:                case 0:
        !            51:                        h.type=c;
        !            52:                        state++;
        !            53:                        break;
        !            54:                case 1:
        !            55:                        h.count0=c;
        !            56:                        state++;
        !            57:                        break;
        !            58:                case 2:
        !            59:                        h.count1=c;
        !            60:                        count=h.count0|(h.count1<<8);
        !            61:                        i=0;
        !            62:                        if(count>DATASIZE)
        !            63:                                panic("count>DATASIZE");
        !            64:                        if(count==0)
        !            65:                                goto zerocount;
        !            66:                        state++;
        !            67:                        break;
        !            68:                case 3:
        !            69:                        indata[i++]=c;
        !            70:                        if(i==count){
        !            71:                zerocount:
        !            72:                                state=count=0;
        !            73:                                return inmesg(h.type);
        !            74:                        }
        !            75:                        break;
        !            76:                }
        !            77:        return 0;
        !            78: }
        !            79: File *
        !            80: whichfile(tag)
        !            81:        register tag;
        !            82: {
        !            83:        register i;
        !            84:        for(i=0; i<file.nused; i++)
        !            85:                if(file.ptr[i]->tag==tag)
        !            86:                        return file.ptr[i];
        !            87:        hiccough((char *)0);
        !            88:        /*NOTREACHED*/
        !            89:        return 0;
        !            90: }
        !            91: inmesg(type)
        !            92:        Tmesg type;
        !            93: {
        !            94:        uchar buf[1025];
        !            95:        register i, m;
        !            96:        long l;
        !            97:        register File *f;
        !            98:        register Posn p0, p1;
        !            99:        Range r;
        !           100:        switch(type){
        !           101:        case -1:
        !           102:                panic("rcv error");
        !           103:        default:
        !           104:                panic("rcv unknown");
        !           105:        case Tcut:
        !           106:                log(0, "Tcut");
        !           107:                f=whichfile(inshort(0));
        !           108:                p0=inlong(2);
        !           109:                p1=inlong(6);
        !           110:                logn(0, (int)p0);
        !           111:                logn(0, (int)p1);
        !           112:                Fdelete(f, p0, p1);
        !           113:                if(Fupdate(f, FALSE, FALSE))
        !           114:                        modnum++;
        !           115:                f->dot.r.p1=f->dot.r.p2=p0;
        !           116:                f->tdot=f->dot.r;   /* terminal knows the value of dot already */
        !           117:                break;
        !           118:        case Tpaste:
        !           119:                log(0, "Tpaste");
        !           120:                f=whichfile(inshort(0));
        !           121:                p0=inlong(2);
        !           122:                logn(0, (int)p0);
        !           123:                for(l=0; l<snarfbuf->nbytes; l+=m){
        !           124:                        m=snarfbuf->nbytes-l;
        !           125:                        if(m>BLOCKSIZE)
        !           126:                                m=BLOCKSIZE;
        !           127:                        Bread(snarfbuf, genbuf, m, l);
        !           128:                        Finsert(f, tempstr(genbuf, m), p0);
        !           129:                }
        !           130:                if(Fupdate(f, FALSE, TRUE))
        !           131:                        modnum++;
        !           132:                f->dot.r.p1=p0;
        !           133:                f->dot.r.p2=p0+snarfbuf->nbytes;
        !           134:                f->tdot.p1= -1; /* force telldot to tell (arguably a BUG) */
        !           135:                telldot(f);
        !           136:                outTs(Hunlockfile, f->tag);
        !           137:                break;
        !           138:        case Tsnarf:
        !           139:                log(0, "Tsnarf");
        !           140:                snarf(whichfile(inshort(0)), inlong(2), inlong(6));
        !           141:                break;
        !           142:        case Ttype:
        !           143:                log(0, "Ttype");
        !           144:                f=whichfile(inshort(0));
        !           145:                p0=inlong(2);
        !           146:                logn(0, (int)p0);
        !           147:                log(0, (char *)indata+6);
        !           148:                i=strlen(indata+6);
        !           149:                Finsert(f, tempstr(indata+6, i), p0);
        !           150:                if(Fupdate(f, FALSE, FALSE))
        !           151:                        modnum++;
        !           152:                if(f==cmd && p0==f->nbytes-i && i>0 && indata[i+6-1]=='\n')
        !           153:                        termcommand();
        !           154:                f->dot.r.p1=f->dot.r.p2=p0+i; /* terminal knows this already */
        !           155:                f->tdot=f->dot.r;
        !           156:                break;
        !           157:        case Tstartfile:
        !           158:                log(0, "Tstartfile");
        !           159:                f=whichfile(inshort(0));
        !           160:                if(!f->rasp)    /* this might be a duplicate message */
        !           161:                        f->rasp=new(List, 1);
        !           162:                current(f);
        !           163:                outTsl(Hbindname, f->tag, inlong(2));
        !           164:                outTs(Hcurrent, f->tag);
        !           165:                logn(0, f->tag);
        !           166:                if(f->state==Unread)
        !           167:                        load(f);
        !           168:                else{
        !           169:                        if(f->nbytes>0){
        !           170:                                rgrow(f->rasp, 0L, f->nbytes);
        !           171:                                outTsll(Hgrow, f->tag, 0L, f->nbytes);
        !           172:                        }
        !           173:                        outTs(Hcheck0, f->tag);
        !           174:                        moveto(f, f->dot.r);
        !           175:                }
        !           176:                break;
        !           177:        case Tstartcmdfile:
        !           178:                log(0, "Tstartcmdfile");
        !           179:                l=inlong(0);
        !           180:                strdup(&genstr, (uchar *)"~~sam~~");
        !           181:                cmd=newfile();
        !           182:                outTsl(Hbindname, cmd->tag, l);
        !           183:                outTs(Hcurrent, cmd->tag);
        !           184:                Fsetname(cmd);
        !           185:                cmd->rasp=new(List, 1);
        !           186:                cmd->state=Clean;
        !           187:                if(cmdstr.n){
        !           188:                        Finsert(cmd, &cmdstr, 0L);
        !           189:                        strdelete(&cmdstr, 0L, (Posn)cmdstr.n);
        !           190:                }
        !           191:                Fupdate(cmd, FALSE, TRUE);
        !           192:                outT0(Hunlock);
        !           193:                break;
        !           194:        case Tstartnewfile:
        !           195:                log(0, "Tstartnewfile");
        !           196:                l=inlong(0);
        !           197:                strdup(&genstr, (uchar *)"");
        !           198:                f=newfile();
        !           199:                f->rasp=new(List, 1);
        !           200:                outTsl(Hbindname, f->tag, l);
        !           201:                Fsetname(f);
        !           202:                outTs(Hcurrent, f->tag);
        !           203:                current(f);
        !           204:                load(f);
        !           205:                break;
        !           206:        case Trequest:
        !           207:                log(0, "Trequest");
        !           208:                f=whichfile(inshort(0));
        !           209:                p0=inlong(2);
        !           210:                logn(0, (int)p0);
        !           211:                logn(0, inshort(6));
        !           212:                if(f->state==Unread)
        !           213:                        panic("Trequest: unread");
        !           214:                p1=p0+inshort(6);
        !           215:                if(p0>f->nbytes){ /* can happen e.g. scrolling during command */
        !           216:                        buf[0]=0;
        !           217:                        r.p1=r.p2=f->nbytes;
        !           218:                }else{
        !           219:                        if(p1>f->nbytes)
        !           220:                                p1=f->nbytes;
        !           221:                        r=rdata(f->rasp, p0, p1-p0);
        !           222:                        i=r.p2-r.p1;
        !           223:                        if(Fchars(f, buf, r.p1, r.p2)!=i)
        !           224:                                panic("Trequest 2");
        !           225:                        buf[i]=0;
        !           226:                }
        !           227:                outTslS(Hdata, f->tag, r.p1, buf);
        !           228:                break;
        !           229:        case Twrite:
        !           230:                log(0, "Twrite");
        !           231:                f=whichfile(inshort(0));
        !           232:                addr.r.p1=0;
        !           233:                addr.r.p2=f->nbytes;
        !           234:                if(f->name.s[0]==0)
        !           235:                        error(Enoname);
        !           236:                strdupstr(&genstr, &f->name);
        !           237:                writef(f);
        !           238:                break;
        !           239:        case Tworkfile:
        !           240:                log(0, "Tworkfile");
        !           241:                logn(0, (int)inlong(2));
        !           242:                logn(0, (int)inlong(6));
        !           243:                f=whichfile(inshort(0));
        !           244:                current(f);
        !           245:                f->dot.r.p1=inlong(2);
        !           246:                f->dot.r.p2=inlong(6);
        !           247:                f->tdot=f->dot.r;
        !           248:                break;
        !           249:        case Tcheck:
        !           250:                log(0, "Tcheck");
        !           251:                /* go through whichfile to check the tag */
        !           252:                outTs(Hcheck, whichfile(inshort(0))->tag);
        !           253:                break;
        !           254:        case Torigin:
        !           255:                log(0, "Torigin");
        !           256:                logn(0, (int)inlong(6));
        !           257:                lookorigin(whichfile(inshort(0)), inlong(2), inlong(6));
        !           258:                break;
        !           259:        case Tclose:
        !           260:                log(0, "Tclose");
        !           261:                f=whichfile(inshort(0));
        !           262:                current(f);
        !           263:                trytoclose(f);
        !           264:                break;
        !           265:        case Tlook:
        !           266:                log(0, "Tlook");
        !           267:                f=whichfile(inshort(0));
        !           268:                p0=inlong(2);
        !           269:                p1=inlong(6);
        !           270:                setgenstr(f, p0, p1);
        !           271:                for(l=0; l<genstr.n; l++){
        !           272:                        i=genstr.s[l];
        !           273:                        if(i && !('a'<=i && i<='z') && !('A'<=i && i<='Z'))
        !           274:                                strinsert(&genstr, tempstr((uchar *)"\\", 1), l++);
        !           275:                }
        !           276:                straddc(&genstr, '\0');
        !           277: {Regexp poot;
        !           278: poot.text=genstr;
        !           279:                nextmatch(f, &poot, p1, 1);     /* BUGGERED */
        !           280:  }
        !           281:                moveto(f, sel);
        !           282:                break;
        !           283:        case Tsearch:
        !           284:                log(0, "Tsearch");
        !           285:                if(curfile==0)
        !           286:                        error(Enofile);
        !           287:                if(lastpat.n==0)
        !           288:                        panic("Tsearch");
        !           289: {Regexp poot;
        !           290: poot.text=lastpat;
        !           291:                nextmatch(curfile, &poot, curfile->dot.r.p2, 1);        /* BUGGERED */
        !           292:  }
        !           293:                moveto(curfile, sel);
        !           294:                break;
        !           295:        case Tsend:
        !           296:                log(0, "Tsend");
        !           297:                p0=inlong(2);
        !           298:                p1=inlong(6);
        !           299:                setgenstr(cmd, p0, p1);
        !           300:                Bdelete(snarfbuf, (Posn)0, snarfbuf->nbytes);
        !           301:                Binsert(snarfbuf, &genstr, (Posn)0);
        !           302:                outTl(Hsnarflen, (long)genstr.n);
        !           303:                if(genstr.s[genstr.n-1]!='\n')
        !           304:                        straddc(&genstr, '\n');
        !           305:                Fdelete(cmd, cmdpt, cmd->nbytes);
        !           306:                Finsert(cmd, &genstr, cmd->nbytes);
        !           307:                Fupdate(cmd, FALSE, TRUE);
        !           308:                cmd->dot.r.p1=cmd->dot.r.p2=cmd->nbytes;
        !           309:                telldot(cmd);
        !           310:                termcommand();
        !           311:                break;
        !           312:        case Tunlockfile:
        !           313:                log(0, "Tunlockfile");
        !           314:                outTs(Hunlockfile, whichfile(inshort(0))->tag);
        !           315:                break;
        !           316:        case Tstartsnarf:
        !           317:                log(0, "Tstartsnarf");
        !           318:                if(snarfbuf->nbytes>BLOCKSIZE)
        !           319:                        error(Etoolong);
        !           320:                outTs(Hsetsnarf, (int)snarfbuf->nbytes);
        !           321:                Bread(snarfbuf, genbuf, (int)snarfbuf->nbytes, (Posn)0);
        !           322:                Write(1, genbuf, (int)snarfbuf->nbytes);
        !           323:                break;
        !           324:        case Tsetsnarf:
        !           325:                log(0, "Tsetsnarf");
        !           326:                m=inshort(0);
        !           327:                if(m>BLOCKSIZE)
        !           328:                        error(Etoolong);
        !           329:                for(i=0; i<m; i++)
        !           330:                        genbuf[i]=rcvchar();
        !           331:                Bdelete(snarfbuf, (Posn)0, snarfbuf->nbytes);
        !           332:                Binsert(snarfbuf, tempstr(genbuf, m), (Posn)0);
        !           333:                outT0(Hunlock);
        !           334:                break;
        !           335:        case Tdclick:
        !           336:                log(0, "Tdclick");
        !           337:                f=whichfile(inshort(0));
        !           338:                p1=inlong(2);
        !           339:                doubleclick(f, p1);
        !           340:                f->tdot.p1=f->tdot.p2=p1;
        !           341:                telldot(f);
        !           342:                outTs(Hunlockfile, f->tag);
        !           343:                break;
        !           344:        case Texit:
        !           345:                log(0, "Texit");
        !           346:                return FALSE;
        !           347:        }
        !           348:        return TRUE;
        !           349: }
        !           350: snarf(f, p1, p2)
        !           351:        register File *f;
        !           352:        register Posn p1, p2;
        !           353: {
        !           354:        register Posn l;
        !           355:        register i;
        !           356:        if(p1==p2)
        !           357:                return;
        !           358:        Bdelete(snarfbuf, (Posn)0, snarfbuf->nbytes);
        !           359:        /* Stage through genbuf to avoid compaction problems */
        !           360:        for(l=p1; l<p2; l+=i){
        !           361:                i=p2-l>BLOCKSIZE? BLOCKSIZE : p2-l;
        !           362:                Fchars(f, genbuf, l, l+i);
        !           363:                Binsert(snarfbuf, tempstr(genbuf, i), snarfbuf->nbytes);
        !           364:        }
        !           365: }
        !           366: inshort(n)
        !           367: {
        !           368:        return indata[n]|(indata[n+1]<<8);
        !           369: }
        !           370: long
        !           371: inlong(n)
        !           372: {
        !           373:        return indata[n]|(indata[n+1]<<8)|
        !           374:                ((long)indata[n+2]<<16)|((long)indata[n+3]<<24);
        !           375: }
        !           376: setgenstr(f, p0, p1)
        !           377:        register File *f;
        !           378:        register Posn p0, p1;
        !           379: {
        !           380:        if(p0!=p1){
        !           381:                if(p1-p0>=TBLOCKSIZE)
        !           382:                        error(Etoolong);
        !           383:                strinsure(&genstr, p1-p0);
        !           384:                genstr.n=p1-p0;
        !           385:                Fchars(f, genstr.s, p0, p1);
        !           386:        }else{
        !           387:                if(snarfbuf->nbytes==0)
        !           388:                        error(Eempty);
        !           389:                if(snarfbuf->nbytes>TBLOCKSIZE)
        !           390:                        error(Etoolong);
        !           391:                Bread(snarfbuf, genbuf, (int)snarfbuf->nbytes, (Posn)0);
        !           392:                strinsure(&genstr, snarfbuf->nbytes);
        !           393:                bcopy(genbuf, genbuf+snarfbuf->nbytes, genstr.s, 1);
        !           394:                genstr.n=snarfbuf->nbytes;
        !           395:        }
        !           396: }
        !           397: outT0(type)
        !           398:        Hmesg type;
        !           399: {
        !           400:        outstart(type);
        !           401:        outsend();
        !           402: }
        !           403: outTl(type, l)
        !           404:        Hmesg type;
        !           405:        long l;
        !           406: {
        !           407:        outstart(type);
        !           408:        outlong(l);
        !           409:        outsend();
        !           410: }
        !           411: outTs(type, s)
        !           412:        Hmesg type;
        !           413: {
        !           414:        outstart(type);
        !           415:        logn(1, s);
        !           416:        outshort(s);
        !           417:        outsend();
        !           418: }
        !           419: outTsS(type, s1, s)
        !           420:        Hmesg type;
        !           421:        uchar *s;
        !           422: {
        !           423:        outstart(type);
        !           424:        outshort(s1);
        !           425:        outcopy(strlen(s)+1, s);
        !           426:        log(1, (char *)s);
        !           427:        outsend();
        !           428: }
        !           429: outTssl(type, s1, s2, l)
        !           430:        Hmesg type;
        !           431:        long l;
        !           432: {
        !           433:        outstart(type);
        !           434:        outshort(s1);
        !           435:        outshort(s2);
        !           436:        outlong(l);
        !           437:        outsend();
        !           438: }
        !           439: outTslS(type, s1, l1, s)
        !           440:        Hmesg type;
        !           441:        Posn l1;
        !           442:        uchar *s;
        !           443: {
        !           444:        char buf[100];
        !           445:        register i;
        !           446:        outstart(type);
        !           447:        outshort(s1);
        !           448:        outlong(l1);
        !           449:        logn(1, (int)l1);
        !           450:        outcopy(strlen(s)+1, s);
        !           451:        i=strlen(s);
        !           452:        if(i>99)
        !           453:                i=99;
        !           454:        buf[i]=0;
        !           455:        while(--i>=0)
        !           456:                buf[i]=s[i];
        !           457:        log(1, buf);
        !           458:        outsend();
        !           459: }
        !           460: outTS(type, s)
        !           461:        Hmesg type;
        !           462:        uchar *s;
        !           463: {
        !           464:        char buf[100];
        !           465:        register i;
        !           466:        outstart(type);
        !           467:        outcopy(strlen(s)+1, s);
        !           468:        i=strlen(s);
        !           469:        if(i>99)
        !           470:                i=99;
        !           471:        buf[i]=0;
        !           472:        while(--i>=0)
        !           473:                buf[i]=s[i];
        !           474:        log(1, buf);
        !           475:        outsend();
        !           476: }
        !           477: outTsllS(type, s1, l1, l2, s)
        !           478:        Hmesg type;
        !           479:        Posn l1, l2;
        !           480:        uchar *s;
        !           481: {
        !           482:        char buf[100];
        !           483:        register i;
        !           484:        outstart(type);
        !           485:        outshort(s1);
        !           486:        outlong(l1);
        !           487:        outlong(l2);
        !           488:        logn(1, (int)l1);
        !           489:        logn(1, (int)l2);
        !           490:        outcopy(strlen(s)+1, s);
        !           491:        i=strlen(s);
        !           492:        if(i>99)
        !           493:                i=99;
        !           494:        buf[i]=0;
        !           495:        while(--i>=0)
        !           496:                buf[i]=s[i];
        !           497:        log(1, buf);
        !           498:        outsend();
        !           499: }
        !           500: outTsll(type, s, l1, l2)
        !           501:        Hmesg type;
        !           502:        Posn l1, l2;
        !           503: {
        !           504:        outstart(type);
        !           505:        outshort(s);
        !           506:        outlong(l1);
        !           507:        outlong(l2);
        !           508:        logn(1, (int)l1);
        !           509:        logn(1, (int)l2);
        !           510:        outsend();
        !           511: }
        !           512: outTsl(type, s, l)
        !           513:        Hmesg type;
        !           514:        Posn l;
        !           515: {
        !           516:        outstart(type);
        !           517:        outshort(s);
        !           518:        outlong(l);
        !           519:        logn(1, (int)l);
        !           520:        outsend();
        !           521: }
        !           522: outstart(type)
        !           523:        Hmesg type;
        !           524: {
        !           525:        switch(type){
        !           526:        case Hnewname:
        !           527:                log(1, "Hnewname");
        !           528:                break;
        !           529:        case Hdelname:
        !           530:                log(1, "Hdelname");
        !           531:                break;
        !           532:        case Hmovname:
        !           533:                log(1, "Hmovname");
        !           534:                break;
        !           535:        case Hbindname:
        !           536:                log(1, "Hbindname");
        !           537:                break;
        !           538:        case Hcurrent:
        !           539:                log(1, "Hcurrent");
        !           540:                break;
        !           541:        case Hgrow:
        !           542:                log(1, "Hgrow");
        !           543:                break;
        !           544:        case Hdata:
        !           545:                log(1, "Hdata");
        !           546:                break;
        !           547:        case Hgrowdata:
        !           548:                log(1, "Hgrowdata");
        !           549:                break;
        !           550:        case Hcut:
        !           551:                log(1, "Hcut");
        !           552:                break;
        !           553:        case Hclean:
        !           554:                log(1, "Hclean");
        !           555:                break;
        !           556:        case Hdirty:
        !           557:                log(1, "Hdirty");
        !           558:                break;
        !           559:        case Hcheck0:
        !           560:                log(1, "Hcheck0");
        !           561:                break;
        !           562:        case Hcheck:
        !           563:                log(1, "Hcheck");
        !           564:                break;
        !           565:        case Hmoveto:
        !           566:                log(1, "Hmoveto");
        !           567:                break;
        !           568:        case Hsetdot:
        !           569:                log(1, "Hsetdot");
        !           570:                break;
        !           571:        case Horigin:
        !           572:                log(1, "Horigin");
        !           573:                break;
        !           574:        case Hclose:
        !           575:                log(1, "Hclose");
        !           576:                break;
        !           577:        case Hunlock:
        !           578:                log(1, "Hunlock");
        !           579:                break;
        !           580:        case Hsetpat:
        !           581:                log(1, "Hsetpat");
        !           582:                break;
        !           583:        case Hsetsnarf:
        !           584:                log(1, "Hsetsnarf");
        !           585:                break;
        !           586:        case Hsnarflen:
        !           587:                log(1, "Hsnarflen");
        !           588:                break;
        !           589:        case Hexit:
        !           590:                log(1, "Hexit");
        !           591:                break;
        !           592:        }
        !           593:        outdata[0]=type;
        !           594:        outcount=0;
        !           595: }
        !           596: outcopy(count, data)
        !           597:        register uchar *data;
        !           598: {
        !           599:        while(count--)
        !           600:                outdata[3+outcount++]= *data++; 
        !           601: }
        !           602: outshort(s)
        !           603: {
        !           604:        uchar buf[2];
        !           605:        buf[0]=s;
        !           606:        buf[1]=s>>8;
        !           607:        outcopy(2, buf);
        !           608: }
        !           609: outlong(l)
        !           610:        long l;
        !           611: {
        !           612:        uchar buf[4];
        !           613:        buf[0]=l;
        !           614:        buf[1]=l>>8;
        !           615:        buf[2]=l>>16;
        !           616:        buf[3]=l>>24;
        !           617:        outcopy(4, buf);
        !           618: }
        !           619: outsend()
        !           620: {
        !           621:        if(outcount>DATASIZE)
        !           622:                panic("outcount>DATASIZE");
        !           623:        outdata[1]=outcount;
        !           624:        outdata[2]=outcount>>8;
        !           625:        Write(1, outdata, outcount+3);
        !           626: }

unix.superglobalmegacorp.com

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