From:	CRDGW2::CRDGW2::MRGATE::"SMTP::CRVAX.SRI.COM::RELAY-INFO-VAX"  1-SEP-1989 16:38
To:	MRGATE::"ARISIA::EVERHART"
Subj:	Apple LaserWriter Symbiont (5 of 12)

Received: From KL.SRI.COM by CRVAX.SRI.COM with TCP; Fri,  1 SEP 89 10:17:35 PDT
Received: from ecsgate.uncecs.edu by KL.SRI.COM with TCP; Fri, 1 Sep 89 10:11:04 PDT
Received: by ecsgate.uncecs.edu (5.59/UNCECS/8-30-88)
	id AA24220; Fri, 1 Sep 89 13:11:07 EDT
Message-Id: <8909011711.AA24220@ecsgate.uncecs.edu>
Date: Fri, 1 Sep 89 13:07 EDT
From: "Bill Bailey, 'The VAXman'" <BAILEYB@ATSUVAX1.BITNET>
Subject: Apple LaserWriter Symbiont (5 of 12)
To: INFO-VAX@KL.SRI.COM
X-Vms-To: INFOVAX

-+-+-+-+-+-+-+-+ START OF PART 5 -+-+-+-+-+-+-+-+
X`009`009laser_buf`091laser_iosb`0911`093`093 = 0;`009/* terminate string */
X`009`009if (!check_operator()) `009writeuserlog();
X`009`125
X
X`009postlaserread();`009`009`009/* issue next read */
X`125
X
X
X/**`009openfile - open the main file.
X*
X*`009return:`009FALSE if open problems.
X*/
Xopenfile()
X`123
X`009int stat;
X`009struct dsc$descriptor_s temp = `1230, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0`12
V5;
X`009struct dsc$descriptor_s fid =
X`009`009`12328, DSC$K_DTYPE_T, DSC$K_CLASS_S, main_nam.nam$t_dvi`125;
X
X`009getitemdescrip(SMBMSG$K_FILE_IDENTIFICATION, &temp, TRUE);
X`009
X`009main_fab = cc$rms_fab;`009`009`009/* init fab */
X`009main_fab.fab$l_nam = &main_nam;`009`009/* use NAM to open by FID */
X`009main_fab.fab$l_fop `124= FAB$M_NAM;
X`009
X`009main_nam = cc$rms_nam;`009`009`009/* init nam */
X`009str$copy_dx(&fid, &temp);
X`009
X`009stat = sys$open(&main_fab);
X`009if (!(stat & 1)) `123`009`009`009/* if open error */
X`009`009stop_reason = stat;
X`009`009return FALSE;
X`009`125
X`009
X`009main_rab = cc$rms_rab;`009`009`009/* initialize rab */
X`009main_rab.rab$l_fab = &main_fab;
X
X`009stat = sys$connect(&main_rab);
X`009if (!(stat & 1)) `123`009`009`009/* if connect error */
X`009`009stop_reason = stat;
X`009`009return FALSE;
X`009`125
X`009return TRUE;
X`125
X
X
X/**`009openuserlog - open user log file.
X*
X*`009Create a file using the file spec of the file to be printed,
X*`009changing the EXT to .LASER_LOG.  Try the logical name`032
X*`009LASER$LOG if this does not work (probably a spooled file).
X*
X*/
Xopenuserlog()
X`123
X`009int stat, i;
X`009struct dsc$descriptor_s temp;
X`009char filename`091256`093, filespec`091255`093, *cp;
X
X`009userlog = -1;`009`009`009/* flag not opened yet */
X
X`009log_fab = cc$rms_fab;`009`009/* init fab */
X
X/*  Build log file name.  If a spooled file, prepend the job name and */
X/*  put the file in LASER$LOG:`009`009`009`009`009      */
X`009
X`009filename`0910`093 = 0; i = 0;
X`009if (spooled_file) `123
X`009`009getitemdescrip(SMBMSG$K_USER_NAME, &temp, TRUE);
X`009`009strncpy(filename, temp.dsc$a_pointer, temp.dsc$w_length);
X`009`009i = temp.dsc$w_length;`009`009/* trim trailing blanks */
X`009`009do `123
X`009`009`009filename`091i`093 = 0;
X`009`009`009if (filename`091--i`093 != ' ') break;
X`009`009`125 while (i > 0);
X`009`009strcat(filename, "-");
X`009`125
X`009
X`009getitemdescrip(SMBMSG$K_FILE_SPECIFICATION, &temp, TRUE);
X`009strncpy(filespec, temp.dsc$a_pointer, temp.dsc$w_length);
X`009filespec`091temp.dsc$w_length`093 = 0;
X`009if (spooled_file) cp = strchr(filespec, '`093') + 1;
X`009else cp = filespec;
X`009strcat(filename, cp);
X`009
X`009log_fab.fab$l_dna = filename;
X`009log_fab.fab$b_dns = strlen(filename);
X`009if (spooled_file) `123
X`009`009log_fab.fab$l_fna = "LASER$LOG:.laser_log;0";
X`009`009log_fab.fab$b_fns = 22;
X`009`125
X`009else `123
X`009`009log_fab.fab$l_fna = ".laser_log;0";
X`009`009log_fab.fab$b_fns = 12;
X`009`125
X`009log_fab.fab$b_rfm = FAB$C_VAR;
X`009log_fab.fab$b_rat = FAB$M_CR;
X`009log_fab.fab$w_mrs = 512;
X
X`009stat = sys$create(&log_fab);
X`009if (!(stat & 1)) return;`009`009/* if not possible */
X`009
X`009log_rab = cc$rms_rab;`009`009`009/* initialize rab */
X`009log_rab.rab$l_fab = &log_fab;
X
X`009stat = sys$connect(&log_rab);
X`009if (!(stat & 1)) return;
X`009
X`009userlog = 0;`009`009`009`009/* flag open, no records */
X`125
X
X
X/**`009postlaserread - post non blocking read for laserchan.
X*/
Xpostlaserread()
X`123
X`009static int term_block`0912`093 = `1230,-1`125;`009/* end on any control
V */
X`009int stat;
X
X`009stat = sys$qio(laser_efn, laserchan, IO$_READPBLK+IO$M_NOECHO,
X`009`009laser_iosb, laser_read_ast, 0,
X`009`009laser_buf, sizeof(laser_buf), 0, term_block, 0, 0);
X`009checkstat(stat, "read qio");
X`125
X
X
X/**`009preset - preset the symbiont.
X*/
Xpreset()
X`123
X`009int stat;
X
X`009stat = lib$get_ef(&laser_efn);`009/* allocate event flag */
X`009
X`009setprivs();`009`009`009/* set process privs */
X`009inititems();`009`009`009/* init item list */
X`009initsymb();`009`009`009/* do jobctl init */
X`125
X`009
X/**`009processtask - process a file.
X*/
Xprocesstask()
X`123
X`009int stat, np, request;
X`009int svector`0912`093 = `1231, SS$_NORMAL`125;`009/* stat vector */
X`009int acctrec`0914`093 = `1230,0,0,0`125;`009`009/* accounting record */
X`009struct dsc$descriptor_s accounting =
X`009`009`123sizeof(acctrec), DSC$K_DTYPE_T, DSC$K_CLASS_S, acctrec`125;
X`009struct dsc$descriptor_s temp = `1230, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0`12
V5;
X`009
X`009if (laserchan == 0) exit(LASER$_STREAMNOTSTART);
X`009
X`009stat = smb$send_to_jobctl(&0, &SMBMSG$K_START_TASK, 0, 0, 0, 0);
X`009checkstat(stat, "processtask: send to jobctl");
X
X`009postlaserread();`009`009`009/* post read  */
X`009syncprinter();`009`009`009`009/* synchronize with printer */
X`009stop_task = 0;`009`009`009`009/* again to make sure */
X`009stop_reason = 0;
X`009checkspooled();`009`009`009`009/* check for spooled file */
X`009openuserlog();`009`009`009`009/* open user log file */
X`009trailer(0);`009`009`009`009/* flag pages */
X`009if (!openfile()) goto skip;`009`009/* open main file */
X/*`009getcopies();*/`009`009`009`009/* send copy count */
X`009getnote();`009`009`009`009/* output possible note */
X`009getparams();`009`009`009`009/* get user parameters */
X`009if (!getsetup()) goto skip;`009`009/* output setup module */
X`009sendfile();`009`009`009`009/* send main file */
X`009skip:
X`009closefile();`009`009`009`009/* close main file */
X`009trailer(1);`009`009`009`009/* send trailer */
X`009sendendsequence();`009`009`009/* send end job sequence */
X`009if (userlog > 0) svector`0911`093 = SS$_CREATED-1; /* if errors logged *
V/
X`009closeuserlog();`009`009`009`009/* close user log */
X`009stat = sys$cancel(laserchan);`009`009/* cancel pending read */
X`009
X`009start_task = FALSE;`009`009`009/* clear flag */
X`009
X`009np = endpage - startpage;`009`009 /* compute page count */
X`009if (np >0) acctrec`0910`093 = np;`009`009 /* if no obvious error */
X
X/*  If stop_task, we were stopped by the job controller.`009*/
X/*  Else, we were stopped by some other error condition`009        */
X
X`009request = SMBMSG$K_TASK_COMPLETE;
X`009if (stop_task) `123`009`009`009 /* if task aborted */
X`009`009request = SMBMSG$K_STOP_TASK;
X`009`009svector`0911`093 = stop_task;
X`009`125
X`009else if (stop_reason) `123
X`009`009svector`0911`093 = stop_reason;
X`009`125
X
X`009releaseitems();`009`009`009`009 /* release item list */
X`009
X`009stat = smb$send_to_jobctl(&0, &request, &accounting,
X`009`0090, 0, svector);
X`009checkstat(stat, "processtask: send to jobctl");
X`125
X
X
X/**`009releaseitems - release item list.
X*
X*`009release dynamic strings gotten by read_items.
X*/
Xreleaseitems()
X`123
X`009int`009i;
X`009struct dsc$descriptor_d temp = `1230, DSC$K_DTYPE_T, DSC$K_CLASS_D, 0`12
V5;
X`009
X`009ii = 0;`009`009`009`009`009 /* clear item index */
X
X`009for (i = 0; i < MAXITEMS; i++) `123
X`009`009if (item`091i`093.buffer == 0) return;`009/* if end of list */
X`009`009temp.dsc$w_length = item`091i`093.item_size;
X`009`009temp.dsc$a_pointer = item`091i`093.buffer;
X`009`009str$free1_dx(&temp);
X`009`009item`091i`093.buffer = 0;
X`009`125
X`125
X
X
X/**`009resetstream - reset the stream.
X*/
Xresetstream()
X`123
X`009int stat;
X
X`009stat = smb$send_to_jobctl(&0, &SMBMSG$K_RESET_STREAM, 0, 0, 0, 0);
X`009checkstat(stat, "resetstream: send to jobctl");
X`009
X`009exit (SS$_NORMAL);
X`125
X
X
X/**`009sendendsequence - send end of job sequence.
X*/
Xsendendsequence()
X`123
Xstatic char getend`091`093 = `123"\004statusdict begin (%%`091 end page   #=
V) print \
Xpagecount pstack pop flush end \r\n\004"`125;
X
X`009int stat;
X`009int daytim`0912`093;`009`009`009`009/* quadword time interval */
X`009int timeoutcount = 0;
X`009int abort_sent = FALSE;
X`009static $DESCRIPTOR(timetowait, "0 :5:00");`009/* +5 min */
X`009
X`009endpage = 0;
X
X`009sys$wake(0,0);`009`009`009`009/* eat pending wakeups */
X`009sys$hiber();`009`009`009`009/* (instant return) */
X`009
X`009WRITELASER(getend,strlen(getend))`009/* write end sequence */
X`009
X`009do `123
X
X`009`009stat = sys$bintim(&timetowait, daytim);
X`009`009checkstat(stat, "bintim");
X`009`009stat = sys$schdwk(0, 0, daytim, 0);`009/* wake up later */
X`009`009checkstat(stat, "schdwk");
X
X`009`009if (endpage) break;`009`009/* if sync occured */
X`009`009stat = sys$hiber();
X`009`009if (endpage) break;`009`009/* if sync occured */
X`009`009if (stop_task) `123`009`009/* if stop_task requested */
X`009`009`009if (!abort_sent) `123
X`009`009`009`009abort_sent = TRUE;
X`009`009`009`009WRITELASER(&0X03,1)`009/* control-c */
X`009`009`009`009lib$wait(&1.0);`009/* wait 1 second */
X`009`009`009`009WRITELASER(&0X04,1)`009/* end of job */
X`009`009`009`009lib$wait(&1.0);`009/* wait 1 second */
X`009`009`009`009WRITELASER(getend,strlen(getend))
X`009`009`009`125
X`009`009`125
X/*  Notify the operator on 10 minute intervals. */
X`009`009
X`009`009if ((++timeoutcount & 1) == 0) `123 /* if interval */
X`009`009`009strcpy(msg.text, "LaserWriter job possibly hung");
X`009`009`009oprmsg_dsc.dsc$w_length = 8 + strlen(msg.text);
X`009`009`009sys$sndopr(&oprmsg_dsc, 0);
X`009`009`125
X`009`009
X`009`125 while (TRUE);
X`009
X`009stat = sys$canwak(0,0);`009/* cancel wakeup requests */
X`125
X
X
X/**`009sendfile - send the main file to the printer.
X*/
Xsendfile()
X`123
X#define IBUFSIZE (16384)
X#define PREFIX_LEN (1)`009`009`009`009/* max extra prefix chars */
X`009int stat, end;
X#if 0
X`009char ibuf`091IBUFSIZE`093;`009`009`009/* input buffer */
X`009char obuf`091IBUFSIZE*2+2`093;`009`009/* output buffer */
X#else
X`009char *ibuf;
X`009char *obuf;
X#endif
X`009char *cp;
X`009int rsz;`009`009`009`009/* record size */
X`009char prn_ctl`0912`093;`009`009`009/* PRN file control bytes */
X`009
X`009ibuf = malloc(IBUFSIZE+PREFIX_LEN);`009/* extra for prefix chars */`032
X`009obuf = malloc(IBUFSIZE*2 + 2);
X
X`009main_rab.rab$l_ubf = ibuf+PREFIX_LEN;
X`009main_rab.rab$w_usz = IBUFSIZE;
X
X/*`009For PRN type records, set up a pointer to the carriage control byte  *
V/
X/*`009pair, or initialize the control byte pair manually.`009`009     */
X
X`009if (main_fab.fab$b_rat & FAB$M_PRN) `123
X`009`009if (main_fab.fab$b_fsz == 2) `123
X`009`009`009main_rab.rab$l_rhb = &prn_ctl;`009/* ptr to PRN ctrl */
X`009`009     `125
X`009`009else `123
X`009`009`009prn_ctl`0910`093 = 0x01;`009/* LF CR before */
X`009`009`009prn_ctl`0911`093 = 0x8d;`009/* CR after */
X`009`009     `125
X`009      `125
X`009do `123`009`009`009`009`009/* send the file */
X`009`009
X`009`009stat = sys$get(&main_rab, 0, 0);`009/* get a record */
X`009`009if ((stat == RMS$_EOF) `124`124 (stop_task `124 stop_reason)) break;
X`009`009if (!(stat & 1)) `123`009`009`009/* if error */
X`009`009`009stop_reason = stat;
X`009`009`009break;
X`009`009`125
X
X`009`009rsz = main_rab.rab$w_rsz;
X`009`009
X/*  Process record control. */
X`009`009
X`009`009cp = ibuf+PREFIX_LEN;`009`009/* Leave room for prefix chs */
X
X`009`009if (ascii `124`124 string) `123
X`009`009        /* if FTN (Fortran) carriage control */
X`009`009`009if (main_fab.fab$b_rat & FAB$M_FTN) `123
X`009`009`009       if (rsz == 0) `123`009/* Null record => blank line */
X`009`009`009`009 cp`091rsz++`093 = ' ';
X`009`009`009       `125
X`009`009`009       switch(*cp) `123
X`009`009`009       case 0:`009`009/* (null) - No CC */
X`009`009`009`009 cp++;`009`009/* ignore column 1 */
X`009`009`009`009 rsz--;
X`009`009`009`009 break;
X`009`009`009       case '0':`009/* 0 - Double Space */
X`009`009`009`009 *cp = '\n';`009/* 2 LF in front, CR at end */
X`009`009`009`009 *--cp = '\n';    `032
X`009`009`009`009 rsz++;
X`009`009`009`009 cp`091rsz++`093 = '\r';
X`009`009`009`009 break;
X`009`009`009       case '1':`009/* 1 - Page Eject */
X`009`009`009`009 *cp = '\n';
X`009`009`009`009 *--cp = '\f';
X`009`009`009`009 rsz++;
X`009`009`009`009 cp`091rsz++`093 = '\r';
X`009`009`009`009 break;
X`009`009`009       case '+':`009/* + - overprint */
X`009`009`009`009 cp++;`009`009/* ignore column 1 */
X`009`009`009`009 cp`091rsz-1`093 = '\r';
X`009`009`009`009 break;
X`009`009`009       case '$':`009/* $ - no trailing CC */
X`009`009`009`009 *cp = '\r';`009/* LF, CR before record */
X`009`009`009`009 *--cp = '\n';    `032
X`009`009`009`009 rsz++;
X`009`009`009`009 break;
X`009`009`009       default :`009/* space, etc. */
X`009`009`009`009 *cp = '\n';
X`009`009`009`009 cp`091rsz++`093 = '\r';
X`009`009`009`009 `125
X
X`009`009`009`125
X
X`009`009`009/*  if implied carriage control */
X`009`009`009if (main_fab.fab$b_rat & FAB$M_CR) `123
X`009`009`009`009*--cp = '\n';`009/* prefix LF, suffix CR */
X`009`009`009`009rsz++;
X`009`009`009`009cp`091rsz++`093 = '\r';
X`009`009`009`125
X
X`009`009`009/*  print carriage control.  Expand and output`009  */
X`009`009`009/* leading carriage control, then expand trailing */
X`009`009`009/* control to output after the text.`009`009  */
X`009`009`009if (main_fab.fab$b_rat & FAB$M_PRN) `123
X`009`009`009`009expand_cc(prn_ctl`0910`093);
X`009`009`009`125
X`009`009`009
X`009`009`009expand_line(cp, obuf, rsz);
X
X`009`009`009if (main_fab.fab$b_rat & FAB$M_PRN)
X`009`009`009`009expand_cc(prn_ctl`0911`093);
X`009`009`125
X`009`009
X`009`009if (hex) `123`009`009`009/* if file to be hexified */
X`009`009`009expand_hex(cp, obuf, rsz);
X`009`009`125
X
X`009`125 while (TRUE);
X`009
X`009free(ibuf);
X`009free(obuf);`009
X
X`009if (!ascii) `123
X`009`009WRITELASER(&0x0A0D,2)
X`009`125
X
X/*  send abort (`094C) if stop_task, else eof (`094D) */
X`009
X`009if (string) `123
X`009`009WRITELASER("EOF\r\n",5)
X`009`125
X
X`009if (stop_task `124 stop_reason) end = 3; else end = 4;
X`009WRITELASER(&end,1)
X`125
X
X
X/**`009setprivs - set process privs.
X*/
Xsetprivs()
X`123
X`009int stat;
X`009static int privs`0912`093 = `123PRV$M_ALLSPOOL+PRV$M_PHY_IO+PRV$M_SYSPRV
V, 0`125;
X
X`009stat = sys$setprv(1, privs, 0, 0);
X`009checkstat(stat, "set privs");
X`125
X
X
X/**`009set_typeahead.
X*
X*`009Set /typeahead on the terminal device so characters will be
X*`009buffered.
X*/
Xset_typeahead(chan)
Xint chan;`009`009`009`009`009/* laserwriter channel */
X`123
X`009int mode`0913`093;
X`009int stat;
X
+-+-+-+-+-+-+-+-  END  OF PART 5 +-+-+-+-+-+-+-+-

