Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!utgpu!water!watnot!watmath!clyde!rutgers!mit-eddie!genrad!decvax!decwrl!cookie.dec.com!wecker From: wecker@cookie.dec.com.UUCP Newsgroups: comp.sys.amiga Subject: VT100 (V2.6 DBW 870227) Part 2 of 2 READ DOCUMENTATION!!! Message-ID: <8260@decwrl.DEC.COM> Date: Tue, 24-Feb-87 12:00:44 EST Article-I.D.: decwrl.8260 Posted: Tue Feb 24 12:00:44 1987 Date-Received: Fri, 27-Feb-87 01:46:33 EST Sender: daemon@decwrl.DEC.COM Organization: Digital Equipment Corporation Lines: 3209 # 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: # script.c # remote.c # window.c # expand.c # kermit.c # xmodem.c # This archive created: Sun Feb 22 23:51:56 1987 echo shar: extracting script.c sed 's/^XX//' << \SHAR_EOF > script.c XX/************************************************************* XX * vt100 terminal emulator - Script file support XX * XX * v2.6 870227 DBW - bug fixes for all the stuff in v2.5 XX * v2.5 870214 DBW - more additions (see readme file) XX * v2.4 861214 DBW - lots of fixes/additions (see readme file) XX * v2.3 861101 DBW - minor bug fixes XX * v2.2 861012 DBW - more of the same XX * v2.1 860915 DBW - new features (see README) XX * 860901 ACS - Added BAUD, PARITY and WORD commands & handling 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#include "vt100.h" XX XXstruct COMMAND { XX void (*func)(); XX char *cname; XX }; XX XXstruct LABEL { XX struct LABEL *next; XX char *name; XX long pos; XX }; XX XXextern long atol(); 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[20]; /* 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 XX/********************** command tables *******************************/ XXstatic struct COMMAND inicmds[] = { /* initialization commands */ XX cmd_bkg, "bac", /* set background color */ XX cmd_bold, "bol", /* set bold color */ XX cmd_buf, "buf", /* set buffer size */ XX cmd_cursor, "cur", /* set cursor color */ XX cmd_depth, "dep", /* set screen depth */ XX cmd_fore, "for", /* set foreground color */ XX cmd_inter, "int", /* interlace ON/OFF */ XX cmd_lines, "lin", /* num lines */ XX cmd_screen, "scr", /* Screen WB/CUST */ XX cmd_volume, "vol", /* set volume */ XX cmd_wb, "wb", /* use WB colors */ XX cmd_null, NULL /* mark the end of the list */ XX }; XXstatic struct COMMAND scrcmds[] = { /* script only commands */ XX cmd_as, "asc", /* ascii send */ XX cmd_beep, "bee", /* Beep */ XX cmd_cap, "cap", /* ascii capture on/off */ XX cmd_cd, "cd", /* change directory */ XX cmd_delay, "del", /* delay amount of seconds */ XX cmd_goto, "got", /* goto label */ XX cmd_kb, "kb", /* kermit bye (for server) */ XX cmd_kg, "kg", /* kermit get file */ XX cmd_kr, "kr", /* kermit receive file */ XX cmd_ks, "ks", /* kermit send file */ XX cmd_on, "on", /* on a 'string' do a cmd */ XX cmd_sb, "sb", /* Send a break */ XX cmd_send, "send", /* send string to host */ XX cmd_wait, "wait", /* wait for a host string */ XX cmd_xr, "xr", /* xmodem receive file */ XX cmd_xs, "xs", /* xmodem send file */ XX cmd_null, NULL /* mark the end of the list */ XX }; XXstatic struct COMMAND commands[]= { /* generally available commands */ XX cmd_appcur, "app", /* turn app. cursor on/off */ XX cmd_baud, "bau", /* Set Baud Rate */ XX cmd_bt, "bre", /* Set Break Time */ XX cmd_conv, "con", /* convert bs to del */ XX cmd_echo, "ech", /* turn echo on or off */ XX cmd_exit, "exi", /* exit script file */ XX cmd_fnc, "f", /* define function key */ XX cmd_key, "key", /* keyscript character */ XX cmd_mode, "mod", /* KERMIT transfer mode */ XX cmd_numkey, "numkey", /* turn numeric kpad on/off */ XX cmd_parity, "parity", /* Set Parity */ XX cmd_swap, "swap", /* Swap BS and DEL */ XX cmd_wrap, "wrap", /* turn wrap on or off */ XX cmd_null, NULL /* mark the end of the list */ 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 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 (strlen(file) == 0 || *file == '#') return(0); XX if ((sf = fopen(file, "r")) == NULL) { XX req("Can't open script file",file,0); 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 XX while(*s && (*s == ' ' || *s == '\t')) s++; XX p = s; XX while(*s && (*s != ' ' && *s != '\t')) s++; XX *l = s-p; XX return(p); XX } XX XXexe_cmd(p,l) XXchar *p; XXint l; XX { XX int i,l2; XX XX /* downcase the command */ XX for (i=0; i= l2 && strncmp(p, inicmds[i].cname, l2) == 0) { XX (*inicmds[i].func)(next_wrd(p+l, &l)); XX return(TRUE); XX } XX } XX XX /* or the script command list */ XX else XX for (i=0; scrcmds[i].func != cmd_null; ++i) { XX l2 = strlen(scrcmds[i].cname); XX if (l >= l2 && strncmp(p, scrcmds[i].cname, l2) == 0) { XX (*scrcmds[i].func)(next_wrd(p+l, &l)); XX return(TRUE); XX } XX } XX XX /* now search for it (in the standard command list) */ XX for (i=0; commands[i].func != cmd_null; ++i) { XX l2 = strlen(commands[i].cname); XX if (l >= l2 && strncmp(p, commands[i].cname, l2) == 0) { XX (*commands[i].func)(next_wrd(p+l, &l)); XX return(TRUE); XX } XX } XX if (doing_init) { XX puts("INIT - unknown command:"); XX puts(p); XX } XX else req("Script - unknown command:",p,0); XX XX return(FALSE); 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 XXdo_script_cmd(stat) XXint stat; XX { XX int len,l; XX char line[256]; XX char *p; XX XX /* if ON command is matched and we were */ XX /* doing a DELAY then abort the delay timer,*/ XX /* except if on_cmd was just a SEND. */ XX if (stat == ONCOMMAND) { XX strcpy(line,on_cmd); XX p = next_wrd(line,&l); XX if (*p != 'S' && script_wait == WAIT_TIMER) { XX AbortIO((char *) &Script_Timer); XX Wait (1L << Script_Timer_Port->mp_SigBit); XX XX /* script will proceed after on command */ XX script_wait = FALSE; XX } XX exe_cmd(p,l); XX return(0); 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 *) XX malloc(sizeof (struct LABEL)); XX } XX else { XX labels->next = (struct LABEL *) XX 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 p = next_wrd(p+l+1, &l); 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) req("Script - label not found: ",golabel,0); 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 req("Script - terminated","",0); 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 *s1,*s2; XX XX s1 = ptr; XX if (*ptr == '"') { XX while(*ptr++ && *ptr != '"') ; XX if (*ptr == '"') { XX *ptr = '\0'; XX ptr = s2 = ++s1; XX while(*s2) { XX if (*s2 != '^') *s1++ = *s2; XX else if (*(s2+1) == '^') *s1++ = *s2++; XX else *s1++ = ((*++s2)|' ')-96; XX s2++; XX } XX *s1 = '\0'; XX return(ptr); XX } XX } XX if (*s1 == '^') { XX *s1 = (*(s1+1)|' ')-96; XX *(s1+1) = '\0'; XX return(s1); XX } XX *(s1+1) = '\0'; XX return(s1); XX } XX XX/***************************** SCRIPT COMMANDS ********************/ XX XXvoid cmd_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 XXvoid cmd_send(str) XXchar *str; XX { XX sendstring(tostring(str)); XX } XX XXvoid cmd_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 XXvoid cmd_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 XXvoid cmd_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 XXvoid cmd_exit(option) XXchar *option; XX { XX char *p; XX int l; XX XX if (doing_init) return; XX XX if (*option) { XX p = next_wrd(option,&l); XX *(p+l) = '\000'; XX if (strcmp(p,"vt100") == 0 || strcmp(p,"VT100") == 0) XX cleanup("Exit vt100 from script",0); XX exit_script(); XX script_start(p); XX } XX else exit_script(); XX } XX XXvoid cmd_ks(file) XXchar *file; XX { XX multi_xfer(file, doksend, 1); XX } XX XXvoid cmd_kr(file) XXchar *file; XX { XX multi_xfer(file, dokreceive, 0); XX } XX XXvoid cmd_kg(file) XXchar *file; XX { XX server = TRUE; XX multi_xfer(file, dokreceive, 0); XX } XX XXvoid cmd_kb() XX { XX saybye(); XX } XX XXvoid cmd_xs(file) XXchar *file; XX { XX multi_xfer(file, XMODEM_Send_File, 1); XX } XX XXvoid cmd_xr(file) XXchar *file; XX { XX multi_xfer(file, XMODEM_Read_File, 1); XX } XX XXvoid cmd_cap(file) XXchar *file; XX { XX do_capture(file); XX } XX XXvoid cmd_as(file) XXchar *file; XX { XX do_send(file); XX } XX XXvoid cmd_cd(name) XXchar *name; XX { XX set_dir(name); XX } XX XXvoid cmd_sb(str) XXchar *str; XX { XX sendbreak(); XX } XX XXvoid cmd_baud(rate) XXchar *rate; XX { XX int i = atoi(rate); XX XX switch( i ) XX { XX case 300: XX case 1200: XX case 2400: XX case 4800: XX case 9600: XX if (doing_init) p_baud = i; XX else setserbaud(i, TRUE); XX break; XX XX default: XX if (doing_init) { XX puts("INIT - invalid baud rate:"); XX puts(rate); XX } XX else req("Script - invalid baud rate: ",rate,0); XX break; XX } XX } XX XXvoid cmd_parity(par) XXchar *par; XX { XX int i; XX XX switch( *par|' ' ) XX { XX case 'n': i = 0; break; XX case 'm': i = 1; break; XX case 's': i = 2; break; XX case 'e': i = 3; break; XX case 'o': i = 4; break; XX XX default: XX if (doing_init) { XX puts("INIT - invalid parity:"); XX puts(par); XX } XX else req("Script - invalid parity: ",par,0); XX return; XX } XX p_parity = i; XX if (doing_init) return; XX XX ClearMenuStrip( mywindow ); /* Remove old menu */ XX InitCommItems(); /* Re-do comm menu */ XX SetMenuStrip(mywindow,&menu[0]); /* Re-display the menu */ XX } XX XXvoid cmd_bt(breaklength) XXchar *breaklength; XX { XX p_break = atol(breaklength); XX if (doing_init) return; XX XX AbortIO(Read_Request); XX Read_Request->io_BrkTime = Write_Request->io_BrkTime = p_break; XX setparams(); XX } XX XXvoid cmd_mode(tmode) XXchar *tmode; XX { XX switch (*tmode|' ') { XX case 'i': XX p_mode = 0; XX break; XX XX case 'c': XX p_mode = 1; XX break; XX XX default: XX if (doing_init) { XX puts("INIT - invalid transfer mode: "); XX puts(tmode); XX } XX else req("Script - invalid transfer mode: ",tmode,0); XX return; XX } XX if (doing_init) return; XX XX ClearMenuStrip(mywindow); XX InitCommItems(); /* Re-do comm menu */ XX SetMenuStrip(mywindow,&menu[0]); XX } XX XXvoid cmd_beep(dummy) XXchar *dummy; XX { XX if (p_volume == 0) DisplayBeep(NULL); XX else { XX BeginIO(&Audio_Request); XX WaitIO(&Audio_Request); XX } XX } XX XXvoid setvar(par,typ,var) XXchar *par; XXint typ,*var; XX { XX int i; XX XX switch (typ) { XX case 0: /* ON/OFF or YES/NO */ XX case 1: /* not case */ XX if ((par[1]|' ') == 'n' || (par[0]|' ') == 'y') *var = 1-typ; XX else *var = typ; XX break; XX XX case 2: /* read hex number */ XX if (sscanf(par,"%x",&i) == 1) *var = i; XX XX break; XX XX case 3: /* read decimal number */ XX if (sscanf(par,"%d",&i) == 1) *var = i; XX break; XX } XX } XX XXvoid cmd_echo(par) XXchar *par; XX { XX setvar(par,0,&p_echo); XX if (doing_init == 0) redoutil(); XX } XX XXvoid cmd_wrap(par) XXchar *par; XX { XX setvar(par,0,&p_wrap); XX if (doing_init == 0) redoutil(); XX } XX XXvoid cmd_numkey(par) XXchar *par; XX { XX setvar(par,1,&p_keyapp); XX if (doing_init == 0) redoutil(); XX } XX XXvoid cmd_appcur(par) XXchar *par; XX { XX setvar(par,0,&p_curapp); XX if (doing_init == 0) redoutil(); XX } XX XXvoid cmd_swap(par) XXchar *par; XX { XX setvar(par,0,&p_bs_del); XX if (doing_init == 0) redoutil(); XX } XX XXvoid cmd_bkg(par) XXchar *par; XX { XX setvar(par,2,&p_background); XX } XX XXvoid cmd_bold(par) XXchar *par; XX { XX setvar(par,2,&p_bold); XX } XX XXvoid cmd_buf(par) XXchar *par; XX { XX setvar(par,3,&p_buffer); XX } XX XXvoid cmd_cursor(par) XXchar *par; XX { XX setvar(par,2,&p_cursor); XX } XX XXvoid cmd_depth(par) XXchar *par; XX { XX setvar(par,3,&p_depth); XX } XX XXvoid cmd_fore(par) XXchar *par; XX { XX setvar(par,2,&p_foreground); XX } XX XXvoid cmd_inter(par) XXchar *par; XX { XX setvar(par,0,&p_interlace); XX } XX XXvoid cmd_lines(par) XXchar *par; XX { XX setvar(par,3,&p_lines); XX } XX XXvoid cmd_screen(par) XXchar *par; XX { XX if ((par[0]|' ') == 'w') p_screen = 0; XX else p_screen = 1; XX } XX XXvoid cmd_wb(par) XXchar *par; XX { XX setvar(par,0,&p_wbcolors); XX } XX XXvoid cmd_key(par) XXchar *par; XX { XX int i; XX XX if (sscanf(par,"%x",&i) == 1) p_keyscript = (char)(i & 0x7f); XX } XX XXvoid cmd_volume(par) XXchar *par; XX { XX setvar(par,3,&p_volume); XX } XX XXvoid cmd_conv(par) XXchar *par; XX { XX setvar(par,0,&p_bs_del); XX if (doing_init == 0) redoutil(); XX } XX XXvoid cmd_fnc(par) XXchar *par; XX { XX char *s; XX int l; XX int i = atoi(par); XX XX s = par; XX if (*s) s = next_wrd(s,&l); /* skip key number */ XX if (*s) s = next_wrd(s+l+1,&l); /* point at desired string */ XX if (*s) s = tostring(s); /* convert the string */ XX if (*s && i > 0 && i < 21) { XX if (i > 10) { XX p_F[i-11] = malloc(strlen(s)+1); XX strcpy(p_F[i-11],s); XX } XX else { XX p_f[i-1] = malloc(strlen(s)+1); XX strcpy(p_f[i-1],s); XX } XX } XX } XX XXvoid cmd_null(dummy) XXchar *dummy; XX { XX } XX SHAR_EOF if test 16463 -ne "`wc -c script.c`" then echo shar: error transmitting script.c '(should have been 16463 characters)' fi echo shar: extracting remote.c sed 's/^XX//' << \SHAR_EOF > remote.c XX/**************************************************** XX * vt100 emulator - remote character interpretation XX * XX * v2.6 870227 DBW - bug fixes for all the stuff in v2.5 XX * v2.5 870214 DBW - more additions (see readme file) XX * v2.4 861214 DBW - lots of fixes/additions (see readme file) XX * v2.3 861101 DBW - minor bug fixes XX * v2.2 861012 DBW - more of the same XX * v2.1 860915 DBW - new features (see README) 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#include "vt100.h" XX XXstatic int p[10]; XXstatic int numpar; XXstatic char escseq[40]; XX XX/************************************************ XX* function to handle remote characters XX*************************************************/ XXvoid doremote(c) XXchar c; XX { XX if (c == 24) { inesc = 0; inctrl = 0; return; } XX if (c == 27 || (inesc >= 0 && c >= ' ')) { doesc(c); return; } XX if (inctrl >= 0 && c >= ' ') { 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 XX /* Collect intermediates */ XX if (c < '0') {escseq[inesc++] = c; return; } XX XX /* by process of elimination, we have a final character. XX Put it in the buffer, and dispatch on the first character XX 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 curmode = FS_NORMAL; p_keyapp = 0; p_curapp = 0; XX inesc = -1; XX a[0] = 0; a[1] = 0; sa[0] = 0; sa[1] = 0; XX redoutil(); XX emit(12); 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 case '=': /* set keypad application mode */ XX p_keyapp = 1; XX redoutil(); XX return; XX XX case '>': /* reset application mode */ XX p_keyapp = 0; XX redoutil(); XX return; XX XX case 'Z': XX sendchar(27); sendstring("[?1;7c"); 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 XX 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 XX /* Only allowed BEFORE parameters */ XX if (inctrl == 0) private = c; 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 most private sequences right now, XX so just punt them */ XX XX if ((private != 0 && private != '?') || badseq != 0) return; XX if (private == '?' && escseq[0] != 'h' && XX escseq[0] != 'l') 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 'L': /* ANSI insert line */ XX case 'M': /* ANSI delete line */ XX if (p[0] <= 0) p[0] = 1; XX ScrollRaster(mywindow->RPort,0L, XX (long)((escseq[0] == 'M' ? 8L : -8L) * p[0]), XX (long)MINX,(long)y-6,(long)(MAXX+7),(long)bot+1); 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;iRPort,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 (private == 0 && p[0] == 20) nlmode = 1; XX else if (private == '?') { XX if (p[0] == 7) p_wrap = 1; XX else if (p[0] == 1) p_curapp = 1; XX redoutil(); XX } XX return; XX XX case 'l': /* Reset parameter */ XX if (private == 0 && p[0] == 20) nlmode = 0; XX else if (private == '?') { XX if (p[0] == 7) p_wrap = 0; XX else if (p[0] == 1) p_curapp = 0; XX redoutil(); XX } 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;7c"); 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 'a': XX doline(0,-6,8,1); XX break; XX XX case 'j': XX case 'm': XX case 'v': doline(4,-6,4,-2); XX if (c=='j') doline(0,-2,4,-2); XX else if (c=='m') doline(4,-2,8,-2); XX else doline(0,-2,8,-2); XX break; XX XX case 'k': XX case 'l': XX case 'w': doline(4,-2,4,1); XX if (c=='k') doline(0,-2,4,-2); XX else if (c=='l') doline(4,-2,8,-2); XX else doline(0,-2,8,-2); XX break; XX XX case 'n': XX case 'q': doline(0,-2,8,-2); XX if (c=='n') doline(4,-6,4,2); XX break; XX XX case 't': XX case 'u': XX case 'x': doline(4,-6,4,1); XX if (c=='t') doline(4,-2,8,-2); XX else if (c=='u') doline(0,-2,4,-2); 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 10085 -ne "`wc -c remote.c`" then echo shar: error transmitting remote.c '(should have been 10085 characters)' fi echo shar: extracting window.c sed 's/^XX//' << \SHAR_EOF > window.c XX/**************************************************** XX * vt100 emulator - window/keyboard support XX * XX * v2.6 870227 DBW - bug fixes for all the stuff in v2.5 XX * v2.5 870214 DBW - more additions (see readme file) XX * v2.4 861214 DBW - lots of fixes/additions (see readme file) XX * v2.3 861101 DBW - minor bug fixes XX * v2.2 861012 DBW - more of the same XX * v2.1 860915 DBW - new features (see README) 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#include "vt100.h" XX XX/* keyboard definitions for toasc() */ XXstatic 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/*************************************************** XX * function to swap the use of backspace and delete XX ***************************************************/ XX XXvoid swap_bs_del() XX { XX if (p_bs_del) p_bs_del = 0; XX else p_bs_del = 1; XX XX keys[0x41] = p_bs_del ? 127 : 8; XX keys[0x46] = p_bs_del ? 8 : 127; XX } XX XX/************************************************* XX * function to get file name (via a requestor) XX *************************************************/ XXvoid req(prmpt,name,getinp) XXchar *prmpt,*name; XXint getinp; XX { XX ULONG class; XX unsigned int code, qual; XX struct IntuiMessage *Msg; XX XX /* Make sure the prompt gets updated */ XX if (numreqs == 1 && strcmp(Prompt,prmpt) != 0) { XX EndRequest(&myrequest,mywindow); XX numreqs = 0; XX } XX XX /* copy in a prompt and a default */ XX strcpy(Prompt,prmpt); XX strcpy(InpBuf,name); XX XX /* If there is a requester... reuse it */ XX if (numreqs == 1) RefreshGadgets(&mystrgad,mywindow,&myrequest); XX XX /* otherwise create it */ XX else { XX if (Request(&myrequest,mywindow) == 0) { XX emits("ERROR - CAN'T CREATE REQUESTOR FOR:\n"); XX emits(Prompt); emit('\n'); XX emits(InpBuf); emit('\n'); XX return; XX } XX else numreqs = 1; XX } XX XX /* if we don't want input, we're done */ XX if (getinp == 0 || numreqs == 0) return; XX XX /* throw away any extra messages */ XX Wait(1L << mywindow->UserPort->mp_SigBit); XX while (Msg = (struct IntuiMessage *)GetMsg(mywindow->UserPort)) XX ReplyMsg(Msg); XX XX /* here is where we pre-select the gadget */ XX if (!ActivateGadget(&mystrgad,mywindow,&myrequest)) { XX XX /* wait for his/her hands to get off the keyboard (Amiga-key) */ XX Delay(20L); XX while (Msg = (struct IntuiMessage *)GetMsg(mywindow->UserPort)) XX ReplyMsg(Msg); XX XX /* try once more before giving up... */ XX ActivateGadget(&mystrgad,mywindow,&myrequest); XX } XX XX /* wait for input to show up */ XX while (1) { XX if ((NewMessage = (struct IntuiMessage *) XX GetMsg(mywindow->UserPort)) == FALSE) { XX Wait(1L<UserPort->mp_SigBit); XX continue; XX } XX class = NewMessage->Class; XX code = NewMessage->Code; XX qual = NewMessage->Qualifier; XX ReplyMsg(NewMessage); XX XX /* the requestor got terminated... yea!! */ XX if (class == REQCLEAR) break; XX XX /* maybe this is a menu item to handle */ XX if (class == MENUPICK) handle_menupick(class,code); XX } XX XX /* all done, so return the result */ XX numreqs = 0; XX strcpy(name,InpBuf); 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 static char wrap_flag = 0; /* are we at column 80? */ 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 if (p_volume == 0) DisplayBeep(NULL); XX else { XX BeginIO(&Audio_Request); XX WaitIO(&Audio_Request); XX } XX break; XX XX default: XX if (c < ' ' || c > '~') break; XX if (p_wrap && wrap_flag && x >= MAXX) { XX x = MINX; XX y += 8; XX if (y > MAXY) { XX y = MAXY; XX ScrollRaster(mywindow->RPort,0L,8L,(long)MINX, XX (long)(MINY-6),(long)(MAXX+7),(long)(MAXY+1)); XX } XX } XX Move(mywindow->RPort,(long)x,(long)y); XX XX if (curmode&FSF_BOLD) { XX if (p_depth > 1) { XX SetAPen(mywindow->RPort,(long)(2+(1^p_screen))); XX SetSoftStyle(mywindow->RPort,(long)curmode,253L); XX } XX else SetSoftStyle(mywindow->RPort,(long)curmode,255L); XX } XX else SetSoftStyle(mywindow->RPort,(long)curmode,255L); XX XX if (curmode&FSF_REVERSE) { XX SetDrMd(mywindow->RPort,(long)(JAM2+INVERSVID)); XX Text(mywindow->RPort,&c,1L); XX SetDrMd(mywindow->RPort,(long)JAM2); XX } XX else Text(mywindow->RPort,&c,1L); XX XX if (curmode&FSF_BOLD) SetAPen(mywindow->RPort,1L); XX x += 8; XX } /* end of switch */ XX XX if (y > MAXY) { XX y = MAXY; XX x = MINX; XX ScrollRaster(mywindow->RPort,0L,8L,(long)MINX, XX (long)(MINY-6),(long)(MAXX+7),(long)(MAXY+1)); XX } XX if (x > MAXX) { XX wrap_flag = 1; XX x = MAXX; XX } XX else wrap_flag = 0; 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 XX Move(mywindow->RPort,(long)x,(long)y); XX i = x / 8; XX if (i+la >= maxcol) { XX if (p_wrap == 0) la = maxcol - i; XX else { XX lookahead[la] = 0; XX emits(lookahead); XX return; XX } XX } XX if (curmode&FSF_BOLD) { XX if (p_depth > 1) { XX SetAPen(mywindow->RPort,(long)(2+(1^p_screen))); XX SetSoftStyle(mywindow->RPort,(long)curmode,253L); XX } XX else SetSoftStyle(mywindow->RPort,(long)curmode,255L); XX } XX else SetSoftStyle(mywindow->RPort,(long)curmode,255L); XX XX if (curmode&FSF_REVERSE) { XX SetDrMd(mywindow->RPort,(long)(JAM2+INVERSVID)); XX Text(mywindow->RPort,lookahead,(long)la); XX SetDrMd(mywindow->RPort,(long)JAM2); XX } XX else Text(mywindow->RPort,lookahead,(long)la); XX if (curmode&FSF_BOLD) SetAPen(mywindow->RPort,1L); XX x += (8 * la); XX } XX XX/****************************** XX* Manipulate cursor XX******************************/ XXvoid cursorflip() 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,qual,local) XXunsigned int code,qual; XXint local; XX { XX unsigned int ctrl,shift,capsl,amiga,alt; XX char c = 0, keypad = 0; XX char *ptr; XX XX ctrl = qual & IEQUALIFIER_CONTROL; XX capsl = qual & IEQUALIFIER_CAPSLOCK; XX amiga = qual & (IEQUALIFIER_LCOMMAND | IEQUALIFIER_RCOMMAND); XX shift = qual & (IEQUALIFIER_LSHIFT | IEQUALIFIER_RSHIFT); XX alt = qual & (IEQUALIFIER_LALT | IEQUALIFIER_RALT); XX XX switch ( code ) XX { XX case 98: XX case 226: XX case 99: XX case 227: XX case 96: XX case 97: XX case 224: XX case 225: XX case 100: XX case 101: XX case 228: XX case 229: XX case 102: XX case 103: XX case 230: XX case 231: c = 0; break; /* ctrl, shift, capsl, amiga, or alt */ XX 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) ptr = p_F[code - 0x50]; XX else ptr = p_f[code - 0x50]; XX if (!script_on && *ptr == p_keyscript) XX script_start(++ptr); XX else sendstring(ptr); XX break; XX case 0x0f: c = (p_keyapp) ? 'p' : '0'; keypad = TRUE; break; XX case 0x1d: c = (p_keyapp) ? 'q' : '1'; keypad = TRUE; break; XX case 0x1e: c = (p_keyapp) ? 'r' : '2'; keypad = TRUE; break; XX case 0x1f: c = (p_keyapp) ? 's' : '3'; keypad = TRUE; break; XX case 0x2d: c = (p_keyapp) ? 't' : '4'; keypad = TRUE; break; XX case 0x2e: c = (p_keyapp) ? 'u' : '5'; keypad = TRUE; break; XX case 0x2f: c = (p_keyapp) ? 'v' : '6'; keypad = TRUE; break; XX case 0x3d: c = (p_keyapp) ? 'w' : '7'; keypad = TRUE; break; XX case 0x3e: c = (p_keyapp) ? 'x' : '8'; keypad = TRUE; break; XX case 0x3f: c = (p_keyapp) ? 'y' : '9'; keypad = TRUE; break; XX case 0x43: c = (p_keyapp) ? 'M' : 13 ; keypad = TRUE; break; XX case 0x4a: c = (p_keyapp) ? 'l' : '-'; keypad = TRUE; break; XX case 0x5f: sendstring("\033Om") ;break; XX case 0x3c: c = (p_keyapp) ? 'n' : '.'; keypad = TRUE; break; XX case 0x4c: XX case 0x4d: XX case 0x4e: XX case 0x4f: sendchar(27); /* cursor keys */ XX if (p_curapp) sendchar('O'); XX else sendchar('['); XX sendchar(code - 11); XX break; XX XX default: XX if (code < 75) c = keys[code]; XX else c = 0; XX } XX XX if (keypad) { XX if (p_keyapp) sendstring("\033O"); XX sendchar(c); XX return(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 else if (c == '6') c = 30; XX else if (c == '-' || c == '?') c = 31; XX } XX if (ctrl && (c == '@' || c == '2' || c == ' ')) { XX if (!local) sendchar(alt?128:0); XX c = 0; XX } XX else if (c != 0 && (!local)) sendchar(alt?c+128:c); XX return((int)c); XX } XX SHAR_EOF if test 10671 -ne "`wc -c window.c`" then echo shar: error transmitting window.c '(should have been 10671 characters)' fi echo shar: extracting expand.c sed 's/^XX//' << \SHAR_EOF > expand.c XX/************************************************************* XX * vt100 terminal emulator - Wild card and Directory support XX * XX * v2.6 870227 DBW - bug fixes for all the stuff in v2.5 XX * v2.5 870214 DBW - more additions (see readme file) XX * v2.4 861214 DBW - lots of fixes/additions (see readme file) XX * v2.3 861101 DBW - minor bug fixes XX * v2.2 861012 DBW - more of the same XX * v2.1 860915 DBW - new features (see README) XX * 860830 Steve Drew Added Wild card support, XX * features(expand.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 * Much of the code from this module extracted from XX * Matt Dillons Shell program. (Thanxs Matt.) XX *************************************************************/ XX XX#include "vt100.h" XX XXstruct DPTR { /* Format of directory fetch ptr */ XX struct FileLock *lock; /* lock on directory */ XX struct FileInfoBlock *fib; /* mod'd fib for entry */ XX}; XX XX/* XX * Disk directory routines XX * XX * XX * diropen() returns a struct DPTR, or NULL if the given file does not XX * exist. stat will be set to 1 if the file is a directory. If the XX * name is "", then the current directory is openned. XX * XX * dirnext() returns 1 until there are no more entries. The **name and XX * *stat are set. *stat = 1 if the file is a directory. XX * XX * dirclose() closes a directory channel. XX * XX */ XX XXstruct DPTR * XXdiropen(name, stat) XXchar *name; XXint *stat; XX{ XX struct DPTR *dp; XX int namelen, endslash = 0; XX struct FileLock *MyLock; XX XX MyLock = (struct FileLock *)( (ULONG) ((struct Process *) XX (FindTask(NULL)))->pr_CurrentDir); XX namelen = strlen(name); XX if (namelen && name[namelen - 1] == '/') { XX name[namelen - 1] = '\0'; XX endslash = 1; XX } XX *stat = 0; XX dp = (struct DPTR *)malloc(sizeof(struct DPTR)); XX if (*name == '\0') XX dp->lock = (struct FileLock *)DupLock (MyLock); XX else XX dp->lock = (struct FileLock *)Lock (name, ACCESS_READ); XX if (endslash) XX name[namelen - 1] = '/'; XX if (dp->lock == NULL) { XX free (dp); XX return (NULL); XX } XX dp->fib = (struct FileInfoBlock *) XX AllocMem((long)sizeof(struct FileInfoBlock), MEMF_PUBLIC); XX if (!Examine (dp->lock, dp->fib)) { XX dirclose (dp); XX return (NULL); XX } XX if (dp->fib->fib_DirEntryType >= 0) XX *stat = 1; XX return (dp); XX} XX XXdirnext(dp, pname, stat) XXstruct DPTR *dp; XXchar **pname; XXint *stat; XX{ XX if (dp == NULL) XX return (0); XX if (ExNext (dp->lock, dp->fib)) { XX *stat = (dp->fib->fib_DirEntryType < 0) ? 0 : 1; XX *pname = dp->fib->fib_FileName; XX return (1); XX } XX return (0); XX} XX XX XXdirclose(dp) XXstruct DPTR *dp; XX{ XX if (dp == NULL) XX return (1); XX if (dp->fib) XX FreeMem (dp->fib, (long)sizeof(*dp->fib)); XX if (dp->lock) XX UnLock (dp->lock); XX free (dp); XX return (1); XX} XX XXfree_expand(av) XXchar **av; XX{ XX char **base = av; XX XX if (av) { XX while (*av) { XX free (*av); XX ++av; XX } XX free (base); XX } XX} XX XX/* XX * EXPAND(wild_name, pac) XX * wild_name - char * (example: "df0:*.c") XX * pac - int * will be set to # of arguments. XX * XX */ XX XX XXchar ** XXexpand(base, pac) XXchar *base; XXint *pac; XX{ XX char **eav = (char **)malloc (sizeof(char *)); XX int eleft, eac; XX XX char *ptr, *name; XX char *bname, *ename, *tail; XX int stat, scr; XX struct DPTR *dp; XX XX *pac = eleft = eac = 0; XX base = strcpy(malloc(strlen(base)+1), base); XX for (ptr = base; *ptr && *ptr != '?' && *ptr != '*'; ++ptr); XX for (; ptr >= base && !(*ptr == '/' || *ptr == ':'); --ptr); XX if (ptr < base) { XX bname = strcpy (malloc(1), ""); XX } else { XX scr = ptr[1]; XX ptr[1] = '\0'; XX bname = strcpy (malloc(strlen(base)+1), base); XX ptr[1] = scr; XX } XX ename = ptr + 1; XX for (ptr = ename; *ptr && *ptr != '/'; ++ptr); XX scr = *ptr; XX *ptr = '\0'; XX tail = (scr) ? ptr + 1 : NULL; XX XX if ((dp = diropen (bname, &stat)) == NULL || stat == 0) { XX free (bname); XX free (base); XX free (eav); XX req ("Could not open directory","",0); XX return (NULL); XX } XX while (dirnext (dp, &name, &stat)) { XX if (compare_ok(ename, name)) { XX if (tail) { XX int alt_ac; XX char *search, **alt_av, **scrav; XX struct FileLock *lock; XX XX if (!stat) /* expect more dirs, but this not a dir */ XX continue; XX lock = (struct FileLock *)CurrentDir (dp->lock); XX search = malloc(strlen(name)+strlen(tail)+2); XX strcpy (search, name); XX strcat (search, "/"); XX strcat (search, tail); XX scrav = alt_av = expand (search, &alt_ac); XX CurrentDir (lock); XX if (scrav) { XX while (*scrav) { XX if (eleft < 2) { XX char **scrav = (char **) XX malloc(sizeof(char *) * (eac + 10)); XX movmem (eav, scrav, sizeof(char *) * (eac + 1)); XX free (eav); XX eav = scrav; XX eleft = 10; XX } XX eav[eac] = malloc(strlen(bname)+strlen(*scrav)+1); XX strcpy(eav[eac], bname); XX strcat(eav[eac], *scrav); XX free (*scrav); XX ++scrav; XX --eleft, ++eac; XX } XX free (alt_av); XX } XX } else { XX if (eleft < 2) { XX char **scrav = (char **) XX malloc(sizeof(char *) * (eac + 10)); XX movmem (eav, scrav, sizeof(char *) * (eac + 1)); XX free (eav); XX eav = scrav; XX eleft = 10; XX } XX eav[eac] = malloc (strlen(bname)+strlen(name)+1); XX eav[eac] = strcpy(eav[eac], bname); XX strcat(eav[eac], name); XX --eleft, ++eac; XX } XX } XX } XX dirclose (dp); XX *pac = eac; XX eav[eac] = NULL; XX free (bname); XX free (base); XX if (eac) XX return (eav); XX free (eav); XX return (NULL); XX} XX XX/* XX * Compare a wild card name with a normal name XX */ XX XX#define MAXB 8 XX XXcompare_ok(wild, name) XXchar *wild, *name; XX{ XX char *w = wild; XX char *n = name; XX char *back[MAXB][2]; XX int bi = 0; XX XX while (*n || *w) { XX switch (*w) { XX case '*': XX if (bi == MAXB) { XX req ("Too many levels of '*'","",0); XX return (0); XX } XX back[bi][0] = w; XX back[bi][1] = n; XX ++bi; XX ++w; XX continue; XXgoback: XX --bi; XX while (bi >= 0 && *back[bi][1] == '\0') XX --bi; XX if (bi < 0) XX return (0); XX w = back[bi][0] + 1; XX n = ++back[bi][1]; XX ++bi; XX continue; XX case '?': XX if (!*n) { XX if (bi) XX goto goback; XX return (0); XX } XX break; XX default: XX if (toupper(*n) != toupper(*w)) { XX if (bi) XX goto goback; XX return (0); XX } XX break; XX } XX if (*n) ++n; XX if (*w) ++w; XX } XX return (1); XX} XX XXset_dir(new) XXchar *new; XX{ XX register char *s; XX int i; XX struct FileLock *lock; XX char temp[60]; XX struct FileInfoBlock *fib; XX XX if (*new != '\000') { XX strcpy(temp, MyDir); XX s = new; XX if (*s == '/') { XX s++; XX for (i=strlen(MyDir); XX MyDir[i] != '/' && MyDir[i] != ':'; XX i--); XX MyDir[i+1] = '\0'; XX strcat(MyDir, s); XX } XX else if (exists(s, ':') == 0) { XX if (MyDir[strlen(MyDir)-1] != ':') XX strcat(MyDir, "/"); XX strcat(MyDir, s); XX } XX else XX strcpy(MyDir, s); XX XX if ((lock = (struct FileLock *)Lock(MyDir, (long)ACCESS_READ)) == 0) { XX req("Directory not found:",MyDir,0); XX strcpy(MyDir, temp); XX } XX else { XX fib = (struct FileInfoBlock *)AllocMem( XX (long)sizeof(struct FileInfoBlock), MEMF_PUBLIC); XX if (fib) { XX if (Examine(lock, fib)) { XX if (fib->fib_DirEntryType > 0) { XX CurrentDir(lock); XX if (MyDirLock != NULL) UnLock(MyDirLock); XX MyDirLock = lock; XX if (MyDir[strlen(MyDir)-1] == '/') XX MyDir[strlen(MyDir)-1] = '\000'; XX } XX else { XX req("Not a Directory:",MyDir,0); XX strcpy(MyDir,temp); XX } XX } XX FreeMem(fib, (long)sizeof(struct FileInfoBlock)); XX } XX else { XX req("Can't change directory... ","No free memory!",0); XX strcpy(MyDir,temp); XX } XX } XX } XX} XX XXexists(s,c) XXchar *s,c; XX { XX while (*s != '\000') XX if (*s++ == c) return(1); XX return(0); XX } SHAR_EOF if test 8710 -ne "`wc -c expand.c`" then echo shar: error transmitting expand.c '(should have been 8710 characters)' fi echo shar: extracting kermit.c sed 's/^XX//' << \SHAR_EOF > kermit.c XX/************************************************************* XX * vt100 terminal emulator - KERMIT protocol support XX * XX * v2.6 870227 DBW - bug fixes for all the stuff in v2.5 XX * v2.5 870214 DBW - more additions (see readme file) XX * v2.4 861214 DBW - lots of fixes/additions (see readme file) XX * v2.3 861101 DBW - minor bug fixes XX * v2.2 861012 DBW - more of the same XX * v2.1 860915 DBW - new features (see README) XX * 860901 ACS - Added eight bit quoting XX * 860830 Steve Drew Wild card support, err recovry,bugs. 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#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 MYEBQ '&' /* 8th bit prefix character */ XX#define MYPAD 0 /* Number of padding charss 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 sendabort, /* flag for aborting send file */ XX rptflg, /* are we doing repeat quoting */ XX ebqflg, /* are we doing 8th bit quoting */ XX notfirst, /* is this the first file received */ 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 ebq, /* Quote character for 8th bit quoting */ 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 sl1[] = "FILE PKT NUM RETR BYTES", XX sl2[] = "%-15s %c %4d %2d %6ld %5s", XX sl3[50], XX mainmode[10]; XX XXFILE *fp; /* file for send/receive */ XX XXchar * XXgetfname(name) /* returns ptr to start of file name from 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 amount, c, wild; XX char *p, **list = NULL; XX XX if (!strcmp(file,"$")) { saybye(); return(2); } XX p = file; XX while(*p && *p != '*' && *p != '?') p++; XX if (*p) { XX wild = TRUE; XX list = expand(file, &amount); XX if (list == NULL) req("KERMIT","No wild card match",0); XX } XX else { XX wild = FALSE; XX amount = 1; XX } XX for (c = 0; c < amount; c++) { XX if (wild == TRUE) p = list[c]; XX else p = file; XX strcpy(filnam,getfname(p)); XX ttime = TTIME_KERMIT; XX tp = retry = n = numtry = 0; totbytes = 0L; XX if ((fp = fopen(p,"r")) == NULL) { XX req("KERMIT: can't open send file:",p,0); XX continue; XX } XX strcpy(mainmode,"SEND"); XX ClearBuffer(); XX if (sendsw()) dostats(' ',"DONE"); XX fclose(fp); XX } XX free_expand(list); XX return TRUE; XX } XX XXdokreceive(file,more) XXchar *file; XXint more; XX { XX int retval; XX XX ttime = TTIME_KERMIT; XX if (!strcmp(file,"$")) { saybye(); return(2); } XX strcpy(filnam, file); XX if (server) strcpy(mainmode,"GET"); XX else strcpy(mainmode,"RECV"); XX tp = retry = n = numtry = notfirst = 0; totbytes = 0L; XX ClearBuffer(); XX retval = recsw(); XX return(retval); XX } XX XXsendsw() XX { XX char sinit(), sfile(), sdata(), seof(), sbreak(); XX sendabort = 0; 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': if (sendabort) return FALSE; XX else return TRUE; XX case 'E': dostats('E',"ERROR"); /* so print the err and abort */ XX print_host_err(ackpkt); XX return(FALSE); XX case 'A': if (timeout == USERABORT) { XX timeout = GOODREAD; XX n = (n+1)%64; XX sendabort = 1; XX dostats('A',"ABORT"); XX strcpy(msgpkt, "D"); XX state = 'Z'; XX break; XX } XX if (timeout == TIMEOUT) dostats('A',"TMOUT"); XX else { /* protocol error dectected by us */ XX dostats('A',"ERROR"); XX print_our_err(); XX } 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 = MYQUOTE; XX numtry = 0; XX retry--; XX n = (n+1)%64; XX return('F'); XX case 'E': return('E'); 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('E'); XX case FALSE: if (timeout == USERABORT) state = 'A'; XX return(state); XX default: XX 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('E'); XX case FALSE: if (timeout == USERABORT) state = 'A'; XX return(state); XX default: XX 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) {*/ /* tell host to discard file */ XX/* timeout = GOODREAD; */ XX/* spack('Z',n,1,"D"); */ XX/* } */ XX/* else */ XX spack('Z',n,sendabort,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('E'); XX case FALSE: return(state); XX default: XX 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('E'); 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 dostats(' ',"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*/ XX XX XXrecsw() XX { XX char rinit(), rfile(), rdata(); XX XX state = 'R'; XX XX while(TRUE) { XX switch(state) { XX case 'R': state = rinit(); break; XX case 'Z': XX case 'F': state = rfile(); break; XX case 'D': state = rdata(); break; XX case 'C': return(TRUE); XX case 'E': XX case 'A': /* 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 if (timeout == USERABORT){ XX /* send an error packet back */ XX dostats('A',"ABORT"); XX spack('E',n,12,"User aborted"); XX } XX else if (timeout == TIMEOUT) { XX /* we timed out waiting */ XX /* will we need to spack here ?*/ XX dostats('A',"TMOUT"); XX } XX /* must be 'E' from host or we XX detected a protocol error */ XX else dostats('A',"ERROR"); XX XX if (state == 'E') print_host_err(msgpkt); XX XX else if (timeout == GOODREAD) /* tell host why */ XX print_our_err(); XX /* will this kill all files ?*/ XX do { XX ttime = 2; XX readchar(); XX } while (timeout == GOODREAD); XX fclose(fp); XX sendstring("\r"); XX return(FALSE); XX default: return(FALSE); XX } XX } 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('E'); 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 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 return(state); XX } XX else return('A'); XX case 'F': XX if (num != n) return('A'); XX strcpy(filnam,msgpkt); XX if (p_convert) { XX char *p; XX p = &filnam[0]; XX while (*p) { *p = tolower(*p); p++; } XX } XX if (notfirst) { XX totbytes = 0L; XX dostats('F',"RECV"); XX } XX /* is the first file so emit actual file name from host */ XX else { XX notfirst++; XX } XX if ((fp = fopen(filnam,"w")) == NULL) { XX req("KERMIT: Unable to create file:",filnam,0); XX strcpy(msgpkt,"VT100 - Kermit - cannot create file: "); XX strcat(msgpkt,filnam); XX spack('E',n,strlen(msgpkt),msgpkt); /* let host know */ XX dostats('E',"ERROR"); XX return ('\0'); /* abort everything */ XX } XX spack('Y',n,0,0); XX oldtry = numtry; XX numtry = 0; XX retry--; XX n = (n+1)%64; XX return('D'); XX XX /* totaly done server sending no more */ 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('E'); 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 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 'Z': XX if (num != n) return('A'); XX spack('Y',n,0,0); XX n = (n+1)%64; XX retry--; XX dostats('Z',"DONE"); XX fclose(fp); XX return('Z'); 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 return(state); XX } XX case 'E': XX return('E'); 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 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,mainmode); XX bufp = buffer; XX ClearBuffer(); 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,mainmode); 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 XX if (ebqflg && b8) { /* Do 8th bit prefix if necessary. */ XX msgpkt[size++] = ebq; XX a = a7; XX } XX 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 XX if ((ebqflg) && (a7 == ebq)) /* Prefix the 8th bit prefix */ XX msgpkt[size++] = quote; /* if doing 8th-bit prefixes */ XX XX msgpkt[size++] = a; XX msgpkt[size] = '\0'; XX } XX XXvoid decode() XX { XX USHORT a, a7, b8; 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 b8 = 0; XX if (ebqflg) { /* 8th-bit prefixing? */ XX if (a == ebq) { /* Yes, got an 8th-bit prefix? */ XX b8 = 0200; /* Yes, remember this, */ XX a = *buf++; /* and get the prefixed character. */ 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 a |= b8; 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_KERMIT); XX data[2] = tochar(MYPAD); XX data[3] = ctl(MYPCHAR); XX data[4] = tochar(MYEOL); XX data[5] = MYQUOTE; XX if ((p_parity > 0) || ebqflg) { /* 8-bit quoting... */ XX data[6] = MYEBQ; /* If parity or flag on, send &. */ XX if ((ebq > 0040 && ebq < 0100) || /* If flag off, then turn it on */ XX (ebq > 0140 && ebq < 0177) || /* if other side has asked us to */ XX (ebq == 'Y')) ebqflg = 1; XX } XX else /* Normally, */ XX data[6] = 'Y'; /* just say we're willing. */ 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 ttime = 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 ebqflg = 0; XX if (data[6] == 0) return; XX ebq = data[6]; XX if ((ebq > 040 && ebq < 0100) || XX (ebq > 0140 && ebq < 0177)) ebqflg = 1; XX else if (((p_parity > 0) || ebqflg) && (ebq == 'Y')) { XX ebqflg = 1; XX ebq = '&'; XX } XX else ebqflg = 0; XX if (data[7] == 0) return; XX if (data[8] == 0) return; XX rptq = data[8]; XX rptflg = ((rptq > 040 && rptq < 0100) || XX (rptq > 0140 && rptq < 0177)); XX } XX XXsaybye() XX { XX int len,num; XX spack('G',n,1,"F"); /* shut down server no more files */ XX rpack(&len,&num,ackpkt); XX } XX XXprint_our_err() XX { XX if (retry > MAXTRY || oldtry > MAXTRY) { XX req("KERMIT:","Too may retries for packet",0); XX strcpy(msgpkt,"VT100 KERMIT: Too many retries for packet"); XX } XX else { XX req("KERMIT:","Protocol Error",0); XX strcpy(msgpkt,"VT100 KERMIT: Protocol Error"); XX } XX spack('E',n,strlen(msgpkt)); XX } XX XXprint_host_err(msg) XX char *msg; XX { XX req("KERMIT Host Error:",msg,0); XX } XX XXdostats(type,stat) XXchar type,*stat; XX { XX if (type == 'Y' || type == 'N' || type == 'G') return; XX sprintf(sl3,sl2,filnam,type,n+(tp*64),retry-1,(long)totbytes,stat); XX if (n==63) tp++; XX req(sl1,sl3,0); XX } XX XXClearBuffer() XX { XX AbortIO(Read_Request); XX Read_Request->IOSer.io_Command = CMD_CLEAR; XX DoIO(Read_Request); XX Read_Request->IOSer.io_Command = CMD_READ; XX SendIO(Read_Request); XX } XX SHAR_EOF if test 22019 -ne "`wc -c kermit.c`" then echo shar: error transmitting kermit.c '(should have been 22019 characters)' fi echo shar: extracting xmodem.c sed 's/^XX//' << \SHAR_EOF > xmodem.c XX/************************************************************* XX * vt100 terminal emulator - XMODEM protocol support XX * XX * v2.6 870227 DBW - bug fixes for all the stuff in v2.5 XX * v2.5 870214 DBW - more additions (see readme file) XX * v2.4 861214 DBW - lots of fixes/additions (see readme file) XX * v2.3 861101 DBW - minor bug fixes XX * v2.2 861012 DBW - more of the same XX * v2.1 860915 DBW - new features (see README) XX * 860901 ACS - Added Parity and Word Length and support code 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#include "vt100.h" XX XXint enablexon = TRUE; XX XXstatic unsigned long parity_settings[4] = { XX 0x96696996, XX 0x69969669, XX 0x69969669, XX 0x96696996 }; 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 int doxon,i,j,k; XX XX doxon = enablexon; XX if (doxon) No_XON(); XX switch (p_parity) { XX case 0: /* no parity */ XX rs_out[0] = ch & 0xFF; XX break; XX XX case 1: /* mark */ XX rs_out[0] = (ch & 0x7F) | 0x80; XX break; XX XX case 2: /* space */ XX rs_out[0] = ch & 0x7F; XX break; XX XX case 3: /* even */ XX case 4: /* odd */ XX i = (ch >> 5) & 0x3; XX j = ch & 0x1F; XX k = ((parity_settings[i] >> j) & 0x1) << 7; XX if (p_parity == 3) /* even parity */ XX rs_out[0] = (ch & 0x7F) | k; XX else /* odd parity */ XX rs_out[0] = (ch & 0x7F) | (k ^ 0x80); XX } XX DoIO(Write_Request); XX if (doxon) Do_XON(); XX } XX XX/* send a break to the host */ XXvoid sendbreak() { XX AbortIO(Read_Request); XX Read_Request->IOSer.io_Command = SDCMD_BREAK; XX DoIO(Read_Request); XX Read_Request->IOSer.io_Command = CMD_READ; XX SendIO(Read_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 SendIO(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 req("ERROR:","User aborted transfer",0); XX timeout = USERABORT; XX return('\0'); XX } XX continue; XX } XX if (rd == FALSE && CheckIO(&Timer)) { XX req("ERROR","Timeout waiting for character",0); 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 & (p_parity == 0 ? 0xFF : 0x7F)); XX } XX XXvoid No_XON() { XX XX /* turn off XON/XOFF processing */ XX enablexon = FALSE; XX Write_Request->io_SerFlags |= SERF_XDISABLED; XX Write_Request->IOSer.io_Command = SDCMD_SETPARAMS; XX DoIO(Write_Request); XX Write_Request->IOSer.io_Command = CMD_WRITE; XX } XX XXvoid Do_XON() { XX /* turn on XON/XOFF processing */ XX enablexon = TRUE; XX Write_Request->io_SerFlags &= ~SERF_XDISABLED; XX Write_Request->IOSer.io_Command = SDCMD_SETPARAMS; XX DoIO(Write_Request); XX Write_Request->IOSer.io_Command = CMD_WRITE; 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 scrstr[40],scrstr2[40]; XX bytes_xferred = 0L; XX ttime = TTIME_SHORT; XX XX if ((fd = creat(file, 0)) < 0) XX { XX req("XMODEM Can't Open File:",file,0); XX return FALSE; XX } XX else XX strcpy(scrstr,"XMODEM Receive, to abort"); XX req(scrstr,"",0); XX XX sectnum = errors = bufptr = 0; XX sendchar(NAK); XX firstchar = 0; XX No_XON(); 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 Do_XON(); XX return FALSE; XX } XX } while (firstchar != SOH && firstchar != EOT); XX XX if (firstchar == SOH) XX { XX sprintf(scrstr2,"Getting Block %4d...",sectnum); XX req(scrstr,scrstr2,0); XX sectcurr = readchar(); XX if (timeout != GOODREAD) { Do_XON(); return FALSE; } XX sectcomp = readchar(); XX if (timeout != GOODREAD) { Do_XON(); 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) { Do_XON(); return FALSE; } XX checksum = (checksum + bufr[j]) & 0xff; XX } XX if (checksum == readchar() && timeout == GOODREAD) XX { XX errors = 0; XX sprintf(scrstr2,"Block %4d verified",sectnum); XX sectnum++; XX bufptr += SECSIZ; XX bytes_xferred += SECSIZ; XX req(scrstr,scrstr2,0); XX if (bufptr == BufSize) XX { XX if (write(fd, bufr, BufSize-128) == EOF) XX { XX req(scrstr,"Error Writing File",0); XX Do_XON(); 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) { Do_XON(); 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) { XX Do_XON(); XX return FALSE; XX } XX req(scrstr,"Received Duplicate Sector",0); XX sendchar(ACK); XX } XX else errorflag = TRUE; XX } XX } XX else errorflag = TRUE; XX } XX if (errorflag == TRUE) XX { XX errors++; XX req(scrstr,"Error",0); 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 Do_XON(); XX return TRUE; XX } XX Do_XON(); 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 scrstr[40],scrstr2[40]; XX bytes_xferred = 0; XX ttime = TTIME_LONG; XX XX if ((fd = open(file, 0)) < 0) { XX req("XMODEM","Cannot Open Send File",0); XX return FALSE; XX } XX else XX strcpy(scrstr,"XMODEM Send, to abort"); XX req(scrstr,"",0); XX attempts = 0; XX sectnum = 1; XX No_XON(); XX /* wait for sync char */ XX j=1; XX while (((c = readchar()) != NAK) && (j++ < ERRORMAX)) XX if (timeout == USERABORT) { Do_XON(); return(FALSE); } XX if (j >= (ERRORMAX)) XX { XX req(scrstr,"Receiver not sending NAKs",0); XX Do_XON(); XX return FALSE; XX } XX XX while ((bytes_to_send = read(fd, bufr, BufSize)) && XX attempts != RETRYMAX) XX { XX if (bytes_to_send == EOF) XX { XX req(scrstr,"Error Reading File",0); XX Do_XON(); XX return FALSE; XX } XX XX bufptr = 0; XX while (bytes_to_send > 0 && attempts != RETRYMAX) XX { XX attempts = 0; XX sprintf(scrstr2,"Sending block %4d",sectnum); XX do { XX req(scrstr,scrstr2,0); 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) { XX req(scrstr,"ABORTED",0); XX Do_XON(); XX return FALSE; XX } XX } while ((c != ACK) && (attempts != RETRYMAX)); XX bufptr += size; XX bytes_xferred += size; XX sprintf(scrstr2,"Sent block %4d",sectnum); XX req(scrstr,scrstr2,0); XX sectnum++; XX } XX } XX close(fd); XX if (attempts == RETRYMAX) XX { XX req(scrstr,"No Acknowledgment, ABORTING",0); XX Do_XON(); 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 req(scrstr,"NO END OF FILE",0); XX } XX Do_XON(); XX return TRUE; XX } XX XX/* allow for multi file xfers separated by commas under XX kermit and XMODEM */ XX XXvoid multi_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 if (name[0] == '$' && name[1] == '\0') { XX saybye(); XX return; XX } XX p = name; XX while(*p == ' ') p++; XX while(*p && *p != ',' && *p != ' ') p++; XX if (*p == '\0') done = TRUE; XX else multi = 1; XX *p = '\0'; XX XX status = ((*mode)(name, multi)); XX if (status == FALSE) close(fd); XX if (!done && timeout != USERABORT) multi_xfer(++p, mode, do_send); XX else emit('\n'); XX server = 0; XX multi = 0; XX } XX SHAR_EOF if test 9859 -ne "`wc -c xmodem.c`" then echo shar: error transmitting xmodem.c '(should have been 9859 characters)' fi # End of shell archive exit 0