Annotation of 43BSDTahoe/new/jove/buf.c, revision 1.1.1.1

1.1       root        1: /***************************************************************************
                      2:  * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne.  JOVE *
                      3:  * is provided to you without charge, and with no warranty.  You may give  *
                      4:  * away copies of JOVE, including sources, provided that this notice is    *
                      5:  * included in all the files.                                              *
                      6:  ***************************************************************************/
                      7: 
                      8: /* Contains commands that deal with creating, selecting, killing and
                      9:    listing buffers, and buffer modes, and find-file, etc. */
                     10: 
                     11: #include "jove.h"
                     12: 
                     13: #ifdef MAC
                     14: #      include "mac.h"
                     15: #else
                     16: #      include <sys/stat.h>
                     17: #endif
                     18: 
                     19: #ifdef MAC
                     20: #      undef private
                     21: #      define private
                     22: #endif
                     23: 
                     24: #ifdef LINT_ARGS
                     25: private Buffer
                     26:        * buf_alloc(void),
                     27:        * mak_buf(void);
                     28: 
                     29: private char * line_cnt(Buffer *, char *);
                     30: 
                     31: private void   
                     32:        BufNSelect(int),
                     33:        defb_wind(Buffer *),
                     34:        kill_buf(Buffer *),
                     35:        mkbuflist(char **);
                     36: #else
                     37: private Buffer
                     38:        * buf_alloc(),
                     39:        * mak_buf();
                     40: 
                     41: private char * line_cnt();
                     42: 
                     43: private void
                     44:        BufNSelect(),
                     45:        defb_wind(),
                     46:        kill_buf(),
                     47:        mkbuflist();
                     48: #endif /* LINT_ARGS */
                     49: 
                     50: #ifdef MAC
                     51: #      undef private
                     52: #      define private static
                     53: #endif
                     54: 
                     55: char   *Mainbuf = "Main",
                     56:        *NoName = "Sans un nom!";
                     57: 
                     58: Buffer *world = 0,             /* First in the list */
                     59:        *curbuf = 0,
                     60:        *lastbuf = 0;   /* Last buffer we were in so we have a default
                     61:                           buffer during a select buffer. */
                     62: 
                     63: /* Toggle BIT in the current buffer's minor mode flags.  If argument is
                     64:    supplied, a positive one always turns on the mode and zero argument
                     65:    always turns it off. */
                     66: 
                     67: void
                     68: TogMinor(bit)
                     69: {
                     70:        if (is_an_arg()) {
                     71:                if (arg_value() == 0)
                     72:                        curbuf->b_minor &= ~bit;
                     73:                else
                     74:                        curbuf->b_minor |= bit;
                     75:        } else
                     76:                curbuf->b_minor ^= bit;
                     77:        UpdModLine = YES;
                     78: }
                     79: 
                     80: /* Creates a new buffer, links it at the end of the buffer chain, and
                     81:    returns it. */
                     82: 
                     83: static Buffer *
                     84: buf_alloc()
                     85: {
                     86:        register Buffer *b,
                     87:                        *lastbp;
                     88: 
                     89:        lastbp = 0;
                     90:        for (b = world; b != 0; lastbp = b, b = b->b_next)
                     91:                ;
                     92: 
                     93:        b = (Buffer *) emalloc(sizeof (Buffer));
                     94:        if (lastbp)
                     95:                lastbp->b_next = b;
                     96:        else
                     97:                world = b;
                     98:        b->b_first = 0;
                     99:        b->b_next = 0;
                    100: #ifdef MAC
                    101:        b->Type = BUFFER;       /* kludge, but simplifies menu handlers */
                    102:        b->Name = 0;
                    103: #endif
                    104:        return b;
                    105: }
                    106: 
                    107: /* Makes a buffer and initializes it.  Obsolete.  Used to take two
                    108:    arguments, a buffer name and a file name. */
                    109: 
                    110: static Buffer *
                    111: mak_buf()
                    112: {
                    113:        register Buffer *newb;
                    114:        register int    i;
                    115: 
                    116:        newb = buf_alloc();
                    117:        newb->b_fname = 0;
                    118:        newb->b_name = NoName;
                    119:        set_ino(newb);
                    120:        newb->b_marks = 0;
                    121:        newb->b_themark = 0;            /* Index into markring */
                    122:        /* No marks yet */
                    123:        for (i = 0; i < NMARKS; i++)
                    124:                newb->b_markring[i] = 0;
                    125:        newb->b_modified = 0;
                    126:        newb->b_type = B_FILE;  /* File until proven SCRATCH */
                    127:        newb->b_ntbf = 0;
                    128:        newb->b_minor = 0;
                    129:        newb->b_major = TEXT;
                    130:        newb->b_first = 0;
                    131:        newb->b_keybinds = 0;
                    132: #ifdef IPROCS
                    133:        newb->b_process = 0;
                    134: #endif
                    135:        initlist(newb);
                    136: #ifdef MAC
                    137:        Bufchange = 1;
                    138: #endif
                    139:        return newb;
                    140: }
                    141: 
                    142: void
                    143: ReNamBuf()
                    144: {
                    145:        register char   *new = 0,
                    146:                        *prompt = ProcFmt,
                    147:                        *second = "%s already exists; new name? ";
                    148: 
                    149:        for (;;) {
                    150:                new = ask((char *) 0, prompt, new);
                    151:                if (!buf_exists(new))
                    152:                        break;
                    153:                prompt = second;
                    154:        }
                    155:        setbname(curbuf, new);
                    156: }
                    157: 
                    158: void
                    159: FindFile()
                    160: {
                    161:        register char   *name;
                    162:        char    fnamebuf[FILESIZE];
                    163: 
                    164:        name = ask_file((char *) 0, curbuf->b_fname, fnamebuf);
                    165:        SetABuf(curbuf);
                    166:        SetBuf(do_find(curwind, name, 0));
                    167: }
                    168: 
                    169: private void
                    170: mkbuflist(bnamp)
                    171: register char  **bnamp;
                    172: {
                    173:        register Buffer *b;
                    174: 
                    175:        for (b = world; b != 0; b = b->b_next)
                    176:                if (b->b_name != 0)
                    177:                        *bnamp++ = b->b_name;
                    178:        *bnamp = 0;
                    179: }
                    180: 
                    181: char *
                    182: ask_buf(def)
                    183: Buffer *def;
                    184: {
                    185:        char    *bnames[100];
                    186:        register char   *bname;
                    187:        register int    offset;
                    188:        char    prompt[100];
                    189: 
                    190:        if (def != 0 && def->b_name != 0)
                    191:                sprintf(prompt, ": %f (default %s) ", def->b_name);
                    192:        else
                    193:                sprintf(prompt, ProcFmt);
                    194:        mkbuflist(bnames);
                    195:        offset = complete(bnames, prompt, RET_STATE);
                    196:        if (offset == EOF)
                    197:                complain((char *) 0);
                    198:        if (offset == ORIGINAL || offset == AMBIGUOUS)
                    199:                bname = Minibuf;
                    200:        else if (offset == NULLSTRING) {
                    201:                if (def)
                    202:                        bname = def->b_name;
                    203:                else
                    204:                        complain((char *) 0);
                    205:        } else if (offset < 0)
                    206:                complain((char *) 0);
                    207:        else
                    208:                bname = bnames[offset];
                    209: 
                    210:        return bname;
                    211: }
                    212: 
                    213: void
                    214: BufSelect()
                    215: {
                    216:        register char   *bname;
                    217: 
                    218:        bname = ask_buf(lastbuf);
                    219:        SetABuf(curbuf);
                    220:        SetBuf(do_select(curwind, bname));
                    221: }
                    222: 
                    223: #ifdef MSDOS
                    224: 
                    225: private void
                    226: BufNSelect(n)
                    227: {
                    228:        char *bnames[100];
                    229:        char *bname;
                    230:        int i;
                    231: 
                    232:        mkbuflist(bnames);
                    233:        for (i=0; i<n; i++)
                    234:            if (bnames[i] == 0)
                    235:               complain("[No such buffer]");
                    236:        bname = bnames[n-1];
                    237:        SetABuf(curbuf);
                    238:        SetBuf(do_select(curwind, bname));
                    239: }
                    240: 
                    241: void Buf1Select() { BufNSelect(1); }
                    242: void Buf2Select() { BufNSelect(2); }
                    243: void Buf3Select() { BufNSelect(3); }
                    244: void Buf4Select() { BufNSelect(4); }
                    245: void Buf5Select() { BufNSelect(5); }
                    246: void Buf6Select() { BufNSelect(6); }
                    247: void Buf7Select() { BufNSelect(7); }
                    248: void Buf8Select() { BufNSelect(8); }
                    249: void Buf9Select() { BufNSelect(9); }
                    250: void Buf10Select() { BufNSelect(10); }
                    251: 
                    252: #endif /* MSDOS */
                    253: 
                    254: private void
                    255: defb_wind(b)
                    256: register Buffer *b;
                    257: {
                    258:        register Window *w = fwind;
                    259:        char    *alt;
                    260: 
                    261:        if (lastbuf == b || lastbuf == 0) {
                    262:                lastbuf = 0;
                    263:                alt = (b->b_next != 0) ? b->b_next->b_name : Mainbuf;
                    264:        } else
                    265:                alt = lastbuf->b_name;
                    266: 
                    267:        do {
                    268:                if (w->w_bufp == b) {
                    269:                        if (one_windp() || alt != Mainbuf)
                    270:                                (void) do_select(w, alt);
                    271:                        else {
                    272:                                Window  *save = w->w_next;
                    273:                                del_wind(w);
                    274:                                w = save->w_prev;
                    275:                        }
                    276:                }
                    277:                w = w->w_next;
                    278:        } while (w != fwind || w->w_bufp == b);
                    279: }
                    280: 
                    281: Buffer *
                    282: getNMbuf()
                    283: {
                    284:        register Buffer *delbuf;
                    285:        register char   *bname;
                    286: 
                    287:        bname = ask_buf(curbuf);
                    288:        if ((delbuf = buf_exists(bname)) == 0)
                    289:                complain("[No such buffer]");
                    290:        if (delbuf->b_modified)
                    291:                confirm("%s modified, are you sure? ", bname);
                    292:        return delbuf;
                    293: }
                    294: 
                    295: void
                    296: BufErase()
                    297: {
                    298:        register Buffer *delbuf;
                    299: 
                    300:        if (delbuf = getNMbuf()) {
                    301:                initlist(delbuf);
                    302:                delbuf->b_modified = 0;
                    303:        }
                    304: }
                    305: 
                    306: private void
                    307: kill_buf(delbuf)
                    308: register Buffer        *delbuf;
                    309: {
                    310:        register Buffer *b,
                    311:                        *lastb = 0;
                    312: #ifndef MAC
                    313:        extern Buffer   *perr_buf;
                    314: #endif
                    315: 
                    316: #ifdef IPROCS
                    317:        pbuftiedp(delbuf);      /* check for lingering processes */
                    318: #endif
                    319:        for (b = world; b != 0; lastb = b, b = b->b_next)
                    320:                if (b == delbuf)
                    321:                        break;
                    322:        if (lastb)
                    323:                lastb->b_next = delbuf->b_next;
                    324:        else
                    325:                world = delbuf->b_next;
                    326: 
                    327: #define okay_free(ptr) if (ptr) free(ptr)
                    328: 
                    329:        lfreelist(delbuf->b_first);
                    330:        okay_free(delbuf->b_name);
                    331:        okay_free(delbuf->b_fname);
                    332:        flush_marks(delbuf);
                    333:        free((char *) delbuf);
                    334: 
                    335:        if (delbuf == lastbuf)
                    336:                SetABuf(curbuf);
                    337: #ifndef MAC
                    338:        if (perr_buf == delbuf) {
                    339:                ErrFree();
                    340:                perr_buf = 0;
                    341:        }
                    342: #endif
                    343:        defb_wind(delbuf);
                    344:        if (curbuf == delbuf)
                    345:                SetBuf(curwind->w_bufp);
                    346: #ifdef MAC
                    347:        Bufchange = 1;
                    348: #endif
                    349: }
                    350: 
                    351: /* offer to kill some buffers */
                    352: 
                    353: void
                    354: KillSome()
                    355: {
                    356:        register Buffer *b,
                    357:                        *next;
                    358:        Buffer  *oldb;
                    359:        register char   *y_or_n;
                    360: 
                    361:        for (b = world; b != 0; b = next) {
                    362:                next = b->b_next;
                    363:                if (yes_or_no_p("Kill %s? ", b->b_name) == NO)
                    364:                        continue;
                    365:                if (IsModified(b)) {
                    366:                        y_or_n = ask("No", "%s modified; should I save it? ", b->b_name);
                    367:                        if (CharUpcase(*y_or_n) == 'Y') {
                    368:                                oldb = curbuf;
                    369:                                SetBuf(b);
                    370:                                SaveFile();
                    371:                                SetBuf(oldb);
                    372:                        }
                    373:                }
                    374:                kill_buf(b);
                    375:        }
                    376: }
                    377: 
                    378: void
                    379: BufKill()
                    380: {
                    381:        Buffer  *b;
                    382: 
                    383:        if ((b = getNMbuf()) == 0)
                    384:                return;
                    385:        kill_buf(b);
                    386: }
                    387: 
                    388: private char *
                    389: line_cnt(b, buf)
                    390: register Buffer        *b;
                    391: char   *buf;
                    392: {
                    393:        register int    nlines = 0;
                    394:        register Line   *lp;
                    395: 
                    396:        for (lp = b->b_first; lp != 0; lp = lp->l_next, nlines++)
                    397:                ;
                    398:        sprintf(buf, "%d", nlines);
                    399:        return buf;
                    400: }
                    401: 
                    402: private char   *TypeNames[] = {
                    403:        0,
                    404:        "Scratch",
                    405:        "File",
                    406:        "Process",
                    407: };
                    408: 
                    409: void
                    410: BufList()
                    411: {
                    412:        register char   *format = "%-2s %-5s %-11s %-1s %-*s  %-s";
                    413:        register Buffer *b;
                    414:        int     bcount = 1,             /* To give each buffer a number */
                    415:                buf_width = 11;
                    416:        char    nbuf[10];
                    417: 
                    418:        for (b = world; b != 0; b = b->b_next)
                    419:                buf_width = max(buf_width, strlen(b->b_name));
                    420: 
                    421:        TOstart("Buffer list", TRUE);   /* true means auto-newline */
                    422: 
                    423:        Typeout("(* means buffer needs saving)");
                    424:        Typeout("(+ means file hasn't been read yet)");
                    425:        Typeout(NullStr);
                    426:        Typeout(format, "NO", "Lines", "Type", NullStr, buf_width, "Name", "File");
                    427:        Typeout(format, "--", "-----", "----", NullStr, buf_width, "----", "----");
                    428:        for (b = world; b != 0; b = b->b_next) {
                    429:                Typeout(format, itoa(bcount++),
                    430:                                line_cnt(b, nbuf),
                    431:                                TypeNames[b->b_type],
                    432:                                IsModified(b) ? "*" :
                    433:                                         b->b_ntbf ? "+" : NullStr,
                    434:                                buf_width,
                    435:                                /* For the * (variable length field) */
                    436:                                b->b_name,
                    437:                                filename(b));
                    438: 
                    439:                if (TOabort)
                    440:                        break;
                    441:        }
                    442:        TOstop();
                    443: }
                    444: 
                    445: void
                    446: bufname(b)
                    447: register Buffer        *b;
                    448: {
                    449:        char    tmp[100],
                    450:                *cp;
                    451:        int     try = 1;
                    452: 
                    453:        if (b->b_fname == 0)
                    454:                complain("[No file name]");
                    455:        cp = basename(b->b_fname);
                    456:        strcpy(tmp, cp);
                    457:        while (buf_exists(tmp)) {
                    458:                sprintf(tmp, "%s.%d", cp, try);
                    459:                try += 1;
                    460:        }
                    461:        setbname(b, tmp);
                    462: }
                    463: 
                    464: void
                    465: initlist(b)
                    466: register Buffer        *b;
                    467: {
                    468:        lfreelist(b->b_first);
                    469:        b->b_first = b->b_dot = b->b_last = 0;
                    470:        (void) listput(b, b->b_first);
                    471:        
                    472:        SavLine(b->b_dot, NullStr);
                    473:        b->b_char = 0;
                    474:        AllMarkSet(b, b->b_dot, 0);
                    475:        if (b == curbuf)
                    476:                getDOT();
                    477: }
                    478: 
                    479: /* Returns pointer to buffer with name NAME, or if NAME is a string of digits
                    480:    returns the buffer whose number equals those digits.  Otherwise, returns
                    481:    0. */
                    482: 
                    483: Buffer *
                    484: buf_exists(name)
                    485: register char  *name;
                    486: {
                    487:        register Buffer *bp;
                    488:        int     n;
                    489: 
                    490:        if (name == 0)
                    491:                return 0;
                    492: 
                    493:        for (bp = world; bp != 0; bp = bp->b_next)
                    494:                if (strcmp(bp->b_name, name) == 0)
                    495:                        return bp;
                    496: 
                    497:        /* Doesn't match any names.  Try for a buffer number... */
                    498: 
                    499:        if (chr_to_int(name, 10, YES, &n) != INT_BAD) {
                    500:                for (bp = world; n > 1; bp = bp->b_next) {
                    501:                        if (bp == 0)
                    502:                                break;
                    503:                        n -= 1;
                    504:                }
                    505:                return bp;
                    506:        }
                    507: 
                    508:        return 0;
                    509: }
                    510: 
                    511: /* Returns buffer pointer with a file name NAME, if one exists.  Stat's the
                    512:    file and compares inodes, in case NAME is a link, as well as the actual
                    513:    characters that make up the file name. */
                    514: 
                    515: Buffer *
                    516: file_exists(name)
                    517: register char  *name;
                    518: {
                    519:        struct stat     stbuf;
                    520:        register struct stat    *s = &stbuf;
                    521:        register Buffer *b = 0;
                    522:        char    fnamebuf[FILESIZE];
                    523: 
                    524: #ifdef MSDOS
                    525:        strlwr(name);
                    526: #endif /* MSDOS */
                    527:        if (name) {
                    528:                PathParse(name, fnamebuf);
                    529:                if (stat(fnamebuf, s) == -1)
                    530:                        s->st_ino = 0;
                    531:                for (b = world; b != 0; b = b->b_next) {
                    532:                        if (
                    533: #ifndef MSDOS
                    534:                            (b->b_ino != 0 && b->b_ino == s->st_ino &&
                    535:                             b->b_dev != 0 && b->b_dev == s->st_dev) ||
                    536: #endif /* MSDOS */
                    537:                            (strcmp(b->b_fname, fnamebuf) == 0))
                    538:                                break;
                    539:                }
                    540:        }
                    541:        return b;
                    542: }
                    543: 
                    544: char *
                    545: ralloc(obj, size)
                    546: register char  *obj;
                    547: {
                    548:        register char   *new;
                    549: 
                    550:        if (obj)
                    551:                new = realloc(obj, (unsigned) size);
                    552:        if (new == 0 || !obj)
                    553:                new = emalloc(size);
                    554:        return new;
                    555: }
                    556: 
                    557: void
                    558: setbname(b, name)
                    559: register Buffer        *b;
                    560: register char  *name;
                    561: {
                    562:        UpdModLine = YES;       /* Kludge ... but speeds things up considerably */
                    563:        if (name) {
                    564:                if (b->b_name == NoName)
                    565:                        b->b_name = 0;
                    566:                b->b_name = ralloc(b->b_name, strlen(name) + 1);
                    567:                strcpy(b->b_name, name);
                    568:        } else
                    569:                b->b_name = 0;
                    570: #ifdef MAC
                    571:        Bufchange = 1;
                    572: #endif
                    573: }
                    574: 
                    575: void
                    576: setfname(b, name)
                    577: register Buffer        *b;
                    578: register char  *name;
                    579: {
                    580:        char    wholename[FILESIZE],
                    581:                oldname[FILESIZE],
                    582:                *oldptr = oldname;
                    583:        Buffer  *save = curbuf;
                    584: 
                    585:        SetBuf(b);
                    586:        UpdModLine = YES;       /* Kludge ... but speeds things up considerably */
                    587:        if (b->b_fname == 0)
                    588:                oldptr = 0;
                    589:        else
                    590:                strcpy(oldname, b->b_fname);
                    591:        if (name) {
                    592: #ifdef MSDOS
                    593:                strlwr(name);
                    594: #endif /* MSDOS */
                    595:                PathParse(name, wholename);
                    596:                curbuf->b_fname = ralloc(curbuf->b_fname, strlen(wholename) + 1);
                    597:                strcpy(curbuf->b_fname, wholename);
                    598:        } else
                    599:                b->b_fname = 0;
                    600:        DoAutoExec(curbuf->b_fname, oldptr);
                    601:        curbuf->b_mtime = curbuf->b_dev = curbuf->b_ino = 0;    /* until they're known. */
                    602:        SetBuf(save);
                    603: #ifdef MAC
                    604:        Bufchange = 1;
                    605: #endif
                    606: }
                    607: 
                    608: void
                    609: set_ino(b)
                    610: register Buffer        *b;
                    611: {
                    612:        struct stat     stbuf;
                    613: 
                    614:        if (b->b_fname == 0 || stat(pr_name(b->b_fname, NO), &stbuf) == -1) {
                    615:                b->b_dev = 0;
                    616:                b->b_ino = 0;
                    617:                b->b_mtime = 0;
                    618:        } else {
                    619:                b->b_dev = stbuf.st_dev;
                    620:                b->b_ino = stbuf.st_ino;
                    621:                b->b_mtime = stbuf.st_mtime;
                    622:        }
                    623: }
                    624: 
                    625: /* Find the file `fname' into buf and put in in window `w' */
                    626: 
                    627: Buffer *
                    628: do_find(w, fname, force)
                    629: register Window        *w;
                    630: register char  *fname;
                    631: {
                    632:        register Buffer *b;
                    633: 
                    634:        b = file_exists(fname);
                    635:        if (b == 0) {
                    636:                b = mak_buf();
                    637:                setfname(b, fname);
                    638:                bufname(b);
                    639:                set_ino(b);
                    640:                b->b_ntbf = 1;
                    641:        }
                    642:        if (force) {
                    643:                Buffer  *oldb = curbuf;
                    644: 
                    645:                SetBuf(b);      /* this'll read the file */
                    646:                SetBuf(oldb);
                    647:        }
                    648:        if (w)
                    649:                tiewind(w, b);
                    650:        return b;
                    651: }
                    652: 
                    653: /* set alternate buffer */
                    654: 
                    655: void
                    656: SetABuf(b)
                    657: Buffer *b;
                    658: {
                    659:        if (b != 0)
                    660:                lastbuf = b;
                    661: }
                    662: 
                    663: 
                    664: /* check to see if BP is a valid buffer pointer */
                    665: int
                    666: valid_bp(bp)
                    667: register Buffer        *bp;
                    668: {
                    669:        register Buffer *b;
                    670: 
                    671:        for (b = world; b != 0; b = b->b_next)
                    672:                if (b == bp)
                    673:                        break;
                    674:        return b != 0;
                    675: }
                    676: 
                    677: void
                    678: SetBuf(newbuf)
                    679: register Buffer        *newbuf;
                    680: {
                    681:        register Buffer *oldb = curbuf,
                    682:                        *b;
                    683: 
                    684:        if (newbuf == curbuf || newbuf == 0)
                    685:                return;
                    686: 
                    687:        if (!valid_bp(newbuf))
                    688:                complain("Internal error: (0x%x) is not a valid buffer pointer!", newbuf);
                    689:        lsave();
                    690:        curbuf = newbuf;
                    691:        curline = newbuf->b_dot;
                    692:        curchar = newbuf->b_char;
                    693:        getDOT();
                    694:        /* do the read now ... */
                    695:        if (curbuf->b_ntbf)
                    696:                read_file(curbuf->b_fname, 0);
                    697: #ifdef MAC
                    698:        Modechange = 1;
                    699: #endif
                    700: 
                    701: #ifdef IPROCS
                    702:        if (oldb != 0 && ((oldb->b_process == 0) != (curbuf->b_process == 0))) {
                    703:                if (curbuf->b_process)
                    704:                        PushPBs();              /* Push process bindings */
                    705:                else if (oldb->b_process)
                    706:                        PopPBs();
                    707:        }
                    708: #endif
                    709: }
                    710: 
                    711: Buffer *
                    712: do_select(w, name)
                    713: register Window        *w;
                    714: register char  *name;
                    715: {
                    716:        register Buffer *new;
                    717: 
                    718:        if ((new = buf_exists(name)) == 0) {
                    719:                new = mak_buf();
                    720:                setfname(new, (char *) 0);
                    721:                setbname(new, name);
                    722:        }
                    723:        if (w)
                    724:                tiewind(w, new);
                    725:        return new;
                    726: }

unix.superglobalmegacorp.com

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