Annotation of coherent/e/bin/ckermit/ckcpro.w, revision 1.1.1.1

1.1       root        1: char *protv = "C-Kermit Protocol Module 5A(052), 23 Nov 92"; /* -*-C-*- */
                      2: 
                      3: /* C K C P R O  -- C-Kermit Protocol Module, in Wart preprocessor notation. */
                      4: /*
                      5:   Author: Frank da Cruz ([email protected], [email protected]),
                      6:   Columbia University Center for Computing Activities.
                      7:   First released January 1985.
                      8:   Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New
                      9:   York.  Permission is granted to any individual or institution to use this
                     10:   software as long as it is not sold for profit.  This copyright notice must be
                     11:   retained.  This software may not be included in commercial products without
                     12:   written permission of Columbia University.
                     13: */
                     14: #include "ckcdeb.h"
                     15: #include "ckcasc.h"
                     16: #include "ckcker.h"
                     17: /*
                     18:  Note -- This file may also be preprocessed by the Unix Lex program, but 
                     19:  you must indent the above #include statements before using Lex, and then
                     20:  restore them to the left margin in the resulting C program before compilation.
                     21:  Also, the invocation of the "wart()" function below must be replaced by an
                     22:  invocation  of the "yylex()" function.  It might also be necessary to remove
                     23:  comments in the %%...%% section.
                     24: */
                     25: 
                     26: /* State definitions for Wart (or Lex) */
                     27: %states ipkt rfile rattr rdata ssinit ssfile ssattr ssdata sseof sseot
                     28: %states serve generic get rgen
                     29: 
                     30: /* External C-Kermit variable declarations */
                     31:   extern char *versio, *srvtxt, *cmarg, *cmarg2, **cmlist;
                     32:   extern char filnam[], ttname[];
                     33:   extern CHAR sstate, *rpar(), encbuf[], *srvptr, *data;
                     34:   extern int timint, rtimo, nfils, hcflg, xflg, flow, mdmtyp, network;
                     35:   extern int cxseen, czseen, server, srvdis, local, displa, bctu, bctr, bctl;
                     36:   extern int quiet, tsecs, parity, backgrd, nakstate, atcapu, wslotn, winlo;
                     37:   extern int wslots, success, xitsta, rprintf, discard, cdtimo, keep, fdispla;
                     38:   extern int timef;
                     39:   extern long speed, ffc;
                     40:   extern char *DIRCMD, *DIRCM2, *DELCMD, *TYPCMD, *SPACMD, *SPACM2, *WHOCMD;
                     41:   extern CHAR *rdatap;
                     42:   extern struct zattr iattr;
                     43: #ifdef DYNAMIC
                     44:   extern CHAR *srvcmd;
                     45: #else
                     46:   extern CHAR srvcmd[];
                     47: #endif /* DYNAMIC */
                     48: 
                     49: #ifndef NOSPL
                     50:   extern int cmdlvl;
                     51: #else
                     52:   extern int tlevel;
                     53: #endif /* NOSPL */
                     54: 
                     55: #ifdef NOMSEND
                     56:   extern int sndsrc;
                     57: #endif /* NOMSEND */
                     58: 
                     59: /* Flags for the ENABLE and DISABLE commands */
                     60: extern int
                     61:   en_cwd, en_del, en_dir, en_fin, en_get, en_bye,
                     62:   en_hos, en_sen, en_spa, en_set, en_typ, en_who;
                     63: 
                     64: /* Global variables declared here */
                     65: 
                     66:   int what = W_NOTHING;                        /* What we're doing */
                     67: 
                     68: /* Local variables */
                     69: 
                     70:   static char vstate = 0;              /* Saved State   */
                     71:   static char vcmd = 0;                /* Saved Command */
                     72: 
                     73:   static int x;                                /* General-purpose integer */
                     74:   static char *s;                      /* General-purpose string pointer */
                     75: 
                     76: /* Macros - Note, BEGIN is predefined by Wart (and Lex) as "state = ", */
                     77: /* BEGIN is NOT a GOTO! */
                     78: #define TINIT  if (tinit() < 0) return(-9)
                     79: #define SERVE  TINIT; nakstate = 1; what = W_NOTHING; BEGIN serve
                     80: #define RESUME if (server) { SERVE; } else { sleep(2); return(0); }
                     81: #define QUIT x=quiet; quiet=1; clsif(); clsof(1); tsecs=gtimer(); quiet=x; \
                     82:  return(1)
                     83: 
                     84: %%
                     85: /*
                     86:   Protocol entry points, one for each start state (sstate).
                     87:   The lowercase letters are internal "inputs" from the user interface.
                     88: */
                     89: 
                     90: s { TINIT;                             /* Do Send command */
                     91:     if (sinit()) BEGIN ssinit;
                     92:        else RESUME; }
                     93: 
                     94: v { TINIT; nakstate = 1; BEGIN get; }                          /* Receive */
                     95: r { TINIT; vstate = get;  vcmd = 0;   sipkt('I'); BEGIN ipkt; } /* Get */
                     96: c { TINIT; vstate = rgen; vcmd = 'C'; sipkt('I'); BEGIN ipkt; } /* Host */
                     97: k { TINIT; vstate = rgen; vcmd = 'K'; sipkt('I'); BEGIN ipkt; } /* Kermit */
                     98: g { TINIT; vstate = rgen; vcmd = 'G'; sipkt('I'); BEGIN ipkt; } /* Generic */
                     99: 
                    100: x { sleep(1); SERVE; }                 /* Be a Server */
                    101: 
                    102: a { if (!data) TINIT;                  /* "ABEND" -- Tell other side. */
                    103:     errpkt((CHAR *)"User cancelled");
                    104:     success = 0;
                    105:     return(0); }                       /* Return from protocol. */
                    106: 
                    107: /*
                    108:   Dynamic states: <current-states>input-character { action }
                    109:   nakstate != 0 means we're in a receiving state, in which we send ACKs & NAKs.
                    110: */
                    111: <rgen,get,serve>S {                    /* Receive Send-Init packet. */
                    112:     if (state == serve && !en_sen) {   /* Not allowed if in server mode */
                    113:        errpkt((CHAR *)"SEND disabled"); /* and SEND is disabled. */
                    114:        SERVE;
                    115:     } else {                           /* OK to go ahead. */
                    116:        nakstate = 1;                   /* Can send NAKs from here. */
                    117:        rinit(rdatap);                  /* Set parameters */
                    118:        bctu = bctr;                    /* Switch to agreed-upon block check */
                    119:        bctl = (bctu == 4) ? 2 : bctu;  /* Set block-check length */
                    120:        what = W_RECV;                  /* Remember we're receiving */
                    121:        resetc();                       /* Reset counters */
                    122:        rtimer();                       /* Reset timer */
                    123:        BEGIN rfile;                    /* Go into receive-file state */
                    124:     }
                    125: }
                    126: 
                    127: /* States in which we get replies back from commands sent to a server. */
                    128: /* Complicated because direction of protocol changes, packet number    */
                    129: /* stays at zero through I-G-S sequence, and complicated even more by  */
                    130: /* sliding windows buffer allocation. */
                    131: 
                    132: <ipkt>Y {                              /* Get ack for I-packet */
                    133:     spar(rdatap);                      /* Set parameters */
                    134: #ifdef COMMENT
                    135:     getsbuf(winlo = 0);                        /* Set window-low back to zero */
                    136: #else
                    137:     winlo = 0;
                    138: #endif /* COMMENT */
                    139:     if (vcmd) {                                /* If sending a generic command */
                    140:        scmd(vcmd,(CHAR *)cmarg);       /* Do that */
                    141:        vcmd = 0;                       /* and then un-remember it. */
                    142:     } else if (vstate == get) srinit();        /* If sending GET command, do that. */
                    143:     rtimer();                          /* Reset the elapsed seconds timer. */
                    144:     winlo = 0;                         /* Window back to 0, again. */
                    145:     nakstate = 1;                      /* Can send NAKs from here. */
                    146:     BEGIN vstate;                      /* Switch to desired state */
                    147: }
                    148: 
                    149: <ipkt>E {                              /* Ignore Error reply to I packet */
                    150: #ifdef COMMENT
                    151:     getsbuf(winlo = 0);                        /* Set window-low back to zero */
                    152: #else
                    153:     winlo = 0;
                    154: #endif /* COMMENT */
                    155:     if (vcmd) {                                /* In case other Kermit doesn't */
                    156:        scmd(vcmd,(CHAR *)cmarg);       /* understand I-packets. */
                    157:        vcmd = 0;                       /* Otherwise act as above... */
                    158:     } else if (vstate == get) srinit();
                    159:     winlo = 0;                         /* Back to packet 0 again. */
                    160:     freerpkt(winlo);                   /* Discard the Error packet. */
                    161:     nakstate = 1;                      /* Can send NAKs from here. */
                    162:     BEGIN vstate;
                    163: }
                    164: 
                    165: <get>Y {               /* Resend of previous I-pkt ACK, same seq number! */
                    166:     srinit();
                    167: }
                    168: 
                    169: /* States in which we're being a server */
                    170: 
                    171: <serve>I {                             /* Get I-packet */
                    172:     spar(rdatap);                      /* Set parameters from it */
                    173:     ack1(rpar());                      /* Respond with our own parameters */
                    174:     pktinit();                         /* Reinitialize packet numbers */
                    175: }
                    176: 
                    177: <serve>R {                             /* Get Receive-Init (GET) */
                    178:     debug(F100,"<serve>R","",0);
                    179:     if (!en_get) {                     /* Only if not disabled!  */
                    180:        errpkt((CHAR *)"GET disabled");
                    181:        SERVE;
                    182:     } else {                           /* OK to go ahead. */
                    183:        srvptr = srvcmd;                /* Point to server command buffer */
                    184:        decode(rdatap,putsrv,0);        /* Decode the GET command into it */
                    185:        /* Accept multiple filespecs */
                    186:         cmarg2 = "";                   /* Don't use cmarg2 */
                    187:        cmarg = "";                     /* Don't use cmarg */
                    188: #ifndef NOMSEND                                /* New way. */
                    189:        nfils = fnparse((char *)srvcmd); /* Use cmlist instead */
                    190: #else
                    191:        nfils = 0 - zxpand((char *)srvcmd);
                    192: #endif /* NOMSEND */
                    193:        nakstate = 0;                   /* Now I'm the sender! */
                    194:        if (sinit()) {                  /* Send Send-Init */
                    195:            timint = chktimo(rtimo,timef); /* Switch to per-packet timer */
                    196:            BEGIN ssinit;               /* If successful, switch state */
                    197:        } else { SERVE; }               /* Else back to server command wait */
                    198:     }
                    199: }
                    200: 
                    201: <serve>G {                             /* Generic server command */
                    202:     srvptr = srvcmd;                   /* Point to command buffer */
                    203:     decode(rdatap,putsrv,0);           /* Decode packet data into it */
                    204:     putsrv('\0');                      /* Insert a couple nulls */
                    205:     putsrv('\0');                      /* for termination */
                    206:     if (srvcmd[0]) {
                    207:        sstate = srvcmd[0];             /* Set requested start state */
                    208:        nakstate = 0;                   /* Now I'm the sender. */
                    209:        what = W_REMO;                  /* Doing a REMOTE command. */
                    210:        if (timint < 1)
                    211:          timint = chktimo(rtimo,timef); /* Switch to per-packet timer */
                    212:        BEGIN generic;                  /* Switch to generic command state */
                    213:     } else {
                    214:        errpkt((CHAR *)"Badly formed server command"); /* report error */
                    215:        SERVE;                          /* & go back to server command wait */
                    216:     }
                    217: }
                    218: 
                    219: <serve>C {                             /* Receive Host command */
                    220:     if (!en_hos) {
                    221:        errpkt((CHAR *)"REMOTE HOST disabled");
                    222:        SERVE;
                    223:     } else {
                    224:        srvptr = srvcmd;                /* Point to command buffer */
                    225:        decode(rdatap,putsrv,0);        /* Decode command packet into it */
                    226:        putsrv('\0');                   /* Null-terminate */
                    227:        nakstate = 0;                   /* Now sending, not receiving */
                    228:        if (syscmd((char *)srvcmd,"")) { /* Try to execute the command */
                    229:            what = W_REMO;              /* Doing a REMOTE command. */
                    230:            if (timint < 1)
                    231:              timint = chktimo(rtimo,timef); /* Switch to per-packet timer */
                    232:            BEGIN ssinit;               /* If OK, send back its output */
                    233:        } else {                        /* Otherwise */
                    234:            errpkt((CHAR *)"Can't do system command"); /* report error */
                    235:            SERVE;                      /* & go back to server command wait */
                    236:        }
                    237:     }
                    238: }
                    239: 
                    240: <serve>q {                             /* User typed Ctrl-C... */
                    241:     if (!en_fin) {
                    242:        errpkt((CHAR *)"QUIT disabled");
                    243:        SERVE;
                    244:     } else {
                    245:        success = 0; QUIT;
                    246:     }
                    247: }
                    248: 
                    249: <serve>N {                             /* Server got a NAK in command-wait */
                    250:     errpkt((CHAR *)"Did you say RECEIVE instead of GET?");
                    251:     SERVE;
                    252: }
                    253: 
                    254: <serve>. {                             /* Any other command in this state */
                    255:     errpkt((CHAR *)"Unimplemented server function"); /* we don't know about */
                    256:     SERVE;                             /* back to server command wait */
                    257: }
                    258: 
                    259: <generic>C {                           /* Got REMOTE CWD command */
                    260:     if (!en_cwd) {
                    261:        errpkt((CHAR *)"REMOTE CD disabled");
                    262:        SERVE;
                    263:     } else {
                    264:        if (!cwd((char *)(srvcmd+1))) errpkt((CHAR *)"Can't change directory");
                    265:        SERVE;                          /* Back to server command wait */
                    266:     }
                    267: }
                    268: 
                    269: <generic>D {                           /* REMOTE DIRECTORY command */
                    270:     char *n2;
                    271:     if (!en_dir) {                     /* If DIR is disabled, */
                    272:        errpkt((CHAR *)"REMOTE DIRECTORY disabled"); /* refuse. */
                    273:        SERVE;
                    274:     } else {                           /* DIR is enabled. */
                    275:        if (!en_cwd) {                  /* But if CWD is disabled */
                    276:            zstrip((char *)(srvcmd+2),&n2); /* and they included a pathname, */
                    277:            if (strcmp((char *)(srvcmd+2),n2)) { /* refuse. */
                    278:                errpkt((CHAR *)"Access denied");
                    279:                SERVE;                  /* Remember, this is not a goto! */
                    280:            }
                    281:        }       
                    282:        if (state == generic) {                 /* It's OK to go ahead. */
                    283:            n2 = (*(srvcmd+2)) ? DIRCMD : DIRCM2;
                    284:            if (syscmd(n2,(char *)(srvcmd+2)))  /* If it can be done */
                    285:              BEGIN ssinit;                     /* send the results back */
                    286:            else {                              /* otherwise */
                    287:                errpkt((CHAR *)"Can't list directory"); /* report failure, */
                    288:                SERVE;                  /* return to server command wait */
                    289:            }
                    290:        }
                    291:     }
                    292: }
                    293: 
                    294: <generic>E {                           /* REMOTE DELETE (Erase) command */
                    295:     char *n2;
                    296:     if (!en_del) {
                    297:        errpkt((CHAR *)"REMOTE DELETE disabled");    
                    298:        SERVE;
                    299:     } else {
                    300:        if (!en_cwd) {                  /* But if CWD is disabled */
                    301:            zstrip((char *)(srvcmd+2),&n2); /* and they included a pathname, */
                    302:            if (strcmp((char *)(srvcmd+2),n2)) { /* refuse. */
                    303:                errpkt((CHAR *)"Access denied");
                    304:                SERVE;                  /* Remember, this is not a goto! */
                    305:            }
                    306:        }       
                    307:        if (state == generic) {                 /* It's OK to go ahead. */
                    308:            if (syscmd(DELCMD,(char *)(srvcmd+2))) /* Try to do it */
                    309:              BEGIN ssinit;                     /* If OK send results back */
                    310:            else {                              /* otherwise */
                    311:                errpkt((CHAR *)"Can't remove file"); /* report failure */
                    312:                SERVE;                  /* & return to server command wait */
                    313:            }
                    314:        }
                    315:     }
                    316: }
                    317: 
                    318: <generic>F {                           /* FINISH */
                    319:     if (!en_fin) {
                    320:        errpkt((CHAR *)"FINISH disabled");    
                    321:        SERVE;
                    322:     } else {
                    323:        ack();                          /* Acknowledge */
                    324:        screen(SCR_TC,0,0l,"");         /* Display */
                    325:        return(0);                      /* Done */
                    326:     }
                    327: }
                    328: 
                    329: <generic>L {                           /* BYE (LOGOUT) */
                    330:     if (!en_bye) {
                    331:        errpkt((CHAR *)"BYE disabled");    
                    332:        SERVE;
                    333:     } else {
                    334:        ack();                          /* Acknowledge */
                    335:        ttres();                        /* Reset the terminal */
                    336:        screen(SCR_TC,0,0l,"");         /* Display */
                    337:        doclean();                      /* Clean up files, etc */
                    338:        return(zkself());               /* Try to log self out */
                    339:     }
                    340: }
                    341: 
                    342: <generic>H {                           /* REMOTE HELP */
                    343:     if (sndhlp()) BEGIN ssinit;                /* Try to send it */
                    344:     else {                             /* If not ok, */
                    345:        errpkt((CHAR *)"Can't send help"); /* send error message instead */
                    346:        SERVE;                          /* and return to server command wait */
                    347:     }
                    348: }
                    349: 
                    350: <generic>S {                           /* REMOTE SET */
                    351:     if (!en_set) {
                    352:        errpkt((CHAR *)"REMOTE SET disabled");
                    353:        SERVE;
                    354:     } else {
                    355:        if (remset((char *)(srvcmd+1))) /* Try to do what they ask */
                    356:          ack();                        /* If OK, then acknowledge */
                    357:        else                            /* Otherwise */
                    358:          errpkt((CHAR *)"Unknown REMOTE SET parameter"); /* give error msg */
                    359:        SERVE;                          /* Return to server command wait */
                    360:     }
                    361: }
                    362: 
                    363: <generic>T {                           /* REMOTE TYPE */
                    364:     char *n2;
                    365:     if (!en_typ) {
                    366:        errpkt((CHAR *)"REMOTE TYPE disabled");
                    367:        SERVE;
                    368:     } else {
                    369:        if (!en_cwd) {                  /* But if CWD is disabled */
                    370:            zstrip((char *)(srvcmd+2),&n2); /* and they included a pathname, */
                    371:            if (strcmp((char *)(srvcmd+2),n2)) { /* refuse. */
                    372:                errpkt((CHAR *)"Access denied");
                    373:                SERVE;                  /* Remember, this is not a goto! */
                    374:            }
                    375:        }       
                    376:        if (state == generic) {                 /* It's OK to go ahead. */
                    377:            if (syscmd(TYPCMD,(char *)(srvcmd+2))) /* Try */
                    378:              BEGIN ssinit;                     /* OK */
                    379:            else {                              /* not OK */
                    380:                errpkt((CHAR *)"Can't type file"); /* give error message */
                    381:                SERVE;                  /* wait for next server command */
                    382:            }
                    383:        }
                    384:     }
                    385: }
                    386: 
                    387: <generic>U {                           /* REMOTE SPACE */
                    388:     if (!en_spa) {
                    389:        errpkt((CHAR *)"REMOTE SPACE disabled");
                    390:        SERVE;
                    391:     } else {
                    392:        x = *(srvcmd+1);                /* Get area to check */
                    393:        x = ((x == '\0') || (x == SP)
                    394: #ifdef OS2
                    395:             || (x == '!')
                    396: #endif /* OS2 */
                    397:             );
                    398:        if (!x && !en_cwd) {            /* If CWD disabled and they gave */
                    399:            errpkt((CHAR *)"Access denied"); /* a non-default area, */
                    400:            SERVE;                      /* refuse. */
                    401:        } else {
                    402: #ifdef OS2
                    403: _PROTOTYP(int sndspace,(int));
                    404:            if (sndspace(x ? toupper(srvcmd[2]) : 0))
                    405:              BEGIN ssinit;             /* Try to send it */
                    406:            else {                      /* If not ok, */
                    407:                errpkt((CHAR *)"Can't send space"); /* send error message */
                    408:                SERVE;                  /* and return to server command wait */
                    409:            }
                    410: #else
                    411:            x = (x ? syscmd(SPACMD,"") : syscmd(SPACM2,(char *)(srvcmd+2)));
                    412:            if (x) {                            /* If we got the info */
                    413:                BEGIN ssinit;                   /* send it */
                    414:            } else {                            /* otherwise */
                    415:                errpkt((CHAR *)"Can't check space"); /* send error message */
                    416:                SERVE;                  /* and await next server command */
                    417:            }
                    418: #endif /* OS2 */
                    419:        }
                    420:     }
                    421: }
                    422: 
                    423: <generic>W {                           /* REMOTE WHO */
                    424:     if (!en_who) {
                    425:        errpkt((CHAR *)"REMOTE WHO disabled");
                    426:        SERVE;
                    427:     } else {
                    428:        if (syscmd(WHOCMD,(char *)(srvcmd+2))) /* The now-familiar scenario. */
                    429:          BEGIN ssinit;
                    430:        else {
                    431:            errpkt((CHAR *)"Can't do who command");
                    432:            SERVE;
                    433:        }
                    434:     }
                    435: }
                    436: 
                    437: <generic>q {
                    438:     if (!en_fin) {                     /* Ctrl-C typed */
                    439:        errpkt((CHAR *)"QUIT disabled");
                    440:        SERVE;
                    441:     } else {
                    442:        success = 0; QUIT;
                    443:     }
                    444: }
                    445: 
                    446: <generic>. {                           /* Anything else in this state... */
                    447:     errpkt((CHAR *)"Unimplemented REMOTE command"); /* Complain */
                    448:     SERVE;                             /* and return to server command wait */
                    449: }
                    450: 
                    451: <rgen>Y {                              /* Short-Form reply */
                    452:     decode(rdatap,puttrm,0);           /* in ACK Data field */
                    453:     if (rdatap && *rdatap) conoll(""); /* Maybe add a CRLF */
                    454:     RESUME;
                    455: }
                    456: 
                    457: <rgen,rfile>F {                                /* File header */
                    458:     xflg = 0;                          /* Not screen data */
                    459:     if (!rcvfil(filnam)) {             /* Figure out local filename */
                    460:        errpkt((CHAR *)"Can't transform filename"); /* Trouble */
                    461:        RESUME;
                    462:     } else {                           /* OK to receive */
                    463:        encstr((CHAR *)filnam);         /* Encode the name */
                    464:        ack1((CHAR *)(encbuf+7));       /* Send it back in ACK */
                    465:        initattr(&iattr);               /* Clear file attribute structure */
                    466:        if (window(wslotn) < 0) {       /* Allocate negotiated window slots */
                    467:            errpkt((CHAR *)"Can't open window");
                    468:            RESUME;
                    469:        }
                    470:        BEGIN rattr;                    /* Now expect Attribute packets */
                    471:     }
                    472: }
                    473: 
                    474: <rgen,rfile>X {                                /* X-packet instead of file header */
                    475:     xflg = 1;                          /* Screen data */
                    476:     ack();                             /* Acknowledge the X-packet */
                    477:     initattr(&iattr);                  /* Initialize attribute structure */
                    478:     if (window(wslotn) < 0) {          /* allocate negotiated window slots */
                    479:        errpkt((CHAR *)"Can't open window");
                    480:        RESUME;
                    481:     }
                    482:     what = W_REMO;                     /* we're doing a REMOTE command */
                    483:     BEGIN rattr;                       /* Expect Attribute packets */
                    484: }
                    485: 
                    486: <rattr>A {                             /* Attribute packet */
                    487:     if (discard) {                     /* If SET FILE COLLISION DISCARD */
                    488:        ack1((CHAR *)"N");              /* refuse it */
                    489:        screen(SCR_ST,ST_REFU,0L,"file collision setting");
                    490:     } else if (gattr(rdatap,&iattr) == 0) { /* Read into attribute structure */
                    491:        ack();                          /* If OK, acknowledge */
                    492:     } else {                           /* Otherwise */
                    493:        ack1((CHAR *)iattr.reply.val);  /* refuse to accept the file */
                    494:        screen(SCR_ST,ST_REFU,0L,getreason(iattr.reply.val)); /* give reason */
                    495:     }
                    496: }
                    497: 
                    498: <rattr>D {                             /* First data packet */
                    499:     if (discard) {                     /* if we're discarding the file */
                    500:        ack1((CHAR *)"X");              /* just ack the data like this. */
                    501:        BEGIN rdata;                    /* and wait for more data packets. */
                    502:     } else {                           /* Not discarding. */
                    503:        if (xflg)                       /* If screen data */
                    504:          x = opent(&iattr);            /* "open" the screen */
                    505:        else                            /* otherwise */
                    506:          x = opena(filnam,&iattr);     /* open the file, with attributes */
                    507:        if (x) {                        /* If file was opened ok */
                    508:            if (decode(rdatap,putfil,1) < 0) { /* decode first data packet */
                    509:                errpkt((CHAR *)"Error writing data");
                    510:                RESUME;
                    511:            }
                    512:            ack();                      /* acknowledge it */
                    513:            BEGIN rdata;                /* and switch to receive-data state */
                    514:        } else {                        /* otherwise */
                    515:            errpkt((CHAR *)"Can't open file");  /* send error message */
                    516:            RESUME;                     /* and quit. */
                    517:        }
                    518:     }
                    519: }
                    520: 
                    521: <rfile>B {                             /* EOT, no more files */
                    522:     ack();                             /* Acknowledge */
                    523:     tsecs = gtimer();                  /* Get timing for statistics */
                    524:     reot();                            /* Do EOT things */
                    525:     RESUME;                            /* and quit */
                    526: }
                    527: 
                    528: <rdata>D {                             /* Data packet */
                    529:     if (cxseen || discard)             /* If file interrupt */
                    530:       ack1((CHAR *)"X");               /* put "X" in ACK */
                    531:     else if (czseen)                   /* If file-group interrupt */
                    532:       ack1((CHAR *)"Z");               /* put "Z" in ACK */
                    533:     else if (decode(rdatap,putfil,1) < 0) { /* Normal case, decode to file */
                    534:        errpkt((CHAR *)"Error writing data"); /* If failure, */
                    535:        clsof(!keep);                   /*   Close & keep/discard the file */
                    536:        RESUME;                         /* Send ACK only after data */
                    537:     } else ack();                      /* written to file OK. */
                    538: }
                    539: 
                    540: <rattr>Z {                             /* EOF immediately after A-Packet. */
                    541:     if (xflg)                          /* Zero-length file. If screen data */
                    542:       x = opent(&iattr);               /* "open" the screen */
                    543:     else                               /* otherwise */
                    544:       x = opena(filnam,&iattr);                /* open the file, with attributes. */
                    545:     if (!x || reof(filnam, &iattr) < 0) { /* Now close & dispose of the file */
                    546:        errpkt((CHAR *)"Can't create file"); /* If problem, send error msg */
                    547:        RESUME;                         /* and quit */
                    548:     } else {                           /* otherwise */
                    549:        ack();                          /* acknowledge the EOF packet */
                    550:        BEGIN rfile;                    /* and await another file */
                    551:     }
                    552: }
                    553: 
                    554: <rdata>Z {                             /* End Of File (EOF) Packet */
                    555: /*  wslots = 1;        */                      /* Window size back to 1 */
                    556: #ifndef COHERENT
                    557: /*
                    558:   Coherent compiler blows up on this switch() statement.
                    559: */
                    560:     x = reof(filnam, &iattr);          /* Handle the EOF packet */
                    561:     switch (x) {                       /* reof() sets the success flag */
                    562:       case -3:                         /* If problem, send error msg */
                    563:        errpkt((CHAR *)"Can't print file"); /* Fatal */
                    564:         RESUME;
                    565:        break;
                    566:       case -2:
                    567:        errpkt((CHAR *)"Can't mail file"); /* Fatal */
                    568:         RESUME;
                    569:        break;
                    570:       case 2:
                    571:       case 3:
                    572:        screen(SCR_EM,0,0l,"Can't delete temp file"); /* Not fatal */
                    573:         RESUME;
                    574:        break;
                    575:       default:
                    576:        if (x < 0) {                    /* Fatal */
                    577:            errpkt((CHAR *)"Can't close file");
                    578:            RESUME;
                    579:        } else {                        /* Success */
                    580:            ack();                      /* Acknowledge the EOF packet */
                    581:            BEGIN rfile;                /* and await another file */
                    582:        }
                    583:     }
                    584: #else
                    585:     if (reof(filnam, &iattr) < 0) {    /* Close and dispose of the file */
                    586:        errpkt((CHAR *)"Error at end of file");
                    587:        RESUME;
                    588:     } else {                           /* reof() sets success flag */
                    589:        ack();
                    590:        BEGIN rfile;
                    591:     }
                    592: #endif /* COHERENT */
                    593: }
                    594: 
                    595: <ssinit>Y {                            /* ACK for Send-Init */
                    596:     spar(rdatap);                      /* set parameters from it */
                    597:     bctu = bctr;                       /* switch to agreed-upon block check */
                    598:     bctl = (bctu == 4) ? 2 : bctu;     /* Set block-check length */
                    599:     what = W_SEND;                     /* Remember we're sending */
                    600:     x = sfile(xflg);                   /* Send X or F header packet */
                    601:     if (x) {                           /* If the packet was sent OK */
                    602:        resetc();                       /* reset per-transaction counters */
                    603:        rtimer();                       /* reset timers */
                    604:        BEGIN ssfile;                   /* and switch to receive-file state */
                    605:     } else {                           /* otherwise send error msg & quit */
                    606:        s = xflg ? "Can't execute command" : "Can't open file";
                    607:        errpkt((CHAR *)s);
                    608:        RESUME;
                    609:     }
                    610: }
                    611: 
                    612: /*
                    613:  These states are necessary to handle the case where we get a server command
                    614:  packet (R, G, or C) reply with an S packet, but the client retransmits the 
                    615:  command packet.  The input() function doesn't catch this because the packet 
                    616:  number is still zero.
                    617: */
                    618: <ssinit>R {                            /* R packet was retransmitted. */
                    619:     xsinit();                          /* Resend packet 0 */
                    620: }
                    621: 
                    622: <ssinit>G {                            /* Same deal if G packet comes again */
                    623:     xsinit();
                    624: }
                    625: 
                    626: <ssinit>C {                            /* Same deal if C packet comes again */
                    627:     xsinit();
                    628: }
                    629: 
                    630: <ssfile>Y {                            /* ACK for F packet */
                    631:     srvptr = srvcmd;                   /* Point to string buffer */
                    632:     decode(rdatap,putsrv,0);           /* Decode data field, if any */
                    633:     putsrv('\0');                      /* Terminate with null */
                    634:     ffc = 0L;                          /* Reset file byte counter */
                    635:     if (*srvcmd) {                     /* If remote name was recorded */
                    636:        if (fdispla == XYFD_C) screen(SCR_AN,0,0L,(char *)srvcmd);
                    637:        tlog(F110," stored as",(char *) srvcmd,0L); /* Transaction log. */
                    638:     }
                    639:     if (atcapu) {                      /* If attributes are to be used */
                    640:        if (sattr(xflg) < 0) {          /* set and send them */
                    641:            errpkt((CHAR *)"Can't send attributes"); /* if problem, say so */
                    642:            RESUME;                          /* and quit */
                    643:        } else BEGIN ssattr;            /* if ok, switch to attribute state */
                    644:     } else {
                    645:        if (window(wslotn) < 0) {
                    646:            errpkt((CHAR *)"Can't open window");
                    647:            RESUME;
                    648:        }
                    649:        if (sdata() < 0) {              /* No attributes, send data */
                    650:            clsif();                    /* If not ok, close input file, */
                    651:            window(1);                  /* put window size back to 1, */
                    652:            seof((CHAR *)"");           /* send EOF packet, */
                    653:            BEGIN sseof;                /* and switch to EOF state. */
                    654:        } else BEGIN ssdata;            /* All ok, switch to send-data state */
                    655:     }
                    656: }
                    657: 
                    658: <ssattr>Y {                            /* Got ACK to A packet */
                    659:     ffc = 0L;                          /* Reset file byte counter */
                    660:     if (rsattr(rdatap) < 0) {          /* Was the file refused? */
                    661:        discard = 1;                    /* Set the discard flag */
                    662:        clsif();                        /* Close the file */
                    663:        sxeof((CHAR *)"D");             /* send EOF with "discard" code */
                    664:        BEGIN sseof;                    /* switch to send-EOF state */
                    665:     } else {
                    666:        if (window(wslotn) < 0) {       /* Allocate negotiated window slots */
                    667:            errpkt((CHAR *)"Can't open window");
                    668:            RESUME;
                    669:        }
                    670:        if (sdata() < 0) {              /* File accepted, send data */
                    671:            clsif();                    /* If problem, close input file */
                    672:            window(1);                  /* Window size back to 1... */
                    673:            seof((CHAR *)"");           /* send EOF packet */
                    674:            BEGIN sseof;                /* and switch to send-EOF state. */
                    675:        } else {                        /* All ok, enter send-data state. */
                    676:            BEGIN ssdata;
                    677:        }
                    678:     }
                    679: }
                    680: 
                    681: <ssdata>Y {                            /* Got ACK to Data packet */
                    682:     canned(rdatap);                    /* Check if file transfer cancelled */
                    683:     if (sdata() < 0) {                 /* Try to send next data */
                    684:        clsif();                        /* If no more data, close file */
                    685:        window(1);                      /* Window size back to 1... */
                    686:        if (cxseen || czseen)           /* If interrupted */
                    687:          seof((CHAR *)"D");            /* send special EOF packet */
                    688:        else seof((CHAR *)"");          /* Otherwise regular EOF packet */
                    689:        BEGIN sseof;                    /* And enter send-eof state */
                    690:     }
                    691: }
                    692: 
                    693: <sseof>Y {                             /* Got ACK to EOF */
                    694:     success = (cxseen == 0 && czseen == 0); /* Set this for IF command */
                    695:     cxseen = 0;                                /* This goes back to zero. */
                    696:     if (gnfile() > 0) {                        /* Any more files to send? */
                    697:        if (sfile(xflg))                /* Yes, try to send next file header */
                    698:          BEGIN ssfile;                 /* if ok, enter send-file state */
                    699:        else {                          /* otherwise */
                    700:            errpkt((CHAR *)"Can't open file");  /* send error message */
                    701:            RESUME;                     /* and quit */
                    702:        }
                    703:     } else {                           /* No next file */
                    704:        tsecs = gtimer();               /* get statistics timers */
                    705:        seot();                         /* send EOT packet */
                    706:        BEGIN sseot;                    /* enter send-eot state */
                    707:     }
                    708: }
                    709: 
                    710: <sseot>Y {                             /* Got ACK to EOT */
                    711:     RESUME;                            /* All done, just quit */
                    712: }
                    713: 
                    714: E {                                    /* Got Error packet, in any state */
                    715:     ermsg((char *)rdatap);             /* Issue message. */
                    716:     success = 0;                       /* For IF SUCCESS/FAIL. */
                    717:     debug(F101,"ckcpro.w sstate at E pkt","",sstate);
                    718:     x = quiet; quiet = 1;              /* Close files silently, */
                    719:     clsif(); clsof(1);                 /* discarding any output file. */
                    720:     tsecs = gtimer();                  /* Get timers */
                    721:     quiet = x;                         /* restore quiet state */
                    722: /*
                    723:   If we are executing commands from a command file or macro, let the command
                    724:   file or macro decide whether to exit, based on SET { TAKE, MACRO } ERROR.
                    725: */
                    726:     if (
                    727: #ifndef NOSPL
                    728:        cmdlvl == 0
                    729: #else
                    730:        tlevel < 0
                    731: #endif /* NOSPL */
                    732:        )
                    733:       if (backgrd && !server)
                    734:        fatal("Protocol error");
                    735:     xitsta |= what;                    /* Save this for doexit(). */
                    736:     RESUME;
                    737: }
                    738: 
                    739: q { QUIT; }                            /* Ctrl-C interrupt during packets. */
                    740: 
                    741: . {                                    /* Anything not accounted for above */
                    742:     errpkt((CHAR *)"Unexpected packet type"); /* Give error message */
                    743:     xitsta |= what;                    /* Save this for doexit(). */
                    744:     RESUME;                            /* and quit */
                    745: }
                    746: %%
                    747: 
                    748: /*  P R O T O  --  Protocol entry function  */
                    749: 
                    750: VOID
                    751: proto() {
                    752: 
                    753:     int x;
                    754:     long lx;
                    755: 
                    756: /* Set up the communication line for file transfer. */
                    757: 
                    758:     if (local && (speed < 0L) && (network == 0)) {
                    759:        screen(SCR_EM,0,0l,"Sorry, you must 'set speed' first");
                    760:        return;
                    761:     }
                    762:     x = -1;
                    763:     if (ttopen(ttname,&x,mdmtyp,cdtimo) < 0) {
                    764:        debug(F111,"failed: proto ttopen local",ttname,local);
                    765:        screen(SCR_EM,0,0l,"Can't open line");
                    766:        return;
                    767:     }
                    768:     if (x > -1) local = x;
                    769:     debug(F111,"proto ttopen local",ttname,local);
                    770: 
                    771:     lx = (local && !network) ? speed : -1;
                    772:     if (ttpkt(lx,flow,parity) < 0) {   /* Put line in packet mode, */
                    773:        screen(SCR_EM,0,0l,"Can't condition line");
                    774:        return;
                    775:     }
                    776:     if (!local) connoi();              /* No console interrupts if remote */
                    777: 
                    778:     if (sstate == 'x') {               /* If entering server mode, */
                    779:        server = 1;                     /* set flag, */
                    780:        debug(F101,"server backgrd","",backgrd);
                    781:        debug(F101,"server quiet","",quiet);
                    782:        if (!quiet && !backgrd) {
                    783:            debug(F100,"SHOULD NOT SEE THIS IF IN BACKGROUND!","",0);
                    784:            if (!local) {               /* and issue appropriate message. */
                    785:                conoll(srvtxt);
                    786:                conoll("KERMIT READY TO SERVE...");
                    787:            } else {
                    788:                conol("Entering server mode on ");
                    789:                conoll(ttname);
                    790:                conoll("Type Ctrl-C to quit.");
                    791:                if (srvdis) intmsg(-1L);
                    792:            }
                    793:        }
                    794:     } else server = 0;
                    795: #ifdef VMS
                    796:     if (!quiet && !backgrd)    /* So message doesn't overwrite prompt */
                    797:       conoll("");
                    798:     if (local) conres();       /* So Ctrl-C will work */
                    799: #endif /* VMS */
                    800: /*
                    801:   If in remote mode, not shushed, not in background, and at top command level,
                    802:   issue a helpful message telling what to do...
                    803: */
                    804:     if (!local && !quiet && !backgrd &&
                    805: #ifndef NOSPL
                    806:        cmdlvl == 0
                    807: #else
                    808:        tlevel < 0
                    809: #endif /* NOSPL */
                    810:        ) {
                    811:        if (sstate == 'v') {
                    812:            conoll("Return to your local Kermit and give a SEND command.");
                    813:            conoll("");
                    814:            conoll("KERMIT READY TO RECEIVE...");
                    815:        } else if (sstate == 's') {
                    816:            conoll("Return to your local Kermit and give a RECEIVE command.");
                    817:            conoll("");
                    818:            conoll("KERMIT READY TO SEND...");
                    819:        } else if ( sstate == 'g' || sstate == 'r' || sstate == 'c' ) {
                    820:            conoll("Return to your local Kermit and give a SERVER command.");
                    821:            conoll("");
                    822:            conoll((sstate == 'r') ?
                    823:                   "KERMIT READY TO GET..." :
                    824:                   "KERMIT READY TO SEND SERVER COMMAND...");
                    825:        }
                    826:     }
                    827:     sleep(1);
                    828: /*
                    829:  The 'wart()' function is generated by the wart program.  It gets a
                    830:  character from the input() routine and then based on that character and
                    831:  the current state, selects the appropriate action, according to the state
                    832:  table above, which is transformed by the wart program into a big case
                    833:  statement.  The function is active for one transaction.
                    834: */
                    835:     wart();                            /* Enter the state table switcher. */
                    836:     
                    837:     if (server) {                      /* Back from packet protocol. */
                    838:        if (!quiet && !backgrd) {       /* Give appropriate message */
                    839:            conoll("");
                    840:            conoll("C-Kermit server done");
                    841:        }
                    842:     }
                    843: /*
                    844:   Note: the following is necessary in case we have just done a remote-mode
                    845:   file transfer, in which case the controlling terminal modes have been
                    846:   changed by ttpkt().  In particular, special characters like Ctrl-C and
                    847:   Ctrl-\ might have been turned off (see ttpkt).  So this call to ttres() is
                    848:   essential.
                    849: */
                    850: #ifndef OS2
                    851:     if (!local)
                    852: #endif /* OS2 */
                    853:       ttres();                         /* Reset the communication device */
                    854:     screen(SCR_TC,0,0l,"");            /* Transaction complete */
                    855:     server = 0;                                /* Not a server any more */
                    856: }

unix.superglobalmegacorp.com

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