1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
|
# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
include <syserr.h>
include <config.h>
include <error.h>
include <prstat.h>
include <fset.h>
include <fio.h>
include <gio.h>
include <gki.h>
include "gtr.h"
# GTR_OPENWS -- Called by gtr_control(pr_psio) to connect a kernel to a
# graphics stream and to initialize the datapath to the kernel.
# The workstation is not physically opened until the GKI open workstation
# directive has been sent to the kernel. There are two types of kernels,
# the builtin (STDGRAPH) kernel, and all external kernels. The external
# kernels reside in connected subprocesses communicating via the central
# process (the CL process) with the graphics task in another subprocess.
procedure gtr_openws (devspec, mode, stream, source_pid)
char devspec[ARB] #I device specification
int mode #I access mode
int stream #I graphics stream
int source_pid #I process which issued the openws directive
int redir_code, dd[LEN_GKIDD], ip
pointer sp, op, tr, tty, kernfname, taskname, device
bool streq()
pointer ttygdes()
int pr_getredir(), ttygets(), gtr_connect(), pr_findproc(), locpr()
extern gtr_reset(), prpsio()
errchk syserr, syserrs, fseti, ttygdes, ttycdes, pr_redir, stg_close, stg_open
errchk gtr_connect, gtr_disconnect
include "gtr.com"
begin
call smark (sp)
call salloc (kernfname, SZ_FNAME, TY_CHAR)
call salloc (taskname, SZ_FNAME, TY_CHAR)
call salloc (device, SZ_FNAME, TY_CHAR)
tr = trdes[stream]
# Extract the device name field from the device specification.
op = device
for (ip=1; devspec[ip] != EOS; ip=ip+1)
if (devspec[ip] == ',')
break
else {
Memc[op] = devspec[ip]
op = op + 1
}
Memc[op] = EOS
# We only connect up the i/o channels, and do not issue the OPENWS
# to the gio kernel, so reset the counter to zero to indicate that
# the workstation has not yet been (logically) opened.
TR_WSOPEN(tr) = 0
# If the stream has been redirected into a file, do not connect a
# kernel.
redir_code = pr_getredir (source_pid, stream)
if (redir_code >= FIRST_FD && redir_code <= LAST_FD) {
call sfree (sp)
return
}
# The graphics stream is a spoolfile in this process (the CL process).
# Spoolfiles are files that are fully buffered in memory and never
# get written to disk. Data is written into the spoolfile and then
# read back out by a different part of the program.
call fseti (stream, F_TYPE, SPOOL_FILE)
call fseti (stream, F_CANCEL, OK)
# If the device is already connected to the stream (or we are
# appending to a connected device) all we need do is reset the
# redirection code for the graphics stream. This code is reset to
# the default value (the code for the stream itself) by the CL when
# a task is spawned.
if (TR_DEVNAME(tr) != EOS && mode == APPEND ||
streq (devspec, TR_DEVNAME(tr))) {
call pr_redir (source_pid, stream, TR_REDIR(tr))
call sfree (sp)
return
}
# Connect the named kernel, i.e., disconnect the old kernel if any
# and connect the new one. Set the redirection information for the
# named stream of the source process.
iferr {
# Close device graphcap descriptor.
if (TR_TTY(tr) != NULL)
call ttycdes (TR_TTY(tr))
# Disconnect old kernel.
if (streq (TR_KERNFNAME(tr), "cl"))
call stg_close()
else if (TR_DEVNAME(tr) != EOS && TR_KERNFNAME(tr) != EOS) {
call gtr_disconnect (TR_PID(tr), TR_IN(tr), TR_OUT(tr), stream)
TR_PID(tr) = NULL
TR_IN(tr) = NULL
TR_OUT(tr) = NULL
}
} then {
TR_DEVNAME(tr) = EOS
call erract (EA_ERROR)
} else
TR_DEVNAME(tr) = EOS
# Get graphcap entry for the new device. The special device name
# "none" indicates that there is no suitable stdgraph device.
if (streq (devspec, "none")) {
switch (stream) {
case STDGRAPH:
call syserr (SYS_GGNONE)
case STDIMAGE:
call syserr (SYS_GINONE)
case STDPLOT:
call syserr (SYS_GPNONE)
default:
call syserr (SYS_GGNONE)
}
} else {
tty = ttygdes (Memc[device])
TR_TTY(tr) = tty
}
# Get the name of the executable file containing the kernel for the
# device. The special name "cl" signifies the builtin STDGRAPH kernel.
if (ttygets (tty, "kf", Memc[kernfname], SZ_FNAME) <= 0) {
call ttycdes (tty)
call syserrs (SYS_GNOKF, Memc[device])
} else if (ttygets (tty, "tn", Memc[taskname], SZ_FNAME) <= 0)
;
# Connect the new kernel.
call strcpy (Memc[kernfname], TR_KERNFNAME(tr), SZ_KERNFNAME)
if (streq (Memc[kernfname], "cl")) {
# Open the stdgraph kernel. Connect the referenced GKI stream to
# the stdgraph kernel. Set a negative redirection code value to
# flag that GIOTR is to be called to filter graphics output from
# the process.
call stg_open (devspec, dd, STDIN, STDOUT, 0, 0, 0)
call gki_inline_kernel (stream, dd)
if (source_pid != NULL)
call pr_redir (source_pid, stream, -stream)
TR_REDIR(tr) = -stream
TR_INTERACTIVE(tr) = YES
} else {
# Spawn subprocess and start up kernel task.
TR_PID(tr) = gtr_connect (Memc[kernfname], Memc[taskname],
devspec, stream, TR_IN(tr), TR_OUT(tr))
# Encode the process slot number of the kernel process in the
# redirection code for the source process (the process which
# issued the openws). If the stream is STDGRAPH or STDIMAGE
# make the redirection code negative to flag that graphics
# output is to be processed through GIOTR (the workstation
# transformation).
if (source_pid != NULL) {
redir_code = (pr_findproc(TR_PID(tr)) * KSHIFT) + stream
if (stream == STDGRAPH || stream == STDIMAGE)
redir_code = -redir_code
call pr_redir (source_pid, stream, redir_code)
TR_REDIR(tr) = redir_code
# Mark the process busy. This flags it it as busy executing
# some subprotocol (in this case processing GKI metacode) and
# prevents commands such as chdir/set from being sent to the
# process and corrupting the IPC protocol.
call prseti (TR_PID(tr), PR_STATUS, P_BUSY)
}
call gki_subkernel (stream, TR_PID(tr), locpr(prpsio))
TR_INTERACTIVE(tr) = NO
}
# Do not change value of DEVNAME until the new kernel has been
# successfully connected, since this variable is used to test if
# the kernel is already connected.
call strcpy (devspec, TR_DEVNAME(tr), SZ_TRDEVNAME)
# Post the gtr_reset procedure to be executed upon process shutdown,
# to close down any connected graphics subkernels in an orderly way.
call onexit (gtr_reset)
call sfree (sp)
end
|