From: MRL@PFC.MIT.EDU (MARK LONDON)
Newsgroups: comp.os.vms
Subject: LASER New (different) LASER symbiont. 3/7
Date: 22 Aug 92 16:22:00 GMT
Distribution: world
Organization: The Internet

-+-+-+-+-+-+-+-+ START OF PART 3 -+-+-+-+-+-+-+-+
X`09`09stop_reason = LASER$_SETUPNOTFOUND;
X`09`09return FALSE;
X`09`7D
X
X/*  Check to see if the setup module ends in _HEX or _STR */
X`09if (!tek && getitemdescrip(SMBMSG$K_FORM_NAME, &temp, FALSE))
X    `09   if (strncmp(temp.dsc$a_pointer, "TEK", 3) == 0) tek = TRUE;
X
X        if (tek && (main_fab.fab$b_rfm == FAB$C_STM `7C`7C`20
X                    main_fab.fab$b_rfm == FAB$C_STMCR `7C`7C`20
X                    main_fab.fab$b_rfm == FAB$C_STMLF)) `7B
X`09`09sys$close(&main_fab, 0, 0);
X`09`09openfile();
X`09`7D
X
X`09if (!tek && key.dsc$w_length >= 4)`7B
X`09   if (strncmp(&key.dsc$a_pointer`5Bkey.dsc$w_length-4`5D,"_HEX", 4) == 0
V)`7B
X`09`09ascii = FALSE;
X`09`09hex = TRUE;
X`09   `7D
X`09  `20
X`09   if (strncmp(&key.dsc$a_pointer`5Bkey.dsc$w_length-4`5D,"_STR", 4) == 0
V)`7B
X`09`09ascii = FALSE;
X`09`09string = TRUE;
X`09   `7D
X        `7D       `20
X
X        if (!tek && string) `7B
X`09`09getitemdescrip(SMBMSG$K_FILE_SPECIFICATION, &temp, TRUE);
X`09`09strcpy(inbuf, "/filename (");
X`09`09strncat(inbuf, temp.dsc$a_pointer, temp.dsc$w_length);
X`09`09strcat(inbuf, ") def\r\n");
X`09`09WRITELASER(inbuf,strlen(inbuf))
X
X/*  Also send the form name if it exists */
X
X`09`09if (getitemdescrip(SMBMSG$K_FORM_NAME, &temp, FALSE)) `7B
X`09`09        if (land)
X`09`09`09`09strcpy(inbuf, "/formname (LANDSCAPE) def \r\n");
X                        else `7B
X`09`09`09`09strcpy(inbuf, "/formname (");
X`09`09`09`09strncat(inbuf, temp.dsc$a_pointer, temp.dsc$w_length);
X`09`09`09`09strcat(inbuf, ") def \r\n");
X                        `7D
X`09`09`09WRITELASER(inbuf,strlen(inbuf))
X`09`09`7D
X`09`7D
X
X/*  Send the setup module */
X
X`09if (tek) `7B
X`09`09strcpy(inbuf,"TEK4014");
X`09`09key.dsc$a_pointer = &inbuf;
X`09`09key.dsc$w_length = strlen(inbuf);
X`09`7D
X
X `09if (!writemodule(key)) `7B
X`09`09stop_reason = LASER$_SETUPNOTFOUND;
X`09`09return FALSE;
X`09`7D
X`09
X        if (tek && port) WRITELASER("portrait\n",9)
X        if (tek) WRITELASER("NP\n",3)
X
X`09return TRUE;
X`7D
X
X
X/**`09inititems - initialize item list.
X*/
Xinititems()
X`7B
X`09int`09i;
X
X`09for (i = 0; i < MAXITEMS; i++) item`5Bi`5D.buffer = 0;
X`7D
X
X
X/**`09initsymb - initialize printer symbiont.
X*/
Xinitsymb()
X`7B
X`09int stat;
X
X`09stat = smb$initialize(&SMBMSG$K_STRUCTURE_LEVEL, jobctl_ast, 0);
X`09checkstat(stat, "initsymb");
X`7D
X
X
X/**`09jobctl_ast - ast routine called by the job controller.
X*/
Xvoid jobctl_ast()
X`7B`09
X`09int`09stat;
X`09int`09request;`09`09`09/* jobctl request */
X`09struct dsc$descriptor_s temp = `7B0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0`7D;
X
X`09stat = smb$read_message(&0, &buffer_des, &request);
X`09if (stat != SS$_NORMAL) exit(stat);
X
X/*  Process the request */
X
X`09switch (request) `7B
X`09`09
X`09`09case SMBMSG$K_START_STREAM:
X`09`09getitems();
X`09`09startstream();
X`09`09break;
X
X`09`09case SMBMSG$K_START_TASK:
X`09`09getitems();
X`09`09start_task = TRUE;
X`09`09stop_task = 0;
X`09`09stop_reason = 0;
X`09`09break;
X
X`09`09case SMBMSG$K_RESUME_TASK:
X`09`09getitems();
X`09`09break;
X
X`09`09case SMBMSG$K_RESET_STREAM:
X`09`09resetstream();
X`09`09break;
X
X`09`09case SMBMSG$K_STOP_STREAM:
X`09`09stopstream();
X`09`09break;
X
X`09`09case SMBMSG$K_PAUSE_TASK:
X`09`09break;
X
X`09`09case SMBMSG$K_STOP_TASK:
X`09`09getitems();
X`09`09getitemdescrip(SMBMSG$K_STOP_CONDITION, &temp, TRUE);
X`09`09stop_task = * (long*) temp.dsc$a_pointer;
X`09`09break;
X`09`7D
X`09sys$wake(0,0);
X`7D
X
X
X/**`09laser_read_ast - laser read ast completion routine.
X*/
Xvoid laser_read_ast(param)
Xint param;
X`7B
X`09int iosb_stat;
X
X`09iosb_stat = laser_iosb`5B0`5D;
X`09if (iosb_stat == 0) return;`09`09/* if incomplete io (?) */
X`09if ((iosb_stat == SS$_ABORT) `7C`7C
X`09`09(iosb_stat == SS$_CANCEL) `7C`7C
X`09`09(iosb_stat == SS$_DATAOVERUN)) return;
X`09if (iosb_stat != SS$_NORMAL) exit(iosb_stat);`09/* if error */
X
X`09if (laser_iosb`5B1`5D) `7B`09`09`09/* if bytes in buffer */
X`09`09laser_buf`5Blaser_iosb`5B1`5D`5D = 0;`09/* terminate string */
X`09`09if (!check_operator()) `09writeuserlog();
X`09`7D
X
X`09postlaserread();`09`09`09/* issue next read */
X`7D
X
X
X/**`09openfile - open the main file.
X*
X*`09return:`09FALSE if open problems.
X*/
Xopenfile()
X`7B
X`09int stat;
X`09struct dsc$descriptor_s temp = `7B0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0`7D;
X`09struct dsc$descriptor_s fid =
X`09`09`7B28, DSC$K_DTYPE_T, DSC$K_CLASS_S, main_nam.nam$t_dvi`7D;
X
X`09getitemdescrip(SMBMSG$K_FILE_IDENTIFICATION, &temp, TRUE);
X`09
X`09main_fab = cc$rms_fab;`09`09`09/* init fab */
X`09main_fab.fab$l_nam = &main_nam;`09`09/* use NAM to open by FID */
X`09main_fab.fab$l_fop `7C= FAB$M_NAM;
X        main_fab.fab$b_fac = 0;
X        if (tek) main_fab.fab$b_fac = FAB$M_BIO`7CFAB$M_GET;
X`09
X`09main_nam = cc$rms_nam;`09`09`09/* init nam */
X`09str$copy_dx(&fid, &temp);
X`09
X`09stat = sys$open(&main_fab);
X`09if (!(stat & 1)) `7B`09`09`09/* if open error */
X`09`09stop_reason = stat;
X`09    `09return FALSE;
X`09`7D`09
X`09
X`09main_rab = cc$rms_rab;`09`09`09/* initialize rab */
X`09main_rab.rab$l_fab = &main_fab;
X
X`09stat = sys$connect(&main_rab);
X`09if (!(stat & 1)) `7B`09`09`09/* if connect error */
X`09`09stop_reason = stat;
X`09`09return FALSE;
X`09`7D
X`09return TRUE;
X`7D
X
X
X/**`09openuserlog - open user log file.
X*
X*`09Create a file using the file spec of the file to be printed,
X*`09changing the EXT to .LASER_LOG.  Try the logical name`20
X*`09LASER$LOG if this does not work (probably a spooled file).
X*
X*/
Xopenuserlog()
X`7B
X`09int stat, i;
X`09struct dsc$descriptor_s temp;
X`09char filename`5B256`5D, filespec`5B255`5D, *cp;
X
X`09log_fab = cc$rms_fab;`09`09/* init fab */
X
X/*  Build log file name.  If a spooled file, prepend the job name and */
X/*  put the file in LASER$LOG:`09`09`09`09`09      */
X`09
X`09filename`5B0`5D = 0; i = 0;
X`09if (spooled_file) `7B
X`09`09getitemdescrip(SMBMSG$K_USER_NAME, &temp, TRUE);
X`09`09strncpy(filename, temp.dsc$a_pointer, temp.dsc$w_length);
X`09`09i = temp.dsc$w_length;`09`09/* trim trailing blanks */
X`09`09do `7B
X`09`09`09filename`5Bi`5D = 0;
X`09`09`09if (filename`5B--i`5D != ' ') break;
X`09`09`7D while (i > 0);
X`09`09strcat(filename, "-");
X`09`7D
X`09
X`09getitemdescrip(SMBMSG$K_FILE_SPECIFICATION, &temp, TRUE);
X`09strncpy(filespec, temp.dsc$a_pointer, temp.dsc$w_length);
X`09filespec`5Btemp.dsc$w_length`5D = 0;
X`09if (spooled_file) cp = strchr(filespec, '`5D') + 1;
X`09else cp = filespec;
X`09strcat(filename, cp);
X`09
X`09log_fab.fab$l_dna = filename;
X`09log_fab.fab$b_dns = strlen(filename);
X`09if (spooled_file) `7B
X`09`09log_fab.fab$l_fna = "LASER$LOG:.laser_log;0";
X`09`09log_fab.fab$b_fns = 22;
X`09`7D
X`09else `7B
X`09`09log_fab.fab$l_fna = ".laser_log;0";
X`09`09log_fab.fab$b_fns = 12;
X`09`7D
X`09log_fab.fab$b_rfm = FAB$C_VAR;
X`09log_fab.fab$b_rat = FAB$M_CR;
X`09log_fab.fab$w_mrs = 512;
X
X`09stat = sys$create(&log_fab);
X`09if (!(stat & 1)) return;`09`09/* if not possible */
X`09
X`09log_rab = cc$rms_rab;`09`09`09/* initialize rab */
X`09log_rab.rab$l_fab = &log_fab;
X
X`09stat = sys$connect(&log_rab);
X`09if (!(stat & 1)) return;
X`09
X`09userlog = 0;`09`09`09`09/* flag open, no records */
X`7D
X
X
X/**`09postlaserread - post non blocking read for laserchan.
X*/
Xpostlaserread()
X`7B
X`09static int term_block`5B2`5D = `7B0,-1`7D;`09/* end on any control */
X`09int stat;
X
X`09stat = sys$qio(laser_efn, laserchan, IO$_READPBLK+IO$M_NOECHO,
X`09`09laser_iosb, laser_read_ast, 0,
X`09`09laser_buf, sizeof(laser_buf), 0, term_block, 0, 0);
X`09checkstat(stat, "read qio");
X`7D
X
X
X/**`09preset - preset the symbiont.
X*/
Xpreset()
X`7B
X`09int stat;
X
X`09stat = lib$get_ef(&laser_efn);`09/* allocate event flag */
X`09stat = lib$get_ef(&stateefn);
X`09
X`09setprivs();`09`09`09/* set process privs */
X`09inititems();`09`09`09/* init item list */
X`09initsymb();`09`09`09/* do jobctl init */
X`7D
X
Xvoid ltatimeout(param)
Xint param;
X`7B
X`09dassgndev();
X`09jobnum = 0;
X`7D
X
Xvoid statetimeout(param)
X
Xint param;
X`7B
X`09int stat;
X`09if (oldiocount < 0 && iocount != -oldiocount-1) `7B
X`09`09stat = sys$getmsg(LASER$_RESUMED, &msglen, &msgd, 15, 0);
X`09`09checkstat(stat,"$getmsg");
X`09`09message`5Bmsglen`5D = 0;
X`09`09queue_name`5Bqueue_name_l`5D = 0;
X`09`09msg`5B5`5D = '%';
X`09`09sprintf(&msg`5B6`5D,&message`5B1`5D,&queue_name);
X`09`09errmsg_dsc.dsc$w_length = strlen(msg) - 5;
X`09`09errmsg_dsc.dsc$a_pointer = &msg`5B5`5D;
X`09`09sndmsg(1);
X`09`09oldiocount = iocount;
X`09`7D else if (iocount == oldiocount) `7B
X`09`09stat = sys$getmsg(LASER$_STALLED, &msglen, &msgd, 15, 0);
X`09`09checkstat(stat,"$getmsg");
X`09`09message`5Bmsglen`5D = 0;
X`09`09queue_name`5Bqueue_name_l`5D = 0;
X`09`09msg`5B5`5D = '%';
X`09`09sprintf(&msg`5B6`5D,&message`5B1`5D,&queue_name);
X`09`09errmsg_dsc.dsc$w_length = strlen(msg);
X`09`09errmsg_dsc.dsc$a_pointer = &msg`5B0`5D;
X`09`09sndmsg(1);
X`09`09oldiocount = -oldiocount-1;
X`09`7D else if (oldiocount >= 0)
X`09`09oldiocount = iocount;
X`09sys$setimr(stateefn,&statetime,&statetimeout,stateefn,0);
X`7D
X
X/**`09processtask - process a file.
X*/
Xprocesstask()
X`7B
X
X`09int stat, np, request;
X`09int svector`5B2`5D = `7B1, SS$_NORMAL`7D;`09/* stat vector */
X`09int acctrec`5B4`5D = `7B0,0,0,0`7D;`09`09/* accounting record */
X`09struct dsc$descriptor_s accounting =
X`09`09`7Bsizeof(acctrec), DSC$K_DTYPE_T, DSC$K_CLASS_S, acctrec`7D;
X`09struct dsc$descriptor_s temp = `7B0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0`7D;
X
X`09int ltatime`5B2`5D= `7B-1*100000000,-1`7D;
X
X`09notify_qual = FALSE;
X
X`09ascii = TRUE;`09`09`09`09/* assume main file is ascii */
X`09hex = FALSE;
X`09string = FALSE;
X        port = FALSE;
X`09land = FALSE;
X`09ps = FALSE;
X`09tek = FALSE;
X`09ansi = FALSE;
X`09stopoutput = FALSE;
X`09nup = FALSE;
X`09notify = FALSE;
X`09userlog = -1;`09`09`09/* flag not opened yet */
X`09
X`09if (laserchan == 0) exit(LASER$_STREAMNOTSTART);
X`09
X`09stat = smb$send_to_jobctl(&0, &SMBMSG$K_START_TASK, 0, 0, 0, 0);
X`09checkstat(stat, "processtask: send to jobctl");
X
X`09getitemdescrip(SMBMSG$K_USER_NAME, &user_notify, TRUE);
X`09`09`09`09`09/* Get username for error messages. */
X`09`7B
X`09`09int flags;
X`09`09struct `7B
X`09`09`09short buffer_length;
X`09`09`09short item_code;
X`09`09`09int buffer_address;
X`09`09`09int return_length_address;
X`09`09`7D itmlst`5B4`5D = `7B4, QUI$_SEARCH_NUMBER, &entry_num, 0,
X`09`09`09       4, QUI$_JOB_FLAGS, &flags, 0,
X`09`09`09       sizeof(queue_name)-1, QUI$_QUEUE_NAME, queue_name, &queue_na
Vme_l,
X`09`09`09       0, 0, 0, 0`7D;
X`09`09getitemdescrip(SMBMSG$K_ENTRY_NUMBER, &temp, TRUE);
X`09`09memcpy(&entry_num,temp.dsc$a_pointer,4);
X`09`09stat = sys$getquiw(0, QUI$_DISPLAY_ENTRY, 0, &itmlst, 0, 0, 0);
X`09`09checkstat(stat, "getquiw");
X`09`09notify_qual = flags & QUI$M_JOB_NOTIFY;
X`09`7D
X
X`09if (lta_device) `7B
X`09   getitemdescrip(SMBMSG$K_ENTRY_NUMBER, &temp, TRUE);
X`09   memcpy(&stat,temp.dsc$a_pointer,4);
X`09   if (stat == jobnum)
X`09      sys$cantim(ltaefn,0);      /* Cancel ast that deassigns device */
X`09   else if (!jobnum) `7B`09`09 /* Deassigning ast already run? */
X`09      jobnum = stat;`09`09 /* Yes, so just store new job number */
X`09      assigndev();
X`09   `7D else `7B
X`09      jobnum = stat;
X`09      sys$cantim(ltaefn,0);  /* Cancel ast that deassigns device */
X`09      dassgndev();`09     /* Deassign to allow other nodes access */
X`09      assigndev();
X`09   `7D
X`09`7D
X
X`09if (notify_qual) `7B
X`09`09char job`5B255`5D;
X`09`09if (getitemdescrip(SMBMSG$K_JOB_NAME, &temp, FALSE)) `20
X`09`09`09strncpy(job, temp.dsc$a_pointer, temp.dsc$w_length);
X`09`09else
X`09`09`09temp.dsc$w_length = 0;
X`09`09job`5Btemp.dsc$w_length`5D = 0;
X`09`09stat = sys$getmsg(LASER$_STARTJOB, &msglen, &msgd, 15, 0);
X`09`09checkstat(stat,"$getmsg");
X`09`09message`5Bmsglen`5D = 0;
X`09`09queue_name`5Bqueue_name_l`5D = 0;
X`09`09msg`5B5`5D = '%';
X`09`09sprintf(&msg`5B6`5D,&message`5B1`5D,&job,entry_num,&queue_name);
X`09`09errmsg_dsc.dsc$w_length = strlen(msg) - 5;
X`09`09errmsg_dsc.dsc$a_pointer = &msg`5B5`5D;
X`09`09sndmsg(0);
X        `7D
X
X`09status_error = FALSE;
X`09postlaserread();`09`09`09/* post read  */
X`09if (!syncprinter() `7C`7C stop_task) goto skip1;
X`09`09`09`09`09`09/* synchronize with printer */
X`09checkspooled();`09`09`09`09/* check for spooled file */
X`09oldiocount = iocount = 0;
X`09sys$setimr(stateefn,&statetime,&statetimeout,stateefn,0);
X`09trailer(0);`09`09`09`09/* flag pages */
X`09if (!openfile()) goto skip;`09`09/* open main file */
X/*`09getcopies();*/`09`09`09`09/* send copy count */
X`09getnote();`09`09`09`09/* output possible note */
X`09if (!getsetup()) goto skip;`09`09/* output setup module */
X`09sendfile();`09`09`09`09/* send main file */
Xskip:
X`09closefile();`09`09`09`09/* close main file */
X`09trailer(1);`09`09`09`09/* send trailer */
X`09sys$cantim(stateefn,0);
X`09sendendsequence();`09`09`09/* send job sequence */
X`09if (notify_qual && userlog > 0) `7B`09/* if errors logged */
X`09`09stat = sys$getmsg(LASER$_CREATELOG, &msglen, &msgd, 15, 0);
X`09`09checkstat(stat,"$getmsg");
X`09`09strncpy(&msg`5B5`5D,message,msglen);
X`09`09errmsg_dsc.dsc$w_length = msglen;
X`09`09errmsg_dsc.dsc$a_pointer = &msg`5B5`5D;
X`09`09sndmsg(0);
X        `7D
X`09closeuserlog();`09`09`09`09/* close user log */
Xskip1:
X`09stat = sys$cancel(laserchan);`09`09/* cancel pending read */
X
X`09start_task = FALSE;`09`09`09/* clear flag */
X
X`09if (lta_device) `7B
X`09   sys$cantim(ltaefn,0);`09/* Cancel deassign lta routine */
X`09   sys$setimr(ltaefn,&ltatime,&ltatimeout,ltaefn,0);
X`09`09`09`09`09/* Requeue timer ast */
X`09`7D
X`09
X`09np = endpage - startpage;`09`09 /* compute page count */
X`09if (np >0) acctrec`5B0`5D = np;`09`09 /* if no obvious error */
X
X/*  If stop_task, we were stopped by the job controller.`09*/
X/*  Else, we were stopped by some other error condition`09        */
X
X`09request = SMBMSG$K_TASK_COMPLETE;
X`09if (stop_task) `7B`09`09`09 /* if task aborted */
X`09`09request = SMBMSG$K_STOP_TASK;
X`09`09svector`5B1`5D = stop_task;
X`09`7D
X`09else if (stop_reason) `7B
X`09`09if (stop_reason == LASER$_MAXITEMS `7C`7C`20
X`09`09    stop_reason == LASER$_ITEMNOTFOUND `7C`7C`20
X`09`09    stop_reason == LASER$_TOOMANYTABS `7C`7C`20
X`09`09    stop_reason == LASER$_FLUSHED `7C`7C`20
X`09`09    stop_reason == LASER$_SETUPNOTFOUND `7C`7C`20
X`09`09    stop_reason == LASER$_INVPARAM) `7B`20
X`09`09`09stat = sys$getmsg(stop_reason, &msglen, &msgd, 15, 0);
X`09`09`09checkstat(stat,"$getmsg");
X`09`09`09strncpy(&msg`5B5`5D,message,msglen);
X`09`09`09errmsg_dsc.dsc$w_length = msglen;
X`09`09`09errmsg_dsc.dsc$a_pointer = &msg`5B5`5D;
X`09`09`09jobid(0);
X                `7D
X`09`09svector`5B1`5D = SS$_ABORT;
X`09`7D
X
X`09releaseitems();`09`09`09`09 /* release item list */
X`09
X`09stat = smb$send_to_jobctl(&0, &request, &accounting,
X`09`090, 0, svector);
X`09checkstat(stat, "processtask: send to jobctl");
X`7D
X
X
X/**`09releaseitems - release item list.
X*
X*`09release dynamic strings gotten by read_items.
X*/
Xreleaseitems()
X`7B
X`09int`09i;
X`09struct dsc$descriptor_d temp = `7B0, DSC$K_DTYPE_T, DSC$K_CLASS_D, 0`7D;
X`09
X`09ii = 0;`09`09`09`09`09 /* clear item index */
X
X`09for (i = 0; i < MAXITEMS; i++) `7B
X`09`09if (item`5Bi`5D.buffer == 0) return;`09/* if end of list */
X`09`09temp.dsc$w_length = item`5Bi`5D.item_size;
X`09`09temp.dsc$a_pointer = item`5Bi`5D.buffer;
X`09`09str$free1_dx(&temp);
X`09`09item`5Bi`5D.buffer = 0;
X`09`7D
X`7D
X
X
X/**`09resetstream - reset the stream.
X*/
Xresetstream()
X`7B
X`09int stat;
X
X`09stat = smb$send_to_jobctl(&0, &SMBMSG$K_RESET_STREAM, 0, 0, 0, 0);
X`09checkstat(stat, "resetstream: send to jobctl");
X`09
X`09exit (SS$_NORMAL);
X`7D
X
X
X/**`09sendendsequence - send end of job sequence.
X*/
Xsendendsequence()
X`7B
Xstatic char getend`5B`5D = `7B"\004statusdict begin (%%`5B end page   #=) pr
Vint \
Xpagecount pstack pop flush end \r\n\004"`7D;
X
X`09int stat;
X`09int daytim`5B2`5D;`09`09`09`09/* quadword time interval */
X`09int abort_sent = FALSE;
X`09static $DESCRIPTOR(timetowait, "0 :1:30");`09/* +1:30 min */
X`09
X`09endpage = 0;
X
X`09sys$wake(0,0);`09`09`09`09/* eat pending wakeups */
X`09sys$hiber();`09`09`09`09/* (instant return) */
X`09
X`09WRITELASER(getend,strlen(getend))`09/* write end sequence */
X`09
X`09do `7B
X
X`09`09stat = sys$bintim(&timetowait, daytim);
X`09`09checkstat(stat, "bintim");
X`09`09stat = sys$schdwk(0, 0, daytim, 0);`09/* wake up later */
X`09`09checkstat(stat, "schdwk");
X`09
X                if (!stop_task) `7B
X`09`09`09if (endpage) break;`09`09/* if sync occured */
X`09`09`09stat = sys$hiber();
X`09`09`09if (endpage) break;`09`09/* if sync occured */
X`09`09`7D
X`09`09if (stop_task) `7B`09`09/* if stop_task requested */
X`09`09`09if (!abort_sent) `7B
X`09`09`09`09abort_sent = TRUE;
X`09`09`09`09WRITELASER(&0X03,1)`09/* control-c */
X`09`09`09`09lib$wait(&1.0);`09/* wait 1 second */
X`09`09`09`09WRITELASER(&0X04,1)`09/* end of job */
X`09`09`09`09lib$wait(&1.0);`09/* wait 1 second */
X`09`09`09`09WRITELASER(getend,strlen(getend))
X`09`09`09`7D
X                        break;
X`09`09`7D
X`09`09
X`09`09if (!notify && !stop_task) `7B
X`09`09`09stat = sys$getmsg(LASER$_STALLED, &msglen, &msgd, 15, 0);
X`09`09`09checkstat(stat,"$getmsg");
X`09`09`09message`5Bmsglen`5D = 0;
X`09`09`09queue_name`5Bqueue_name_l`5D = 0;
X`09`09`09msg`5B5`5D = '%';
X`09`09`09sprintf(&msg`5B6`5D,&message`5B1`5D,&queue_name);
X`09`09`09errmsg_dsc.dsc$w_length = strlen(msg);
X`09`09`09errmsg_dsc.dsc$a_pointer = &msg`5B0`5D;
X`09`09`09sndmsg(1);
X`09`09`09notify = TRUE;
X`09`09`7D
X`09`09
X`09`7D while (TRUE);
X
X`09if (endpage && notify && !stop_task) `7B
X`09`09stat = sys$getmsg(LASER$_RESUMED, &msglen, &msgd, 15, 0);
X`09`09checkstat(stat,"$getmsg");
X`09`09message`5Bmsglen`5D = 0;
X`09`09queue_name`5Bqueue_name_l`5D = 0;
X`09`09msg`5B5`5D = '%';
X`09`09sprintf(&msg`5B6`5D,&message`5B1`5D,&queue_name);
X`09`09errmsg_dsc.dsc$w_length = strlen(msg) - 5;
X`09`09errmsg_dsc.dsc$a_pointer = &msg`5B5`5D;
X`09`09sndmsg(0);
X`09`09notify = FALSE;
X`09`7D
X`09
X`09stat = sys$canwak(0,0);`09/* cancel wakeup requests */
X`7D
X
X
X/**`09sendfile - send the main file to the printer.
X*/
Xsendfile()
X`7B
X#define IBUFSIZE (16384)
X#define PREFIX_LEN (1)`09`09`09`09/* max extra prefix chars */
X`09int stat, end;
X#if 0
X`09char ibuf`5BIBUFSIZE`5D;`09`09`09/* input buffer */
X`09char obuf`5BIBUFSIZE*2+2`5D;`09`09/* output buffer */
X#else
X`09char *ibuf;
X`09char *obuf;
X#endif
X`09char *cp;
X`09int rsz = 0;`09`09`09`09/* record size */
X`09char prn_ctl`5B2`5D;`09`09`09/* PRN file control bytes */
X`09int first = TRUE, orsz = 0;
X`09
X`09ibuf = malloc(IBUFSIZE+PREFIX_LEN);`09/* extra for prefix chars */`20
X`09obuf = malloc(IBUFSIZE*2 + 2);
X
X`09main_rab.rab$l_ubf = ibuf+PREFIX_LEN;
X`09main_rab.rab$w_usz = IBUFSIZE;
X
X/*`09For PRN type records, set up a pointer to the carriage control byte  */
X/*`09pair, or initialize the control byte pair manually.`09`09     */
X`09`09
X        if (tek)                       /* if file is tektronix, init */
X               tek2ps(cp, obuf, &-1);
X
X`09if (main_fab.fab$b_rat & FAB$M_PRN) `7B
X`09`09if (main_fab.fab$b_fsz == 2) `7B
X`09`09`09main_rab.rab$l_rhb = &prn_ctl;`09/* ptr to PRN ctrl */
X`09`09     `7D
X`09`09else `7B
X`09`09`09prn_ctl`5B0`5D = 0x01;`09/* LF CR before */
X`09`09`09prn_ctl`5B1`5D = 0x8d;`09/* CR after */
X`09`09     `7D
X`09`7D
X
X`09do `7B`09`09`09`09`09/* send the file */
X`09`09if (main_fab.fab$b_fac & FAB$M_BIO)`20
X`09`09`09stat = sys$read(&main_rab, 0, 0);`09/* get a record */
X`09`09else
X`09`09`09stat = sys$get(&main_rab, 0, 0);`09/* get a record */
X
X`09`09if (!first `7C`7C stat != RMS$_RTB) `7B
X`09`09`09if ((stat == RMS$_EOF) `7C`7C (stop_task `7C stop_reason)) break;
X`09`09`09if (!(stat & 1)) `7B`09`09`09/* if error */
X`09`09`09`09stop_reason = stat;
X`09`09`09`09break;
X`09`09`09`7D
X`09`09`7D
X
X`09`09if (stopoutput) break;
X`09`09
X`09`09rsz = main_rab.rab$w_rsz;
X`09`09
X`09`09cp = ibuf+PREFIX_LEN;`09`09/* Leave room for prefix chs */
X
X`09`09if (first && !tek && !ps && !ansi) `7B
X`09`09 `09if (stat != RMS$_RTB &&rsz && string &&
X`09`09`09   (((main_fab.fab$b_rat & FAB$M_FTN) && cp`5B1`5D=='%')
X`09                   `7C`7C (!(main_fab.fab$b_rat & FAB$M_FTN) &&
X`09`09`09   (cp`5B0`5D=='%' `7C`7C
X`09`09`09   (rsz > 1 && cp`5B0`5D==10 && cp`5B1`5D=='%'))))) `7B
X                                ascii = TRUE;
X`09                        string = FALSE;
X`09`09`09`09ps = TRUE;
X`09                `7D
X`09`09`09if (!ps) `7B
X`09`09`09`09tek = (stat == RMS$_RTB);
X`09`09`09`09if (!tek && rsz) `7B
X`09`09`09`09`09int i;`20
X`09`09`09`09`09for (i=0; i<rsz && !tek; i++)
X`09`09`09`09`09`09if (cp`5Bi`5D == 29) tek = TRUE;
X`09`09`09`09`7D
X`09`09`09`7D
X`09`09`09if (tek) `7B
X`09`09`09`09$DESCRIPTOR(tek4014, "TEK4014");
X`09`09`09`09if (stat == RMS$_RTB) sys$close(&main_fab, 0, 0);
X`09`09`09`09tek = TRUE;
X`09`09`09        hex = FALSE;
X`09`09        `09string = FALSE;
X`09`09`09        ps = FALSE;
X`09`09`09`09if (stat == RMS$_RTB) openfile();
X`09`09`09`09if (!writemodule(tek4014)) `7B
X`09`09`09`09`09stop_reason = LASER$_SETUPNOTFOUND;
X`09`09`09`09`09free(ibuf);
X`09`09`09`09`09free(obuf);`09
X`09`09`09`09`09return FALSE;
X`09`09`09`09`7D
X`09`09`09        WRITELASER("NP\n",3)
X`09`09`09        if (port) WRITELASER("portrait\n",9)
X`09`09                tek2ps(cp, obuf, &-1);
X`09`09`09`09if (stat == RMS$_RTB) `7B
X`09`09`09`09`09main_rab.rab$l_ubf = cp+PREFIX_LEN;
X`09`09`09`09`09main_rab.rab$w_usz = IBUFSIZE;
X        `09                `09stat = sys$read(&main_rab, 0, 0);
X`09`09`09`09`7D
X`09                `7D
X                `7D
X
X`09`09first = FALSE;
X/*  Process record control. */
X
X`09`09if (ascii `7C`7C string) `7B
X`09`09        /* if FTN (Fortran) carriage control */
X`09`09`09if (main_fab.fab$b_rat & FAB$M_FTN) `7B
X`09`09`09       if (rsz == 0) `7B`09/* Null record => blank line */
X`09`09`09`09 cp`5Brsz++`5D = ' ';
X`09`09`09       `7D
X`09`09`09       switch(*cp) `7B
X`09`09`09       case 0:`09`09/* (null) - No CC */
X`09`09`09`09 cp++;`09`09/* ignore column 1 */
X`09`09`09`09 rsz--;
X`09`09`09`09 break;
X`09`09`09       case '0':`09/* 0 - Double Space */
X`09`09`09`09 *cp = '\n';`09/* 2 LF in front, CR at end */
X`09`09`09`09 *--cp = '\n';    `20
X`09`09`09`09 rsz++;
X`09`09`09`09 cp`5Brsz++`5D = '\r';
X`09`09`09`09 break;
X`09`09`09       case '1':`09/* 1 - Page Eject */
X`09`09`09`09 *cp = '\n';
X`09`09`09`09 *--cp = '\f';
X`09`09`09`09 rsz++;
X`09`09`09`09 cp`5Brsz++`5D = '\r';
X`09`09`09`09 break;
X`09`09`09       case '+':`09/* + - overprint */
X`09`09`09`09 cp++;`09`09/* ignore column 1 */
X`09`09`09`09 cp`5Brsz-1`5D = '\r';
X`09`09`09`09 break;
X`09`09`09       case '$':`09/* $ - no trailing CC */
X`09`09`09`09 *cp = '\r';`09/* LF, CR before record */
X`09`09`09`09 *--cp = '\n';    `20
X`09`09`09`09 rsz++;
X`09`09`09`09 break;
X`09`09`09       default :`09/* space, etc. */
X`09`09`09`09 *cp = '\n';
X`09`09`09`09 cp`5Brsz++`5D = '\r';
X`09`09`09`09 `7D
X
X`09`09`09`7D
X
X`09`09`09/*  if implied carriage control */
X`09`09`09if (main_fab.fab$b_rat & FAB$M_CR) `7B
X`09`09`09`09*--cp = '\n';`09/* prefix LF, suffix CR */
X`09`09`09`09rsz++;
X`09`09`09`09cp`5Brsz++`5D = '\r';
X`09`09`09`7D
X
X`09`09`09/*  print carriage control.  Expand and output`09  */
X`09`09`09/* leading carriage control, then expand trailing */
X`09`09`09/* control to output after the text.`09`09  */
X`09`09`09if (main_fab.fab$b_rat & FAB$M_PRN) `7B
X`09`09`09`09expand_cc(prn_ctl`5B0`5D);
X`09`09`09`7D
X`09`09`09
X`09`09`09if (string)`20
X`09`09`09`09expand_line(cp, obuf, rsz);
X`09`09`09else `7B
X`09`09`09`09if (orsz + rsz > IBUFSIZE) `7B
X`09`09`09`09`09WRITELASERBUF(obuf,orsz)`20
X                                        orsz = 0;
X`09                        `7D
X`09`09`09`09memcpy(&obuf`5Borsz`5D,cp,rsz);
X                                orsz = orsz + rsz;
X                        `7D
X
X`09`09`09if (main_fab.fab$b_rat & FAB$M_PRN)
X`09`09`09`09expand_cc(prn_ctl`5B1`5D);
X`09`09`7D
X`09`09
X                if (tek)                       /* if file is tektronix */
X                        tek2ps(cp, obuf, &rsz);
X`09`09else if (hex)`09`09`09/* if file to be hexified */
X`09`09`09expand_hex(cp, obuf, rsz);
X
X`09`7D while (TRUE);
X
X        if (!(stop_task `7C stop_reason `7C stopoutput)) `7B
X                if (orsz) WRITELASERBUF(obuf,orsz)
X
X                if (tek && rsz != -1) tek2ps("\037\014", obuf, &2);
X
X                if (string) WRITELASER("EOF\r\n",5)
X
X                if (nup) WRITESTRING("userdict /DMM-nup-post known`7BDMM-nup
V-post`7Dif\r\n")
X        `7D
X
X`09if (!ascii) WRITELASER(&0x0A0D,2)
X`20
X`09free(ibuf);
X`09free(obuf);`09
X
X/*  send abort (`5EC) if stop_task, else eof (`5ED) */
X
X`09if (stop_task `7C stop_reason) end = 3; else end = 4;
X`09WRITELASER(&end,1)
X`7D
X
X
X/**`09setprivs - set process privs.
X*/
Xsetprivs()
X`7B
X`09int stat;
X`09static int privs`5B2`5D =
X`09   `7BPRV$M_ALLSPOOL+PRV$M_PHY_IO+PRV$M_SYSPRV+PRV$M_OPER+PRV$M_WORLD,0`7
VD;
X
X`09stat = sys$setprv(1, privs, 0, 0);
X`09checkstat(stat, "set privs");
X`7D
X
X
X
X/**`09set_typeahead.
X*
X*`09Set /typeahead on the terminal device so characters will be
X*`09buffered.
X*/
Xset_typeahead(chan)
Xint chan;`09`09`09`09`09/* laserwriter channel */
X`7B
X`09int mode`5B3`5D;
X`09int stat;
X
X`09stat = sys$qiow(0, chan, IO$_SENSEMODE, 0, 0, 0,
X`09`09mode, 12, 0, 0, 0, 0);
X`09if (!(stat & 1)) return stat;
X`09
X`09mode`5B1`5D &= `7E(TT$M_NOTYPEAHD);`09`09/* clear notypeahead */
X`09stat = sys$qiow(0, chan, IO$_SETMODE, 0, 0, 0,`09
X`09`09mode, 12, 0, 0, 0, 0);
X
X`09return stat;
X`7D
X
X
X/**`09startstream - start the stream.
X*/
Xstartstream()
X`7B
X`09int`09stat;
X`09static int svector`5B2`5D = `7B1,0`7D;`09`09/* status vector */
X
X`09struct dsc$descriptor_s device = `7B0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0`7D
V;
X`09struct dsc$descriptor_s temp = `7B0, DSC$K_DTYPE_T, DSC$K_CLASS_S, 0`7D;
X`09
X`09getitemdescrip(SMBMSG$K_DEVICE_NAME, &device, TRUE);
X
X`09lta_device = strstr(device.dsc$a_pointer,"LTA");
X`09if (lta_device) lib$get_ef(&ltaefn);
X
X/*  Copy the library file specification, if it exists */
X`09
X`09if (getitemdescrip(SMBMSG$K_LIBRARY_SPECIFICATION, &temp, FALSE))
X`09`09str$copy_dx(&library_spec, &temp);
X
X`09svector`5B1`5D = sys$alloc(&device, 0, 0, 0, 0);
X`09if (svector`5B1`5D == SS$_NORMAL)`20
X`09`09svector`5B1`5D = sys$assign(&device, &laserchan, 0, 0);
X`09if (svector`5B1`5D != SS$_NORMAL) `7B
X`09`09stat = smb$send_to_jobctl(&0, &SMBMSG$K_START_STREAM,
X`09`09`090, 0, 0, svector);
X`09`09checkstat(stat, "startstream: send to jobctl");
X`09`09return;
X`09`7D
X
X`09set_typeahead(laserchan);`09`09/* set terminal typeahead */
X`09
X`09stat = smb$send_to_jobctl(&0, &SMBMSG$K_START_STREAM,
X`09`090, 0, 0, 0);`09`09`09/* ok */
X`09checkstat(stat, "startstream: send to jobctl");
X`7D
X
Xdassgndev()
X`7B
X`09int stat;`09
X`09stat = sys$qiow(0, laserchan,IO$_TTY_PORT+IO$M_LT_DISCON, 0, 0, 0,
X`09`090, 0, 0, 0, 0, 0);
X`7D
X
Xassigndev()
X`7B
X`09int stat, send = 1;
X`09unsigned short iosb`5B4`5D;
X`09iosb`5B0`5D = 0;
X`09while (!(iosb`5B0`5D & 1)) `7B
X`09`09stat = sys$qiow(0, laserchan,IO$_TTY_PORT+IO$M_LT_CONNECT, iosb, 0, 0,
X`09`09`09`090, 0, 0, 0, 0, 0);
X`09`09if (send && iosb`5B0`5D == SS$_TIMEOUT) `7B
X`09`09`09stat = sys$getmsg(LASER$_TIMEOUT, &msglen, &msgd, 15, 0);
X`09`09`09checkstat(stat,"$getmsg");
X`09`09`09message`5Bmsglen`5D = 0;
X`09`09`09queue_name`5Bqueue_name_l`5D = 0;
X`09`09`09msg`5B5`5D = '%';
X`09`09`09sprintf(&msg`5B6`5D,&message`5B1`5D,&queue_name);
X`09`09`09errmsg_dsc.dsc$w_length = strlen(msg) - 5;
X`09`09`09errmsg_dsc.dsc$a_pointer = &msg`5B5`5D;
X`09`09`09sndmsg(1);
X`09`09`09send = 0;
X`09`09`7D else if (send && iosb`5B0`5D == SS$_ABORT) `7B
X`09`09`09stat = sys$getmsg(LASER$_ABORT, &msglen, &msgd, 15, 0);
X`09`09`09checkstat(stat,"$getmsg");
X`09`09`09message`5Bmsglen`5D = 0; `20
X`09`09`09queue_name`5Bqueue_name_l`5D = 0;
X`09`09`09msg`5B5`5D = '%';
X`09`09`09sprintf(&msg`5B6`5D,&message`5B1`5D,&queue_name,iosb`5B1`5D);
X`09`09`09errmsg_dsc.dsc$w_length = strlen(msg) - 5;
X`09`09`09errmsg_dsc.dsc$a_pointer = &msg`5B5`5D;
X`09`09`09sndmsg(1);
X`09`09`09send = 0;
X`09`09`7D
X`09`09if (!(iosb`5B0`5D & 1)) lib$wait(&1.0);`09/* wait 1 second */
X`09`7D
X`7D
X
X
X/**`09stopstream - stop the stream.
X*/
Xstopstream()
X`7B
X`09int stat;
X
X`09if (lta_device && jobnum)
X`09`09stat = sys$qio(0, laserchan,IO$_TTY_PORT+IO$M_LT_DISCON, 0, 0, 0,
X`09`090, 0, 0, 0, 0, 0);
X
X`09stat = sys$dassgn(laserchan);
X`09checkstat(stat, "stopstream: dassgn");
X`09laserchan = 0;
X
X`09stat = smb$send_to_jobctl(&0, &SMBMSG$K_STOP_STREAM, 0, 0, 0, 0);
X`09checkstat(stat, "stopstream: send to jobctl");
X`09
X`09exit(SS$_NORMAL);
X`7D
X
X
X/**`09syncprinter - get synchronized with printer.
X*/
Xsyncprinter()
X`7B
Xstatic char getstart`5B`5D = `7B
X"\004\
Xversion (23.0) eq `7B statusdict /Patch1Installed known not `7B \
X(%%`5B patch needed `5D%%\n) print `7D if `7D if \
Xstatusdict begin (%%`5B start page #=) print \
Xpagecount pstack pop flush end \r\n\004"`7D;
X
X`09int stat;
X`09int daytim`5B2`5D;`09`09`09`09/* quadword time interval */
X`09static $DESCRIPTOR(timetowait, "0 ::10");`09/* +10 sec */
X`09static $DESCRIPTOR(patch, "PATCH");
X`09int firstabort;
X`09static int expiretime`5B`5D = `7B1,1*60/10,5*60/10,10*60/10,60*60/10`7D;
V /* notify intervals */
X#define NEXPIRES (sizeof(expiretime)/sizeof(int))
X`09startpage = 0;
X
X`09status_idle = FALSE;
X`09
X`09firstabort = TRUE;
X`09do `7B
X`09`09lib$wait(&1.0);`09`09`09/* wait 1 second */
X`09`09WRITELASER(&0x14,1)`09`09/* `5ET */
X
X`09`09stat = sys$bintim(&timetowait, daytim);
X`09`09checkstat(stat, "bintim");
X`09`09stat = sys$schdwk(0, 0, daytim, 0);`09/* wake up later */
X`09`09checkstat(stat, "schdwk");
X
X`09`09stat = sys$hiber();
X`09`09if (status_idle) break;`09/* if sync occured */
X
X/*  Abort whatever is happening */
X
X`09`09if (!status_error) `7B
X`09`09`09WRITELASER(&0X03,1)`09`09/* control-c */
X`09`09`09lib$wait(&1.0);`09`09`09/* wait 1 second */
X`09`09`09WRITELASER(&0X04,1)`09`09/* end of job */
X`09`09`09lib$wait(&1.0);`09`09`09/* wait 1 second */
X`09`09`7D
X
X/*  Notify the user. */
X`09`09
X`09`09if (!notify && !firstabort && !stop_task) `7B
X`09`09`09stat = sys$getmsg(LASER$_STALLED, &msglen, &msgd, 15, 0);
X`09`09`09checkstat(stat,"$getmsg");
X`09`09`09message`5Bmsglen`5D = 0;
X`09`09`09queue_name`5Bqueue_name_l`5D = 0;
X`09`09`09msg`5B5`5D = '%';
X`09`09`09sprintf(&msg`5B6`5D,&message`5B1`5D,&queue_name);
X`09`09`09errmsg_dsc.dsc$w_length = strlen(msg);
X`09`09`09errmsg_dsc.dsc$a_pointer = &msg`5B0`5D;
X`09`09`09sndmsg(1);
X`09`09`09notify = TRUE;
X`09`09`7D
X
X`09`09firstabort = FALSE;
X`09`09
X`09`7D while (TRUE);
X
X`09stat = sys$canwak(0,0);`09/* cancel wakeup requests */
X
X        if (stop_task) return FALSE;
X
X`09if (status_idle && notify) `7B
X`09`09stat = sys$getmsg(LASER$_RESUMED, &msglen, &msgd, 15, 0);
X`09`09checkstat(stat,"$getmsg");
X`09`09message`5Bmsglen`5D = 0;
X`09`09queue_name`5Bqueue_name_l`5D = 0;
X`09`09msg`5B5`5D = '%';
X`09`09sprintf(&msg`5B6`5D,&message`5B1`5D,&queue_name);
X`09`09errmsg_dsc.dsc$w_length = strlen(msg) - 5;
X`09`09errmsg_dsc.dsc$a_pointer = &msg`5B5`5D;
X`09`09sndmsg(0);
X`09`09notify = FALSE;
X`09`7D
X`09
X`09do `7B
X`09`09WRITELASER(getstart,strlen(getstart))
X
X`09`09stat = sys$bintim(&timetowait, daytim);
X`09`09checkstat(stat, "bintim");
X`09`09stat = sys$schdwk(0, 0, daytim, 0);`09/* wake up later */
X`09`09checkstat(stat, "schdwk");
X
X`09`09stat = sys$hiber();
X`09`09if (startpage) break;`09/* if sync occured */
X
X/*  Notify the user. */
X`09`09
X`09`09if (!notify && !stop_task) `7B
X`09`09`09stat = sys$getmsg(LASER$_STALLED, &msglen, &msgd, 15, 0);
X`09`09`09checkstat(stat,"$getmsg");
X`09`09`09message`5Bmsglen`5D = 0;
X`09`09`09queue_name`5Bqueue_name_l`5D = 0;
X`09`09`09msg`5B5`5D = '%';
X`09`09`09sprintf(&msg`5B6`5D,&message`5B1`5D,&queue_name);
X`09`09`09errmsg_dsc.dsc$w_length = strlen(msg);
X`09`09`09errmsg_dsc.dsc$a_pointer = &msg`5B0`5D;
X`09`09`09sndmsg(1);
X`09`09`09notify = TRUE;
X`09`09`7D
X`09`09
X`09`7D while (TRUE);
X`09
X`09stat = sys$canwak(0,0);`09/* cancel wakeup requests */
X
X        if (stop_task) return FALSE;
X
X`09if (startpage && notify) `7B
X`09`09stat = sys$getmsg(LASER$_RESUMED, &msglen, &msgd, 15, 0);
X`09`09checkstat(stat,"$getmsg");
X`09`09message`5Bmsglen`5D = 0;
X`09`09queue_name`5Bqueue_name_l`5D = 0;
X`09`09msg`5B5`5D = '%';
X`09`09sprintf(&msg`5B6`5D,&message`5B1`5D,&queue_name);
X`09`09errmsg_dsc.dsc$w_length = strlen(msg) - 5;
X`09`09errmsg_dsc.dsc$a_pointer = &msg`5B5`5D;
X`09`09sndmsg(0);
X`09`09notify = FALSE;
X`09`7D
X`09
X/*  This looks like a good place to send the patch module */
X
X`09if (patchneeded) `7B`09`09`09/* if patch needed */
X`09`09patchneeded = FALSE;
X`09`09writemodule(patch);`09`09/* write the patch module */
X`09`09WRITELASER(&4, 1)
X`09`7D
X
X`09return TRUE;
X`7D
X`09
X
X/**`09trailer - issue job trailer.
X*/
Xtrailer(which)
Xint which;`09`09`09`09`09/* 0 if flag, 1 if trailer */
X`7B
X`09int ctl, stat, stop;
X`09short msglen;
X`09char buf`5B1024`5D;`09`09`09`09/* scratch buffer */
X`09char time`5B24`5D;
X`09char user`5B20`5D,job`5B255`5D, file`5B255`5D, message`5B257`5D;
X`09char *cp;
X`09static char z = 0;
+-+-+-+-+-+-+-+-  END  OF PART 3 +-+-+-+-+-+-+-+-

Newsgroups: comp.os.vms