Path: utzoo!utgpu!water!watmath!clyde!att-cb!ihnp4!inuxc!iuvax!pur-ee!j.cc.purdue.edu!ahh From: ahh@j.cc.purdue.edu (Brent L. Woods) Newsgroups: comp.sources.amiga Subject: vt100 version 2.8 Message-ID: <6494@j.cc.purdue.edu> Date: 25 Feb 88 10:35:45 GMT Organization: Co-Moderators Unlimited. Lines: 2110 Approved: ahh@j.cc.purdue.edu (Brent Woods) Program Name: vt100 (version 2.8) Submitted By: acs@uts.amdahl.com (Tony Sumrall) Summary: vt100 terminal emulator. Poster Boy: Brent Woods (ahh@j.cc.purdue.edu) Tested. Part 2 of 4 NOTES: This program was tested by our Guest Moderator, Robert Tillotson. He had a couple of problems with the program at first (a couple of Guru errors, and we think that the vt100 task hung around instead of exiting properly; not certain, though), but when we (Rob, Pat, and I) tested it a few hours ago, none of us had any problems. I dunno. It seems to work okay now. Probably some fluke or other. Brent Woods, Co-Moderator, comp.{sources,binaries}.amiga USENET: ...!j.cc.purdue.edu!ahh ARPANET: ahh@j.cc.purdue.edu BITNET: PODUM@PURCCVM PHONE: +1 (317) 743-8421 USNAIL: 320 Brown St., #406 / West Lafayette, IN 47906 ================================================================ #! /bin/sh # # This is a shell archive. Save this into a file, edit it # and delete all lines above this comment. Then give this # file to sh by executing the command "sh file". The files # will be extracted into the current directory owned by # you with default permissions. # # The files contained herein are: # # -rw-r--r-- 1 acs other 7980 Feb 1 18:53 expand.c # -rw-r--r-- 1 acs other 19521 Feb 1 18:53 init.c # -rw-r--r-- 1 acs other 25220 Feb 1 18:54 kermit.c # echo 'x - expand.c' if test -f expand.c; then echo 'shar: not overwriting expand.c'; else sed 's/^X//' << '________This_Is_The_END________' > expand.c X/************************************************************* X * vt100 terminal emulator - Wild card and Directory support X * X * v2.8 880117 ACS - See the README file X * v2.7 870825 ACS - Use the *InfoMsg*() routines in window.c rather X * than req(). X * v2.6 870227 DBW - bug fixes for all the stuff in v2.5 X * v2.5 870214 DBW - more additions (see readme file) X * v2.4 861214 DBW - lots of fixes/additions (see readme file) X * v2.3 861101 DBW - minor bug fixes X * v2.2 861012 DBW - more of the same X * v2.1 860915 DBW - new features (see README) X * 860830 Steve Drew Added Wild card support, X * features(expand.c) X * v2.0 860809 DBW - Major rewrite X * v1.1 860720 DBW - Switches, 80 cols, colors, bug fixes X * v1.0 860712 DBW - First version released X * X * Much of the code from this module extracted from X * Matt Dillons Shell program. (Thanxs Matt.) X *************************************************************/ X X#include "vt100.h" X Xstruct DPTR { /* Format of directory fetch ptr */ X struct FileLock *lock; /* lock on directory */ X struct FileInfoBlock *fib; /* mod'd fib for entry */ X}; X X/* X * Disk directory routines X * X * X * diropen() returns a struct DPTR, or NULL if the given file does not X * exist. stat will be set to 1 if the file is a directory. If the X * name is "", then the current directory is openned. X * X * dirnext() returns 1 until there are no more entries. The **name and X * *stat are set. *stat = 1 if the file is a directory. X * X * dirclose() closes a directory channel. X * X */ X Xstruct DPTR * Xdiropen(name, stat) Xchar *name; Xint *stat; X{ X struct DPTR *dp; X int namelen, endslash = 0; X struct FileLock *MyLock; X X MyLock = (struct FileLock *)( (ULONG) ((struct Process *) X (FindTask(NULL)))->pr_CurrentDir); X namelen = strlen(name); X if (namelen && name[namelen - 1] == '/') { X name[namelen - 1] = '\0'; X endslash = 1; X } X *stat = 0; X dp = (struct DPTR *)malloc(sizeof(struct DPTR)); X if (*name == '\0') X dp->lock = (struct FileLock *)DupLock (MyLock); X else X dp->lock = (struct FileLock *)Lock (name, ACCESS_READ); X if (endslash) X name[namelen - 1] = '/'; X if (dp->lock == NULL) { X free (dp); X return (NULL); X } X dp->fib = (struct FileInfoBlock *) X AllocMem((long)sizeof(struct FileInfoBlock), MEMF_PUBLIC); X if (!Examine (dp->lock, dp->fib)) { X dirclose (dp); X return (NULL); X } X if (dp->fib->fib_DirEntryType >= 0) X *stat = 1; X return (dp); X} X Xdirnext(dp, pname, stat) Xstruct DPTR *dp; Xchar **pname; Xint *stat; X{ X if (dp == NULL) X return (0); X if (ExNext (dp->lock, dp->fib)) { X *stat = (dp->fib->fib_DirEntryType < 0) ? 0 : 1; X *pname = dp->fib->fib_FileName; X return (1); X } X return (0); X} X X Xdirclose(dp) Xstruct DPTR *dp; X{ X if (dp == NULL) X return (1); X if (dp->fib) X FreeMem (dp->fib, (long)sizeof(*dp->fib)); X if (dp->lock) X UnLock (dp->lock); X free (dp); X return (1); X} X Xfree_expand(av) Xchar **av; X{ X char **base = av; X X if (av) { X while (*av) { X free (*av); X ++av; X } X free (base); X } X} X X/* X * EXPAND(wild_name, pac) X * wild_name - char * (example: "df0:*.c") X * pac - int * will be set to # of arguments. X * X */ X X Xchar ** Xexpand(base, pac) Xchar *base; Xint *pac; X{ X char **eav = (char **)malloc (sizeof(char *)); X int eleft, eac; X X char *ptr, *name; X char *bname, *ename, *tail; X int stat, scr; X struct DPTR *dp; X X *pac = eleft = eac = 0; X base = strcpy(malloc(strlen(base)+1), base); X for (ptr = base; *ptr && *ptr != '?' && *ptr != '*'; ++ptr); X for (; ptr >= base && !(*ptr == '/' || *ptr == ':'); --ptr); X if (ptr < base) { X bname = strcpy (malloc(1), ""); X } else { X scr = ptr[1]; X ptr[1] = '\0'; X bname = strcpy (malloc(strlen(base)+1), base); X ptr[1] = scr; X } X ename = ptr + 1; X for (ptr = ename; *ptr && *ptr != '/'; ++ptr); X scr = *ptr; X *ptr = '\0'; X tail = (scr) ? ptr + 1 : NULL; X X if ((dp = diropen (bname, &stat)) == NULL || stat == 0) { X free (bname); X free (base); X free (eav); X InfoMsg1Line("Could not open directory"); X return (NULL); X } X while (dirnext (dp, &name, &stat)) { X if (compare_ok(ename, name)) { X if (tail) { X int alt_ac; X char *search, **alt_av, **scrav; X struct FileLock *lock; X X if (!stat) /* expect more dirs, but this not a dir */ X continue; X lock = (struct FileLock *)CurrentDir (dp->lock); X search = malloc(strlen(name)+strlen(tail)+2); X strcpy (search, name); X strcat (search, "/"); X strcat (search, tail); X scrav = alt_av = expand (search, &alt_ac); X CurrentDir (lock); X if (scrav) { X while (*scrav) { X if (eleft < 2) { X char **scrav = (char **) X malloc(sizeof(char *) * (eac + 10)); X movmem (eav, scrav, sizeof(char *) * (eac + 1)); X free (eav); X eav = scrav; X eleft = 10; X } X eav[eac] = malloc(strlen(bname)+strlen(*scrav)+1); X strcpy(eav[eac], bname); X strcat(eav[eac], *scrav); X free (*scrav); X ++scrav; X --eleft, ++eac; X } X free (alt_av); X } X } else { X if (eleft < 2) { X char **scrav = (char **) X malloc(sizeof(char *) * (eac + 10)); X movmem (eav, scrav, sizeof(char *) * (eac + 1)); X free (eav); X eav = scrav; X eleft = 10; X } X eav[eac] = malloc (strlen(bname)+strlen(name)+1); X eav[eac] = strcpy(eav[eac], bname); X strcat(eav[eac], name); X --eleft, ++eac; X } X } X } X dirclose (dp); X *pac = eac; X eav[eac] = NULL; X free (bname); X free (base); X if (eac) X return (eav); X free (eav); X return (NULL); X} X X/* X * Compare a wild card name with a normal name X */ X X#define MAXB 8 X Xcompare_ok(wild, name) Xchar *wild, *name; X{ X char *w = wild; X char *n = name; X char *back[MAXB][2]; X int bi = 0; X X while (*n || *w) { X switch (*w) { X case '*': X if (bi == MAXB) { X InfoMsg1Line("Too many levels of '*'"); X return (0); X } X back[bi][0] = w; X back[bi][1] = n; X ++bi; X ++w; X continue; Xgoback: X --bi; X while (bi >= 0 && *back[bi][1] == '\0') X --bi; X if (bi < 0) X return (0); X w = back[bi][0] + 1; X n = ++back[bi][1]; X ++bi; X continue; X case '?': X if (!*n) { X if (bi) X goto goback; X return (0); X } X break; X default: X if (toupper(*n) != toupper(*w)) { X if (bi) X goto goback; X return (0); X } X break; X } X if (*n) ++n; X if (*w) ++w; X } X return (1); X} X Xset_dir(new) Xchar *new; X{ X register char *s; X int i; X struct FileLock *lock; X char temp[60]; X struct FileInfoBlock *fib; X X if (*new != '\000') { X strcpy(temp, MyDir); X s = new; X if (*s == '/') { X s++; X for (i=strlen(MyDir); X MyDir[i] != '/' && MyDir[i] != ':'; X i--); X MyDir[i+1] = '\0'; X strcat(MyDir, s); X } X else if (exists(s, ':') == 0) { X if (MyDir[strlen(MyDir)-1] != ':') X strcat(MyDir, "/"); X strcat(MyDir, s); X } X else X strcpy(MyDir, s); X X if ((lock = (struct FileLock *)Lock(MyDir, (long)ACCESS_READ)) == 0) { X InfoMsg2Line("Directory not found:",MyDir); X strcpy(MyDir, temp); X } X else { X fib = (struct FileInfoBlock *)AllocMem( X (long)sizeof(struct FileInfoBlock), MEMF_PUBLIC); X if (fib) { X if (Examine(lock, fib)) { X if (fib->fib_DirEntryType > 0) { X UnLock(CurrentDir(lock)); X if (MyDir[strlen(MyDir)-1] == '/') X MyDir[strlen(MyDir)-1] = '\000'; X } X else { X InfoMsg2Line("Not a Directory:",MyDir); X strcpy(MyDir,temp); X } X } X FreeMem(fib, (long)sizeof(struct FileInfoBlock)); X } X else { X InfoMsg1Line("Can't change directory...No free memory!"); X strcpy(MyDir,temp); X } X } X } X} X Xexists(s,c) Xchar *s,c; X { X while (*s != '\000') X if (*s++ == c) return(1); X return(0); X } ________This_Is_The_END________ if test `wc -l < expand.c` -ne 355; then echo 'shar: expand.c was damaged during transit (should have been 355 bytes)' fi fi ; : end of overwriting check echo 'x - init.c' if test -f init.c; then echo 'shar: not overwriting init.c'; else sed 's/^X//' << '________This_Is_The_END________' > init.c X/*************************************************************** X * vt100 - terminal emulator - initialization X * X * v2.8 880117 ACS - See the README file X * v2.7 870825 ACS - Allow execution of all script files specified on X * command line (companion to changes in script.c). X * Rolled menu init into one routine (do_menu_init()). X * v2.6 870227 DBW - bug fixes for all the stuff in v2.5 X * v2.5 870214 DBW - more additions (see readme file) X * v2.4 861214 DBW - lots of fixes/additions (see readme file) X * v2.3 861101 DBW - minor bug fixes X * v2.2 861012 DBW - more of the same X * v2.1 860915 DBW - new features (see README) X * 860901 ACS - Added Parity and Word Length and support code X * 860823 DBW - Integrated and rewrote lots of code X * v2.0 860809 DBW - Major rewrite X * v1.1 860720 DBW - Switches, 80 cols, colors, bug fixes X * v1.0 860712 DBW - First version released X * X ***************************************************************/ X X#include "vt100.h" X Xstruct Device *ConsoleDevice = NULL; Xstruct IOStdReq ConReq; Xextern APTR OrigWindowPtr; Xextern int capture; /* in vt100.c */ X X/* Used by script.c for script file chaining. */ Xint script_files_todo = 0; Xchar **script_files = NULL; X Xchar line[256]; X X/* Command key equivalences per menu. Manipulated by script.c */ X X/* Equivalences for the File menu... */ Xstruct filecmd { X char mo; /* Mode */ X char se; /* Send */ X char re; /* Receive */ X char kg; /* Kermit Get */ X char kb; /* Kermit Bye */ X char ca; /* Capture or Capturing */ X char nl; X} filecmd_chars = { ' ', '^', 'V', 'G', 'B', ' ', '\0' }; X X/* Equivalences for Mode sub-menu... */ Xstruct mode_cmd { X char as; /* ascii mode */ X char xm; /* xmodem mode */ X char xmc; /* xmodemcrc mode */ X char ke; /* kermit mode */ X char nl; X} modecmd_chars = { ' ', 'X', ' ', 'K', '\0' }; X X/* Equivalences for the Baud Rate sub-menu... */ Xstruct baudcmd { X char b03; /* 0300 */ X char b12; /* 1200 */ X char b24; /* 2400 */ X char b48; /* 4800 */ X char b96; /* 9600 */ X char bnl; X} baudcmd_chars = { ' ', 'L', 'H', ' ', ' ', '\0' }; X X/* Equivalences for the Parity sub-menu... */ Xstruct parcmd { X char no; /* NOne */ X char ma; /* MArk */ X char sp; /* SPace */ X char ev; /* EVen */ X char od; /* ODd */ X char nl; X} parcmd_chars = { 'N', ' ', ' ', 'E', 'O', '\0' }; X X/* Equivalences for the Xfer Mode sub-menu... */ Xstruct modcmd { X char im; /* IMage */ X char tx; /* TeXt */ X char cn; /* CoNvert */ X char nl; X} modcmd_chars = { 'I', 'T', ' ', '\0' }; X X/* Equivalences for the Script menu... */ Xstruct scrcmd { X char em; /* Execute Macro */ X char ab; /* Abort Macro */ X char nl; X} scrcmd_chars = { 'M', 'A', '\0' }; X X/* Equivalences for the Utility menu... */ Xstruct utilcmd { X char sb; /* Send Break */ X char hu; /* Hang Up */ X char cd; /* Change Dir */ X char cs; /* Clear Screen */ X char ec; /* ECho */ X char wr; /* WRap */ X char nk; /* Num Key */ X char ac; /* App Cur */ X char bs; /* BS<->DEL */ X char xb; /* Xfer beep */ X char nl; X} utilcmd_chars = { '.', ' ', 'D', ' ', ' ', 'W', 'K', 'C', ' ', ' ', '\0' }; X Xextern char myfontname[]; X Xstatic char *filetext[] = { X "Protocol", X "Send", X "Receive", X "Kermit Get", X "Kermit BYE", X "Capture" X}; X Xstatic char *modetext[] = { X " Ascii", X " Xmodem", X " XmodemCRC", X " Kermit" X}; X Xstatic char *commtext[] = { X "Baud Rate", X "Parity ", X "Xfer Mode" X}; X Xstatic char *baudtext[] = { X " 300", X " 1200", X " 2400", X " 4800", X " 9600" X}; X Xstatic char *partext[] = { X " None ", X " Mark ", X " Space", X " Even ", X " Odd " X}; X Xstatic char *modtext[] = { X " Image ", X " Text ", X " Convert" X}; X Xstatic char *scrtext[] = { X "Execute Macro", X "Abort Execution" X}; X Xstatic char *utiltext[] = { X "Send Break", X "Hang Up", X "Change Dir", X "Clear Scrn", X " Echo", X " Wrap", X " Num Key", X " App Cur", X " BS<->DEL", X " Xfer Beep" X}; X Xstruct HowToInit { X int LeftEdge; X int Width; X ULONG Flags; X char **text; X char *cmdkeys; X}; X Xstatic struct HowToInit menu_init[] = { X { 0, 120+40, ITEMTEXT | ITEMENABLED | HIGHCOMP, X filetext, (char *)(&filecmd_chars) }, X {75, 92+40, ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT, X modetext, (char *)(&modecmd_chars) }, X { 0, 88, ITEMTEXT | ITEMENABLED | HIGHCOMP, X commtext, NULL }, X { 75, 56+40, ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT, X baudtext, (char *)(&baudcmd_chars) }, X { 75, 56+40, ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT, X partext, (char *)(&parcmd_chars) }, X { 75, 80+40, ITEMTEXT | ITEMENABLED | HIGHCOMP | CHECKIT, X modtext, (char *)(&modcmd_chars) }, X { 0, 160, ITEMTEXT | ITEMENABLED | HIGHCOMP, X scrtext, (char *)(&scrcmd_chars) }, X { 0, 88+40, ITEMTEXT | ITEMENABLED | HIGHCOMP, X utiltext, (char *)(&utilcmd_chars) } X}; X X#define FILE_INIT_ENTRY (&(menu_init[0])) X#define MODE_INIT_ENTRY (&(menu_init[1])) X#define COMM_INIT_ENTRY (&(menu_init[2])) X#define RS_INIT_ENTRY (&(menu_init[3])) X#define PAR_INIT_ENTRY (&(menu_init[4])) X#define XF_INIT_ENTRY (&(menu_init[5])) X#define SCRIPT_INIT_ENTRY (&(menu_init[6])) X#define UTIL_INIT_ENTRY (&(menu_init[7])) X Xvoid do_menu_init(); X Xchar *InitDefaults(argc,argv) Xint argc; Xchar **argv; X { X FILE *fd = NULL; X char *p, *t, *ifile; X int l, dont_init = 0; X X doing_init = 1; /* make sure we only allow INIT script commands */ X if (argc > 1) { X int start_of_script_files = 1; X X if(strcmp(argv[1], "-i") == 0) { /* No init file */ X dont_init = 1; X start_of_script_files = 2; X } X else if(strcmp(argv[1], "+i") == 0) { /* Use specified init file */ X start_of_script_files = 3; X if((fd=fopen(argv[2],"r")) == NULL) { X ifile = AllocMem((LONG)(strlen(argv[2])+3), MEMF_PUBLIC|MEMF_CLEAR); X strcpy(ifile, "S:"); X strcat(ifile, argv[2]); X fd = fopen(ifile, "r"); X FreeMem(ifile, (LONG)(strlen(argv[2])+3)); X ifile = NULL; X } X } X if(start_of_script_files > argc) X script_files_todo = 0; X else X script_files_todo = argc - start_of_script_files; /* # of cmdline script files left */ X script_files = &(argv[start_of_script_files]); /* Ptr to first of 'em */ X } X X if((p_font == NULL) || (p_font[0] == '\0')) X strcpy(myfontname, "topaz"); X else X strcpy(myfontname, p_font); /* Init font name */ X strcat(myfontname, ".font"); X X if(!dont_init) X if((fd == NULL) && ((fd=fopen("vt100.init","r")) == NULL)) X fd=fopen("s:vt100.init","r"); X X if(fd != NULL) { X while (fgets(line,256,fd) != 0) { X line[strlen(line)-1] = '\000'; X p = next_wrd(&line[0],&l); X if (*p) { X *p |= ' '; X if (p[1]) p[1] |= ' '; X if (*p == '#') continue; X if (*p == 'e' && p[1] == 'x') break; X exe_cmd(p,l); X } X } X fclose(fd); X } X doing_init = 0; X X IntuitionBase = (struct IntuitionBase *) X OpenLibrary("intuition.library", INTUITION_REV); X if( IntuitionBase == NULL ) X cleanup("can't open intuition",1); X X GfxBase = (struct GfxBase *) X OpenLibrary("graphics.library",GRAPHICS_REV); X if( GfxBase == NULL ) X cleanup("can't open graphics library",2); X X /* Now set up all the screen info as necessary */ X if(p_lines == 0) /* Wants to use everything available */ X if(p_interlace) X p_lines = ((GfxBase->NormalDisplayRows*2) - 6) / 8; X else X p_lines = ((GfxBase->NormalDisplayRows - 6) / 8); X X if (p_interlace == 0) { X if (p_lines > 24) p_lines = 24; X MINY = 14; X NewWindow.Height = (long)((p_lines*8)+8); X } X else { X if (p_lines > 48) p_lines = 48; X MINY = 16; X NewScreen.ViewModes |= LACE; X NewWindow.Height = (long)((p_lines*8)+10); X } X NewWindow.MinHeight = NewWindow.Height; X NewWindow.MaxHeight = NewWindow.Height; X NewWindow.TopEdge = 0L; X MAXY = ((p_lines-1)*8) + MINY; X top = MINY; X bot = MAXY; X savx = MINX; X savy = MINY; X if (p_screen == 1) { X if (p_depth > 2) p_depth = 2; X if (p_depth < 1) p_depth = 1; X NewScreen.Depth = (long)p_depth; X X NewScreen.Height = (long)((p_lines*8)+16); X X if (p_interlace == 1) X NewScreen.TopEdge = (long)(400 - NewScreen.Height); X else X NewScreen.TopEdge = (long)(208 - NewScreen.Height); X } X else { X p_depth = 2L; X NewWindow.TopEdge = 0L; X NewWindow.Screen = NULL; X NewReqWindow.Screen = NULL; X NewWindow.Type = WBENCHSCREEN; X NewReqWindow.Type = WBENCHSCREEN; X } X X /* see if we exit with a startup script */ X if (*p == 'e') { X p = next_wrd(p+l+1,&l); X if (*p) return(p); X } X if (script_files_todo > 0) { X script_files_todo--; X return(*(script_files++)); X } X return(NULL); X } X Xvoid InitDevs() X{ XUSHORT colors[4]; Xint i; XBYTE *b,*c; Xstruct Process *mproc; Xchar temp[80]; X Xif (p_screen == 1) { X if ((myscreen = (struct Screen *)OpenScreen(&NewScreen)) == NULL) X cleanup("can't open screen",3); X NewWindow.Screen = myscreen; X NewReqWindow.Screen = myscreen; X } X Xif ((mywindow = (struct Window *)OpenWindow(&NewWindow)) == NULL) X cleanup("can't open window",4); X Xif(OpenDevice("console.device", -1L, &ConReq, 0L)) X cleanup("can't open console", 4); XConsoleDevice = ConReq.io_Device; X Xif(p_screen == 1) { /* Cause system reqs to come to this screen */ X mproc = (struct Process *)FindTask(0L); X OrigWindowPtr = mproc->pr_WindowPtr; X mproc->pr_WindowPtr = (APTR)mywindow; X} Xif ((myfont = (struct TextFont *)OpenFont(&myattr)) == NULL) { X sprintf(temp, "Can't open font %s", myfontname); X cleanup(temp, 4); X} X Xmyviewport = (struct ViewPort *)ViewPortAddress(mywindow); Xmyrastport = (struct RastPort *)mywindow->RPort; X XSetFont(myrastport,myfont); X Xif (p_depth > 1) myrequest.BackFill = 2; Xif (p_screen != 0 && p_wbcolors == 0) { X colors[0] = p_background; X colors[1] = p_foreground; X colors[2] = p_bold; X colors[3] = p_cursor; X if (p_depth == 1) X LoadRGB4(myviewport,(struct ColorMap *)colors,2L); X else X LoadRGB4(myviewport,(struct ColorMap *)colors,4L); X } X XRead_Request = (struct IOExtSer *) X AllocMem((long)sizeof(*Read_Request),MEMF_PUBLIC|MEMF_CLEAR); XRead_Request->io_SerFlags = 0L; XRead_Request->IOSer.io_Message.mn_ReplyPort = CreatePort(0L,0L); Xif(OpenDevice(SERIALNAME,(LONG)p_unit,Read_Request,NULL)) X cleanup("Cant open Read device",5); Xrs_in = malloc(p_buffer+1); XRead_Request->io_SerFlags = 0L; XRead_Request->io_Baud = p_baud; XRead_Request->io_ReadLen = 8L; XRead_Request->io_WriteLen = 8L; XRead_Request->io_CtlChar = 0x11130000L; XRead_Request->io_RBufLen = p_buffer; XRead_Request->io_BrkTime = p_break; XRead_Request->IOSer.io_Command = SDCMD_SETPARAMS; XDoIO(Read_Request); XRead_Request->IOSer.io_Command = CMD_READ; XRead_Request->IOSer.io_Length = 1; XRead_Request->IOSer.io_Data = (APTR) &rs_in[0]; X XWrite_Request = (struct IOExtSer *) X AllocMem((long)sizeof(*Write_Request),MEMF_PUBLIC|MEMF_CLEAR); Xb = (BYTE *)Read_Request; Xc = (BYTE *)Write_Request; Xfor (i=0;iIOSer.io_Message.mn_ReplyPort = CreatePort(0L,0L); XWrite_Request->IOSer.io_Command = CMD_WRITE; XWrite_Request->IOSer.io_Length = 1; XWrite_Request->IOSer.io_Data = (APTR) &rs_out[0]; X XTimer_Port = CreatePort("Timer Port",0L); XScript_Timer_Port = CreatePort("Timer Port",0L); X Xif (OpenDevice(TIMERNAME, UNIT_VBLANK, (char *) &Timer, 0) || X OpenDevice(TIMERNAME, UNIT_VBLANK, (char *) &Script_Timer, 0)) X cleanup("can't open timer device",7); X XTimer.tr_node.io_Message.mn_ReplyPort = Timer_Port; XTimer.tr_node.io_Command = TR_ADDREQUEST; XTimer.tr_node.io_Flags = 0; XTimer.tr_node.io_Error = 0; X XScript_Timer.tr_node.io_Message.mn_ReplyPort = Script_Timer_Port; XScript_Timer.tr_node.io_Command = TR_ADDREQUEST; XScript_Timer.tr_node.io_Flags = 0; XScript_Timer.tr_node.io_Error = 0; X XBeepWave = (UBYTE *)AllocMem(BEEPSIZE,(long)(MEMF_CHIP|MEMF_CLEAR)); Xif (BeepWave != 0) BeepWave[0] = 100; X XAudio_Port = CreatePort("Audio Port",0L); X XAudio_Request.ioa_Request.io_Message.mn_ReplyPort = Audio_Port; XAudio_Request.ioa_Request.io_Message.mn_Node.ln_Pri = 85; XAudio_Request.ioa_Data = Audio_AllocMap; XAudio_Request.ioa_Length = (ULONG) sizeof(Audio_AllocMap); X Xif (OpenDevice(AUDIONAME, NULL, (char *) &Audio_Request, NULL)) X cleanup("can't open audio device",8); X XAudio_Request.ioa_Request.io_Command = CMD_WRITE; XAudio_Request.ioa_Request.io_Flags = ADIOF_PERVOL; XAudio_Request.ioa_Data = BeepWave; XAudio_Request.ioa_Length = BEEPSIZE; XAudio_Request.ioa_Period = COLORCLOCK / (BEEPSIZE * BEEPFREQ); XAudio_Request.ioa_Volume = p_volume; XAudio_Request.ioa_Cycles = 100; X} X X/*****************************************************************/ X/* The following function initializes the structure arrays */ X/* needed to provide the File menu topic. */ X/*****************************************************************/ Xvoid InitFileItems() X{ X int n; X X if(capture == TRUE) X filetext[FILEMAX-1] = "Capturing"; X else X filetext[FILEMAX-1] = "Capture"; X do_menu_init(FileItem, FileText, FILE_INIT_ENTRY, FILEMAX); X FileItem[0].SubItem = ModeItem; X do_menu_init(ModeItem, ModeText, MODE_INIT_ENTRY, MODEMAX); X for( n=0; n MODEMAX) X p_xproto = MODEMAX-1; X ModeItem[p_xproto].Flags |= CHECKED; X} X X/****************************************************************** X/* Main Comm menu X/* set up for Baud & Parity submenus X/******************************************************************/ Xvoid InitCommItems() X{ X int n; X X do_menu_init(CommItem, CommText, COMM_INIT_ENTRY, COMMAX); X CommItem[0].SubItem = RSItem; X CommItem[1].SubItem = ParItem; X CommItem[2].SubItem = XFItem; X X/*****************************************************************/ X/* The following initializes the structure arrays */ X/* needed to provide the BaudRate Submenu topic. */ X/*****************************************************************/ X X do_menu_init(RSItem, RSText, RS_INIT_ENTRY, RSMAX); X for( n=0; n 3) UtilItem[n].Flags |= CHECKIT; X } X X if (p_echo) UtilItem[4].Flags |= CHECKED; X if (p_wrap) UtilItem[5].Flags |= CHECKED; X if (p_keyapp == 0) UtilItem[6].Flags |= CHECKED; X if (p_curapp) UtilItem[7].Flags |= CHECKED; X if (p_bs_del) UtilItem[8].Flags |= CHECKED; X if (p_xbeep) UtilItem[9].Flags |= CHECKED; X swap_bs_del(); /* Setup keys[] properly... */ X swap_bs_del(); /* ...for mode */ X} X X/****************************************************************/ X/* The following function inits the Menu structure array with */ X/* appropriate values for our simple menu. Review the manual */ X/* if you need to know what each value means. */ X/****************************************************************/ Xvoid InitMenu() X{ Xmenu[0].NextMenu = &menu[1]; Xmenu[0].LeftEdge = 5; Xmenu[0].TopEdge = 0; Xmenu[0].Width = 40; Xmenu[0].Height = 10; Xmenu[0].Flags = MENUENABLED; Xmenu[0].MenuName = "File"; /* text for menu-bar display */ Xmenu[0].FirstItem = &FileItem[0]; /* pointer to first item in list */ X Xmenu[1].NextMenu = &menu[2]; Xmenu[1].LeftEdge = 55; Xmenu[1].TopEdge = 0; Xmenu[1].Width = 88; Xmenu[1].Height = 10; Xmenu[1].Flags = MENUENABLED; Xmenu[1].MenuName = "Comm Setup"; /* text for menu-bar display */ Xmenu[1].FirstItem = &CommItem[0]; /* pointer to first item in list */ X Xmenu[2].NextMenu = &menu[3]; Xmenu[2].LeftEdge = 153; Xmenu[2].TopEdge = 0; Xmenu[2].Width = 56; Xmenu[2].Height = 10; Xmenu[2].Flags = MENUENABLED; Xmenu[2].MenuName = "Script"; /* text for menu-bar display */ Xmenu[2].FirstItem = &ScriptItem[0]; /* pointer to first item in list*/ X Xmenu[3].NextMenu = NULL; Xmenu[3].LeftEdge = 225; Xmenu[3].TopEdge = 0; Xmenu[3].Width = 64; Xmenu[3].Height = 10; Xmenu[3].Flags = MENUENABLED; Xmenu[3].MenuName = "Utility"; /* text for menu-bar display */ Xmenu[3].FirstItem = &UtilItem[0]; /* pointer to first item in list*/ X} X Xvoid do_menu_init(menuitem, menutext, initentry, max) Xstruct MenuItem menuitem[]; Xstruct IntuiText menutext[]; Xstruct HowToInit *initentry; Xint max; X{ X int n, nplus1; X char **temp; X X /* initialize each menu item and IntuiText with loop */ X for( n=0; n < max; n++ ) { X nplus1 = n + 1; X temp = initentry->text; X menutext[n].IText = (UBYTE *)temp[n]; X menuitem[n].NextItem = &menuitem[nplus1]; X menuitem[n].LeftEdge = initentry->LeftEdge; X menuitem[n].TopEdge = 10 * n; X menuitem[n].Width = initentry->Width; X menuitem[n].Height = 10; X menuitem[n].Flags = initentry->Flags; X menuitem[n].MutualExclude = 0; X menuitem[n].ItemFill = (APTR)&menutext[n]; X menuitem[n].SelectFill = NULL; X if((initentry->cmdkeys != NULL) && (initentry->cmdkeys[n] != ' ')) { X menuitem[n].Command = initentry->cmdkeys[n]; X menuitem[n].Flags |= COMMSEQ; X } X else menuitem[n].Command = 0; X menuitem[n].SubItem = NULL; X menuitem[n].NextSelect = 0; X X menutext[n].FrontPen = 0; X menutext[n].BackPen = 1; X menutext[n].DrawMode = JAM2;/* render in fore and background */ X menutext[n].LeftEdge = 0; X menutext[n].TopEdge = 1; X menutext[n].ITextFont = NULL; X menutext[n].NextText = NULL; X } X menuitem[max-1].NextItem = NULL; X} ________This_Is_The_END________ if test `wc -l < init.c` -ne 666; then echo 'shar: init.c was damaged during transit (should have been 666 bytes)' fi fi ; : end of overwriting check echo 'x - kermit.c' if test -f kermit.c; then echo 'shar: not overwriting kermit.c'; else sed 's/^X//' << '________This_Is_The_END________' > kermit.c X/************************************************************* X * vt100 terminal emulator - KERMIT protocol support X * X * v2.8 880117 ACS - See the README file X * v2.7 870825 ACS - Fixed the "multiple-send" problem in X * doksend() et al; show status using the *InfoMsg*() X * routines in window.c; fixed erroneous calls to X * spack() and rpack(); better error handling. X * v2.6 870227 DBW - bug fixes for all the stuff in v2.5 X * v2.5 870214 DBW - more additions (see readme file) X * v2.4 861214 DBW - lots of fixes/additions (see readme file) X * v2.3 861101 DBW - minor bug fixes X * v2.2 861012 DBW - more of the same X * v2.1 860915 DBW - new features (see README) X * 860901 ACS - Added eight bit quoting X * 860830 Steve Drew Wild card support, err recovry,bugs. X * 860823 DBW - Integrated and rewrote lots of code X * 860811 Steve Drew multi filexfer, bugs, status line ect.. X * v2.0 860809 DBW - Major rewrite X * v1.1 860720 DBW - Switches, 80 cols, colors, bug fixes X * v1.0 860712 DBW - First version released X * X *************************************************************/ X X#include "vt100.h" X X#define MAXPACKSIZ 94 /* Maximum msgpkt size */ X#define CR 13 /* ASCII Carriage Return */ X#define LF 10 /* ASCII line feed */ X#define SP 32 /* ASCII space */ X#define DEL 127 /* Delete (rubout) */ X X#define MAXTRY 5 /* Times to retry a msgpkt */ X#define MYQUOTE '#' /* Quote character I will use */ X#define MYRPTQ '~' /* Repeat quote character */ X#define MYEBQ '&' /* 8th bit prefix character */ X#define MYPAD 0 /* Number of padding charss I will need */ X#define MYPCHAR 0 /* Padding character I need (NULL) */ X#define MYEOL '\n' /* End-Of-Line character I need */ X#define IDOLONG 2 /* I do LONG packets! */ X X#define tochar(ch) ((ch) + ' ') X#define unchar(ch) ((ch) - ' ') X#define ctl(ch) ((ch) ^ 64 ) X X/* Global Variables */ X Xint sending, /* Indicates that we're sending, not receiving */ X lastpkt, /* Last successful packet # sent/received */ X ulp, /* Using LONG packets */ X size, /* Size of present data */ X osize, /* Size of last data entry */ X rpsiz, /* Maximum receive msgpkt size */ X spsiz, /* Maximum send msgpkt size */ X timint, /* Time interval to wait */ X pad, /* How much padding to send */ X n, /* Packet number */ X tp, /* total packets */ X numtry, /* Times this msgpkt retried */ X retry, /* total retries */ X oldtry, /* Times previous msgpkt retried */ X sendabort, /* flag for aborting send file */ X rptflg, /* are we doing repeat quoting */ X ebqflg, /* are we doing 8th bit quoting */ X notfirst, /* is this the first file received */ X first, /* is this the first time in a file */ X rpt, /* current repeat count */ X next, /* what is the next character */ X t; /* current character */ Xlong totbytes; /* total bytes xfered on this file */ X Xchar state, /* Present state of the automaton */ X padchar, /* Padding character to send */ X eol, /* End-Of-Line character to send */ X quote, /* Quote character in incoming data */ X rptq, /* Quote character for repeats */ X ebq, /* Quote character for 8th bit quoting */ X ackpkt[MAXPACKSIZ+20], /* ACK/NAK packet buffer */ X *msgpkt, /* Message Packet buffer is AllocMem()d */ X *spackbuf, /* Dynamically allocated buffer for spack() */ X filnam[40], /* remote file name */ X snum[10], X mainmode[10]; X XFILE *fp; /* file for send/receive */ X Xchar * Xgetfname(name) /* returns ptr to start of file name from spec */ Xchar *name; X{ X int l; X X l = strlen(name); X while(l && name[l] != '/' && name[l] != ':') l--; X if (name[l] == '/' || name[l] == ':') l++; X return(name += l); X} X Xdoksend(file,more) Xchar *file; Xint more; X{ X int amount, c, wild; X char *p, **list = NULL; X X msgpkt = (char *)AllocMem((long)(MAXLONGPKS+20), MEMF_PUBLIC|MEMF_CLEAR); X spackbuf = (char *)AllocMem((long)(MAXLONGPKS+20), MEMF_PUBLIC|MEMF_CLEAR); X sending = 1; X if (!strcmp(file,"$")) { saybye(); return(USERABORT); } X p = file; X while(*p && *p != '*' && *p != '?') p++; X if (*p) { X wild = TRUE; X list = expand(file, &amount); X if (list == NULL) InfoMsg1Line("KERMIT: No wild card match"); X } X else { X wild = FALSE; X amount = 1; X } X /* The "multiple send" problem is brought about by attempting to X ** send multiple files in a single "batch" (via globbing, e.g. *.foo) X ** to a remote kermit that is NOT in server mode. A 'Z' packet X ** (meaning end-of-file) is sent after each of the files with a 'B' X ** packet (meaning end-of-batch) coming after the last 'Z' packet. X ** The old code reset the packet # on each iteration. We do it X ** outside of the for loop. */ X n = lastpkt = 0; X ulp = 0; /* Assume we won't use LONG packets */ X for (c = 0; c < amount; c++) { X if (wild == TRUE) p = list[c]; X else p = file; X strcpy(filnam,getfname(p)); X ttime = TTIME_KERMIT; X tp = retry = numtry = 0; totbytes = 0L; X if ((fp = fopen(p,"r")) == NULL) { X InfoMsg2Line("KERMIT: Can't open send file:", p); X continue; X } X strcpy(mainmode,"SEND"); X ClearBuffer(); X X /* This is another piece of the multiple-send fix. Sendsw() needs X ** to know 1) that this is the first file so it can send a send-init X ** packet and 2) if this is the last file so it can send a B packet X ** to indicate end-of-batch. The last piece of the multiple-send fix X ** is in sendsw() itself. */ X if ( sendsw(c == 0, c >= (amount-1)) ) /* Successful send? */ X ScrollInfoMsg(1); X fclose(fp); X } X free_expand(list); X FreeMem(spackbuf, (long)(MAXLONGPKS+20)); X FreeMem(msgpkt, (long)(MAXLONGPKS+20)); X return(TRUE); X} X Xdokreceive(file,more) Xchar *file; Xint more; X{ X int retval; X X msgpkt = (char *)AllocMem((long)(MAXLONGPKS+20), MEMF_PUBLIC|MEMF_CLEAR); X spackbuf = (char *)AllocMem((long)(MAXLONGPKS+20), MEMF_PUBLIC|MEMF_CLEAR); X ttime = TTIME_KERMIT; X sending = 0; X if (!strcmp(file,"$")) { saybye(); return(USERABORT); } X strcpy(filnam, file); X if (server) strcpy(mainmode,"GET"); X else strcpy(mainmode,"RECV"); X tp = lastpkt = retry = n = numtry = notfirst = 0; totbytes = 0L; X ClearBuffer(); X retval = recsw(); X FreeMem(spackbuf, (long)(MAXLONGPKS+20)); X FreeMem(msgpkt, (long)(MAXLONGPKS+20)); X return(retval); X} X Xsendsw(firstfile, lastfile) Xint firstfile, lastfile; /* Multiple-send fix */ X{ X char sinit(), sfile(), sdata(), seof(), sbreak(); X sendabort = 0; X /* Multiple-send fix. If this is the first file of the batch then enter X ** send-init state otherwise just enter send-file state. */ X if(firstfile) X state = 'S'; X else X state = 'F'; X while(TRUE) { X switch(state) { X case 'S': state = sinit(); break; X case 'F': state = sfile(); break; X case 'D': state = sdata(); break; X case 'Z': state = seof(); break; X case 'B': if (lastfile || sendabort) { X /* Multiple-send fix. If this is the last file then X ** send a B packet to indicate end-of-batch. */ X state = sbreak(); X break; X } X return(TRUE); /* Otherwise, just return. */ X case 'C': if (sendabort) return(FALSE); X else return(TRUE); X case 'E': dostats('E',"ERROR"); /* so print the err and abort */ X print_host_err(ackpkt); X return(FALSE); X case 'A': if (timeout == USERABORT) { X timeout = GOODREAD; X n = (n+1)%64; X sendabort = 1; X dostats('A',"ABORT"); X strcpy(msgpkt, "D"); X state = 'Z'; X break; X } X if (timeout == TIMEOUT) dostats('A',"TMOUT"); X else { /* protocol error dectected by us */ X dostats('A',"ERROR"); X print_our_err(); X } X return(FALSE); X default: return(FALSE); X } X } X} X Xchar sinit() X{ X int num, len; X X retry++; X if (numtry++ > MAXTRY) return('A'); X spar(msgpkt); X X spack('S',n,13,msgpkt); X switch(rpack(&len,&num,ackpkt)) { X case 'N': return(state); X case 'Y': if (n != num) return(state); X rpar(ackpkt, len); X if (eol == 0) eol = '\n'; X if (quote == 0) quote = MYQUOTE; X numtry = 0; X retry--; X n = (n+1)%64; X return('F'); X case 'E': return('E'); X case FALSE: if (timeout == USERABORT) state = 'A'; X return(state); X default: return('A'); X } X} X Xchar sfile() X{ X int num, len; X X retry++; X if (numtry++ > MAXTRY) return('A'); X X spack('F',n,strlen(filnam),filnam); X switch(rpack(&len,&num,ackpkt)) { X case 'N': X num = (--num<0 ? 63:num); X if (n != num) return(state); X case 'Y': X if (n != num) return(state); X numtry = 0; X retry--; X n = (n+1)%64; X first = 1; X size = getpkt(); X return('D'); X case 'E': X return('E'); X case FALSE: if (timeout == USERABORT) state = 'A'; X return(state); X default: X return('A'); X } X} X Xchar sdata() X{ X int num, len; X X retry++; X if (numtry++ > MAXTRY) return('A'); X X spack('D',n,size,msgpkt); X switch(rpack(&len,&num,ackpkt)) { X case 'N': X num = (--num<0 ? 63:num); X if (n != num) return(state); X case 'Y': X if (n != num) return(state); X numtry = 0; X retry--; X n = (n+1)%64; X if ((size = getpkt()) == 0) return('Z'); X return('D'); X case 'E': X return('E'); X case FALSE: if (timeout == USERABORT) state = 'A'; X return(state); X default: X return('A'); X } X} X Xchar seof() X{ X int num, len; X retry++; X if (numtry++ > MAXTRY) return('A'); X X/* if (timeout == USERABORT) {*/ /* tell host to discard file */ X/* timeout = GOODREAD; */ X/* spack('Z',n,1,"D"); */ X/* } */ X/* else */ X spack('Z',n,sendabort,msgpkt); X switch(rpack(&len,&num,ackpkt)) { X case 'N': X num = (--num<0 ? 63:num); X if (n != num) return(state); X case 'Y': X if (n != num) return(state); X numtry = 0; X dostats('Z',"DONE"); X retry--; X n = (n+1)%64; X return('B'); X case 'E': return('E'); X case FALSE: return(state); X default: return('A'); X } X} X Xchar sbreak() X{ X int num, len; X retry++; X if (numtry++ > MAXTRY) return('A'); X X spack('B',n,0,msgpkt); X switch (rpack(&len,&num,ackpkt)) { X case 'N': X num = (--num<0 ? 63:num); X if (n != num) return(state); X case 'Y': X if (n != num) return(state); X dostats('B', "DONE"); X numtry = 0; X retry--; X n = (n+1)%64; X return('C'); X case 'E': return('E'); X case FALSE: return(state); X default: return ('A'); X } X} X X/* timeout equals USERABORT so lets end the file and quit */ X/* when host receives 'Z' packet with "D" in data field he */ X/* should discard the file. */ X/* Xsabort() X{ X dostats(' ',"ABORT"); X n = (n+1)%64; X retry--; X state = 'Z'; X while (state == 'Z') state = seof(); X while (state == 'B') state = sbreak(); X return(FALSE); X} X*/ X X Xrecsw() X{ X char rinit(), rfile(), rdata(); X int first_time = 1; X X state = 'R'; X X while(TRUE) { X switch(state) { X case 'R': ulp = 0; /* Assume we won't use LONG packets */ X state = rinit(); X break; X case 'Z': X case 'F': state = rfile(first_time); first_time = 0; X break; X case 'D': state = rdata(); X break; X case 'C': return(TRUE); X case 'E': X case 'A': /* easy way to cleanly abort X should really send and ACK X with "X" in data field and X wait for host to abort but X not all kermits support X this feature. */ X if (timeout == USERABORT){ X /* send an error packet back */ X dostats('A',"ABORT"); X spack('E',n,12,"User aborted"); X } X else if (timeout == TIMEOUT) { X /* we timed out waiting */ X /* will we need to spack here ?*/ X dostats('A',"TMOUT"); X } X /* must be 'E' from host or we detected a protocol X ** error */ X else dostats('A',"ERROR"); X X if (state == 'E') print_host_err(msgpkt); X else if (timeout == GOODREAD) /* tell host why */ X print_our_err(); X /* will this kill all files ?*/ X do { X ttime = 2; X readchar(); X } while (timeout == GOODREAD); X fclose(fp); X sendstring("\r"); X return(FALSE); X default: return(FALSE); X } X } X} X Xchar rinit() X{ X int len, num, temp; X retry++; X if (numtry++ > MAXTRY) return('A'); X X if (server) spack('R',n,strlen(filnam),filnam); X else spack('N',n,0,""); X switch(rpack(&len,&num,msgpkt)) { X case 'S': X rpar(msgpkt, len); X /* Rpar() will set ulp if we can use long packets. We can't use X ** that value right away cause we've gotta ACK with normal pkts. */ X temp = ulp; ulp = 0; X spar(msgpkt); X spack('Y',n,13,msgpkt); X ulp = temp; /* Restore using long pkts flag */ X oldtry = numtry; X numtry = 0; X retry--; X n = (n+1)%64; X return('F'); X case 'E': X return('E'); X case 'N': /* Other side NAKed us... */ X return(state); /* ...so try again */ X case FALSE: X if (timeout == USERABORT) return('A'); X if (timeout == TIMEOUT) return(state); /* Resend Rec-init on a timeout */ X spack('N',n,0,""); X return(state); X default: X return('A'); X } X} X Xchar rfile(first_time) Xint first_time; X{ X int num, len, temp; X USHORT a, a7, b8; X char *fileptr, *buf; X X retry++; X if (numtry++ > MAXTRY) return('A'); X X switch(rpack(&len,&num,msgpkt)) { X case 'S': X if (oldtry++ > MAXTRY) return('A'); X if (num == ((n==0) ? 63:n-1)) { X /* Rpar() will set ulp if we can use long packets. We can't use X ** that value right away cause we've gotta ACK with normal pkts. */ X temp = ulp; ulp = 0; X spar(msgpkt); X spack('Y',num,13,msgpkt); X ulp = temp; X numtry = 0; X return(state); X } X else return('A'); X case 'Z': X if (oldtry++ > MAXTRY) return('A'); X if (num == ((n==0) ? 63:n-1)) { X spack('Y',num,0,""); X ScrollInfoMsg(1); X numtry = 0; X return(state); X } X else return('A'); X case 'F': X if (num != n) return('A'); X if(!first_time) { /* Scroll the Z packet line up */ X dostats('Z', "DONE"); X ScrollInfoMsg(1); X } X buf = msgpkt; X fileptr = filnam; X while ((a = *buf++) != '\0') { /* Terminator added by rpack() */ X if (rptflg) { X if (a == rptq) { X rpt = unchar(*buf++); X a = *buf++; X } X } X b8 = 0; X if (ebqflg) { /* 8th-bit prefixing? */ X if (a == ebq) { /* Yes, got an 8th-bit prefix? */ X b8 = 0200; /* Yes, remember this, */ X a = *buf++; /* and get the prefixed character. */ X } X } X if (a == quote) { X a = *buf++; X a7 = a & 0177; X if ((a7 >= 0100 && a7 <= 0137) || a7 == '?') a = ctl(a); X } X a |= b8; X if (rpt == 0) rpt = 1; X if (p_mode == 1 && a == '\r') continue; X for (; rpt > 0; rpt--) *fileptr++ = a; X *fileptr = '\0'; /* Terminate the filename */ X } X X if (p_convert) { X char *p; X p = &filnam[0]; X while (*p) { *p = tolower(*p); p++; } X } X if (notfirst) { X totbytes = 0L; X dostats('F',"RECV"); X } X else { /* is the first file so emit actual file name from host */ X notfirst++; X } X if ((fp = fopen(filnam,"w")) == NULL) { X InfoMsg2Line("KERMIT: Unable to create file:", filnam); X strcpy(msgpkt,"VT100 - Kermit - cannot create file: "); X strcat(msgpkt,filnam); X spack('E',n,strlen(msgpkt),msgpkt); /* let host know */ X dostats('E',"ERROR"); X return ('\0'); /* abort everything */ X } X spack('Y',n,0,""); X oldtry = numtry; X numtry = 0; X retry--; X n = (n+1)%64; X return('D'); X X /* totaly done server sending no more */ X case 'B': X if (num != n) return ('A'); X spack('Y',n,0,""); X dostats('B', "DONE"); X ScrollInfoMsg(1); X retry--; X return('C'); X case 'E': X return('E'); X case FALSE: X if (timeout == USERABORT) return('A'); X spack('N',n,0,""); X return(state); X default: X return ('A'); X } X} X Xchar rdata() X{ X int num, len; X retry++; X if (numtry++ > MAXTRY) return('A'); X X switch(rpack(&len,&num,msgpkt)) { X case 'D': X if (num != n) { X if (oldtry++ > MAXTRY) return('A'); X if (num == ((n==0) ? 63:n-1)) { X spack('Y',num,6,msgpkt); X numtry = 0; X return(state); X } X else return('A'); X } X decode(); X spack('Y',n,0,""); X oldtry = numtry; X numtry = 0; X retry--; X n = (n+1)%64; X return('D'); X case 'Z': X if (num != n) return('A'); X spack('Y',n,0,""); X n = (n+1)%64; X dostats('Z',"DONE"); X retry--; X fclose(fp); X return('Z'); X case 'F': X if (oldtry++ > MAXTRY) return('A'); X if (num == ((n==0) ? 63:n-1)) { X spack('Y',num,0,""); X numtry = 0; X return(state); X } X case 'E': X return('E'); X case FALSE: X if (timeout == USERABORT) return('A'); X spack('N',n,0,""); X return(state); X default: X return('A'); X } X} X X Xspack(type,num,len,data) Xchar type, *data; Xint num, len; X{ X int i; X char chksum, t; X register char *bufp; X X if(sending && (lastpkt != num)) { X tp++; X lastpkt = num; X } X dostats(type,mainmode); X bufp = spackbuf; X ClearBuffer(); X X for (i=1; i<=pad; i++) sendchar(padchar); X X *bufp++ = SOH; X if(ulp && len > (MAXPACKSIZ-3)) /* Using long packets */ X t = tochar(0); X else X t = tochar(len+3); X *bufp++ = t; chksum = t; X t = tochar(num); X *bufp++ = t; chksum += t; X *bufp++ = type; chksum += type; X if(ulp && len > (MAXPACKSIZ-3)) { /* Using long packets */ X unsigned int pl = len + 1; X X t = tochar(pl / 95); X *bufp++ = t; chksum += t; X t = tochar(pl % 95); X *bufp++ = t; chksum += t; X t = tochar((((chksum&0300) >> 6)+chksum)&077); X *bufp++ = t; chksum += t; X } X for (i=0; i> 6)+chksum)&077; X *bufp++ = tochar(chksum); X if (eol) X *bufp++ = eol; /* Use sender's requested end-of-line */ X if (eol != '\r') X *bufp++ = '\r'; X *bufp++ = '\n'; X *bufp = '\0'; X sendstring(spackbuf); X} X Xrpack(len,num,data) Xint *len, *num; Xchar *data; X{ X int i, done; X char type, cchksum, rchksum; X char t = '\0'; X X do { X t = readchar(); X if (timeout != GOODREAD) return(FALSE); X } while (t != SOH); X X done = FALSE; X while (!done) { X t = readchar(); X if (timeout != GOODREAD) return(FALSE); X if (t == SOH) continue; X cchksum = t; X *len = unchar(t)-3; X t = readchar(); X if (timeout != GOODREAD) return(FALSE); X if (t == SOH) continue; X cchksum += t; X *num = unchar(t); X t = readchar(); X if (timeout != GOODREAD) return(FALSE); X if (t == SOH) continue; X cchksum += t; X type = t; X if((*len == -3) && ulp) { /* Using long packets */ X t = readchar(); X if (timeout != GOODREAD) return(FALSE); X if (t == SOH) continue; X cchksum += t; X *len = unchar(t)*95; X t = readchar(); X if (timeout != GOODREAD) return(FALSE); X if (t == SOH) continue; X cchksum += t; X *len += unchar(t); X (*len)--; X t = readchar(); X if (timeout != GOODREAD) return(FALSE); X if (t == SOH) continue; X if(unchar(t) != ((((cchksum&0300) >> 6)+cchksum)&077)) return(FALSE);; X cchksum += t; X } X for (i=0; i<*len; i++) { X t = readchar(); X if (timeout != GOODREAD) return(FALSE); X if (t == SOH) continue; X cchksum = cchksum + t; X data[i] = t; X } X data[*len] = 0; X t = readchar(); X if (timeout != GOODREAD) return(FALSE); X rchksum = unchar(t); X t = readchar(); X if (timeout != GOODREAD) return(FALSE); X if (t == SOH) continue; X done = TRUE; X } X if(type != 'B' && type != 'Z') X dostats(type,mainmode); X cchksum = (((cchksum&0300) >> 6)+cchksum)&077; X if (cchksum != rchksum) return(FALSE); X if(!sending && (*num != lastpkt)) { X tp++; X lastpkt = *num; X } X return((int)type); X} X Xgetpkt() { X int i,eof; X X static char leftover[10] = { '\0', '\0', '\0', '\0', '\0', X '\0', '\0', '\0', '\0', '\0' }; X X if (first == 1) { X first = 0; X *leftover = '\0'; X t = getc(fp); X if (t == EOF) { X first = 1; X return(size = 0); X } X totbytes++; X } X else if (first == -1) { X first = 1; X return(size = 0); X } X for (size = 0; (msgpkt[size] = leftover[size]) != '\0'; size++) ; X *leftover = '\0'; X rpt = 0; X eof = 0; X while (!eof) { X next = getc(fp); X if (next == EOF) { X first = -1; X eof = 1; X } X else totbytes++; X osize = size; X encode(t); X t = next; X if (size == spsiz-3) return(size); X if (size > spsiz-3) { X for (i = 0; (leftover[i] = msgpkt[osize+i]) != '\0'; i++) X ; X size = osize; X msgpkt[size] = '\0'; X return(size); X } X } X return(size); X} X Xvoid encode(a) Xchar a; X{ X int a7,b8; X X if (p_mode == 1 && a == '\n') { X rpt = 0; X msgpkt[size++] = quote; X msgpkt[size++] = ctl('\r'); X if (size <= spsiz-3) osize = size; X msgpkt[size++] = quote; X msgpkt[size++] = ctl('\n'); X msgpkt[size] = '\0'; X return; X } X if (rptflg) { X if (a == next && (first == 0)) { X if (++rpt < 94) return; X else if (rpt == 94) { X msgpkt[size++] = rptq; X msgpkt[size++] = tochar(rpt); X rpt = 0; X } X } X else if (rpt == 1) { X rpt = 0; X encode(a); X if (size <= spsiz-3) osize = size; X rpt = 0; X encode(a); X return; X } X else if (rpt > 1) { X msgpkt[size++] = rptq; X msgpkt[size++] = tochar(++rpt); X rpt = 0; X } X } X a7 = a & 0177; X b8 = a & 0200; X X if (ebqflg && b8) { /* Do 8th bit prefix if necessary. */ X msgpkt[size++] = ebq; X a = a7; X } X X if ((a7 < SP) || (a7==DEL)) { X msgpkt[size++] = quote; X a = ctl(a); X } X if (a7 == quote) msgpkt[size++] = quote; X if ((rptflg) && (a7 == rptq)) msgpkt[size++] = quote; X X if ((ebqflg) && (a7 == ebq)) /* Prefix the 8th bit prefix */ X msgpkt[size++] = quote; /* if doing 8th-bit prefixes */ X X msgpkt[size++] = a; X msgpkt[size] = '\0'; X} X Xvoid decode() X{ X USHORT a, a7, b8; X char *buf; X X buf = msgpkt; X rpt = 0; X X while ((a = *buf++) != '\0') { /* Terminator added by rpack() */ X if (rptflg) { X if (a == rptq) { X rpt = unchar(*buf++); X a = *buf++; X } X } X b8 = 0; X if (ebqflg) { /* 8th-bit prefixing? */ X if (a == ebq) { /* Yes, got an 8th-bit prefix? */ X b8 = 0200; /* Yes, remember this, */ X a = *buf++; /* and get the prefixed character. */ X } X } X if (a == quote) { X a = *buf++; X a7 = a & 0177; X if ((a7 >= 0100 && a7 <= 0137) || a7 == '?') a = ctl(a); X } X a |= b8; X if (rpt == 0) rpt = 1; X if (p_mode == 1 && a == '\r') continue; X totbytes += rpt; X for (; rpt > 0; rpt--) putc(a, fp); X } X return; X} X Xvoid spar(data) Xchar data[]; X{ X data[0] = tochar(MAXPACKSIZ); X data[1] = tochar(TTIME_KERMIT); X data[2] = tochar(MYPAD); X data[3] = ctl(MYPCHAR); X data[4] = tochar(MYEOL); X data[5] = MYQUOTE; X if ((p_parity > 0) || ebqflg) { /* 8-bit quoting... */ X data[6] = MYEBQ; /* If parity or flag on, send &. */ X if ((ebq > 0040 && ebq < 0100) || /* If flag off, then turn it on */ X (ebq > 0140 && ebq < 0177) || /* if other side has asked us to */ X (ebq == 'Y')) X ebqflg = 1; X } X else /* Normally, */ X data[6] = 'Y'; /* just say we're willing. */ X data[7] = '1'; X data[8] = MYRPTQ; X data[9] = tochar(IDOLONG); /* Tell 'em I do LONG packets */ X data[10] = tochar(0); /* Don't do windows */ X data[11] = tochar(p_kmaxpack / 95); X data[12] = tochar(p_kmaxpack % 95); X data[13] = '\0'; X} X Xvoid rpar(data, len) Xchar data[]; Xint len; X{ X int ospsiz; X X spsiz = unchar(data[0]); X ospsiz = spsiz; X ttime = unchar(data[1]); X pad = unchar(data[2]); X padchar = ctl(data[3]); X eol = unchar(data[4]); X quote = data[5]; X rptflg = 0; X ebqflg = 0; X if (len >= 6 && data[6] != 0) { X ebq = data[6]; X if ((ebq > 040 && ebq < 0100) || X (ebq > 0140 && ebq < 0177)) ebqflg = 1; X else if (((p_parity > 0) || ebqflg) && (ebq == 'Y')) { X ebqflg = 1; X ebq = '&'; X } X else ebqflg = 0; X } X if (len >= 8 && data[8] != 0) { X rptq = data[8]; X rptflg = ((rptq > 040 && rptq < 0100) || X (rptq > 0140 && rptq < 0177)); X } X if(len >= 9 && data[9] != 0) { X int capas; X for(capas=9; data[capas] & 1; capas++) ; /* Skip over continuations */ X if((ulp = (data[9] & IDOLONG)) == IDOLONG) { X spsiz = 500; /* Default if no packet size specified */ X if(len >= capas+3) { X spsiz = unchar((data[capas+2]) * 95) + unchar(data[capas+3]); X if(spsiz > MAXLONGPKS) X spsiz = MAXLONGPKS; X else if(spsiz < 10) /* Reasonable? */ X spsiz = 500; X } X } X } X} X Xsaybye() X{ X int len,num; X if(numreqs != 0) /* Requester's up... */ X Delay(5L); /* ...so wait for Intuition, just in case. */ X spack('G',n,1,"F"); /* shut down server no more files */ X rpack(&len,&num,ackpkt); X} X Xprint_our_err() X{ X if (retry > MAXTRY || oldtry > MAXTRY) { X InfoMsg1Line("KERMIT: Too may retries for packet"); X strcpy(msgpkt,"VT100 KERMIT: Too many retries for packet"); X } X else { X InfoMsg1Line("KERMIT: Protocol Error"); X strcpy(msgpkt,"VT100 KERMIT: Protocol Error"); X } X spack('E',n,strlen(msgpkt),msgpkt); X} X Xprint_host_err(msg) Xchar *msg; X{ X InfoMsg2Line("KERMIT: Host Error:", msg); X} X Xdostats(type,stat) Xchar type,*stat; X{ X char *statusform = "%5s %-15.15s Pkt: %4d Retr: %2d Bytes: %6ld Type: %c", X status[80]; X X if (type == 'Y' || type == 'N' || type == 'G') return; X X sprintf(status, statusform, stat, filnam, tp, retry-1, X (LONG)totbytes, type); X InfoMsgNoScroll(status); X} X XClearBuffer() X{ X AbortIO(Read_Request); X Wait(1L << Read_Request->IOSer.io_Message.mn_ReplyPort->mp_SigBit); X WaitIO(Read_Request); X Read_Request->IOSer.io_Command = CMD_CLEAR; X DoIO(Read_Request); X Read_Request->IOSer.io_Command = CMD_READ; X SendIO(Read_Request); X} ________This_Is_The_END________ if test `wc -l < kermit.c` -ne 1028; then echo 'shar: kermit.c was damaged during transit (should have been 1028 bytes)' fi fi ; : end of overwriting check exit 0