aboutsummaryrefslogtreecommitdiff
path: root/sys/etc/prgline.x
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@gmail.com>2015-07-08 20:46:52 -0400
committerJoseph Hunkeler <jhunkeler@gmail.com>2015-07-08 20:46:52 -0400
commitfa080de7afc95aa1c19a6e6fc0e0708ced2eadc4 (patch)
treebdda434976bc09c864f2e4fa6f16ba1952b1e555 /sys/etc/prgline.x
downloadiraf-linux-fa080de7afc95aa1c19a6e6fc0e0708ced2eadc4.tar.gz
Initial commit
Diffstat (limited to 'sys/etc/prgline.x')
-rw-r--r--sys/etc/prgline.x204
1 files changed, 204 insertions, 0 deletions
diff --git a/sys/etc/prgline.x b/sys/etc/prgline.x
new file mode 100644
index 00000000..21ec1780
--- /dev/null
+++ b/sys/etc/prgline.x
@@ -0,0 +1,204 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+include <config.h>
+include <syserr.h>
+include <ctype.h>
+include <fset.h>
+
+define XMIT 0
+define XFER 1
+
+# PRGETLINE -- Get a line of text from a process. The function is equivalent
+# to the ordinary FIO getline with the exception that pseudofile read and
+# write directives are intercepted and processed. Hence, the reader sees a
+# stream of application specific commands need not know about pseudofile i/o.
+# The function of PRGETLINE is such that it can be used in place of GETLINE
+# on any file; pseudofile directives are recognized and process only if the
+# FD is associated with a connected subprocess.
+
+int procedure prgetline (fd, lbuf)
+
+int fd # parent's input IPC from child process
+char lbuf[SZ_LINE] # output line buffer
+
+char ch
+int nchars, maxchars, nchars_read, raw_mode_set, ndigits
+int bufsize, outfd, destfd, pr, pseudofile, line_type, offset
+pointer sp, buf, ip
+
+char getc()
+int getline(), read(), fstati(), ctoi(), itoc()
+errchk syserr, getline, fstati, read, write, pr_decodeargs, putc, getc
+include "prc.com"
+
+begin
+ call smark (sp)
+
+ pr = 0
+ buf = NULL
+ raw_mode_set = 0
+
+ repeat {
+ nchars = getline (fd, lbuf)
+
+ # Return immediately if not XMIT or XFER directive. This code is
+ # exercised heavily when performing raw mode i/o, hence some
+ # clarity is sacrificed for the sake of efficiency.
+ #
+ # Syntax: "xmit(P,NNN)" or "xfer(P,NNN)"
+ # 12345678 12345678
+ #
+ # where P is the pseudofile code (0<P<10) and NNN is the size of
+ # the data block in chars. In the following code all explicit
+ # integer constants refer to the character offsets shown above.
+
+ if (lbuf[1] != 'x' || nchars == EOF) {
+ break
+ } else if (lbuf[2] == 'm') {
+ if (lbuf[3] == 'i' && lbuf[4] == 't' && lbuf[5] == '(') {
+ line_type = XMIT
+ pseudofile = TO_INTEG (lbuf[6])
+ } else
+ break
+ } else if (lbuf[2] == 'f') {
+ if (lbuf[3] == 'e' && lbuf[4] == 'r' && lbuf[5] == '(') {
+ line_type = XFER
+ pseudofile = TO_INTEG (lbuf[6])
+ } else
+ break
+ } else
+ break
+
+ # Ignore directive if FD not associated with a process. To minimize
+ # searches of the process table we keep track of the slot number
+ # of the last active pid.
+
+ if (pr == 0) {
+ if (pr_infd[pr_lastio] == fd && pr_pid[pr_lastio] != NULL)
+ pr = pr_lastio
+ else {
+ for (pr=1; pr <= MAX_CHILDPROCS; pr=pr+1)
+ if (pr_pid[pr] != NULL)
+ if (pr_infd[pr] == fd)
+ break
+ if (pr > MAX_CHILDPROCS)
+ break
+ pr_lastio = pr
+ }
+ outfd = pr_outfd[pr]
+ }
+
+ # Map pseudofile code to a file descriptor in the local process.
+
+ destfd = pr_pstofd[pr,pseudofile]
+
+
+ # RAW mode transfers are handled as a special case to minimize the
+ # per-character overhead.
+
+ if (lbuf[8] == '1' && lbuf[9] == ')') {
+ if (line_type == XMIT) {
+ # XMIT
+ if (getc (fd, ch) == EOF)
+ call syserr (SYS_PRIPCSYNTAX)
+
+ # Clear RAW input mode if newline is encountered in output.
+ # Only works for STDIN/STDOUT, but that is all raw mode is
+ # used for with pseudofiles.
+
+ if (ch == '\n')
+ if (destfd == STDOUT) {
+ call fseti (STDIN, F_RAW, NO)
+ if (raw_mode_set == STDIN)
+ raw_mode_set = 0
+ }
+
+ call putc (destfd, ch)
+ call flush (destfd)
+
+ } else {
+ # XFER
+ if (raw_mode_set != destfd) {
+ call fseti (destfd, F_RAW, YES)
+ raw_mode_set = destfd
+ }
+
+ if (getc (destfd, ch) == EOF)
+ call putline (outfd, "0\n")
+ else {
+ call putline (outfd, "1\n")
+ call flush (outfd)
+ call putc (outfd, ch)
+ }
+ call flush (outfd)
+ }
+ next
+ }
+
+
+ # GENERAL XMIT or XFER directive. Read a block of data from one
+ # stream and transmit it to the other stream.
+
+ if (buf == NULL) {
+ bufsize = fstati (fd, F_BUFSIZE)
+ call salloc (buf, bufsize, TY_CHAR)
+ }
+
+ offset = 8
+ if (ctoi (lbuf, offset, nchars) <= 0)
+ call syserr (SYS_PRIPCSYNTAX)
+
+ if (line_type == XMIT) {
+ # XMIT -- Copy the block of data from the IPC channel to the
+ # destination file.
+
+ nchars_read = read (fd, Memc[buf], nchars)
+ if (nchars_read != nchars)
+ call syserr (SYS_PRIPCSYNTAX)
+ else {
+ # Clear RAW input mode if set and newline is encountered
+ # in the output stream.
+
+ if (destfd == STDOUT)
+ if (fstati (STDIN, F_RAW) == YES)
+ for (ip=buf+nchars-1; ip >= buf; ip=ip-1)
+ if (Memc[ip] == '\n') {
+ call fseti (STDIN, F_RAW, NO)
+ if (raw_mode_set == STDIN)
+ raw_mode_set = 0
+ break
+ }
+
+ call write (destfd, Memc[buf], nchars)
+ call flush (destfd)
+ }
+ next
+
+ } else {
+ # XFER -- Read up to maxchars chars from the input file and
+ # pass them on to the output IPC channel.
+
+ maxchars = min (nchars, bufsize)
+ nchars = read (destfd, Memc[buf], maxchars)
+ if (nchars == EOF)
+ nchars = 0
+
+ # Write the byte count record followed by the data record.
+ # These must be written as two separate records or deadlock
+ # will occur (with the reader waiting for the second record).
+
+ ndigits = itoc (nchars, lbuf, SZ_LINE)
+ lbuf[ndigits+1] = '\n'
+ call write (outfd, lbuf, ndigits + 1)
+ call flush (outfd)
+
+ call write (outfd, Memc[buf], nchars)
+ call flush (outfd)
+
+ next
+ }
+ }
+
+ call sfree (sp)
+ return (nchars)
+end