Annotation of coherent/a/usr/bob/uusrc/dcp/dcpsys.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * dcpsys.c
                      3:  *
                      4:  * System File Parsing and Initial Login Negotiation Routines for uucico
                      5:  */
                      6: 
                      7: /* #include <sys/dir.h> */
                      8: #include "dirent.h"
                      9: #include <ctype.h>
                     10: #include "dcp.h"
                     11: #include "lsys.h"
                     12: 
                     13: /*
                     14:  *  Communication Protocol Declarations and Definitions
                     15:  */
                     16: 
                     17: #define PROTOS  "g"
                     18: int (*getpkt)(), (*sendpkt)(), (*openpk)(), (*closepk)();
                     19: 
                     20: extern int ggetpkt(), gsendpkt(), gopenpk(), gclosepk();
                     21: #if 0
                     22: extern int kgetpkt(), ksendpkt(), kopenpk(), kclosepk();
                     23: extern int rgetpkt(), rsendpkt(), ropenpk(), rclosepk();
                     24: extern int tgetpkt(), tsendpkt(), topenpk(), tclosepk();
                     25: #endif
                     26: 
                     27: typedef struct proto {
                     28:        char type;              /* One character Protocol Type  */
                     29:        int (*getpkt)();        /* Get Packet Function          */
                     30:        int (*sendpkt)();       /* Send Packet Function         */
                     31:        int (*openpk)();        /* Open Packet Function         */
                     32:        int (*closepk)();       /* Close Packet Function        */
                     33: } PROTO;
                     34: 
                     35: PROTO protolst[] =
                     36: {
                     37:        { 'g', ggetpkt, gsendpkt, gopenpk, gclosepk },
                     38: #if 0
                     39:        { 'k', kgetpkt, ksendpkt, kopenpk, kclosepk },
                     40:        { 'r', rgetpkt, rsendpkt, ropenpk, rclosepk },
                     41:        { 't', tgetpkt, tsendpkt, topenpk, tclosepk },
                     42: #endif
                     43:        { '\0' }
                     44: };
                     45: 
                     46: int    leavelock = 0;          /* Leave the rmtname lock file  */
                     47: 
                     48: /*
                     49:  * getsystem()
                     50:  * Retrieve and Process an "L.sys" file entry.
                     51:  */
                     52: 
                     53: getsystem()
                     54: {
                     55:        if ( lsys_next() == 0 )
                     56:                return('A');
                     57: 
                     58:        rmtname = lsys_value(sys_e);
                     59:        if ( strcmp(rmtname, sysname) ) {
                     60:                if ( strcmp(sysname, "all") && strcmp(sysname, "any") )
                     61:                        return('I');
                     62:                if ( scandir() != 'S' )
                     63:                        return('I');
                     64:        }
                     65:        printmsg(M_CALL, "Thinking of calling system: %s", rmtname);
                     66:        if ( !checktime(lsys_value(sched_e)) )
                     67:                return('I');
                     68: 
                     69:        open_the_logfile("uucico");
                     70:        if (cfp != NULL)
                     71:                fclose(cfp);    /* in case matched scandir */
                     72:        if ( lockit(rmtname) < 0 ) {
                     73:                plog(M_CALL, "Site Locked: %s", rmtname);
                     74:                close_logfile();
                     75:                return('I');
                     76:        } 
                     77:        return('S');
                     78: }
                     79: 
                     80: /*
                     81:  * checkrmt()
                     82:  * Scan through L.sys file to verify that we know about the given
                     83:  * remote system name.
                     84:  * Returns: (1) if we found match, (0) if rmtname unknown.
                     85:  */
                     86: 
                     87: checkrmt()
                     88: {
                     89:        lsys_open();
                     90:        while ( lsys_next() ) {
                     91:                if ( strcmp(rmtname, lsys_value(sys_e)) == 0 )
                     92:                        return(1);
                     93:        }
                     94:        lsys_close();
                     95:        return(0);
                     96: }
                     97: 
                     98: /*
                     99:  *  rmsg(msg, maxlen)  char *msg;  int maxlen;
                    100:  *  Read a ^P (DLE) type msg from the remote uucp.  (startup negotiation).
                    101:  *
                    102:  *  wmsg(msg)  char *msg;
                    103:  *  Write a ^P (DLE) type msg to the remote uucp.  (startup negotiation).
                    104:  */
                    105: 
                    106: #define        MAXDROP 2048    /* Maximum characters to drop waiting for ^P    */
                    107: 
                    108: rmsg(msg, maxlen)
                    109: char *msg;
                    110: int maxlen;
                    111: {
                    112:        char ch;
                    113:        register char *cp;
                    114:        int i;
                    115: 
                    116:        for (i=0; i<MAXDROP; i++) {
                    117:                if ( sread(&ch, 1, MSGTIME) != 1 )
                    118:                        goto badrmsg;
                    119:                if ( ch == DLE )
                    120:                        break;
                    121:        }
                    122:        if ( ch != DLE )
                    123:                goto nodle;
                    124: 
                    125:        for (cp=msg,i=1; i<maxlen; i++) {
                    126:                if ( sread(&ch, 1, MSGTIME) != 1 )
                    127:                        goto badrmsg;
                    128:                if ( (ch == '\0') || (ch == '\r') || (ch == '\n') )
                    129:                        break;
                    130:                *cp++ = ch;
                    131:        }
                    132:        *cp = '\0';
                    133:        printmsg(M_DEBUG, "rmsg {%s}", visib(msg));
                    134:        return( strlen(msg) );
                    135: 
                    136: badrmsg:
                    137:        *cp = '\0';
                    138:        printmsg(M_CALL, "Bad received message {%s}", visib(msg));
                    139:        return(-1);
                    140: nodle:
                    141:        *cp = '\0';
                    142:        printmsg(M_CALL, "Remote machine not sending DLE startup (uucico)");
                    143:        return(-1);
                    144: }
                    145: 
                    146: wmsg(msg)
                    147: char *msg;
                    148: {
                    149:        char buf[2] = {'\0', DLE};
                    150: 
                    151:        printmsg(M_DEBUG, "wmsg {%s}", visib(msg));
                    152:        swrite(&buf[0], 2);
                    153:        swrite(msg, strlen(msg));
                    154:        swrite(&buf[0], 1);
                    155: }
                    156: 
                    157: /*
                    158:  * startup()
                    159:  *
                    160:  * Initiate communication with a remote uucp.
                    161:  */
                    162: 
                    163: #define        FAIL1(x)        {errmsg=(x); errarg=NULL; goto failure;}
                    164: #define        FAIL2(x, y)     {errmsg=(x); errarg=(y); goto failure;}
                    165: 
                    166: startup()
                    167: {
                    168:        char msg[BUFSIZ];
                    169:        char *errmsg, *errarg, *cp, ch;
                    170:        static char locbuf[SITELEN+1];
                    171:        static char *readymsg = "Ready for transactions";
                    172: 
                    173:        sysended = 0;
                    174:        leavelock = 0;
                    175:        if (role == MASTER) {
                    176:                if ( rmsg(msg, BUFSIZ) < 0 )
                    177:                        FAIL1("Logon failed: 1st msg (broken communication?)");
                    178:                printmsg(M_CALLMSG, "1st msg = {%s}", visib(msg));
                    179: 
                    180:                if ( strncmp(msg, "Shere", 5) )
                    181:                        FAIL1("Bad format for 1st msg");
                    182:                if ( (msg[5] == '\0') || (msg[5] == '\n') ||
                    183:                     (msg[6] == '\0') || (msg[6] == '\n') )
                    184:                        plog(M_CALL, "Warning: Null sitename contacted");
                    185:                else if ( strncmp(&msg[6], rmtname, SITESIG) )
                    186:                        FAIL2("Incorrect sitename contacted: %s", &msg[6]);
                    187: 
                    188:                sprintf(msg, "S%.*s -Q0 -x%d", SITESIG, nodename, debuglevel);
                    189:                printmsg(M_CALLMSG, "Reply to 1st msg = {%s}", msg);
                    190:                wmsg(msg);
                    191: 
                    192:                if ( rmsg(msg, BUFSIZ) < 0 )
                    193:                        FAIL1("Logon failed: 2nd msg (remote site stale LCK?)");
                    194: 
                    195:                printmsg(M_CALLMSG, "2nd msg = {%s}", visib(msg));
                    196:                if ( strncmp(msg, "ROK", 2) )
                    197:                        FAIL1("Bad format for 2nd msg");
                    198: 
                    199:                if ( rmsg(msg, BUFSIZ) < 0 )
                    200:                        FAIL1("Logon failed: 3rd msg (broken communication?)");
                    201:                printmsg(M_CALLMSG, "3rd msg = {%s}", visib(msg));
                    202:                if ( *msg != 'P' )
                    203:                        FAIL1("Bad format for 3rd msg");
                    204:                ch = 'N';
                    205:                for (cp=PROTOS; *cp; cp++)
                    206:                        if ( index(&msg[1], *cp) != NULL ) {
                    207:                                ch = *cp;
                    208:                                break;
                    209:                        }
                    210:                sprintf(msg, "U%c", ch);
                    211:                printmsg(M_CALLMSG, "Reply to 3rd msg = {%s}", msg);
                    212:                wmsg(msg);
                    213:                if ( ch == 'N' )
                    214:                        FAIL1("No common protocol");
                    215:                setproto(ch);
                    216:                plog(M_CALL, readymsg);
                    217:                return('D');
                    218:        } else {
                    219:                sprintf(msg, "Shere=%s", nodename);
                    220:                printmsg(M_CALLMSG, "1st msg = {%s}", msg);
                    221:                wmsg(msg);
                    222: 
                    223:                if ( rmsg(msg, BUFSIZ) < 0 )
                    224:                        FAIL1("Logon failed: 1st reply (wrong sitename?)");
                    225:                printmsg(M_CALLMSG, "Reply to 1st msg = {%s}", visib(msg));
                    226:                if ( *msg != 'S' )
                    227:                        FAIL1("Bad format for reply to 1st msg");
                    228:                if ( (cp=index(msg+1, ' ')) != NULL )
                    229:                        *cp = '\0';
                    230:                if ( strlen(msg) > (SITELEN+1) )
                    231:                        FAIL1("Received sitename to long");
                    232:                strcpy(locbuf, msg+1);
                    233:                rmtname = &locbuf[0];
                    234: #ifdef BBS
                    235: #define BBSUSER        "bbsuser"
                    236: 
                    237:                /*
                    238:                 * For BBS, anonymous caller's sitename is replaced by the
                    239:                 * device name, notice we skip over "/dev/".
                    240:                 */
                    241:                {
                    242:                        char *tmp;
                    243: 
                    244:                        if ( (strcmp(rmtname, BBSUSER) == 0) &&
                    245:                             ((tmp=ttyname(fileno(stdin))) != NULL) )
                    246:                                sprintf(locbuf, "U%s", tmp+5);
                    247:                        printmsg(M_DEBUG, "BBS replaced new rmtname: <%s>",
                    248:                                                                 rmtname);
                    249:                }
                    250: #endif
                    251:                open_the_logfile("uucico");
                    252:                plog(M_CALL, "Call received from %s {%d} (V%s)",
                    253:                                                rmtname, processid, version);
                    254:                plog(M_CALL,"Locking remote site %s",rmtname);
                    255:                if ( lockit(rmtname) < 0 ) {
                    256:                        leavelock = 1;
                    257:                        FAIL2("Incoming site %s already locked", rmtname);
                    258:                }
                    259: 
                    260:                if ( !checkrmt() )
                    261:                        FAIL2("Unknown host %s", rmtname);
                    262: 
                    263:                if ( (rdevname=ttyname(fileno(stdin))) == NULL )
                    264:                        FAIL1("No attached tty device.");
                    265:                rdevname += 5;
                    266: 
                    267:        /* The incoming device will already have been locked by login.  */
                    268:                if (MASTER == role) { 
                    269:                        if ( locktty(rdevname) < 0 ) {
                    270:                                cp = rdevname;
                    271:                                rdevname = NULL;
                    272:                                FAIL2("Incoming device locked: %s", cp);
                    273:                        }
                    274:                }
                    275: 
                    276:                sprintf(msg, "ROK");
                    277:                printmsg(M_CALLMSG, "2nd msg = {%s}", msg);
                    278:                wmsg(msg);
                    279:                sprintf(msg, "P%s", PROTOS);
                    280:                printmsg(M_CALLMSG, "3rd msg = {%s}", msg);
                    281:                wmsg(msg);
                    282:                if ( rmsg(msg, BUFSIZ) < 0 )
                    283:                        FAIL1("Logon failure: 3rd reply (lost communication?)");
                    284:                printmsg(M_CALLMSG, "Reply to 3rd msg = {%s}", visib(msg));
                    285:                if ( (msg[0] != 'U') || (index(PROTOS, msg[1]) == NULL) )
                    286:                        FAIL1("No common communications protocol");
                    287:                setproto(msg[1]);
                    288:                plog(M_CALL, readymsg);
                    289:                return('R');
                    290:        }
                    291: 
                    292: failure:
                    293:        plog(M_CALL, errmsg, errarg);
                    294:        terminatelevel++;
                    295:        return('Y');
                    296: }
                    297: 
                    298: /*
                    299:  * Assign the global protocol function variables to the specified
                    300:  * protocol type.
                    301:  */
                    302: 
                    303: setproto(type)
                    304: char type;
                    305: {
                    306:        register PROTO *p;
                    307: 
                    308:        for(p=&protolst[0]; (p->type!='\0') && (p->type!=type); p++) ;
                    309: 
                    310:        if (p->type == '\0')
                    311:                fatal("setproto('%c'): Unknown protocol type", type);
                    312:        printmsg(M_CALL, "Agreed protocol: %c", type);
                    313:        getpkt  = p->getpkt;
                    314:        sendpkt = p->sendpkt;
                    315:        openpk  = p->openpk;
                    316:        closepk = p->closepk;
                    317: 
                    318: }
                    319: 
                    320: /*
                    321:  *  expectstr(str, timeout)  char *str; int timeout;
                    322:  *
                    323:  *  Wait to receive the specified "str" from the serial connection.
                    324:  *  Returns: (1) if string received,
                    325:  *          (0) for timeout occurred before string received.
                    326:  */
                    327: 
                    328: expectstr(str, timeout)
                    329: char *str;
                    330: int timeout;
                    331: {
                    332:        register char *cp;
                    333:        char buf[BUFSIZ], ch;
                    334:        int retval = 0;
                    335:        int len;
                    336: 
                    337:        printmsg(M_DEBUG, "waiting for {%s}", str);
                    338: 
                    339:        if ( strcmp(str, "\"\"") == 0 )
                    340:                retval = 1;
                    341:        len = strlen(str);
                    342: 
                    343:        cp = &buf[0];
                    344:        while ( !retval && (sread(&ch, 1, timeout) == 1) ) {
                    345:                *cp++ = ch;
                    346:                if ( (cp-buf) < len )
                    347:                        continue;
                    348:                *cp = '\0';
                    349:                if ( strncmp(str, cp-len, len) == 0 )
                    350:                        retval = 1;
                    351:                if ( cp == &buf[BUFSIZ-1] )
                    352:                        break;
                    353:        }
                    354:        printmsg(M_CALL, "actually received {%s}", visbuf(buf, cp-buf));
                    355:        if ( retval )
                    356:                printmsg(M_CALL, "got that");
                    357:        return(retval);
                    358: }
                    359: 
                    360: /*
                    361:  *  sendstr(str) char *str;
                    362:  *  Send string of chat script out the communications line.
                    363:  */
                    364: 
                    365: sendstr(str)
                    366: char *str;
                    367: {
                    368:        register char *cp = str;
                    369:        char ch;
                    370:        int slash, nocr;
                    371: 
                    372:        sleep(1);
                    373:        if ( strncmp(str, "\"\"", 2) == 0 )
                    374:                str = "";
                    375: 
                    376:        nocr = slash = 0;
                    377:        while ( (ch=*cp++) ) {
                    378:                if ( !slash ) {
                    379:                        if ( strncmp(cp-1, "EOT", 3) == 0 ) {
                    380:                                swrite("\004", 1);
                    381:                                cp += 2;
                    382:                        } else if ( strncmp(cp-1, "BREAK", 4) == 0 ) {
                    383:                                sendbrk();
                    384:                                cp += 4;
                    385:                        } else if ( ch == '\\' ) {
                    386:                                slash = 1;
                    387:                        } else {
                    388:                                swrite(&ch, 1);
                    389:                        }
                    390:                        continue;
                    391:                }
                    392:                switch( ch ) {
                    393:                case 'b':
                    394:                        swrite("\b", 1);
                    395:                        break;
                    396:                case 'c':
                    397:                        nocr = 1;
                    398:                        break;
                    399:                case 'd':
                    400:                        sleep(2);
                    401:                        break;
                    402:                case 'K':
                    403:                        sendbrk();
                    404:                        break;
                    405:                case 'n':
                    406:                        swrite("\n", 1);
                    407:                        break;
                    408:                case 'N':
                    409:                        swrite("\0", 1);
                    410:                        break;
                    411:                case 'p':
                    412:                        sleep(1);
                    413:                        break;
                    414:                case 'r':
                    415:                        swrite("\r", 1);
                    416:                        break;
                    417:                case 's':
                    418:                        swrite(" ", 1);
                    419:                        break;
                    420:                case 't':
                    421:                        swrite("\t", 1);
                    422:                        break;
                    423:                case '\\':
                    424:                        swrite("\\", 1);
                    425:                        break;          
                    426:                default:
                    427:                        if ( !isdigit(ch) ||
                    428:                             !isdigit(*cp) ||
                    429:                             !isdigit(*(cp+1)) )
                    430:                                fatal("Can't parse chat script: {%s}", str);
                    431:                        ch = ((ch-'0')<<6) | ((*cp-'0')<<3) | (*(cp+1));
                    432:                        swrite(&ch, 1);
                    433:                        break;
                    434:                }
                    435:                slash = 0;
                    436:        }
                    437:        if ( !nocr )
                    438:                swrite("\r", 1);
                    439: }
                    440: 
                    441: /*
                    442:  * callup()
                    443:  * Initiate the call, and walk through the chat script.
                    444:  */
                    445: 
                    446: callup()
                    447: {
                    448:        char *device, *speed, *phone;
                    449:        char *expect, *send, *dsh;
                    450:        int i;
                    451: 
                    452:        plog(M_CALL, "Calling site %s {%d} (V%s)", rmtname, processid, version);
                    453:        
                    454:        device = lsys_value(device_e);
                    455:        speed  = lsys_value(speed_e);
                    456:        phone  = lsys_value(phone_e);
                    457: 
                    458:        if ( strcmp(device, "ACU") == 0 ) {
                    459:                if ( !dcpdial(NULL, speed, phone) )
                    460:                        goto calluperr;
                    461:        } else if ( !dcpdial(device, speed, NULL) )
                    462:                goto calluperr;
                    463: 
                    464:        for (i=0; (expect=lsys_expect(i)) != NULL; i++) {
                    465:                for (;;) {
                    466:                        printmsg(M_CALL, "callup: expecting {%s}", expect);
                    467:                        if ( (dsh=index(expect, '-')) != NULL )
                    468:                                *dsh++ = '\0';
                    469:                        if ( expectstr(expect, MSGTIME) )
                    470:                                break;
                    471:                        if ( dsh == NULL ) {
                    472:                                plog(M_CALL, "Login failed.");
                    473:                                goto calluperr;
                    474:                        }
                    475:                        if ( (expect=index(dsh, '-')) == NULL )
                    476:                                fatal("Chat script syntax error: %s", dsh);
                    477:                        *expect++ = '\0';
                    478:                        printmsg(M_CALL, "callup: send alternate {%s}", dsh);
                    479:                        sendstr(dsh);
                    480:                }
                    481:                send = lsys_send(i);
                    482:                printmsg(M_CALL, "callup: sending {%s}", send);
                    483:                sendstr(send);
                    484:        }
                    485:        return('P');
                    486: 
                    487: calluperr:
                    488:        terminatelevel++;
                    489:        return('Y');
                    490: }
                    491: 
                    492: /*
                    493:  *  sysend()
                    494:  *  End UUCP session.
                    495:  */
                    496: 
                    497: sysend()
                    498: {
                    499: 
                    500:        /* We may have a problem here. Someone else may be removing the remote
                    501:         * device lock file before we call unlocktty. Tests have shown this to
                    502:         * be unimportant because the lock file IS being removed. A warning
                    503:         * will be printed to the log files for users to check for locks.
                    504:         * Hopefully, this isn't going to be a bug.  Bob H. 11/22/91.
                    505:         */
                    506: 
                    507:        /* December 4, 1991: Problem solved(?). When we are in master mode,
                    508:         * we call dcpundial, which calls the hangup, which, in turn, calls
                    509:         * undial. Undial removes the locks on the device. Thie following
                    510:         * code USED to call dcpundial if in master mode, and THEN continued
                    511:         * to call the unlocktty function, which had previously been called
                    512:         * by dcpundial. I snuck in an 'else' statement to get around this.
                    513:         * Tests show that this solves the problem described above, but who
                    514:         * knows if this will cause problems when we are NOT in master mode.
                    515:         */
                    516: 
                    517:        if ( lockttyexist(rdevname) ) {
                    518:                if ( role == MASTER ){
                    519:                        printmsg(M_DEBUG,"Sysend: calling undial and hangup routines.");
                    520:                        dcpundial();
                    521:                }else{
                    522:                        plog(M_CALL,"Sysend: Removing remote device lock file.");
                    523:                        if(unlocktty(rdevname) != 0){
                    524:                                plog(M_CALL,"sysend: Possible lock file removal failure.");
                    525:                        }
                    526:                }
                    527:        }
                    528: 
                    529:        /* May 05, 1992 (Bob H.) problems communicating with a 386 based bbs
                    530:         * and a customer complaint from Germany lead to the discovery of a
                    531:         * condition where undial() was never called, which meant that cicio
                    532:         * NEVER hung up the phone! Adding the dcpundial() in the following
                    533:         * if... resolves this.
                    534:         */
                    535:        if ( !leavelock && lockexist(rmtname) ){
                    536:                dcpundial();
                    537:                plog(M_CALL,"Removing remote site lock");
                    538:                if(lockrm(rmtname) != 0){
                    539:                        printmsg(M_LOG,"sysend: Remote site Lock file removal failed!");
                    540:                        plog(M_CALL,"sysend: Remote site lock file removal failed!");
                    541:                }
                    542:        }
                    543:        plog(M_CALL, terminatelevel ?
                    544:                "Abnormal completion {%d}" :
                    545:                "Call completing normally {%d}", processid);
                    546:        close_logfile();
                    547:        sysended = 1;
                    548:        return( (role == MASTER) ? 'I': 'A' );
                    549: }
                    550: 
                    551: /*
                    552:  * scandir()
                    553:  *
                    554:  * scan work dir for "C." files matching current remote host (rmtname)
                    555:  * return:
                    556:  *        Y    - can't open file
                    557:  *        S    - ok
                    558:  *        Q    - no files 
                    559:  */
                    560: 
                    561: extern DIR *opendir();
                    562: extern struct direct *readdir();
                    563: 
                    564: scandir()
                    565: {
                    566:        char fn[DIRSIZ+1];
                    567:        char dirname[CTLFLEN];
                    568:        DIR *dirp;
                    569:        struct dirent *dp;
                    570: 
                    571:        sprintf(dirname, "%s/%s", SPOOLDIR, rmtname); /* build spool dir name */
                    572:        printmsg(M_INFO, "Scandir: %s", dirname);
                    573: 
                    574:        if ((dirp=opendir(dirname)) == NULL)    /* open spool dir */
                    575:                return('Q');
                    576: 
                    577:        fn[0] = fn[DIRSIZ] = '\0';
                    578:        while ( (dp=readdir(dirp)) != NULL ) {
                    579:                printmsg(M_DEBUG, "Scandir: %s", dp->d_name);
                    580:                if ( strncmp("C.", dp->d_name, 2) )     /* is this a C. file? */
                    581:                        continue;
                    582:                if ( (fn[0] == '\0') || (strncmp(dp->d_name, fn, DIRSIZ) < 0) )
                    583:                        strncpy(fn, dp->d_name, DIRSIZ);
                    584:        }
                    585:        closedir(dirp);
                    586: 
                    587:        if (fn[0] != '\0') {
                    588:                sprintf(cfile, "%s/%s/%s", SPOOLDIR, rmtname, fn);
                    589:                printmsg(M_DEBUG, "Scandir: cfile: %s", cfile);
                    590:                if ((cfp = fopen(cfile, "r")) == NULL) {
                    591:                        plog(M_DEBUG, "Unable to open control file %s", cfile);
                    592:                        terminatelevel++;
                    593:                        return('Y');
                    594:                }
                    595:                return('S');
                    596:        }
                    597:        return('Q');
                    598: }

unix.superglobalmegacorp.com

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