|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - downloadIndex: ┃ T t ┃
Length: 8233 (0x2029) Types: TextFile Names: »talk.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki └─ ⟦this⟧ »EUUGD11/euug-87hel/sec8/uutty/talk.c«
#include "uutty.h" /* ** This routine assumes that it is talking to a port connected ** to a VMEbus device with an on-board debugger. It exchanges ** some pleasantries to verify this fact, then procedes to ask ** the debugger to show it the requested chunk of its memory. */ talk() { int c, i, n, r; int baddies, lowers, uppers; int messages; D4("talk()"); r = 0; ss = S_INIT; D4("State %d=%s",ss,gestate()); lockwait(); /* Try to avoid collisions */ if (device) target = device; /* ** We have a long list of initialization strings here. ** This has come in handy in a few cases, but usually ** they are mostly null. */ if (m_init ) Awrite(m_init); if (m_init1) {Awrite(m_init1); sleep(SLEEP1);} if (m_init2) {Awrite(m_init2); sleep(SLEEP2);} if (m_init3) {Awrite(m_init3); sleep(SLEEP3);} ss = S_INIT; D4("State %d=%s",ss,gestate()); if (m_login) Awrite(m_login); ss = S_LOGIN; D4("State %d=%s",ss,gestate()); Response; nudge: /* Try to elicit a response */ D3("Nudge."); if (++nudges > Nudges) { E("Too many nudges."); r = 1; Dead; } lockwait(); /* Try to avoid interference */ Resync; if (m_nudge) /* Is a nudge message defined? */ Awrite(m_nudge); /* If so, send it */ idle: /* We will now accept anything */ D3("Idle."); ss = S_IDLE; /* Note we're awaiting a response */ D4("State %d=%s",ss,gestate()); messages = 0; /* Counter to trigger nudges */ response: /* Read a response */ D4("Response: state=%d=%s",ss,gestate()); if (debug > 0 && target != oldtarg) { if (debug >= 3) P("%s Talking to %s.",getime(),target); oldtarg = target; } /* ** Check for any of a list of known debugger prompts. ** If we don't get one of then, try to nudge the debugger, ** and try again, giving up after some number of tries. */ errno = 0; D4("talk:l_tries=%d",l_tries); sleep(1); /* Sheer laziness */ lockwait(); if (ss != S_PASSWD) /* If not expecting password, do echoing if requested */ echoing = echofl; while ((n = Pread(eol0,rsp,rspmax)) <= 0) { D3("No response."); /* ** Note this program loops forever waiting for something to come down the line. ** You might want to do something else here if there's no input. */ } D4("talk:Pread()=%d",n); rsp[n] = 0; ++messages; if (debug) { dbgtimep = getime(); if (debug >= 2) Ascdnm(rsp,n,"Got:"); if (debug >= 4) Hexdnm(rsp,n,"Got:"); } /* ** Next, we do some preliminary checking for sanity of the input. ** Since this program's duty is to do login interviews, the only ** input we really want is something that might be a login id or ** a password. Another likely input is a nudge from a counterpart ** on the other end, to which we respond with a prompt. */ if (n < 3) { /* Just "\r", "\n", or "\r\n" is a nudge */ D4("Short response, %d chars.",n); switch (c = rsp[0]) { case 0x03: /* ^C = ETX (usually means "die") */ if (debug) P("%s: ^C in input, quitting.",getime()); die(c); case '\n': /* ^J = LF */ case '\r': /* ^M = CR */ case 0x04: /* ^D = EOT */ case 0x02: /* ^B = STX */ case 0x01: /* ^A = SOH */ ss = S_IDLE; /* Flush garbage from buffer */ D4("State %d=%s",ss,gestate()); lockwait(); if (ibfa < ibfz) { /* Is there input waiting? */ D3("Nudge plus garbage received, ignored."); Resync; /* Flush garbage from buffer */ } else { /* No input waiting */ D3("Nudged; send login prompt \"%s\"",m_login); Awrite(m_login); /* Send them a login prompt */ ss = S_LOGIN; /* Note that we did it */ D4("State %d=%s",ss,gestate()); messages = 0; } Response; /* See if there's a response */ case 0x10: /* This is a uucp Start-of-message */ D3("We seem to be talking to a UUCP demon."); makeraw(dev); /* Paranoia! */ Awrite("OOOOOOOO\r"); /* Try to get it to stop */ Resync; /* Discard the rest of the message */ if (m_init) Awrite(m_init); ss = S_INIT; /* Try to get back to idle state */ D4("State %d=%s",ss,gestate()); Response; } } baddies = lowers = uppers = 0;/* These are for counting letters */ D4("Scan id for char classes..."); for (i=0; i<n; i++) { /* Examine the response for nasty stuff */ c = rsp[i]; /* One byte at a time */ if (islower(c)) { ++lowers; /* Lower-case letters are desirable */ D6("c=%02X-'%c' lowers=%d",c,dsp(c),lowers); } else if (isupper(c)) { ++uppers; /* Upper-case letters are acceptable */ D6("c=%02X-'%c' uppers=%d",c,dsp(c),uppers); } else /* Everything else is dubious */ switch (c) { case 0x03: /* Special goody to let others kill us */ case 0x02: case 0x01: if (debug) P("%s: %02X in input, quitting [id]",getime(),c); die(c); case '#': /* These are likely shell prompts */ case '$': /* Default Bourne shell prompt */ case '%': /* Default C- shell prompt */ case '>': /* Popular prompt in some circles */ if (i >= n-2) { /* Likely only if at end of input */ shprompt(rsp); /* Can we handle it? */ Response; } /* If earlier in string, reject it */ case 0x00: case 0x04: case 0x05: case 0x06: case 0x07: case 0x08: case 0x09: case 0x0B: case 0x0C: case 0x0E: case 0x0F: case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x17: case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D: case 0x1E: case 0x1F: case ' ' : case ':' : /* None of these are acceptable in ids or passwords */ D3("Invalid char %02x='%c' in input.",c,dsp(c)); ++baddies; break; } } if (baddies || ((lowers+uppers) == 0)) { /* Is it acceptable? */ D4("Unacceptable; baddies=%d lowers=%d uppers=%d.",baddies,lowers,uppers); Resync; /* No; drop buffered input */ lockwait(); if (baddies && messages > THRESH) { makeraw(dev); /* Others may have munged the driver */ if (m_init) { Awrite(m_init); ss = S_INIT; D4("State %d=%s",ss,gestate()); } else { Awrite(m_login); ss = S_LOGIN; D4("State %d=%s",ss,gestate()); } messages = 0; } ss = S_IDLE; D4("State %d=%s",ss,gestate()); Response; } switch (ss) { /* Special actions depending on state */ case S_EXIT: /* We are trying to exit */ if (m_exit) { /* Is there an exit command? */ Awrite(m_exit); /* If so, send it */ ss = S_EXIT; /* Note again that we're trying to quit */ D4("State %d=%s",ss,gestate()); } Response; case S_IDLE: /* We're waiting for the other end to act */ D4("Got id while idle."); c = rsp[0]; /* First char of response is sometimes special */ goto maybeid; case S_LOGIN: /* We just sent a login prompt */ D4("Got response to login prompt."); maybeid: /* We may have a login id */ D4("Got possible login id."); if (lowers == 0) { /* No lower-case letters; it's not an id */ lockwait(); /* Make sure we're not interfering */ makeraw(dev); /* Paranoia! */ if (m_init) { /* Do we have a special init string? */ Awrite(m_init); ss = S_INIT; D4("State %d=%s",ss,gestate()); } Response; /* Go wait for next input */ } i = checkid(rsp); /* Put it through final tests */ if (i <= 0) { /* If it fails... */ if (debug) { dbgtimep = getime(); if (debug >= 2) Ascdnm(rsp,n,"Bad id:"); if (debug >= 4) Hexdnm(rsp,n,"Bad id:"); } Resync; /* Get port into known state */ sleep(5); /* Extra delay for safety's sake */ ss = S_IDLE; D4("State %d=%s",ss,gestate()); Response; /* Go wait for next input */ } /* It sure looks like an id */ D3("Send password prompt \"%s\"",m_passwd); echoing = 0; Awrite(m_passwd); ss = S_PASSWD; D4("State %d=%s",ss,gestate()); Response; case S_PASSWD: /* We just sent a password prompt */ D4("Got response to password prompt."); i = pswd(rsp); /* Check it out to see if it's a good guy */ if (i <= 0) { /* Successful call won't return */ D3("Unacceptable password \"%s\"",rsp); Response; } E("pswd(\"%s\")=%d Shouldn't happen.",rsp,i); Response; default: D4("ss=%d not special",ss); } if (debug) { dbgtimep = getime(); if (debug >= 2) Ascdnm(rsp,n,"Ignore:"); if (debug >= 4) Hexdnm(rsp,n,"Ignore:"); } Response; dead: P("Giving up; %s seems to be dead.",target); return r; }