Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!nbires!hao!hplabs!pyramid!decwrl!wecker@cookie.dec.com From: wecker@cookie.dec.com (DAVE TANSTAAFL WECKER) Newsgroups: net.micro.amiga Subject: VT100 terminal emulator (V2.0 DBW 860823) Part 2 of 2 Message-ID: <4993@decwrl.DEC.COM> Date: Mon, 25-Aug-86 14:40:20 EDT Article-I.D.: decwrl.4993 Posted: Mon Aug 25 14:40:20 1986 Date-Received: Wed, 27-Aug-86 09:42:57 EDT Sender: daemon@decwrl.DEC.COM Organization: Digital Equipment Corporation Lines: 2241 [I apologize for posting this here (instead of MOD.AMIGA.SOURCES/BINARIES), but I haven't been able to get through to the moderator for 3 weeks, and people have been asking for the new release.] # This is a shell archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #----cut here-----cut here-----cut here-----cut here----# #!/bin/sh # shar: Shell Archiver # Run the following text with /bin/sh to create: # window.c # remote.c # kermit.c # xmodem.c # script.c # This archive created: Sun Aug 24 16:25:59 1986 echo shar: extracting window.c sed 's/^XX//' << \SHAR_EOF > window.c XX/**************************************************** XX * vt100 emulator - window/keyboard support XX * XX * 860823 DBW - Integrated and rewrote lots of code XX * v2.0 860809 DBW - Major rewrite XX * v1.1 860720 DBW - Switches, 80 cols, colors, bug fixes XX * v1.0 860712 DBW - First version released XX * XX ****************************************************/ XX XX#define MODULE_WINDOW 1 XX#include "vt100.h" XX XX/* forward declarations for LATTICE */ XXvoid filename(); XXvoid emits(); XXvoid emit(); XXvoid emitbatch(); XXvoid cursoroff(); XXvoid cursoron(); XX XX/************************************************* XX* function to get file name XX*************************************************/ XXvoid filename(name) XXchar name[]; XX { XX char c; XX ULONG class; XX unsigned int code; XX int keepgoing,i; XX keepgoing = TRUE; XX i=0; XX while (keepgoing) { XX while( NewMessage=(struct IntuiMessage *)GetMsg(mywindow->UserPort) ) XX { XX class = NewMessage->Class; XX code = NewMessage->Code; XX ReplyMsg( NewMessage ); XX if (class=RAWKEY) XX { XX c = toasc(code,1); XX name[i]=c; XX if (name[i] != 0) XX { XX if (name[i] == 13) XX { XX name[i]=0; XX keepgoing = FALSE; XX } XX else XX { XX if (name[i] == 8 || name[i] == 127) XX { XX i -= 2; XX if (i < -1) i = -1; XX else { XX if (x == MINX) { y -= 8; x = MAXX; } XX emit(8); XX emit(32); XX emit(8); XX } XX } XX else XX emit(c); XX if (x == MAXX) emits("\n"); XX } XX i += 1; XX } XX } XX } /* end of new message loop */ XX } /* end of god knows what */ XX emit(13); XX emit(10); XX } /* end of function */ XX XX XX/************************************************* XX* function to print a string XX*************************************************/ XXvoid emits(string) XXchar string[]; XX { XX int i; XX char c; XX XX i=0; XX while (string[i] != 0) XX { XX c=string[i]; XX if (c == 10) emit(13); XX emit(c); XX i += 1; XX } XX } XX XX/************************************************* XX* function to output ascii chars to window XX*************************************************/ XXvoid emit(c) XXchar c; XX { XX Move(mywindow->RPort,(long)x,(long)y); XX XX c &= 0x7F; XX switch( c ) XX { XX case '\t': XX x += 64 - ((x-MINX) % 64); XX break; XX XX case 10: /* lf */ XX y += 8; XX break; XX XX case 13: /* cr */ XX x = MINX; XX break; XX XX case 8: /* backspace */ XX x -= 8; XX if (x < MINX) x = MINX; XX break; XX XX case 12: /* page */ XX x = MINX; XX y = MINY; XX SetAPen(mywindow->RPort,0L); XX RectFill(mywindow->RPort,(long)MINX, XX (long)(MINY-7),(long)(MAXX+7),(long)(MAXY+1)); XX SetAPen(mywindow->RPort,1L); XX break; XX XX case 7: /* bell */ XX DisplayBeep(NULL); XX ClipBlit(mywindow->RPort,0L,0L,mywindow->RPort,0L,0L, XX (long)MAXX,(long)MAXY,0x50L); XX ClipBlit(mywindow->RPort,0L,0L,mywindow->RPort,0L,0L, XX (long)MAXX,(long)MAXY,0x50L); XX break; XX XX default: XX if (c < ' ' || c > '~') break; XX if (curmode&REVERSE) { XX Text(mywindow->RPort," ",1L); XX Move(mywindow->RPort,(long)x,(long)y); XX SetDrMd(mywindow->RPort,(long)INVERSVID); XX if (curmode&BOLD) XX SetAPen(mywindow->RPort,(long)(2+(1^p_screen))); XX Text(mywindow->RPort,&c,1L); XX if (curmode&UNDERLINE) RectFill(mywindow->RPort, XX (long)(x-1),(long)(y+1),(long)(x+8),(long)(y+1)); XX if (curmode&BOLD) SetAPen(mywindow->RPort,1L); XX SetDrMd(mywindow->RPort,(long)JAM2); XX } XX else { XX if (curmode&BOLD) XX SetAPen(mywindow->RPort,(long)(2+(1^p_screen))); XX Text(mywindow->RPort,&c,1L); XX if (curmode&UNDERLINE) RectFill(mywindow->RPort, XX (long)(x-1),(long)(y+1),(long)(x+8),(long)(y+1)); XX if (curmode&BOLD) SetAPen(mywindow->RPort,1L); XX } XX x += 8; XX } /* end of switch */ XX XX while (x > MAXX) x -= 8; XX while (y > MAXY) { XX y -= 8; XX x = MINX; XX ScrollRaster(mywindow->RPort,0L,8L,(long)MINX, XX (long)(MINY-6),(long)(MAXX+7),(long)(MAXY+1)); XX } XX } XX XX/************************************************* XX* function to output ascii chars to window (batched) XX*************************************************/ XXvoid emitbatch(la,lookahead) XXint la; XXchar *lookahead; XX { XX int i; XX Move(mywindow->RPort,(long)x,(long)y); XX i = x / 8; XX if (i+la > maxcol) la = maxcol-i; XX if (curmode&REVERSE) { XX Text(mywindow->RPort,blanks,(long)la); XX Move(mywindow->RPort,(long)x,(long)y); XX SetDrMd(mywindow->RPort,(long)INVERSVID); XX if (curmode&BOLD) XX SetAPen(mywindow->RPort,(long)(2+(1^p_screen))); XX Text(mywindow->RPort,lookahead,(long)la); XX if (curmode&UNDERLINE) RectFill(mywindow->RPort, XX (long)(x-1),(long)(y+1),(long)((x+8*la)+8),(long)(y+1)); XX if (curmode&BOLD) SetAPen(mywindow->RPort,1L); XX SetDrMd(mywindow->RPort,(long)JAM2); XX } XX else { XX if (curmode&BOLD) XX SetAPen(mywindow->RPort,(long)(2+(1^p_screen))); XX Text(mywindow->RPort,lookahead,(long)la); XX if (curmode&UNDERLINE) RectFill(mywindow->RPort, XX (long)(x-1),(long)(y+1),(long)((x+8*la)+8),(long)(y+1)); XX if (curmode&BOLD) SetAPen(mywindow->RPort,1L); XX } XX x += (8 * la); XX } XX XX/****************************** XX* Manipulate cursor XX******************************/ XXvoid cursoroff() XX { XX SetDrMd(mywindow->RPort,(long)COMPLEMENT); XX SetAPen(mywindow->RPort,3L); XX RectFill(mywindow->RPort, XX (long)(x-1),(long)(y-6),(long)(x+8),(long)(y+1)); XX SetAPen(mywindow->RPort,1L); XX SetDrMd(mywindow->RPort,(long)JAM2); XX } XX XXvoid cursoron() XX { XX SetDrMd(mywindow->RPort,(long)COMPLEMENT); XX SetAPen(mywindow->RPort,3L); XX RectFill(mywindow->RPort, XX (long)(x-1),(long)(y-6),(long)(x+8),(long)(y+1)); XX SetAPen(mywindow->RPort,1L); XX SetDrMd(mywindow->RPort,(long)JAM2); XX } XX XX/************************************************ XX* function to take raw key data and convert it XX* into ascii chars XX**************************************************/ XXint toasc(code,local) XXunsigned int code; XXint local; XX { XX static int ctrl = FALSE; XX static int shift = FALSE; XX static int capsl = FALSE; XX char c; XX static char keys[75] = { XX '`','1','2','3','4','5','6','7','8','9','0','-' , XX '=','\\', 0, '0','q','w','e','r','t','y','u','i','o' , XX 'p','[',']', 0, '1','2','3','a','s','d','f','g','h' , XX 'j','k','l',';','\'', 0, 0, '4','5','6', 0, 'z','x','c','v', XX 'b','n','m',44,'.','/', 0, '.','7','8','9',' ',8, XX '\t',13,13,27,127,0,0,0,'-' } ; XX XX switch ( code ) XX { XX case 98: capsl = TRUE; c = 0;break; XX case 226: capsl = FALSE;c = 0;break; XX case 99: ctrl = TRUE; c = 0;break; XX case 227: ctrl = FALSE; c = 0;break; XX case 96: XX case 97: shift = TRUE; c = 0;break; XX case 224: XX case 225: shift = FALSE;c = 0;break; XX case 0x50: XX case 0x51: XX case 0x52: XX case 0x53: XX case 0x54: XX case 0x55: XX case 0x56: XX case 0x57: XX case 0x58: XX case 0x59: c = 0; XX if (shift) sendstring(p_F[code - 0x50]); XX else sendstring(p_f[code - 0x50]); XX break; XX case 0x0f: c=0; sendstring("Op"); break; XX case 0x1d: c=0; sendstring("Oq"); break; XX case 0x1e: c=0; sendstring("Or"); break; XX case 0x1f: c=0; sendstring("Os"); break; XX case 0x2d: c=0; sendstring("Ot"); break; XX case 0x2e: c=0; sendstring("Ou"); break; XX case 0x2f: c=0; sendstring("Ov"); break; XX case 0x3d: c=0; sendstring("Ow"); break; XX case 0x3e: c=0; sendstring("Ox"); break; XX case 0x3f: c=0; sendstring("Oy"); break; XX case 0x43: c=0; sendstring("OM"); break; XX case 0x4a: c=0; sendstring("Ol"); break; XX case 0x5f: c=0; sendstring("Om"); break; XX case 0x3c: c=0; sendstring("On"); break; XX case 0x4c: c=0; sendstring("[A"); break; XX case 0x4d: c=0; sendstring("[B"); break; XX case 0x4e: c=0; sendstring("[C"); break; XX case 0x4f: c=0; sendstring("[D"); break; XX XX default: XX if (code < 75) c = keys[code]; XX else c = 0; XX } XX XX /* add modifiers to the keys */ XX XX if (c != 0) { XX if (shift) { XX if ((c <= 'z') && (c >= 'a')) c -= 32; XX else XX switch( c ) { XX case '[': c = '{'; break; XX case ']': c = '}'; break; XX case '\\': c = '|'; break; XX case '\'': c = '"'; break; XX case ';': c = ':'; break; XX case '/': c = '?'; break; XX case '.': c = '>'; break; XX case ',': c = '<'; break; XX case '`': c = '~'; break; XX case '=': c = '+'; break; XX case '-': c = '_'; break; XX case '1': c = '!'; break; XX case '2': c = '@'; break; XX case '3': c = '#'; break; XX case '4': c = '$'; break; XX case '5': c = '%'; break; XX case '6': c = '^'; break; XX case '7': c = '&'; break; XX case '8': c = '*'; break; XX case '9': c = '('; break; XX case '0': c = ')'; break; XX default: break; XX } XX } XX else if (capsl && (c <= 'z') && (c >= 'a')) c -= 32; XX } XX if (ctrl) { XX if (c >= '`' && c <= 127) c -= 96; XX else if (c >= '@' && c <= '_') c -= 64; XX } XX if (c != 0 && (!local)) sendchar(c); XX return((int)c); XX } XX SHAR_EOF if test 8526 -ne "`wc -c window.c`" then echo shar: error transmitting window.c '(should have been 8526 characters)' fi echo shar: extracting remote.c sed 's/^XX//' << \SHAR_EOF > remote.c XX/**************************************************** XX * vt100 emulator - remote character interpretation XX * XX * 860823 DBW - Integrated and rewrote lots of code XX * v2.0 860803 DRB - Rewrote the control sequence parser XX * v1.1 860720 DBW - Switches, 80 cols, colors, bug fixes XX * v1.0 860712 DBW - First version released XX * XX ****************************************************/ XX XX#define MODULE_REMOTE 1 XX#include "vt100.h" XX XXstatic int p[10]; XXstatic int numpar; XXstatic char escseq[40]; XX XXvoid doctrl(); XXvoid doesc(); /* force correct denomination */ XXvoid doerase(); XXvoid doindex(); XX XX/************************************************ XX* function to handle remote characters XX*************************************************/ XXvoid doremote(c) XXchar c; XX { XX if (c == 27 || inesc >= 0) { doesc(c); return; } XX if (inctrl >= 0) { doctrl(c); return; } XX if (c == 10 || c == 11 || c == 12) { XX if (nlmode) doindex('E'); else doindex('D'); XX return; XX } XX if (c == 13) { XX if (!nlmode) emit(c); XX return; XX } XX if (c == 15) { alt = 0; return; } XX if (c == 14) { alt = 1; return; } XX if (a[alt] && c > 94 && c < 127) { doalt(c); return; } XX emit(c); XX } XX XXvoid doesc(c) XXchar c; XX{ XX if (inesc < 0) { inesc = 0; return; } XX if (c == 27 || c == 24) { inesc = -1; return; } XX if (c < ' ' || c == 127) return; /* Ignore control chars */ XX if (c < '0') {escseq[inesc++] = c; return; } /* Collect intermediates */ XX XX /* by process of elimination, we have a final character. Put it in XX the buffer, and dispatch on the first character in the buffer */ XX XX escseq[inesc] = c; XX inesc = -1; /* No longer collecting a sequence */ XX switch (escseq[0]) /* Dispatch on the first received */ XX { XX case '[': /* Control sequence introducer */ XX numpar = 0; /* No parameters yet */ XX private = 0; /* Not a private sequence (yet?) */ XX badseq = 0; /* Good until proven bad */ XX p[0] = p[1] = 0; /* But default the first parameter */ XX inctrl = 0; /* We are in a control sequence */ XX return; /* All done for now ... */ XX XX case 'D': case 'E': case 'M': /* Some kind of index */ XX doindex (c); /* Do the index */ XX return; /* Return */ XX XX case '7': /* Save cursor position */ XX savx = x; savy = y; savmode = curmode; savalt = alt; XX sa[0] = a[0]; sa[1] = a[1]; XX return; XX XX case '8': /* Restore cursor position */ XX x = savx; y = savy; alt = savalt; curmode = savmode; XX a[0] = sa[0]; a[1] = sa[1]; XX return; XX XX case 'c': /* Reset */ XX top = MINY; bot = MAXY; savx = MINX; savy = MINY; XX a[0] = 0; a[1] = 0; sa[0] = 0; sa[1] = 0; XX emit(12); return; XX inesc = -1; XX return; XX XX case '(': /* Change character set */ XX if (c == '0' || c == '2') a[0] = 1; else a[0] = 0; XX return; XX XX case ')': /* Change the other character set */ XX if (c == '0' || c == '2') a[1] = 1; else a[1] = 0; XX return; XX XX /* If we didn't match anything, we can just return, happy in the XX knowledge that we've at least eaten the whole sequence */ XX XX } /* End of switch */ XX return; XX} XX XXvoid doctrl(c) XXchar c; XX{ XX int i; XX XX if (c == 27 || c == 24) { inctrl = -1; return; } XX if (c < ' ' || c == 127) return; /* Ignore control chars */ XX XX /* First, look for some parameter characters. If the very first XX parameter character isn't a digit, then we have a private sequence */ XX XX if (c >= '0' && c < '@') XX { XX /* can't have parameters after intermediates */ XX if (inctrl > 0) {badseq++ ; return; } XX switch (c) XX { XX case '0': case '1': case '2': case '3': case '4': XX case '5': case '6': case '7': case '8': case '9': XX p[numpar] = p[numpar] * 10 + (c - '0'); XX return; XX XX case ';': XX p[++numpar] = 0; /* Start a new parameter */ XX return; XX XX case '<': case '=': case '>': case '?': /* Can only mean private */ XX if (inctrl = 0) private = c; /* Only allowed BEFORE parameters */ XX return; XX XX /* if we come here, it's a bad sequence */ XX } XX badseq++; /* Flag the bad sequence */ XX } XX XX if (c < '0') /* Intermediate character */ XX { XX escseq[inctrl++] = c; /* Save the intermediate character */ XX return; XX } XX XX /* if we get here, we have the final character. Put it in the XX escape sequence buffer, then dispatch the control sequence */ XX XX numpar++; /* Reflect the real number of parameters */ XX escseq[inctrl++] = c; /* Store the final character */ XX escseq[inctrl] = '\000'; /* Tie off the buffer */ XX inctrl = -1; /* End of the control sequence scan */ XX XX /* Don't know how to do any private sequences right now, so just punt XX them */ XX XX if (private != 0 || badseq != 0) return; XX XX switch (escseq[0]) /* Dispatch on first intermediate or final */ XX { XX case 'A': if (p[0]<=0) p[0] = 1; XX y -= 8*p[0]; if (ybot) y = bot; return; XX case 'C': if (p[0]<=0) p[0] = 1; XX x += 8*p[0]; if (x>MAXX) x = MAXX; return; XX case 'D': if (p[0]<=0) p[0] = 1; XX x -= 8*p[0]; if (x MAXY) y = MAXY; XX if (x > MAXX) x = MAXX; XX if (y < MINY) y = MINY; XX if (x < MINX) x = MINX; XX return; XX XX case 'r': /* Set scroll region */ XX if (p[0] <= 0) p[0] = 1; XX if (p[1] <= 0) p[1] = p_lines; XX top = (--p[0]*8)+MINY; bot = (--p[1]*8)+MINY; XX if (top < MINY) top = MINY; XX if (bot > MAXY) bot = MAXY; XX if (top > bot) { top = MINY; bot = MAXY; } XX x = MINX; y = MINY; XX return; XX XX case 'm': /* Set graphic rendition */ XX for (i=0;i 1) curmode |= BOLD; XX else curmode |= REVERSE; XX break; XX XX case 4: XX curmode |= UNDERLINE; XX break; XX XX default: XX curmode |= REVERSE; XX break; XX } XX } XX return; XX XX case 'K': /* Erase in line */ XX doerase(); XX return; XX XX case 'J': /* Erase in display */ XX if (p[0] < 0) p[0] = 0; XX SetAPen(mywindow->RPort,0L); XX if (p[0] == 0) { XX if (y < MAXY) RectFill(mywindow->RPort, XX (long)MINX,(long)(y+2),(long)(MAXX+7),(long)(MAXY+1)); XX } XX else if (p[0] == 1) { XX if (y > MINY) RectFill(mywindow->RPort, XX (long)MINX,(long)(MINY-6),(long)(MAXX+7),(long)(y-7)); XX } XX else RectFill(mywindow->RPort, XX (long)MINX,(long)(MINY-6),(long)(MAXX+7),(long)(MAXY+1)); XX SetAPen(mywindow->RPort,1L); XX doerase(); return; XX XX case 'h': /* Set parameter */ XX if (p[0] == 20) nlmode = 1; XX return; XX XX case 'l': /* Reset parameter */ XX if (p[0] == 20) nlmode = 0; XX return; XX XX case 'x': XX sendchar(27); sendstring("[3;1;8;64;64;1;0x"); return; XX XX case 'n': XX if (p[0] == 6) { XX sendchar(27); XX sprintf(escseq,"[%d;%dR",((y-MINY)/8)+1,((x-MINX)/8)+1); XX sendstring(escseq); return; XX } XX sendchar(27); sendstring("[0n"); return; XX XX case 'c': XX sendchar(27); sendstring("[?1;0c"); return; XX } XX XX /* Don't know how to do this one, so punt it */ XX} XX XXvoid doindex(c) XXchar c; XX { XX if (c != 'M') { XX if (c == 'E') x = MINX; XX if (y > bot) if (y < MAXY) y += 8; XX if (y == bot) XX ScrollRaster(mywindow->RPort,0L,8L,(long)MINX,(long)(top-6), XX (long)(MAXX+7),(long)(bot+1)); XX if (y < bot) y += 8; XX } XX else { XX if (y < top) if (y > MINY) y -= 8; XX if (y == top) XX ScrollRaster(mywindow->RPort,0L,-8L,(long)MINX,(long)(top-6), XX (long)(MAXX+7),(long)(bot+1)); XX if (y > top) y -= 8; XX } XX return; XX } XX XXdoalt(c) XXchar c; XX { XX int oldx,newx; XX inesc = -1; XX oldx = x; emit(' '); newx = x; XX x = oldx; XX SetAPen(mywindow->RPort,1L); XX switch (c) { XX case 'j': XX case 'm': XX case 'v': doline(4,-8,4,-4); XX if (c=='j') doline(0,-4,4,-4); XX else if (c=='m') doline(4,-4,8,-4); XX else doline(0,-4,8,-4); XX break; XX XX case 'k': XX case 'l': XX case 'w': doline(4,-4,4,0); XX if (c=='k') doline(0,-4,4,-4); XX else if (c=='l') doline(4,-4,8,-4); XX else doline(0,-4,8,-4); XX break; XX XX case 'n': XX case 'q': doline(0,-4,8,-4); XX if (c=='n') doline(4,-8,4,0); XX break; XX XX case 't': XX case 'u': XX case 'x': doline(4,-8,4,0); XX if (c=='t') doline(4,-4,8,-4); XX else if (c=='u') doline(0,-4,4,-4); XX break; XX } XX x = newx; XX } XX XXdoline(x1,y1,x2,y2) { XX RectFill(mywindow->RPort,(long)(x+x1),(long)(y+y1), XX (long)(x+x2),(long)(y+y2)); XX } XX XXvoid doerase() XX { XX if (p[0] < 0) p[0] = 0; XX SetAPen(mywindow->RPort,0L); XX if (p[0] == 0) RectFill(mywindow->RPort,(long)x,(long)(y-6), XX (long)(MAXX+7),(long)(y+1)); XX else if (p[0] == 1) RectFill(mywindow->RPort, XX (long)MINX,(long)(y-6),(long)(x+7),(long)(y+1)); XX else RectFill(mywindow->RPort, XX (long)MINX,(long)(y-6),(long)(MAXX+7),(long)(y+1)); XX SetAPen(mywindow->RPort,1L); XX return; XX } XX SHAR_EOF if test 8794 -ne "`wc -c remote.c`" then echo shar: error transmitting remote.c '(should have been 8794 characters)' fi echo shar: extracting kermit.c sed 's/^XX//' << \SHAR_EOF > kermit.c XX/************************************************************* XX * vt100 terminal emulator - KERMIT protocol support XX * XX * 860823 DBW - Integrated and rewrote lots of code XX * 860811 Steve Drew multi filexfer, bugs, status line ect.. XX * v2.0 860809 DBW - Major rewrite XX * v1.1 860720 DBW - Switches, 80 cols, colors, bug fixes XX * v1.0 860712 DBW - First version released XX * XX *************************************************************/ XX XX#define MODULE_KERMIT 1 XX#include "vt100.h" XX XX#define MAXPACKSIZ 94 /* Maximum msgpkt size */ XX#define CR 13 /* ASCII Carriage Return */ XX#define LF 10 /* ASCII line feed */ XX#define SP 32 /* ASCII space */ XX#define DEL 127 /* Delete (rubout) */ XX XX#define MAXTRY 5 /* Times to retry a msgpkt */ XX#define MYQUOTE '#' /* Quote character I will use */ XX#define MYRPTQ '~' /* Repeat quote character */ XX#define MYPAD 0 /* Number of padding characters I will need */ XX#define MYPCHAR 0 /* Padding character I need (NULL) */ XX#define MYEOL '\n' /* End-Of-Line character I need */ XX XX#define tochar(ch) ((ch) + ' ') XX#define unchar(ch) ((ch) - ' ') XX#define ctl(ch) ((ch) ^ 64 ) XX XX/* Global Variables */ XX XXint XX size, /* Size of present data */ XX osize, /* Size of last data entry */ XX rpsiz, /* Maximum receive msgpkt size */ XX spsiz, /* Maximum send msgpkt size */ XX timint, /* Time interval to wait */ XX pad, /* How much padding to send */ XX n, /* Packet number */ XX tp, /* total packets */ XX numtry, /* Times this msgpkt retried */ XX retry, /* total retries */ XX oldtry, /* Times previous msgpkt retried */ XX rptflg, /* are we doing repeat quoting */ XX first, /* is this the first time in a file */ XX rpt, /* current repeat count */ XX next, /* what is the next character */ XX t; /* current character */ XXlong XX totbytes; /* total bytes xfered on this file */ XX XXchar XX state, /* Present state of the automaton */ XX padchar, /* Padding character to send */ XX eol, /* End-Of-Line character to send */ XX quote, /* Quote character in incoming data */ XX rptq, /* Quote character for repeats */ XX ackpkt[MAXPACKSIZ+20], /* ACK/NAK packet buffer */ XX msgpkt[MAXPACKSIZ+20], /* Message Packet buffer */ XX filnam[40]; /* remote file name */ XX snum[10]; XX XXvoid encode(), decode(), rpar(), spar(); XX XXFILE *fp; /* file for send/receive */ XX XXint shutdown = 0; /* shut down server after all xfers complete */ XX XXchar * XXgetfname(name) /* returns pointer to start of file name from file spec */ XXchar *name; XX { XX int l; XX XX l = strlen(name); XX while(l && name[l] != '/' && name[l] != ':') l--; XX if (name[l] == '/' || name[l] == ':') l++; XX return(name += l); XX } XX XXdoksend(file,more) XXchar *file; XXint more; XX { XX int retval; XX XX ttime = TTIME_LONG; XX if (!strcmp(file,"$")) { saybye(); return(2); } XX if (file[strlen(file)-1] == '$') { XX shutdown = 1; XX file[strlen(file)-1] = '\0'; XX } XX if ((fp = fopen(file,"r")) == NULL) { XX emits("Cannot open send file\n"); XX return FALSE; XX } XX getready(file,more); XX emits("SEND"); XX retval = sendsw(); XX if (retval) { x = 600; emits("DONE"); } XX curmode = 0; XX if (shutdown) saybye(); XX emits("\n"); XX fclose(fp); XX return(retval); XX } XX XXdokreceive(file,more) XXchar *file; XXint more; XX { XX int retval; XX XX ttime = TTIME_LONG; XX if (!strcmp(file,"$")) { saybye(); return(2); } XX if (file[strlen(file)-1] == '$') { XX shutdown = 1; XX file[strlen(file)-1] = '\0'; XX } XX if ((fp = fopen(file,"w")) == NULL) { XX emits("Cannot open file\n"); XX return FALSE; XX } XX getready(file,more); XX emits("RECV"); XX retval = recsw(); XX if (retval) { x = 600; emits("DONE"); } XX curmode = 0; XX if (shutdown) saybye(); XX emits("\n"); XX fclose(fp); XX return(retval); XX } XX XXgetready(file,more) XX char *file; XX int more; XX { XX if (!more) { XX emits("Remote file name ["); XX emits(getfname(file)); XX emits("]: "); XX filename(filnam); XX if (filnam[0] == 0) strcpy(filnam,getfname(file)); XX emits("Type to abort transfer\n"); XX } XX else strcpy(filnam,getfname(file)); XX eatup(); XX tp = retry = 0; totbytes = 0L; n = numtry = 0; XX want_message = FALSE; /* tell readchar no error msgs status bar instead */ XX statusline(); XX x = 600; XX } XX XX XXsendsw() XX { XX char sinit(), sfile(), sdata(), seof(), sbreak(); XX XX state = 'S'; XX while(TRUE) { XX switch(state) { XX case 'S': state = sinit(); break; XX case 'F': state = sfile(); break; XX case 'D': state = sdata(); break; XX case 'Z': state = seof(); break; XX case 'B': state = sbreak(); break; XX case 'C': return(TRUE); XX case 'A': x = 600; XX if (timeout == USERABORT) { sabort(); return(FALSE); } XX if (timeout == TIMEOUT) emits("TMOUT"); XX else emits("ERROR"); XX return(FALSE); XX default: return(FALSE); XX } XX } XX } XX XXchar sinit() XX { XX int num, len; XX XX retry++; XX if (numtry++ > MAXTRY) return('A'); XX spar(msgpkt); XX XX spack('S',n,9,msgpkt); XX switch(rpack(&len,&num,ackpkt)) { XX case 'N': return(state); XX case 'Y': if (n != num) return(state); XX rpar(ackpkt); XX if (eol == 0) eol = '\n'; XX if (quote == 0) quote = '#'; XX numtry = 0; XX retry--; XX n = (n+1)%64; XX return('F'); XX case 'E': return('A'); XX case FALSE:if (timeout == USERABORT) state = 'A'; XX return(state); XX default: return('A'); XX } XX } XX XXchar sfile() XX { XX int num, len; XX XX retry++; XX if (numtry++ > MAXTRY) return('A'); XX XX spack('F',n,strlen(filnam),filnam); XX switch(rpack(&len,&num,ackpkt)) { XX case 'N': XX num = (--num<0 ? 63:num); XX if (n != num) return(state); XX case 'Y': XX if (n != num) return(state); XX numtry = 0; XX retry--; XX n = (n+1)%64; XX first = 1; XX size = getpkt(); XX return('D'); XX case 'E': XX return('A'); XX case FALSE: if (timeout == USERABORT) state = 'A'; XX return(state); XX default: return('A'); XX } XX } XX XXchar sdata() XX { XX int num, len; XX XX retry++; XX if (numtry++ > MAXTRY) return('A'); XX XX spack('D',n,size,msgpkt); XX switch(rpack(&len,&num,ackpkt)) { XX case 'N': XX num = (--num<0 ? 63:num); XX if (n != num) return(state); XX case 'Y': XX if (n != num) return(state); XX numtry = 0; XX retry--; XX n = (n+1)%64; XX if ((size = getpkt()) == 0) return('Z'); XX return('D'); XX case 'E': XX return('A'); XX case FALSE: if (timeout == USERABORT) state = 'A'; XX return(state); XX default: return('A'); XX } XX } XX XXchar seof() XX { XX int num, len; XX retry++; XX if (numtry++ > MAXTRY) return('A'); XX XX if (timeout == USERABORT) { XX timeout = GOODREAD; XX spack('Z',n,1,"D"); /* tell host to discard file */ XX } XX else spack('Z',n,0,msgpkt); XX switch(rpack(&len,&num,ackpkt)) { XX case 'N': XX num = (--num<0 ? 63:num); XX if (n != num) return(state); XX case 'Y': XX if (n != num) return(state); XX numtry = 0; XX retry--; XX n = (n+1)%64; XX return('B'); XX case 'E': XX return('A'); XX case FALSE: return(state); XX default: return('A'); XX } XX } XX XXchar sbreak() XX { XX int num, len; XX retry++; XX if (numtry++ > MAXTRY) return('A'); XX XX spack('B',n,0,msgpkt); XX switch (rpack(&len,&num,ackpkt)) { XX case 'N': XX num = (--num<0 ? 63:num); XX if (n != num) return(state); XX case 'Y': XX if (n != num) return(state); XX numtry = 0; XX retry--; XX n = (n+1)%64; XX return('C'); XX case 'E': XX return('A'); XX case FALSE: return(state); XX default: return ('A'); XX } XX } XX XX/* timeout equals USERABORT so lets end the file and quit */ XX/* when host receives 'Z' packet with "D" in data field he */ XX/* should discard the file. */ XX XXsabort() XX { XX emits("ABORT"); XX n = (n+1)%64; XX retry--; XX state = 'Z'; XX while (state == 'Z') state = seof(); XX while (state == 'B') state = sbreak(); XX return(FALSE); XX } XX XXrecsw() XX { XX char rinit(), rfile(), rdata(), rbreak(); XX XX state = 'R'; XX XX while(TRUE) { XX switch(state) { XX case 'R': state = rinit(); break; XX case 'F': state = rfile(); break; XX case 'D': state = rdata(); break; XX case 'Z': state = rbreak(); break; XX case 'C': return(TRUE); XX case 'A': x = 600; XX if (timeout == USERABORT){/* easy way to cleanly abort XX should really send and ACK XX with "X" in data field and XX wait for host to abort but XX not all kermits support XX this feature. */ XX emits("ABORT"); XX spack('E',n,0,0); /* send an error packet back */ XX } XX else if (timeout == TIMEOUT) emits("TMOUT"); XX else emits("ERROR"); XX return(FALSE); XX } XX } XX } XX XXchar rinit() XX { XX int len, num; XX retry++; XX if (numtry++ > MAXTRY) return('A'); XX XX if (server) spack('R',n,strlen(filnam),filnam); XX else spack('N',n,0,0); XX switch(rpack(&len,&num,msgpkt)) { XX case 'S': XX rpar(msgpkt); XX spar(msgpkt); XX spack('Y',n,9,msgpkt); XX oldtry = numtry; XX numtry = 0; XX retry--; XX n = (n+1)%64; XX return('F'); XX case 'E': XX return('A'); XX case FALSE: XX if (timeout == USERABORT) return('A'); XX spack('N',n,0,0); XX return(state); XX default: XX return('A'); XX } XX } XX XXchar rfile() XX { XX int num, len; XX retry++; XX if (numtry++ > MAXTRY) return('A'); XX XX switch(rpack(&len,&num,msgpkt)) { XX case 'S': XX if (oldtry++ > MAXTRY) return('A'); XX if (num == ((n==0) ? 63:n-1)) { XX spar(msgpkt); XX spack('Y',num,9,msgpkt); XX retry--; XX numtry = 0; XX return(state); XX } XX else return('A'); XX case 'Z': XX if (oldtry++ > MAXTRY) return('A'); XX if (num == ((n==0) ? 63:n-1)) { XX spack('Y',num,0,0); XX numtry = 0; XX retry--; XX return(state); XX } XX else return('A'); XX case 'F': XX if (num != n) return('A'); XX spack('Y',n,0,0); XX oldtry = numtry; XX numtry = 0; XX retry--; XX n = (n+1)%64; XX return('D'); XX case 'B': XX if (num != n) return ('A'); XX spack('Y',n,0,0); XX retry--; XX return('C'); XX case 'E': XX return('A'); XX case FALSE: XX if (timeout == USERABORT) return('A'); XX spack('N',n,0,0); XX return(state); XX default: XX return ('A'); XX } XX } XX XXchar rdata() XX { XX int num, len; XX retry++; XX if (numtry++ > MAXTRY) return('A'); XX XX switch(rpack(&len,&num,msgpkt)) { XX case 'D': XX if (num != n) { XX if (oldtry++ > MAXTRY) return('A'); XX if (num == ((n==0) ? 63:n-1)) { XX spack('Y',num,6,msgpkt); XX retry--; XX numtry = 0; XX return(state); XX } XX else return('A'); XX } XX decode(); XX spack('Y',n,0,0); XX oldtry = numtry; XX numtry = 0; XX retry--; XX n = (n+1)%64; XX return('D'); XX case 'F': XX if (oldtry++ > MAXTRY) return('A'); XX if (num == ((n==0) ? 63:n-1)) { XX spack('Y',num,0,0); XX numtry = 0; XX retry--; XX return(state); XX } XX else return('A'); XX case 'Z': XX if (num != n) return('A'); XX spack('Y',n,0,0); XX n = (n+1)%64; XX retry--; XX return('Z'); XX case 'E': XX return('A'); XX case FALSE: XX if (timeout == USERABORT) return('A'); XX spack('N',n,0,0); XX return(state); XX default: XX return('A'); XX } XX } XX XXchar rbreak() XX { XX int num, len; XX retry++; XX if (numtry++ > MAXTRY) return('A'); XX XX switch(rpack(&len,&num,msgpkt)) { XX case 'B': XX spack('Y',n,0,0); XX return('C'); XX case 'Z': XX spack('Y',n,0,0); XX return('Z'); XX case 'E': XX return('A'); XX case FALSE: XX spack('N',n,0,0); XX return(state); XX default: XX return('A'); XX } XX } XX XXspack(type,num,len,data) XXchar type, *data; XXint num, len; XX { XX int i; XX char chksum, buffer[100]; XX register char *bufp; XX XX dostats(type); XX bufp = buffer; XX for (i=1; i<=pad; i++) sendchar(padchar); XX XX *bufp++ = SOH; XX *bufp++ = tochar(len+3); XX chksum = tochar(len+3); XX *bufp++ = tochar(num); XX chksum += tochar(num); XX *bufp++ = type; XX chksum += type; XX XX for (i=0; i> 6)+chksum)&077; XX *bufp++ = tochar(chksum); XX *bufp++ = '\r'; XX *bufp++ = '\n'; XX *bufp = 0; XX sendstring(buffer); XX } XX XXrpack(len,num,data) XXint *len, *num; XXchar *data; XX { XX int i, done; XX char type, cchksum, rchksum; XX char t = '\0'; XX XX do { XX t = readchar(); XX if (timeout != GOODREAD) return(FALSE); XX } while (t != SOH); XX XX done = FALSE; XX while (!done) { XX t = readchar(); XX if (timeout != GOODREAD) return(FALSE); XX if (t == SOH) continue; XX cchksum = t; XX *len = unchar(t)-3; XX t = readchar(); XX if (timeout != GOODREAD) return(FALSE); XX if (t == SOH) continue; XX cchksum = cchksum + t; XX *num = unchar(t); XX t = readchar(); XX if (timeout != GOODREAD) return(FALSE); XX if (t == SOH) continue; XX cchksum = cchksum + t; XX type = t; XX for (i=0; i<*len; i++) { XX t = readchar(); XX if (timeout != GOODREAD) return(FALSE); XX if (t == SOH) continue; XX cchksum = cchksum + t; XX data[i] = t; XX } XX data[*len] = 0; XX t = readchar(); XX if (timeout != GOODREAD) return(FALSE); XX rchksum = unchar(t); XX t = readchar(); XX if (timeout != GOODREAD) return(FALSE); XX if (t == SOH) continue; XX done = TRUE; XX } XX dostats(type); XX cchksum = (((cchksum&0300) >> 6)+cchksum)&077; XX if (cchksum != rchksum) return(FALSE); XX return((int)type); XX } XX XXgetpkt() { XX int i,eof; XX XX static char leftover[10] = { '\0', '\0', '\0', '\0', '\0', XX '\0', '\0', '\0', '\0', '\0' }; XX XX if (first == 1) { XX first = 0; XX *leftover = '\0'; XX t = getc(fp); XX if (t == EOF) { XX first = 1; XX return(size = 0); XX } XX totbytes++; XX } XX else if (first == -1) { XX first = 1; XX return(size = 0); XX } XX for (size = 0; (msgpkt[size] = leftover[size]) != '\0'; size++) ; XX *leftover = '\0'; XX rpt = 0; XX eof = 0; XX while (!eof) { XX next = getc(fp); XX if (next == EOF) { XX first = -1; XX eof = 1; XX } XX else totbytes++; XX osize = size; XX encode(t); XX t = next; XX if (size == spsiz-3) return(size); XX if (size > spsiz-3) { XX for (i = 0; (leftover[i] = msgpkt[osize+i]) != '\0'; i++) ; XX size = osize; XX msgpkt[size] = '\0'; XX return(size); XX } XX } XX return(size); XX } XX XXvoid encode(a) XXchar a; XX { XX int a7,b8; XX XX if (p_mode == 1 && a == '\n') { XX rpt = 0; XX msgpkt[size++] = quote; XX msgpkt[size++] = ctl('\r'); XX if (size <= spsiz-3) osize = size; XX msgpkt[size++] = quote; XX msgpkt[size++] = ctl('\n'); XX msgpkt[size] = '\0'; XX return; XX } XX if (rptflg) { XX if (a == next && (first == 0)) { XX if (++rpt < 94) return; XX else if (rpt == 94) { XX msgpkt[size++] = rptq; XX msgpkt[size++] = tochar(rpt); XX rpt = 0; XX } XX } XX else if (rpt == 1) { XX rpt = 0; XX encode(a); XX if (size <= spsiz-3) osize = size; XX rpt = 0; XX encode(a); XX return; XX } XX else if (rpt > 1) { XX msgpkt[size++] = rptq; XX msgpkt[size++] = tochar(++rpt); XX rpt = 0; XX } XX } XX a7 = a & 0177; XX b8 = a & 0200; XX if ((a7 < SP) || (a7==DEL)) { XX msgpkt[size++] = quote; XX a = ctl(a); XX } XX if (a7 == quote) msgpkt[size++] = quote; XX if ((rptflg) && (a7 == rptq)) msgpkt[size++] = quote; XX msgpkt[size++] = a; XX msgpkt[size] = '\0'; XX } XX XXvoid decode() XX { XX USHORT a, a7; XX char *buf; XX XX buf = msgpkt; XX rpt = 0; XX XX while ((a = *buf++) != '\0') { XX if (rptflg) { XX if (a == rptq) { XX rpt = unchar(*buf++); XX a = *buf++; XX } XX } XX if (a == quote) { XX a = *buf++; XX a7 = a & 0177; XX if ((a7 >= 0100 && a7 <= 0137) || a7 == '?') a = ctl(a); XX } XX if (rpt == 0) rpt = 1; XX if (p_mode == 1 && a == '\r') continue; XX totbytes += rpt; XX for (; rpt > 0; rpt--) putc(a, fp); XX } XX return; XX } XX XXvoid spar(data) XXchar data[]; XX { XX data[0] = tochar(MAXPACKSIZ); XX data[1] = tochar(TTIME_LONG); XX data[2] = tochar(MYPAD); XX data[3] = ctl(MYPCHAR); XX data[4] = tochar(MYEOL); XX data[5] = MYQUOTE; XX data[6] = 'N'; XX data[7] = '1'; XX data[8] = MYRPTQ; XX data[9] = '\0'; XX } XX XXvoid rpar(data) XXchar data[]; XX { XX spsiz = unchar(data[0]); XX timint = unchar(data[1]); XX pad = unchar(data[2]); XX padchar = ctl(data[3]); XX eol = unchar(data[4]); XX quote = data[5]; XX rptflg = 0; XX if (data[6] == 0) return; XX if (data[7] == 0) return; XX if (data[8] == 0) return; XX rptq = data[8]; XX rptflg = ((rptq > 040 && rptq < 0100) || (rptq > 0140 && rptq < 0177)); XX } XX XXsaybye() XX { XX int len,num; XX shutdown = 0; XX spack('G',n,1,"F"); /* shut down server no more files */ XX rpack(&len,&num,ackpkt); XX } XX XXstatusline() XX { XX emits ("\nFile: Pckt: Pckt No: Retrn: Bytes: Stat: "); XX x = 48; XX curmode = 1; XX emits (filnam); XX return(0); XX } XX XXdostats(type) XXchar type; XX { XX if (type != 'Y' && type != 'N' && type != 'G') { XX x = 224; XX emit(type); XX x = 312; XX sprintf(snum,"%4d",n+(tp * 64)); XX emits(snum); XX if (n==63) tp++; XX x = 408; XX sprintf(snum,"%2d",retry-1); XX emits(snum); XX x = 488; XX sprintf(snum,"%6ld",(long)totbytes); XX emits(snum); XX } XX } XX XX/* allow for multi file xfers separated by commas under kermit and XMODEM */ XX XXmulti_xfer(name,mode,do_send) XXchar *name; XXint (*mode)(); XXint do_send; XX { XX int done = 0; XX int status; XX char *p; XX XX p = name; XX while(*p && *p != ',') p++; XX if (*p == '\0') { XX done = TRUE; XX if (multi == 1) multi++; XX } XX else multi = 1; XX *p = '\0'; XX status = ((*mode)(name, multi)); XX if (status == TRUE) { XX if (do_send) emits("Sent File: "); XX else emits("Received File: "); XX emits(name); XX emits("\n"); XX emit(8); XX } XX else if (status == FALSE) XX { XX close(fd); XX if (do_send) emits("Send Failed: "); XX else emits("Receive Failed: "); XX emits(name); XX emits("\n"); XX emit(8); XX } XX if (!done) multi_xfer(++p, mode, do_send); XX server = 0; XX multi = 0; XX } XX XX/* gobble up all garb that we received while getting file name strings */ XX XXeatup() XX { XX while(CheckIO(Read_Request)) { XX WaitIO(Read_Request); XX BeginIO(Read_Request); XX } XX } XX SHAR_EOF if test 20179 -ne "`wc -c kermit.c`" then echo shar: error transmitting kermit.c '(should have been 20179 characters)' fi echo shar: extracting xmodem.c sed 's/^XX//' << \SHAR_EOF > xmodem.c XX/************************************************************* XX * vt100 terminal emulator - XMODEM protocol support XX * XX * 860823 DBW - Integrated and rewrote lots of code XX * 860815 Steve Drew: readchar inproved with real timeouts XX * v2.0 860809 DBW - Major rewrite XX * v1.1 860720 DBW - Switches, 80 cols, colors, bug fixes XX * v1.0 860712 DBW - First version released XX * XX *************************************************************/ XX XX#define MODULE_XMODEM 1 XX#include "vt100.h" XX XX/* forward declarations for LATTICE */ XXvoid sendstring(); XXvoid sendchar(); XX XX/************************************************************ XX* Send a string (using sendchar below) XX************************************************************/ XX XXvoid sendstring(s) XXchar *s; XX { XX char c; XX XX while ((c = *s++) != '\000') sendchar(c); XX } XX XX/**************************************************************/ XX/* send char and read char functions for the xmodem function */ XX/************************************************************/ XXvoid sendchar(ch) XXint ch; XX { XX rs_out[0] = ch & 0xFF; XX DoIO(Write_Request); XX } XX XXint readchar() XX { XX int rd,ch; XX XX Timer.tr_time.tv_secs = ttime; XX Timer.tr_time.tv_micro = 0; XX SendIO((char *) &Timer.tr_node); XX XX rd = FALSE; XX while (rd == FALSE) XX { XX Wait((1L << Read_Request->IOSer.io_Message.mn_ReplyPort->mp_SigBit) | XX ( 1L << mywindow->UserPort->mp_SigBit) | XX ( 1L << Timer_Port->mp_SigBit)); XX if (CheckIO(Read_Request)) XX { XX WaitIO(Read_Request); XX ch=rs_in[0]; XX rd = TRUE; XX BeginIO(Read_Request); XX } XX if (NewMessage=(struct IntuiMessage *)GetMsg(mywindow->UserPort)) { XX if ((NewMessage->Class == RAWKEY) && (NewMessage->Code == 69)) XX { XX AbortIO((char *) &Timer); XX Wait (1L << Timer_Port->mp_SigBit); XX if (want_message) XX emits("\nUser aborted transfer\n"); XX timeout = USERABORT; XX return('\0'); XX } XX continue; XX } XX if (rd == FALSE && CheckIO(&Timer)) { XX if (want_message) XX emits("\nTimeout waiting for character\n"); XX timeout = TIMEOUT; XX return('\0'); XX } XX } /* end while */ XX AbortIO((char *) &Timer); XX Wait (1L << Timer_Port->mp_SigBit); XX timeout = GOODREAD; XX return(ch & 0xFF); XX } XX XX/**************************************/ XX/* xmodem send and recieve functions */ XX/************************************/ XX XXint XMODEM_Read_File(file) XXchar *file; XX { XX int firstchar, sectnum, sectcurr, sectcomp, errors, errorflag; XX unsigned int checksum, j, bufptr; XX char numb[10]; XX bytes_xferred = 0L; XX ttime = TTIME_SHORT; XX want_message = TRUE; /* tell readchar to print any error msgs */ XX XX if ((fd = creat(file, 0)) < 0) XX { XX emits("Cannot Open File\n"); XX return FALSE; XX } XX else XX emits("Receiving File\n\nType to abort transfer\n"); XX XX sectnum = errors = bufptr = 0; XX sendchar(NAK); XX firstchar = 0; XX while (firstchar != EOT && errors != ERRORMAX) XX { XX errorflag = FALSE; XX XX do { /* get sync char */ XX firstchar = readchar(); XX if (timeout != GOODREAD) { XX if (timeout == USERABORT || errors++ == ERRORMAX) XX return FALSE; XX } XX } while (firstchar != SOH && firstchar != EOT); XX XX if (firstchar == SOH) XX { XX emits("Getting Block "); XX sprintf(numb, "%d", sectnum); XX emits(numb); XX emits("..."); XX sectcurr = readchar(); XX if (timeout != GOODREAD) return FALSE; XX sectcomp = readchar(); XX if (timeout != GOODREAD) return FALSE; XX if ((sectcurr + sectcomp) == 255) XX { XX if (sectcurr == ((sectnum + 1) & 0xff)) XX { XX checksum = 0; XX for (j = bufptr; j < (bufptr + SECSIZ); j++) XX { XX bufr[j] = readchar(); XX if (timeout != GOODREAD) return FALSE; XX checksum = (checksum + bufr[j]) & 0xff; XX } XX if (checksum == readchar() && timeout == GOODREAD) XX { XX errors = 0; XX sectnum++; XX bufptr += SECSIZ; XX bytes_xferred += SECSIZ; XX emits("verified\n"); XX if (bufptr == BufSize) XX { XX if (write(fd, bufr, BufSize-128) == EOF) XX { XX emits("\nError Writing File\n"); XX return FALSE; XX } XX bufptr = 128; XX for (j = 0; j < 128; j++) XX bufr[j] = bufr[(BufSize-128)+j]; XX } XX sendchar(ACK); XX } XX else XX { XX errorflag = TRUE; XX if (timeout == USERABORT) return FALSE; XX } XX } XX else XX { XX /* got a duplicate sector */ XX if (sectcurr == (sectnum & 0xff)) XX { XX /* wait until we time out for 5secs */ XX do { XX readchar(); XX } while (timeout == GOODREAD); XX if (timeout == USERABORT) return FALSE; XX emits("\nReceived Duplicate Sector\n"); XX sendchar(ACK); XX } XX else errorflag = TRUE; XX } XX } XX else errorflag = TRUE; XX } XX if (errorflag == TRUE) XX { XX errors++; XX emits("\nError\n"); XX sendchar(NAK); XX } XX } /* end while */ XX if ((firstchar == EOT) && (errors < ERRORMAX)) XX { XX sendchar(ACK); XX while (bufptr > 0 && (bufr[--bufptr] == 0x00 || XX bufr[bufptr] == 0x1A)) ; XX write(fd, bufr, ++bufptr); XX close(fd); XX return TRUE; XX } XX return FALSE; XX } XX XXint XMODEM_Send_File(file) XXchar *file; XX { XX int sectnum, bytes_to_send, size, attempts, c; XX unsigned checksum, j, bufptr; XX char numb[10]; XX bytes_xferred = 0; XX ttime = TTIME_LONG; XX want_message = TRUE; /* tell readchar to print any error msgs */ XX XX if ((fd = open(file, 0)) < 0) { XX emits("Cannot Open Send File\n"); XX return FALSE; XX } XX else XX emits("Sending File\n\nType to abort transfer\n"); XX attempts = 0; XX sectnum = 1; XX /* wait for sync char */ XX j=1; XX while (((c = readchar()) != NAK) && (j++ < ERRORMAX)) XX if (timeout == USERABORT) return(FALSE); XX if (j >= (ERRORMAX)) XX { XX emits("\nReceiver not sending NAKs\n"); XX return FALSE; XX } XX XX while ((bytes_to_send = read(fd, bufr, BufSize)) && attempts != RETRYMAX) XX { XX if (bytes_to_send == EOF) XX { XX emits("\nError Reading File\n"); XX return FALSE; XX } XX XX bufptr = 0; XX while (bytes_to_send > 0 && attempts != RETRYMAX) XX { XX attempts = 0; XX emits("Block "); XX sprintf(numb, "%d ", sectnum); XX emits(numb); XX do { XX emits("."); XX sendchar(SOH); XX sendchar(sectnum); XX sendchar(~sectnum); XX checksum = 0; XX size = SECSIZ <= bytes_to_send ? SECSIZ : bytes_to_send; XX bytes_to_send -= size; XX for (j = bufptr; j < (bufptr + SECSIZ); j++) XX if (j < (bufptr + size)) { XX sendchar(bufr[j]); XX checksum += bufr[j]; XX } XX else sendchar(0); XX sendchar(checksum); XX attempts++; XX c = readchar(); XX if (timeout == USERABORT) {emits("\n"); return FALSE;} XX } while ((c != ACK) && (attempts != RETRYMAX)); XX bufptr += size; XX bytes_xferred += size; XX emits(" sent\n"); XX sectnum++; XX } XX } XX close(fd); XX if (attempts == RETRYMAX) XX { XX emits("\nNo Acknowledgment Of Sector, Aborting\n"); XX return FALSE; XX } XX else XX { XX attempts = 0; XX do { XX sendchar(EOT); XX attempts++; XX } while ((readchar() != ACK) && XX (attempts != RETRYMAX) && XX (timeout != USERABORT)) ; XX if (attempts == RETRYMAX) XX emits("\nNo Acknowledgment Of End Of File\n"); XX } XX return TRUE; XX } XX SHAR_EOF if test 7250 -ne "`wc -c xmodem.c`" then echo shar: error transmitting xmodem.c '(should have been 7250 characters)' fi echo shar: extracting script.c sed 's/^XX//' << \SHAR_EOF > script.c XX/************************************************************* XX * vt100 terminal emulator - Script file support XX * XX * 860823 DBW - Integrated and rewrote lots of code XX * 860815 Steve Drew: Initial version written of SCRIPT.C XX * v2.0 860809 DBW - Major rewrite XX * v1.1 860720 DBW - Switches, 80 cols, colors, bug fixes XX * v1.0 860712 DBW - First version released XX * XX *************************************************************/ XX XX#define MODULE_SCRIPT 1 XX XX#include "vt100.h" XX XXextern char *fgets(),*malloc(); XXextern long ftell(); XX XXstruct COMMAND { XX int (*func)(); XX char *cname; XX}; XX XXstruct LABEL { XX struct LABEL *next; XX char *name; XX long pos; XX}; XX XX XX XX/**************** globals needed ******************/ XX XXchar on_string[20]; /* string to match on for on cmd */ XXchar wait_string[20]; /* string to match of for wait cmd */ XXchar golabel[20]; /* label we are looking for in goto */ XXchar on_cmd[255]; /* command to execute when on matchs*/ XXint onsize; /* size of on_string */ XXint waitsize; /* size of wait_string */ XXint onpos; /* position in on string for search */ XXint waitpos; /* pos in wait_string for search */ XXint on_match; /* flag set while doing on_cmd */ XXFILE *sf; /* file pointer for script file */ XXstruct LABEL *lbase = NULL; /* will point to first label */ XXstruct LABEL *labels; /* current label pointer */ XX XXint cmd_send(), cmd_wait(), cmd_on(), cmd_goto(), cmd_delay(), cmd_done(), XX cmd_ks(), cmd_kg(), cmd_kr(), cmd_xs(), cmd_xr(), cmd_cap(), cmd_as(), XX cmd_null(), cmd_kb(); XX XXchar *next_wrd(), *tostring(); XX XX XX/********************** command table **********************************/ XX XXstatic struct COMMAND commands[]= { XX cmd_send, "SEND", /* send string to host */ XX cmd_wait, "WAIT", /* wait for a string from host */ XX cmd_on, "ON", /* on a 'string' do a cmd */ XX cmd_goto, "GOTO", /* goto label */ XX cmd_delay, "DELAY", /* delay amount of seconds */ XX cmd_done, "EXIT", /* exit script file */ XX cmd_ks, "KS", /* kermit send file */ XX cmd_kr, "KR", /* kermit receive file */ XX cmd_kg, "KG", /* kermit get file */ XX cmd_kb, "KB", /* kermit bye (for server) */ XX cmd_xs, "XS", /* xmodem send file */ XX cmd_xr, "XR", /* xmodem receive file */ XX cmd_cap, "CAPTURE", /* ascii capture on/off */ XX cmd_as, "ASCII_SEND", /* ascii send */ XX cmd_null, NULL XX}; XX XX/********************************************************************/ XX/* checks char to see if match with on string or wait_string */ XX/* if on string match oncmd gets executed imediately, */ XX/* if wait_string match script_wait is set. */ XX/********************************************************************/ XX XXchk_script(c) XXchar c; XX{ XX if (on_string[0] != '\0') { XX if (on_string[onpos] == c) { XX onpos++; XX if (onpos == onsize) { XX on_match = TRUE; XX do_script_cmd(ONCOMMAND); XX on_match = FALSE; XX return(0); XX } XX } XX else onpos = 0; XX } XX XX if (wait_string[0] != '\0') { XX if (wait_string[waitpos] != c) { XX waitpos = 0; XX return(0); XX } XX waitpos++; XX if (waitpos != waitsize) return(0); XX wait_string[0] = '\0'; XX script_wait = FALSE; XX } XX} XX XXscript_start(file) XXchar *file; XX{ XX if ((sf = fopen(file, "r")) == NULL) { XX emits("Can't open script file\n"); XX return(0); XX } XX script_on = TRUE; XX script_wait = FALSE; XX wait_string[0] = '\0'; XX on_string[0] = '\0'; XX on_match = FALSE; XX lbase = NULL; XX} XX XX/* return pointer to next word. set l to size of the word */ XX XXchar *next_wrd(s,l) XXchar *s; XXint *l; XX{ XX char *p; XX while(*s && (*s == ' ' || *s == 9)) s++; XX p = s; XX while(*s && (*s != ' ' && *s != 9)) s++; XX *l = s-p; XX return(p); XX} XX XXexe_cmd(p,l) XXchar *p; XXint l; XX{ XX int i; XX XX for (i=0; commands[i].func != cmd_null; ++i) XX if (strncmp(p, commands[i].cname, l) == 0) { XX (*commands[i].func)(next_wrd(p+l, &l)); XX return(TRUE); XX } XX emits ("\nScript - unknown command: "); XX emits (p); XX emits ("\n"); XX} XX XXstruct LABEL *find_label(lname) XXchar *lname; XX{ XX struct LABEL *label; XX XX label = lbase; XX while(label != NULL) { XX if (strcmp(label->name, lname) == 0) return (label); XX label = label->next; XX } XX return(NULL); XX} XX XX XXdo_script_cmd(stat) XXint stat; XX{ XX int len,l; XX char line[256]; XX char *p; XX XX if (stat == ONCOMMAND) { /* if ON command is matched and we were */ XX strcpy(line,on_cmd); /* doing a DELAY then abort the delay timer,*/ XX p = next_wrd(line,&l); /* except if on_cmd was just a SEND. */ XX if (*p != 'S' && script_wait == WAIT_TIMER) { XX AbortIO((char *) &Script_Timer); XX Wait (1L << Script_Timer_Port->mp_SigBit); XX script_wait = FALSE; /* script will proceed after on command */ XX } XX exe_cmd(p,l); XX return(0); XX } XX XX script_wait = FALSE; XX while(fgets(line,256,sf) != NULL) { XX len = strlen(line); XX line[--len] = '\0'; XX p = next_wrd(&line[0], &l); XX if (*(p + l - 1) == ':') { /* its a label */ XX *(p + l - 1) = '\0'; XX if (find_label(p) == NULL) { /* it's a new label */ XX if (lbase == NULL) { /* it's the first label */ XX labels = lbase = (struct LABEL *) malloc (sizeof (struct LABEL)); XX } XX else { XX labels->next = XX (struct LABEL *) malloc (sizeof (struct LABEL)); XX labels = labels->next; XX } XX labels->pos = ftell(sf); XX labels->name = malloc(l); XX labels->next = NULL; XX strcpy(labels->name, p); XX if (stat == GOTOLABEL && strcmp(p, golabel) == 0) XX stat = NEXTCOMMAND; XX } XX if (l < len) p = next_wrd(p+l+1, &l); XX else return(0); XX } /* end of it's a label */ XX if (stat == GOTOLABEL || *p == '#') continue; XX if (*p) exe_cmd(p,l); XX return(0); XX } /* end of while */ XX if (stat == GOTOLABEL) { XX emits("\nScript - label not found: "); XX emits(golabel); XX emits("\n"); XX } XX exit_script(); XX} XX XXexit_script() XX{ XX if (script_wait == WAIT_TIMER) /* timer not done yet */ XX AbortIO((char *) &Script_Timer); /* so abort it */ XX emits("\nScript - terminated\n"); XX script_on = FALSE; XX script_wait = TRUE; XX fclose(sf); XX} XX XX/* remove quotes terminate string & return pointer to start */ XX XXchar *tostring(ptr) XXchar *ptr; XX{ XX char *s; XX XX s = ptr; XX if (*ptr == '"') { XX while(*ptr++ && *ptr !='"'); XX if (*ptr == '"') { XX *ptr = '\0'; XX ptr = s+1; XX while(*s++) if (*s == '|') *s = '\r'; XX return(ptr); XX } XX } XX if (*s == '^') { XX *s = *(s+1)-64; XX *(s+1) = '\0'; XX return(s); XX } XX *(s+1) = '\0'; XX return(s); XX} XX XXcmd_goto(lname) XXchar *lname; XX{ XX struct LABEL *label; XX /* if on_cmd was a goto kill wait state */ XX if (on_match) { wait_string[0] = '\0'; script_wait = FALSE; } XX if ((label = find_label(lname)) == NULL) { /* is it forward */ XX strcpy(golabel,lname); XX do_script_cmd(GOTOLABEL); XX } XX else { XX fseek(sf,(long)(label->pos),0); XX } XX} XX XXcmd_send(str) XXchar *str; XX{ XX sendstring(tostring(str)); XX} XX XX XXcmd_wait(str) XXchar *str; XX{ XX str = tostring(str); XX *(str+20) = '\0'; /* 20 characters max */ XX strcpy(wait_string, str); XX waitsize = strlen(str); XX script_wait = WAIT_STRING; XX} XX XXcmd_on(str) XXchar *str; XX{ XX char *p; XX XX p = tostring(str); XX strcpy(on_string, p); XX onsize = strlen(p); XX *(p+onsize+2+20) = '\0'; /* 20 characters max */ XX strcpy(on_cmd,p+onsize+2); XX} XX XXcmd_delay(seconds) XXchar *seconds; XX{ XX script_wait = WAIT_TIMER; XX Script_Timer.tr_time.tv_secs = atoi(seconds); XX Script_Timer.tr_time.tv_micro = 0; XX SendIO((char *) &Script_Timer.tr_node); XX} XX XXcmd_done() XX{ XX exit_script(); XX} XX XXcmd_ks(file) XXchar *file; XX{ XX multi_xfer(file, doksend, 1); XX} XX XXcmd_kr(file) XXchar *file; XX{ XX multi_xfer(file, dokreceive, 0); XX} XX XXcmd_kg(file) XXchar *file; XX{ XX server = TRUE; XX multi_xfer(file, dokreceive, 0); XX} XX XXcmd_kb() XX{ XX saybye(); XX} XX XXcmd_xs(file) XXchar *file; XX{ XX multi_xfer(file, XMODEM_Send_File, 1); XX} XX XXcmd_xr(file) XXchar *file; XX{ XX multi_xfer(file, XMODEM_Read_File, 1); XX} XX XXcmd_cap(file) XXchar *file; XX{ XXdo_capture(file); XX} XX XXcmd_as(file) XXchar *file; XX{ XXdo_send(file); XX} XX XXcmd_null(file) XXchar *file; XX{ XX} XX SHAR_EOF if test 9364 -ne "`wc -c script.c`" then echo shar: error transmitting script.c '(should have been 9364 characters)' fi # End of shell archive exit 0