/* * ********************* * * K E R M I T . C * * ********************* * * Kermit-P/OS main program. More later. * * By: * Robert B. Denny * 10-Jan-84 * * Edits: * * 12-Jan-84 RBD Add server command GET. * 13-Jan-83 RBD Add server FINISH & LOGOUT. Rework KERFIL spawning * so shares common code. * 14-Jan-84 RBD Add permanent storage of setup values. * */ /* * Undefine the following when MNU and HLP file * are assigned by the application installation * file. Eventually, we'll get logicals implemented * in the C library for P/OS!!! */ #define TESTING #include #include #include #include #define IDENT "Y1.1.C" ident IDENT; int $$narg = 1; /* * Kermit variable parameters & defaults */ static word baud = 1200; /* Current baud rate */ static word stripfs = TRUE; /* TRUE to strip filespecs */ /* * The following definitions MUST correspond to the * option numbers in the format menu!! (HACK!!) */ #define NP8 1 /* 1 = 8 bit none */ #define EP7 2 /* 2 = 7-bit even */ #define OP7 3 /* 3 = 7-bit odd */ static word format = NP8; /* Data format */ /* * The following definitions MUST correspond to the * option numbers in the format menu!! (HACK!!) */ #define TYPE1 1 #define TYPE2 2 #define TYPE3 3 static word blkchk = TYPE1; /* Block check (1,2 or 3) */ /* * The following definitions MUST correspond to the * option numbers in the format menu!! (HACK!!) */ #define ASCMODE 1 #define IMAGE 2 #define QMAGE 3 static word xmode = ASCMODE; /* Transfer mode */ /* * Permanent storage of setup data */ #define SETUP_FILE "LB:[ZZSYS]KERSETUP.DAT" static FILE *setdat; /* * Menu data */ static int stat[8]; /* Used everywhere */ static char action[8]; static int main_fl = FALSE; static char *msg1 = ""; static char *msg2 = ""; static char *clrseq = "\033[1;1H\033[J"; static char *failed = "Operation failed"; static char *complete = "Operation complete"; static char *wrgkey = "You pressed the wrong function key"; static char *unsup = "Option not working yet"; static char m1buf[80]; extern int $dsw; /* * ****************** * * MAIN ROUTINE * * ****************** */ main() { #ifdef TESTING /* * The following 2 POSRES calls may be eliminated when the * program is run via an application installation file. */ if(p$mfile("KERMIT.MNU", stat) != 1) my_err("Failed to open KERMIT.MNU"); if(p$hfile("KERMIT.HLP", "KERMAIN", stat) != 1) my_err("Failed to open KERMIT.HLP"); #endif /* * Open the setup data file & read old values in. If open fails, * create new one. */ if((setdat = fopen(SETUP_FILE, "r")) == NULL) { if((setdat = fopen(SETUP_FILE, "w")) == NULL) { sprintf(m1buf, "Failed to create %s. RMS code = %d\n", SETUP_FILE, $$ferr); p$fatler(m1buf); } else fprintf(setdat, "%d,%d,%d,%d,%d\n", baud, stripfs, format, blkchk, xmode); } else { fgets(m1buf, 32, setdat); sscanf(m1buf, "%d,%d,%d,%d,%d", &baud, &stripfs, &format, &blkchk, &xmode); } fclose(setdat); /* * Main loop */ while(TRUE) { main_fl = FALSE; display("KERMAIN"); switch(stat[0]) { case 1: /* DO key */ switch(stat[1]) /*** HACK -- use action string!! ***/ { case 1: msg1 = do_kfi('s'); ; break; case 2: msg1 = do_kfi('r'); ; break; case 3: msg1 = do_kfi('g'); ; break; case 4: msg1 = connect(); break; case 5: msg1 = do_kfi('e'); ; break; case 6: msg1 = do_kfi('q'); ; break; case 7: msg1 = show(); break; case 8: msg1 = set(); break; case 9: msg1 = view(); break; case 10: msg1 = files(); break; default: msg1 = unsup; } break; case -14: /* Function key */ switch(stat[1]) { case 10: /* Exit */ case 9: /* Main Screen */ printf("%s", clrseq); fflush(stdout); p$hclose(stat); p$mclose(stat); exits(1); default: msg1 = wrgkey; } break; default: my_error("MENU error"); } } } /* * ********************* * * ACTION ROUTINES * * ********************* */ /* * DO_KFI - Kick off KERFIL for specified operation * * FINISH takes you to CONNECT, LOGOUT takes you to VIEW. */ do_kfi(code) char code; { char cmdlin[40]; char buf[10]; sprintf(cmdlin, "kfi %c%sb %d", code, fmtopt(buf), baud); if(code == 'q' || spawnit("KFI ", cmdlin) != EX$SUC) return(view()); else if(code == 'e') return(connect()); else return(complete); } /* * CONNECT - terminal emulation (use PRO/Comm for now) * * NOTE: DTE returns funny status. */ connect() { #ifdef REALTHING if(spawnit("DTE ", NULL) != EX$SUC) return(failed); else return(complete); #else spawnit("DTE ", NULL); return(""); #endif } /* * SHOW - Show parameters */ static char *bc_dec[] = { "Single character checksum", "Two character checksum", "Three character CRC-CCITT" }; static char *df_dec[] = { "8 bits, no parity", "7 bits, even parity", "7 bits, odd parity" }; static char *ft_dec[] = { "ASCII (text files)", "Image (8-bit data format)", "Image (7-bit with 8th bit quoting)" }; show() { printf("%s\033#6Kermit-P/OS Version %s:\n", clrseq, IDENT); printf("Block-check type: %s\n", bc_dec[blkchk-1]); printf("Receive startup delay: 30 sec.\n"); printf("File transfer mode: %s\n", ft_dec[xmode-1]); printf("IBM mode Not supported\n"); printf("Incomplete file disposition Deaccess locked\n"); printf("Link protocol:\n"); printf(" Line used XK0: (Comm port)\n"); printf(" Local echo Not supported\n"); printf(" Data rate (baud rate) %d bits/sec.\n", baud); printf(" Data format %s\n", df_dec[format-1]); printf("Packet protocol:\n"); printf(" Packet length 94 bytes\n"); printf(" Padding length 0\n"); printf(" Pad character NUL (00 hex)\n"); printf(" Timeout 10 sec.\n"); printf(" Retry maximum 10 retries\n"); printf(" End-of-line character CR (0D hex)\n"); printf(" Control quoting character '#' (23 hex)\n"); printf(" 8th-bit quoting character Not supported\n"); printf(" Run-length encoding char. Not supported\n"); printf(" Start of packet character SOH (01 hex)\n\n"); printf("Press RESUME to continue ..."); fflush(stdout); wtres(); return(""); } /* * SET - Set communication parameters */ set() { msg1 = ""; while(TRUE) { display("KERSET"); switch(stat[0]) { case 1: /* DO key */ switch(stat[1]) { case 1: msg1 = s_speed(); updset(); break; case 3: msg1 = s_xfer(); updset(); break; case 5: msg1 = s_fspec(); updset(); break; default: msg1 = unsup; } break; case -14: switch(stat[1]) { case 9: /* Main screen */ main_fl = TRUE; case 10: return(""); default: msg1 = wrgkey; } break; default: my_err("MENU error"); } if(main_fl) return(msg1); /* Lower level MAIN screen */ } } /* * S_SPEED - Set data rate */ s_speed() { msg1 = ""; while(TRUE) { display("KERSPEED"); switch(stat[0]) { case 1: /* DO key */ switch(stat[1]) { case 1: baud = 300; break; case 2: baud = 1200; break; case 3: baud = 2400; break; case 4: baud = 4800; break; case 5: baud = 9600; break; case 6: baud = 19200; break; default: msg1 = "Speed selection error"; continue; } sprintf(m1buf, "Data rate is now %d bits/sec.\n", baud); return(m1buf); case -14: switch(stat[1]) { case 9: /* Main screen */ main_fl = TRUE; case 10: return("No change to data rate"); default: msg1 = wrgkey; } break; default: my_err("MENU error"); } } } /* * S_XFER - Set data format */ s_xfer() { msg1 = ""; while(TRUE) { display("KERXFR"); switch(stat[0]) { case 1: /* DO key */ switch(stat[1]) { case 1: xmode = ASCMODE; return("File type is ASCII"); case 2: xmode = IMAGE; return("File type is IMAGE (8-bit)"); default: return(unsup); } break; case -14: switch(stat[1]) { case 9: /* Main screen */ main_fl = TRUE; case 10: return("No change to file type"); default: msg1 = wrgkey; } break; default: my_err("MENU error"); } } } /* * S_FSPEC - Set file spec handling */ s_fspec() { msg1 = ""; while(TRUE) { display("KERFSPEC"); switch(stat[0]) { case 1: /* DO key */ switch(stat[1]) { case 1: stripfs = TRUE; return("Short file specifications"); case 2: stripfs = FALSE; return("Full P/OS file specifications"); default: return(unsup); } break; case -14: switch(stat[1]) { case 9: /* Main screen */ main_fl = TRUE; case 10: return("No change to file spec handling"); default: msg1 = wrgkey; } break; default: my_err("MENU error"); } } } /* * VIEW - Switch to message/status display */ view() { spawnit("C$VUTL", NULL); return(""); } /* * FILES - Switch to file services */ files() { spawnit("C$FUTL", NULL); return(""); } /* * ********************* * * LOCAL FUNCTIONS * * ********************* */ /* * DISPLAY - Load and display selected menu */ display(frame) char *frame; { if(p$mframe(frame, action, sizeof(action), stat) != 1) my_err("MFRAME error"); p$menu(action, sizeof(action), FALSE, msg1, msg2, stat); } /* * FMTOPT - Format command line options for KERFIL & KERDTE */ fmtopt(buf) char *buf; { register char *cp; cp = buf; if(xmode != ASCMODE) *cp++ = 'i'; if(!stripfs) *cp++ = 'f'; *cp++ = '\0'; return(buf); } /* * MY_ERROR - Fatal application errors */ my_error(str) char *str; { sprintf(m1buf, "%s status = [%d, %d]", str, stat[0], stat[1]); p$fatler(m1buf); } /* * SPAWNIT - Switch to offspring task */ #define SPWN_EFN 16 spawnit(task, cmd) char *task; char *cmd; { rad50 tname[2]; int cmdlen; char buf[80]; printf(clrseq); fflush(stdout); if(cmd == 0 || (cmdlen = strlen(cmd)) == 0) cmd = 0; ascr50(strlen(task), task, tname); qiow(IO_DET, 1, 1, 0, 0, 0); /* Detach terminal */ if(spwn(tname, 0, SPWN_EFN, 0, stat, cmd, cmdlen) != IS_SUC) { sprintf(buf, "Spawn of task \"%s\" failed. Code = %d\n", task, $dsw); p$fatler(buf); } stse(SPWN_EFN); qiow(IO_ATT|TF_ESQ, 1, 1, 0, 0, 0); /* Re-attach terminal (???) */ return(stat[0]); } /* * updset - Update the setup file */ updset() { if((setdat = fopen(SETUP_FILE, "a")) == NULL) { sprintf(m1buf, "Failed to open %s for update. RMS code = %d\n", SETUP_FILE, $$ferr); p$fatler(m1buf); } fseek(setdat, 0l, 0); fprintf(setdat, "%d,%d,%d,%d,%d\n", baud, stripfs, format, blkchk, xmode); fclose(setdat); }