KARNEY%PPC.MFENET@NMFECC.ARPA (07/19/88)
+-+-+-+ Beginning of part 4 +-+-+-+
X`009if (tiosb.stats != SS$_DATAOVERUN) check(tiosb.stats);
X`009input_state = NORMAL;
X }
X break;
X }
X switch (input_char) {
X case '\016':
X input_state = CREATE;
X break;
X case '\024':
X input_state = TOP;
X break;
X case '\032':
X if (count_processes()) {
X`009diag();
X sprintf(buf,"[Do you really want to quit (y or n)?]%s\007",ceol);
X term_msg(buf);
X`009input_state = END;
X }
X else exit(SS$_NORMAL);
X break;
X case '\010':
X print_help();
X input_state = NORMAL;
X break;
X case '?':
X diag();
X input_state = NORMAL;
X break;
X case '\002':
X case '\017':
X case '\020':
X case '\027':
X if (input_char == '\002') desc = "Buffer";
X else if (input_char == '\017') desc = "Discard";
X else if (input_char == '\020') desc = "Print";
X else if (input_char == '\027') desc = "Stop";
X nmode = input_char + 0140;
X if (cur < 0) {
X`009defmode = nmode;
X`009sprintf(buf,"%s[%s output by default]%s",bos,desc,ceoln);
X }
X else {
X`009mode[cur] = nmode;
X`009pmode[cur] = nmode;
X`009sprintf(buf,"%s[%s output from process %c]%s",bos,desc,
X`009`009name[cur],ceoln);
X }
X term_msg(buf);
X input_state = NORMAL;
X break;
X case '\177':
X input_state = NORMAL;
X break;
X default:
X nname = toupper(input_char);
X if (nname >= 'A' && nname <= 'Z') {
X`009mov_to(nname,input_char < 'a',"",switch_create ? CREATE : SWITCH);
X } else term_msg("\007");
X input_state = NORMAL;
X break;
X }
X break;
X case CREATE:
X case TOP:
X switch (input_char) {
X case '\016':
X input_state = CREATE;
X break;
X case '\024':
X input_state = TOP;
X break;
X case '\010':
X print_help();
X input_state = NORMAL;
X break;
X case '?':
X diag();
X input_state = NORMAL;
X break;
X case '\177':
X input_state = NORMAL;
X break;
X default:
X nname = toupper(input_char);
X if (nname >= 'A' && nname <= 'Z') {
X`009mov_to(nname,input_char < 'a',"",input_state);
X } else term_msg("\007");
X input_state = NORMAL;
X break;
X }
X break;
X case END:
X if (toupper(input_char) == 'Y') {
X term_msg(" Yes\r");
X exit(SS$_NORMAL);
X } else {
X term_msg(" No\r\n");
X }
X input_state = NORMAL;
X break;
X }
X /* re-post read AST on real term */
X check(SYS$QIO(0,tt_chn,IO$_READVBLK,&tiosb,&tt_srv,0,
X &input_char,1,0,0,0,0));
X}
X
Xget_tt_info()
X{
X $DESCRIPTOR(d_tt, "SYS$COMMAND");
X /* Get a channel & mailbox of terminal */
X check(LIB$ASN_WTH_MBX(&d_tt,&ttmbsiz,&ttmaxsiz,&tt_chn,&tt_mb_chn));
X /* Get the terminal characteristics. */
X check(SYS$QIOW(0,tt_chn,IO$_SENSEMODE,0,0,0,&tt_chr,ttchrlen,0,0,0,0));
X tt_sav_chr = tt_chr;
X tt_chr.ttchr |= TT$M_NOECHO; /* term will be Noecho */
X tt_chr.ttchr &= `126TT$M_HOSTSYNC; /* no host sync */
X if (flow_control) tt_chr.ttchr |= TT$M_TTSYNC; /* do sync at BOSS level */
X else tt_chr.ttchr &= `126TT$M_TTSYNC; /* do sync at subprocess level */
X tt_chr.xchar |= TT2$M_PASTHRU; /* it will be PASTRHU */
X if (brkthru) {
X tt_chr.ttchr |= TT$M_MBXDSABL; /* no hangup messages */
X tt_chr.ttchr |= TT$M_NOBRDCST; /* disable direct broadcast */
X tt_chr.xchar |= TT2$M_BRDCSTMBX; /* send them to mailbox instead */
X }
X check(SYS$QIOW(0,tt_chn,IO$_SETMODE,0,0,0,&tt_chr,ttchrlen,0,0,0,0));
X}
X
Xfix_a_tp(n) /* Set up a Pseudo term */
Xint n;
X{
X int dev_depend, tp_chn;
X struct CHARBLK tw_chr;
X struct IOSBBLK iosb;
X struct DVIBLK dvi_stuff = {4, DVI$_DEVDEPEND, &dev_depend, 0, 0};
X
X $DESCRIPTOR(d_pynam,"PYA0:"); /* Template. */
X $DESCRIPTOR(d_finaltp, &finaltp[n]);
X /* Assign a mailbox to PYA */
X check(LIB$ASN_WTH_MBX(&d_pynam,&mbsiz,&maxsiz,&py_chn[n],&py_mb_chn[n]));
X/*
X * Use $GETDVI to get the device dependent characteristics, which
X * contains the associated terminal device's unit number.
X */
X check(SYS$GETDVI(0,py_chn[n],0,&dvi_stuff,&iosb,0,0,0));
X check(iosb.stats);
X tw_chr= tt_sav_chr;
X tw_chr.xchar|= TT2$M_HANGUP;
X sprintf(&finaltp[n],"TWA%d:",dev_depend);
X d_finaltp.dsc$w_length = strlen(&finaltp[n]);
X`009`009`009`009/* Get a channel on this TWA */
X if (bad(SYS$ASSIGN(&d_finaltp,&tp_chn,0,0))) {
X sprintf(&finaltp[n],"TPA%d:",dev_depend); /* TWA doesn't work; try TPA */
X d_finaltp.dsc$w_length = strlen(&finaltp[n]);
X check(SYS$ASSIGN(&d_finaltp,&tp_chn,0,0));
X }
X if (no_phy_io) check(SYS$SETPRV(1,&priv,0,0));
X`009`009`009`009/* Make it look like a terminal */
X if (bad(SYS$QIOW(0,tp_chn,IO$_SETCHAR,0,0,0, /* This needs PHY_IO priv */
X &tw_chr,ttchrlen,0,0,0,0)))
X check(SYS$QIOW(0,tp_chn,IO$_SETMODE,0,0,0,
X &tw_chr,ttchrlen,0,0,0,0));
X if (no_phy_io) check(SYS$SETPRV(0,&priv,0,0));
X check(SYS$DASSGN(tp_chn)); /* We don't need it. only the mailbox */
X /* in fact keeping it kills us. */
X}
X
Xbroadcast_handler()`009`009/* handle broadcasts to BOSS */
X{
X int j, len;
X
X $DESCRIPTOR(d_tt_mb,tt_mb);
X $DESCRIPTOR(d_finaltp,finaltp[cur]);
X
X check(tiosbmb.stats);`009`009/* Check status */
X len = ((0377 & tt_mb[21]) << 8) + (0377 & tt_mb[20]); /* message length */
X if (cur < 0) {
X term_msg("\r\n");
X check(SYS$QIOW(0,tt_chn,IO$_WRITEVBLK,0,0,0,&(tt_mb[22]),len,0,0,0,0));
X term_msg("\r");
X }
X else {
X d_tt_mb.dsc$w_length = len;
X d_tt_mb.dsc$a_pointer = &(tt_mb[22]);
X if (no_oper) check(SYS$SETPRV(1,&privs,0,0));
X check(SYS$BRKTHRU(0,&d_tt_mb,&d_finaltp,
X`009`009 BRK$C_DEVICE,0,32,0,BRK$C_USER16,0,0,0));
X if (no_oper) check(SYS$SETPRV(0,&privs,0,0));
X }
X check(SYS$QIO(0,tt_mb_chn,IO$_READVBLK,&tiosbmb,&broadcast_handler,0,
X &tt_mb,ttmbsiz,0,0,0,0));
X}
X
Xpost_term_reads() /* Read AST on real term */
X{
X if (brkthru)
X check(SYS$QIO(0,tt_mb_chn,IO$_READVBLK,&tiosbmb,&broadcast_handler,0,
X`009`009 &tt_mb,ttmbsiz,0,0,0,0));
X else
X check(SYS$QIO(0,tt_mb_chn,IO$_READVBLK,&tiosbmb,0,0,
X`009`009 &tt_mb,ttmbsiz,0,0,0,0));
X check(SYS$QIO(0,tt_chn,IO$_READVBLK,&tiosb,&tt_srv,0,
X &input_char,1,0,0,0,0));
X}
X
Xpost_pty_reads(n) /* Read AST on Pseudo-term */
Xint n;
X{
X char cr = '\r';
X
X if (init) return(0);
X py_post[n] = 1;
X check(SYS$QIO(0,py_mb_chn[n],IO$_READVBLK,&miosb[n],&mb_srv,n,
X &py_mb[n],mbsiz,0,0,0,0));
X check(SYS$QIO(0,py_chn[n],IO$_READVBLK,&piosb[n],&py_srv,n,
X &tpline[n],linesz,0,0,0,0));
X if (proc_type[n] == TOP) {
X check(SYS$QIOW(0,py_chn[n],IO$_WRITEVBLK,&tiosb,0,0,
X &cr,1,0,0,0,0));
X if (tiosb.stats != SS$_DATAOVERUN) check(tiosb.stats);
X }
X}
X
Xint
Xfire_up(n,nname,proc_mode) /* Fire up subprocess n */
Xint n,proc_mode;
Xchar nname;
X{
X int val;
X name[n] = nname;
X procno[nname - 'A'] = n;
X count[n] = 0; /* Initialize buffer count */
X blocked[n] = 0; /* It starts unblocked */
X py_post[n] = 0;
X mode[n] = defmode;
X pmode[n] = defmode;
X buflen[n] = 0;
X proc_type[n] = proc_mode;
X enable_hangup[n] = 0;
X pid[n] = 0;
X fix_a_tp(n); /* Set a pseudo terminal by TT info */
X check(SYS$CANCEL(py_chn[n])); /* Don't need this Half of pseudo-ter */
X val = (proc_type[n] == TOP) ? 1 :
X low_lib_spawn(n,&finaltp[n],&pid[n],name[n]); /* Spawn a subprocess. */
X if (!bad(val)) post_pty_reads(n); /* Set up AST */
X else comp_srv(n); /* Mark the process as non-existent */
X return(val);
X}
X
Xinitialize() /* Initialize everything */
X{
X int j,item;
X $DESCRIPTOR(d_boss_id,"BOSS$ID");
X $DESCRIPTOR(d_lnm_process,"LNM$PROCESS");
X
X for (j = 0; j < nproc; j++) name[j] = '\0'; /* Initialize variables */
X for (j = 0; j < nalph; j++) procno[j] = -1;
X`009`009`009`009/* Save old value of BOSS$ID */
X j = SYS$TRNLNM(0,&d_lnm_process,&d_boss_id,&super_ac_mode,&trnlnm_item);
X if (!bad(j) && trnlnm_string_len == 1) {
X oboss_id = trnlnm_string[0];
X j = LIB$DELETE_LOGICAL(&d_boss_id,0);
X }
X
X item = JPI$_PROCPRIV;`009`009/* Check whether have PHY_IO & OPER */
X check(LIB$GETJPI(&item,0,0,&priv,0,0));
X no_phy_io = !(priv[0] & PRV$M_PHY_IO);
X no_oper = !(priv[0] & PRV$M_OPER);
X item = JPI$_IMAGPRIV;`009`009/* Check whether we can do BRKTHRU */
X check(LIB$GETJPI(&item,0,0,&priv,0,0));
X brkthru = ((priv[0] & PRV$M_OPER) || !no_oper);
X priv[0] = PRV$M_PHY_IO; priv[1] = 0;
X privs[0] = PRV$M_OPER; privs[1] = 0;
X if (no_phy_io) check(SYS$SETPRV(0,&priv,0,0));
X if (no_oper) check(SYS$SETPRV(0,&privs,0,0));
X get_tt_info(); /* Initialize terminal */
X start_up();`009`009`009/* Start up processes */
X post_term_reads();
X}
X
X/* Next two routines taken from FILE program by Joe Meadows Jr. */
X
Xlong int cli_present(s)
X char *s;
X{
X static struct dsc$descriptor s_desc = {0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
X
X s_desc.dsc$w_length = strlen(s);
X s_desc.dsc$a_pointer = s;
X return(cli$present(&s_desc));
X}
X
Xlong int cli_get_value(s1,s2)
X char *s1,**s2;
X{
X static struct dsc$descriptor s1_desc={0,DSC$K_DTYPE_T,DSC$K_CLASS_S,0};
X static struct dsc$descriptor s2_desc={0,DSC$K_DTYPE_T,DSC$K_CLASS_D,0};
X static char null = '\0';
X static struct dsc$descriptor null_desc={1,DSC$K_DTYPE_T,DSC$K_CLASS_S,&null};
X long int status;
X
X s1_desc.dsc$w_length = strlen(s1);
X s1_desc.dsc$a_pointer = s1;
X
X status = cli$get_value(&s1_desc,&s2_desc);
X
X if (status & 1)
X {
X str$append(&s2_desc,&null_desc);
X *s2 = s2_desc.dsc$a_pointer;
X }
X else
X *s2 = 0;
X return(status);
X}
X
Xprocess_command_line()
X{
X long int status,boss_len;
X short int length;
X $DESCRIPTOR(d_line,buf);
X $DESCRIPTOR(d_cldline,buf);
X $DESCRIPTOR(d_boss_term,"BOSS$TERM");
X $DESCRIPTOR(d_lnm_file_dev,"LNM$FILE_DEV");
X
X strcpy(buf,"BOSS ");
X boss_len = strlen(buf);
X d_line.dsc$w_length = d_line.dsc$w_length - boss_len;
X d_line.dsc$a_pointer = d_line.dsc$a_pointer + boss_len;
X check(lib$get_foreign(&d_line,0,&length,0));
X buf[length + boss_len] = '\0';
X d_cldline.dsc$w_length = length + boss_len;
X status = cli$dcl_parse(&d_cldline,BOSS_CLD,0,0,0);
X if (bad(status)) exit(STS$K_ERROR+STS$M_INHIB_MSG);
X
X status = cli_get_value("COMMAND_CHARACTER",&retval);
X if (bad(status)) ctlchar = 034;
X else sscanf(retval,"%d",&ctlchar);
X if (ctlchar < 0 || ctlchar > 0177 || ctlchar == 032) {
X printf("[Illegal command character (%d); using C-\\ instead]\n",ctlchar);
X ctlchar = 034;
X`009`009`009`009/* disallow C-z as a command character */
X }
X if (ctlchar < 040) sprintf(ctlchar_str,"C-%c",tolower(ctlchar+0100));
X else if (ctlchar == 040) strcpy(ctlchar_str,"SPC");
X else if (ctlchar == 0177) strcpy(ctlchar_str,"DEL");
X else sprintf(ctlchar_str,"%c",ctlchar);
X
X status = cli_get_value("BEGIN_PROMPT",&retval);
X if (bad(status)) strcpy(prompt_begin,"");
X else strcpy(prompt_begin,retval);
X
X status = cli_get_value("END_PROMPT",&retval);
X if (bad(status)) strcpy(prompt_end,"");
X else strcpy(prompt_end,retval);
X
X status = cli_get_value("DEFAULT_OUTPUT_FLAG",&retval);
X if (bad(status)) defmode = 'b';
X else defmode = tolower(retval[0]);
X
X status = cli_present("SWITCH_CREATE");
X switch_create = !bad(status);
X
X status = cli_present("FLOW_CONTROL");
X flow_control = !bad(status);
X
X status = cli_get_value("DELETE_CHARACTER",&retval);
X if (bad(status)) delete_char = 0177;
X else sscanf(retval,"%d",&delete_char);
X if (delete_char < 0 || delete_char > 0177) {
X printf("[Illegal delete character (%d); using DEL instead]\n",delete_char);
X ctlchar = 0177;
X }
X
X status = SYS$TRNLNM(0,&d_lnm_file_dev,&d_boss_term,0,&trnlnm_item);
X if (bad(status)) strcpy(trnlnm_string,"VT100");
X else trnlnm_string[trnlnm_string_len] = '\0';
X if (trnlnm_string[0] == 'V') { /* VT100 */
X clr = "\033[r\033[4l\033[H\033[2J"; /* Clear screen reset scroll */
X bos = "\033[r\033[4l\033[99;1H\n"; /* Go to bottom of screen */
X ceol = "\033[K";`009`009/* Clear to end-of-line */
X ceoln = "\033[K\r\n";`009/* Clear to end-of-line and newline */
X } else if (trnlnm_string[0] == 'A') { /* ADM3A */
X clr = "\032";
X bos = "\033=7 \n";
X ceol = " \010\010\010";
X ceoln = " \r\n";
X } else {`009`009`009/* UNKNOWN */
X clr = "\r\n";
X bos = "\r\n";
X ceol = "";
X ceoln = "\r\n";
X }
X}
X
Xint start_up()
X{
X long int status,j,n;
X char nname[30], output_flags[30], stuff_flag, odefmode;
X
X cur = -1;
X input_state = PENDING;
X init = 1;
X
X status = cli_present("START_PROCESS");
X if (!bad(status)) {
X stuff_flag = 1;
X j = 0;
X while (j < 30 && !bad(cli_get_value("START_PROCESS",&retval))) {
X if (strlen(retval) != 1) break;
X nname[j] = toupper(retval[0]);
X if (nname[j] < 'A' && nname[j] > 'Z') break;
X j++;
X }
X n = j;
X j = 0;
X while (j < n && !bad(cli_get_value("OUTPUT_FLAGS",&retval))) {
X output_flags[j] = tolower(retval[0]);
X j++;
X }
X while (j < n) {
X output_flags[j] = defmode;
X j++;
X }
X for (j = 0; j < n; j++) {
X if (stuff_flag) {
X`009status = cli_get_value("STUFF_STRING",&retval);
X`009if (bad(status)) {
X`009 stuff_flag = 0;
X`009 strcpy(stuff_buf,"");
X`009} else {
X`009 strcpy(stuff_buf,retval);
X`009 if (strlen(retval) > 0) strcat(stuff_buf,"\015");
X`009}
X }
X odefmode = defmode;
X defmode = output_flags[j];
X status = mov_to(nname[j],0,stuff_buf,CREATE);
X defmode = odefmode;
X if (bad(status)) break;
X input_state = NORMAL;
X }
X }
X init = 0;
X for (j = 0; j < nproc; j++) if (name[j] > 0) post_pty_reads(j);
X}
X
Xmain( )
X{
X int exit_handler[4] = {0,quit,0,&st};
X
X process_command_line();
X check(SYS$DCLEXH(&exit_handler)); /* Define Exit handler (quit) */
X if (ctlchar < 040)
X printf("Begin BOSS %s\nType control-%c control-h for information\n",
X`009 VERSION,tolower(ctlchar+0100));
X else
X printf("Begin BOSS %s\nType %s control-h for information\n",
X`009 VERSION,ctlchar_str);
X initialize();
X sys$hiber();
X}
$ GOSUB UNPACK_FILE
$ FILE_IS = "BOSS_CLD.CLD"
$ CHECKSUM_IS = 1913354040
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
Xmodule boss_cld
Xdefine verb boss
X`009qualifier command_character, nonnegatable, default,
X`009`009value(default="28",type=$number)
X`009qualifier delete_character, nonnegatable, default,
X`009`009value(default="127",type=$number)
X`009qualifier start_process, nonnegatable,
X`009`009value(required,list)
X`009qualifier stuff_string, nonnegatable,
X`009`009value(required,list)
X`009qualifier output_flags, nonnegatable,
X`009`009value(required,list,type=output_flag)
X`009qualifier begin_prompt, negatable,
X`009`009value
X`009qualifier end_prompt, negatable, default,
X`009`009value(default="> ")
X`009qualifier default_output_flag, nonnegatable, default,
X`009`009value(type=output_flag)
X`009qualifier switch_create, negatable
X`009qualifier flow_control, negatable
X
Xdefine type output_flag
X`009keyword b, default
X`009keyword o
X`009keyword p
X`009keyword w
$ GOSUB UNPACK_FILE
$ FILE_IS = "BOSS_BUILD.COM"
$ CHECKSUM_IS = 855795594
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X$! Procedure for compiling and linking BOSS.
X$!
X$ cc boss
X$ set command/object boss_cld
X$ link/notraceback boss,boss_cld,sys$input/opt
Xsys$library:vaxcrtl/share
$ GOSUB UNPACK_FILE
$ FILE_IS = "BOSS_INSTALL.COM"
$ CHECKSUM_IS = 1029728184
$ COPY SYS$INPUT VMS_SHARE_DUMMY.DUMMY
X$! Procedure for installing BOSS. This goes into the system startup file.
X$!
X$ boss_dir = "usr:[utility]"`009! Edit to point to where BOSS.EXE resides
X$ install = "$install/command_mode"
X$ if f$file("''boss_dir'boss.exe","known") then install delete 'boss_dir'boss
X$ install create 'boss_dir'boss/priv=(phy_io,oper)/header/open/shared
$ GOSUB UNPACK_FILE
$ EXIT
-+-+-+-+-+ End of part 4 +-+-+-+-+-