Annotation of 43BSD/bin/csh/sh.glob.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1980 Regents of the University of California.
                      3:  * All rights reserved.  The Berkeley Software License Agreement
                      4:  * specifies the terms and conditions for redistribution.
                      5:  */
                      6: 
                      7: #ifndef lint
                      8: static char *sccsid = "@(#)sh.glob.c   5.4 (Berkeley) 5/13/86";
                      9: #endif
                     10: 
                     11: #include "sh.h"
                     12: #include <sys/dir.h>
                     13: 
                     14: /*
                     15:  * C Shell
                     16:  */
                     17: 
                     18: int    globcnt;
                     19: 
                     20: char   *gpath, *gpathp, *lastgpathp;
                     21: int    globbed;
                     22: bool   noglob;
                     23: bool   nonomatch;
                     24: char   *entp;
                     25: char   **sortbas;
                     26: int    sortscmp();
                     27: 
                     28: #define sort() qsort((char *)sortbas, &gargv[gargc] - sortbas, \
                     29:                      sizeof(*sortbas), sortscmp), sortbas = &gargv[gargc]
                     30: 
                     31: 
                     32: char **
                     33: glob(v)
                     34:        register char **v;
                     35: {
                     36:        char agpath[BUFSIZ];
                     37:        char *agargv[GAVSIZ];
                     38: 
                     39:        gpath = agpath; gpathp = gpath; *gpathp = 0;
                     40:        lastgpathp = &gpath[sizeof agpath - 2];
                     41:        ginit(agargv); globcnt = 0;
                     42: #ifdef GDEBUG
                     43:        printf("glob entered: "); blkpr(v); printf("\n");
                     44: #endif
                     45:        noglob = adrof("noglob") != 0;
                     46:        nonomatch = adrof("nonomatch") != 0;
                     47:        globcnt = noglob | nonomatch;
                     48:        while (*v)
                     49:                collect(*v++);
                     50: #ifdef GDEBUG
                     51:        printf("glob done, globcnt=%d, gflag=%d: ", globcnt, gflag); blkpr(gargv); printf("\n");
                     52: #endif
                     53:        if (globcnt == 0 && (gflag&1)) {
                     54:                blkfree(gargv), gargv = 0;
                     55:                return (0);
                     56:        } else
                     57:                return (gargv = copyblk(gargv));
                     58: }
                     59: 
                     60: ginit(agargv)
                     61:        char **agargv;
                     62: {
                     63: 
                     64:        agargv[0] = 0; gargv = agargv; sortbas = agargv; gargc = 0;
                     65:        gnleft = NCARGS - 4;
                     66: }
                     67: 
                     68: collect(as)
                     69:        register char *as;
                     70: {
                     71:        register int i;
                     72: 
                     73:        if (any('`', as)) {
                     74: #ifdef GDEBUG
                     75:                printf("doing backp of %s\n", as);
                     76: #endif
                     77:                (void) dobackp(as, 0);
                     78: #ifdef GDEBUG
                     79:                printf("backp done, acollect'ing\n");
                     80: #endif
                     81:                for (i = 0; i < pargc; i++)
                     82:                        if (noglob) {
                     83:                                Gcat(pargv[i], "");
                     84:                                sortbas = &gargv[gargc];
                     85:                        } else
                     86:                                acollect(pargv[i]);
                     87:                if (pargv)
                     88:                        blkfree(pargv), pargv = 0;
                     89: #ifdef GDEBUG
                     90:                printf("acollect done\n");
                     91: #endif
                     92:        } else if (noglob || eq(as, "{") || eq(as, "{}")) {
                     93:                Gcat(as, "");
                     94:                sort();
                     95:        } else
                     96:                acollect(as);
                     97: }
                     98: 
                     99: acollect(as)
                    100:        register char *as;
                    101: {
                    102:        register int ogargc = gargc;
                    103: 
                    104:        gpathp = gpath; *gpathp = 0; globbed = 0;
                    105:        expand(as);
                    106:        if (gargc == ogargc) {
                    107:                if (nonomatch) {
                    108:                        Gcat(as, "");
                    109:                        sort();
                    110:                }
                    111:        } else
                    112:                sort();
                    113: }
                    114: 
                    115: /*
                    116:  * String compare for qsort.  Also used by filec code in sh.file.c.
                    117:  */
                    118: sortscmp(a1, a2)
                    119:        char **a1, **a2;
                    120: {
                    121: 
                    122:         return (strcmp(*a1, *a2));
                    123: }
                    124: 
                    125: expand(as)
                    126:        char *as;
                    127: {
                    128:        register char *cs;
                    129:        register char *sgpathp, *oldcs;
                    130:        struct stat stb;
                    131: 
                    132:        sgpathp = gpathp;
                    133:        cs = as;
                    134:        if (*cs == '~' && gpathp == gpath) {
                    135:                addpath('~');
                    136:                for (cs++; letter(*cs) || digit(*cs) || *cs == '-';)
                    137:                        addpath(*cs++);
                    138:                if (!*cs || *cs == '/') {
                    139:                        if (gpathp != gpath + 1) {
                    140:                                *gpathp = 0;
                    141:                                if (gethdir(gpath + 1))
                    142:                                        error("Unknown user: %s", gpath + 1);
                    143:                                (void) strcpy(gpath, gpath + 1);
                    144:                        } else
                    145:                                (void) strcpy(gpath, value("home"));
                    146:                        gpathp = strend(gpath);
                    147:                }
                    148:        }
                    149:        while (!isglob(*cs)) {
                    150:                if (*cs == 0) {
                    151:                        if (!globbed)
                    152:                                Gcat(gpath, "");
                    153:                        else if (stat(gpath, &stb) >= 0) {
                    154:                                Gcat(gpath, "");
                    155:                                globcnt++;
                    156:                        }
                    157:                        goto endit;
                    158:                }
                    159:                addpath(*cs++);
                    160:        }
                    161:        oldcs = cs;
                    162:        while (cs > as && *cs != '/')
                    163:                cs--, gpathp--;
                    164:        if (*cs == '/')
                    165:                cs++, gpathp++;
                    166:        *gpathp = 0;
                    167:        if (*oldcs == '{') {
                    168:                (void) execbrc(cs, NOSTR);
                    169:                return;
                    170:        }
                    171:        matchdir(cs);
                    172: endit:
                    173:        gpathp = sgpathp;
                    174:        *gpathp = 0;
                    175: }
                    176: 
                    177: matchdir(pattern)
                    178:        char *pattern;
                    179: {
                    180:        struct stat stb;
                    181:        register struct direct *dp;
                    182:        register DIR *dirp;
                    183: 
                    184:        dirp = opendir(gpath);
                    185:        if (dirp == NULL) {
                    186:                if (globbed)
                    187:                        return;
                    188:                goto patherr2;
                    189:        }
                    190:        if (fstat(dirp->dd_fd, &stb) < 0)
                    191:                goto patherr1;
                    192:        if (!isdir(stb)) {
                    193:                errno = ENOTDIR;
                    194:                goto patherr1;
                    195:        }
                    196:        while ((dp = readdir(dirp)) != NULL) {
                    197:                if (dp->d_ino == 0)
                    198:                        continue;
                    199:                if (match(dp->d_name, pattern)) {
                    200:                        Gcat(gpath, dp->d_name);
                    201:                        globcnt++;
                    202:                }
                    203:        }
                    204:        closedir(dirp);
                    205:        return;
                    206: 
                    207: patherr1:
                    208:        closedir(dirp);
                    209: patherr2:
                    210:        Perror(gpath);
                    211: }
                    212: 
                    213: execbrc(p, s)
                    214:        char *p, *s;
                    215: {
                    216:        char restbuf[BUFSIZ + 2];
                    217:        register char *pe, *pm, *pl;
                    218:        int brclev = 0;
                    219:        char *lm, savec, *sgpathp;
                    220: 
                    221:        for (lm = restbuf; *p != '{'; *lm++ = *p++)
                    222:                continue;
                    223:        for (pe = ++p; *pe; pe++)
                    224:        switch (*pe) {
                    225: 
                    226:        case '{':
                    227:                brclev++;
                    228:                continue;
                    229: 
                    230:        case '}':
                    231:                if (brclev == 0)
                    232:                        goto pend;
                    233:                brclev--;
                    234:                continue;
                    235: 
                    236:        case '[':
                    237:                for (pe++; *pe && *pe != ']'; pe++)
                    238:                        continue;
                    239:                if (!*pe)
                    240:                        error("Missing ]");
                    241:                continue;
                    242:        }
                    243: pend:
                    244:        if (brclev || !*pe)
                    245:                error("Missing }");
                    246:        for (pl = pm = p; pm <= pe; pm++)
                    247:        switch (*pm & (QUOTE|TRIM)) {
                    248: 
                    249:        case '{':
                    250:                brclev++;
                    251:                continue;
                    252: 
                    253:        case '}':
                    254:                if (brclev) {
                    255:                        brclev--;
                    256:                        continue;
                    257:                }
                    258:                goto doit;
                    259: 
                    260:        case ','|QUOTE:
                    261:        case ',':
                    262:                if (brclev)
                    263:                        continue;
                    264: doit:
                    265:                savec = *pm;
                    266:                *pm = 0;
                    267:                (void) strcpy(lm, pl);
                    268:                (void) strcat(restbuf, pe + 1);
                    269:                *pm = savec;
                    270:                if (s == 0) {
                    271:                        sgpathp = gpathp;
                    272:                        expand(restbuf);
                    273:                        gpathp = sgpathp;
                    274:                        *gpathp = 0;
                    275:                } else if (amatch(s, restbuf))
                    276:                        return (1);
                    277:                sort();
                    278:                pl = pm + 1;
                    279:                continue;
                    280: 
                    281:        case '[':
                    282:                for (pm++; *pm && *pm != ']'; pm++)
                    283:                        continue;
                    284:                if (!*pm)
                    285:                        error("Missing ]");
                    286:                continue;
                    287:        }
                    288:        return (0);
                    289: }
                    290: 
                    291: match(s, p)
                    292:        char *s, *p;
                    293: {
                    294:        register int c;
                    295:        register char *sentp;
                    296:        char sglobbed = globbed;
                    297: 
                    298:        if (*s == '.' && *p != '.')
                    299:                return (0);
                    300:        sentp = entp;
                    301:        entp = s;
                    302:        c = amatch(s, p);
                    303:        entp = sentp;
                    304:        globbed = sglobbed;
                    305:        return (c);
                    306: }
                    307: 
                    308: amatch(s, p)
                    309:        register char *s, *p;
                    310: {
                    311:        register int scc;
                    312:        int ok, lc;
                    313:        char *sgpathp;
                    314:        struct stat stb;
                    315:        int c, cc;
                    316: 
                    317:        globbed = 1;
                    318:        for (;;) {
                    319:                scc = *s++ & TRIM;
                    320:                switch (c = *p++) {
                    321: 
                    322:                case '{':
                    323:                        return (execbrc(p - 1, s - 1));
                    324: 
                    325:                case '[':
                    326:                        ok = 0;
                    327:                        lc = 077777;
                    328:                        while (cc = *p++) {
                    329:                                if (cc == ']') {
                    330:                                        if (ok)
                    331:                                                break;
                    332:                                        return (0);
                    333:                                }
                    334:                                if (cc == '-') {
                    335:                                        if (lc <= scc && scc <= *p++)
                    336:                                                ok++;
                    337:                                } else
                    338:                                        if (scc == (lc = cc))
                    339:                                                ok++;
                    340:                        }
                    341:                        if (cc == 0)
                    342:                                error("Missing ]");
                    343:                        continue;
                    344: 
                    345:                case '*':
                    346:                        if (!*p)
                    347:                                return (1);
                    348:                        if (*p == '/') {
                    349:                                p++;
                    350:                                goto slash;
                    351:                        }
                    352:                        for (s--; *s; s++)
                    353:                                if (amatch(s, p))
                    354:                                        return (1);
                    355:                        return (0);
                    356: 
                    357:                case 0:
                    358:                        return (scc == 0);
                    359: 
                    360:                default:
                    361:                        if ((c & TRIM) != scc)
                    362:                                return (0);
                    363:                        continue;
                    364: 
                    365:                case '?':
                    366:                        if (scc == 0)
                    367:                                return (0);
                    368:                        continue;
                    369: 
                    370:                case '/':
                    371:                        if (scc)
                    372:                                return (0);
                    373: slash:
                    374:                        s = entp;
                    375:                        sgpathp = gpathp;
                    376:                        while (*s)
                    377:                                addpath(*s++);
                    378:                        addpath('/');
                    379:                        if (stat(gpath, &stb) == 0 && isdir(stb))
                    380:                                if (*p == 0) {
                    381:                                        Gcat(gpath, "");
                    382:                                        globcnt++;
                    383:                                } else
                    384:                                        expand(p);
                    385:                        gpathp = sgpathp;
                    386:                        *gpathp = 0;
                    387:                        return (0);
                    388:                }
                    389:        }
                    390: }
                    391: 
                    392: Gmatch(s, p)
                    393:        register char *s, *p;
                    394: {
                    395:        register int scc;
                    396:        int ok, lc;
                    397:        int c, cc;
                    398: 
                    399:        for (;;) {
                    400:                scc = *s++ & TRIM;
                    401:                switch (c = *p++) {
                    402: 
                    403:                case '[':
                    404:                        ok = 0;
                    405:                        lc = 077777;
                    406:                        while (cc = *p++) {
                    407:                                if (cc == ']') {
                    408:                                        if (ok)
                    409:                                                break;
                    410:                                        return (0);
                    411:                                }
                    412:                                if (cc == '-') {
                    413:                                        if (lc <= scc && scc <= *p++)
                    414:                                                ok++;
                    415:                                } else
                    416:                                        if (scc == (lc = cc))
                    417:                                                ok++;
                    418:                        }
                    419:                        if (cc == 0)
                    420:                                bferr("Missing ]");
                    421:                        continue;
                    422: 
                    423:                case '*':
                    424:                        if (!*p)
                    425:                                return (1);
                    426:                        for (s--; *s; s++)
                    427:                                if (Gmatch(s, p))
                    428:                                        return (1);
                    429:                        return (0);
                    430: 
                    431:                case 0:
                    432:                        return (scc == 0);
                    433: 
                    434:                default:
                    435:                        if ((c & TRIM) != scc)
                    436:                                return (0);
                    437:                        continue;
                    438: 
                    439:                case '?':
                    440:                        if (scc == 0)
                    441:                                return (0);
                    442:                        continue;
                    443: 
                    444:                }
                    445:        }
                    446: }
                    447: 
                    448: Gcat(s1, s2)
                    449:        char *s1, *s2;
                    450: {
                    451:        register char *p, *q;
                    452:        int n;
                    453: 
                    454:        for (p = s1; *p++;)
                    455:                ;
                    456:        for (q = s2; *q++;)
                    457:                ;
                    458:        gnleft -= (n = (p - s1) + (q - s2) - 1);
                    459:        if (gnleft <= 0 || ++gargc >= GAVSIZ)
                    460:                error("Arguments too long");
                    461:        gargv[gargc] = 0;
                    462:        p = gargv[gargc - 1] = xalloc((unsigned)n);
                    463:        for (q = s1; *p++ = *q++;)
                    464:                ;
                    465:        for (p--, q = s2; *p++ = *q++;)
                    466:                ;
                    467: }
                    468: 
                    469: addpath(c)
                    470:        char c;
                    471: {
                    472: 
                    473:        if (gpathp >= lastgpathp)
                    474:                error("Pathname too long");
                    475:        *gpathp++ = c & TRIM;
                    476:        *gpathp = 0;
                    477: }
                    478: 
                    479: rscan(t, f)
                    480:        register char **t;
                    481:        int (*f)();
                    482: {
                    483:        register char *p;
                    484: 
                    485:        while (p = *t++)
                    486:                while (*p)
                    487:                        (*f)(*p++);
                    488: }
                    489: 
                    490: trim(t)
                    491:        register char **t;
                    492: {
                    493:        register char *p;
                    494: 
                    495:        while (p = *t++)
                    496:                while (*p)
                    497:                        *p++ &= TRIM;
                    498: }
                    499: 
                    500: tglob(t)
                    501:        register char **t;
                    502: {
                    503:        register char *p, c;
                    504: 
                    505:        while (p = *t++) {
                    506:                if (*p == '~')
                    507:                        gflag |= 2;
                    508:                else if (*p == '{' && (p[1] == '\0' || p[1] == '}' && p[2] == '\0'))
                    509:                        continue;
                    510:                while (c = *p++)
                    511:                        if (isglob(c))
                    512:                                gflag |= c == '{' ? 2 : 1;
                    513:        }
                    514: }
                    515: 
                    516: char *
                    517: globone(str)
                    518:        register char *str;
                    519: {
                    520:        char *gv[2];
                    521:        register char **gvp;
                    522:        register char *cp;
                    523: 
                    524:        gv[0] = str;
                    525:        gv[1] = 0;
                    526:        gflag = 0;
                    527:        tglob(gv);
                    528:        if (gflag) {
                    529:                gvp = glob(gv);
                    530:                if (gvp == 0) {
                    531:                        setname(str);
                    532:                        bferr("No match");
                    533:                }
                    534:                cp = *gvp++;
                    535:                if (cp == 0)
                    536:                        cp = "";
                    537:                else if (*gvp) {
                    538:                        setname(str);
                    539:                        bferr("Ambiguous");
                    540:                } else
                    541:                        cp = strip(cp);
                    542: /*
                    543:                if (cp == 0 || *gvp) {
                    544:                        setname(str);
                    545:                        bferr(cp ? "Ambiguous" : "No output");
                    546:                }
                    547: */
                    548:                xfree((char *)gargv); gargv = 0;
                    549:        } else {
                    550:                trim(gv);
                    551:                cp = savestr(gv[0]);
                    552:        }
                    553:        return (cp);
                    554: }
                    555: 
                    556: /*
                    557:  * Command substitute cp.  If literal, then this is
                    558:  * a substitution from a << redirection, and so we should
                    559:  * not crunch blanks and tabs, separating words only at newlines.
                    560:  */
                    561: char **
                    562: dobackp(cp, literal)
                    563:        char *cp;
                    564:        bool literal;
                    565: {
                    566:        register char *lp, *rp;
                    567:        char *ep;
                    568:        char word[BUFSIZ];
                    569:        char *apargv[GAVSIZ + 2];
                    570: 
                    571:        if (pargv) {
                    572:                abort();
                    573:                blkfree(pargv);
                    574:        }
                    575:        pargv = apargv;
                    576:        pargv[0] = NOSTR;
                    577:        pargcp = pargs = word;
                    578:        pargc = 0;
                    579:        pnleft = BUFSIZ - 4;
                    580:        for (;;) {
                    581:                for (lp = cp; *lp != '`'; lp++) {
                    582:                        if (*lp == 0) {
                    583:                                if (pargcp != pargs)
                    584:                                        pword();
                    585: #ifdef GDEBUG
                    586:                                printf("leaving dobackp\n");
                    587: #endif
                    588:                                return (pargv = copyblk(pargv));
                    589:                        }
                    590:                        psave(*lp);
                    591:                }
                    592:                lp++;
                    593:                for (rp = lp; *rp && *rp != '`'; rp++)
                    594:                        if (*rp == '\\') {
                    595:                                rp++;
                    596:                                if (!*rp)
                    597:                                        goto oops;
                    598:                        }
                    599:                if (!*rp)
                    600: oops:
                    601:                        error("Unmatched `");
                    602:                ep = savestr(lp);
                    603:                ep[rp - lp] = 0;
                    604:                backeval(ep, literal);
                    605: #ifdef GDEBUG
                    606:                printf("back from backeval\n");
                    607: #endif
                    608:                cp = rp + 1;
                    609:        }
                    610: }
                    611: 
                    612: backeval(cp, literal)
                    613:        char *cp;
                    614:        bool literal;
                    615: {
                    616:        int pvec[2];
                    617:        int quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0;
                    618:        char ibuf[BUFSIZ];
                    619:        register int icnt = 0, c;
                    620:        register char *ip;
                    621:        bool hadnl = 0;
                    622:        char *fakecom[2];
                    623:        struct command faket;
                    624: 
                    625:        faket.t_dtyp = TCOM;
                    626:        faket.t_dflg = 0;
                    627:        faket.t_dlef = 0;
                    628:        faket.t_drit = 0;
                    629:        faket.t_dspr = 0;
                    630:        faket.t_dcom = fakecom;
                    631:        fakecom[0] = "` ... `";
                    632:        fakecom[1] = 0;
                    633:        /*
                    634:         * We do the psave job to temporarily change the current job
                    635:         * so that the following fork is considered a separate job.
                    636:         * This is so that when backquotes are used in a
                    637:         * builtin function that calls glob the "current job" is not corrupted.
                    638:         * We only need one level of pushed jobs as long as we are sure to
                    639:         * fork here.
                    640:         */
                    641:        psavejob();
                    642:        /*
                    643:         * It would be nicer if we could integrate this redirection more
                    644:         * with the routines in sh.sem.c by doing a fake execute on a builtin
                    645:         * function that was piped out.
                    646:         */
                    647:        mypipe(pvec);
                    648:        if (pfork(&faket, -1) == 0) {
                    649:                struct wordent paraml;
                    650:                struct command *t;
                    651: 
                    652:                (void) close(pvec[0]);
                    653:                (void) dmove(pvec[1], 1);
                    654:                (void) dmove(SHDIAG, 2);
                    655:                initdesc();
                    656:                arginp = cp;
                    657:                while (*cp)
                    658:                        *cp++ &= TRIM;
                    659:                (void) lex(&paraml);
                    660:                if (err)
                    661:                        error(err);
                    662:                alias(&paraml);
                    663:                t = syntax(paraml.next, &paraml, 0);
                    664:                if (err)
                    665:                        error(err);
                    666:                if (t)
                    667:                        t->t_dflg |= FPAR;
                    668:                (void) signal(SIGTSTP, SIG_IGN);
                    669:                (void) signal(SIGTTIN, SIG_IGN);
                    670:                (void) signal(SIGTTOU, SIG_IGN);
                    671:                execute(t, -1);
                    672:                exitstat();
                    673:        }
                    674:        xfree(cp);
                    675:        (void) close(pvec[1]);
                    676:        do {
                    677:                int cnt = 0;
                    678:                for (;;) {
                    679:                        if (icnt == 0) {
                    680:                                ip = ibuf;
                    681:                                icnt = read(pvec[0], ip, BUFSIZ);
                    682:                                if (icnt <= 0) {
                    683:                                        c = -1;
                    684:                                        break;
                    685:                                }
                    686:                        }
                    687:                        if (hadnl)
                    688:                                break;
                    689:                        --icnt;
                    690:                        c = (*ip++ & TRIM);
                    691:                        if (c == 0)
                    692:                                break;
                    693:                        if (c == '\n') {
                    694:                                /*
                    695:                                 * Continue around the loop one
                    696:                                 * more time, so that we can eat
                    697:                                 * the last newline without terminating
                    698:                                 * this word.
                    699:                                 */
                    700:                                hadnl = 1;
                    701:                                continue;
                    702:                        }
                    703:                        if (!quoted && (c == ' ' || c == '\t'))
                    704:                                break;
                    705:                        cnt++;
                    706:                        psave(c | quoted);
                    707:                }
                    708:                /*
                    709:                 * Unless at end-of-file, we will form a new word
                    710:                 * here if there were characters in the word, or in
                    711:                 * any case when we take text literally.  If
                    712:                 * we didn't make empty words here when literal was
                    713:                 * set then we would lose blank lines.
                    714:                 */
                    715:                if (c != -1 && (cnt || literal))
                    716:                        pword();
                    717:                hadnl = 0;
                    718:        } while (c >= 0);
                    719: #ifdef GDEBUG
                    720:        printf("done in backeval, pvec: %d %d\n", pvec[0], pvec[1]);
                    721:        printf("also c = %c <%o>\n", c, c);
                    722: #endif
                    723:        (void) close(pvec[0]);
                    724:        pwait();
                    725:        prestjob();
                    726: }
                    727: 
                    728: psave(c)
                    729:        char c;
                    730: {
                    731: 
                    732:        if (--pnleft <= 0)
                    733:                error("Word too long");
                    734:        *pargcp++ = c;
                    735: }
                    736: 
                    737: pword()
                    738: {
                    739: 
                    740:        psave(0);
                    741:        if (pargc == GAVSIZ)
                    742:                error("Too many words from ``");
                    743:        pargv[pargc++] = savestr(pargs);
                    744:        pargv[pargc] = NOSTR;
                    745: #ifdef GDEBUG
                    746:        printf("got word %s\n", pargv[pargc-1]);
                    747: #endif
                    748:        pargcp = pargs;
                    749:        pnleft = BUFSIZ - 4;
                    750: }

unix.superglobalmegacorp.com

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