aboutsummaryrefslogtreecommitdiff
path: root/unix/os/zfiopl.c
blob: 264688349ddd4b3371706bf3edc4265bc23f285f (plain) (blame)
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
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
 */

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>

#define	import_kernel
#define	import_knames
#define	import_zfstat
#define	import_prtype
#define import_spp
#include <iraf.h>

/*
 * ZFIOPL -- IRAF FIO interface to plotter devices.  A plotter
 * is opened as a streaming type (no seeks) write-only binary device.
 * FIO writes NCAR metacode to the plotter.  This metacode is spooled
 * in a temporary file and then disposed of to the plotter by calling
 * an OS metacode translator to process the file.  The spoolfile is then
 * deleted.
 *
 * The system and device dependent information necessary to perform these
 * functions is contained in three strings passed as the "device" parameter
 * to ZOPNPL.  The strings come from the GRAPHCAP entry for the device.
 * The format of such a string is
 *
 *	device D spoolfile D dispose_cmd EOS
 *
 * where DEVICE is the logical device name (not used herein), D is the field
 * delimiter character (the first nonalphnumeric character encountered after
 * the device field), SPOOLFILE is a UNIX pathname to be passed to MKTEMP
 * to create the spoolfile pathname, and DISPOSE_CMD is a fill-in-the-blanks
 * template for a UNIX shell command which will dispose of the spoolfile to
 * the plotter device.
 */

extern	int save_prtype;

#define	SZ_OSCMD	512		/* buffer for dispose cmd	*/
#define	SZ_PLSTR	256		/* zopnpl plotter argument	*/

struct dplotter {
	char	*name;			/* logical gdevice name		*/
	char	*spoolfile;		/* spoolfile string		*/
	char	*dispose;		/* dispose format string	*/
};

struct oplotter {
	long	wbytes;			/* nbytes written to device	*/
	struct	dplotter *pl;		/* device code as above		*/
	int	status;			/* status of last write		*/
	char	spoolfile[SZ_PATHNAME+1];
};

struct	dplotter dpltr;			/* machdep plotter info		*/
struct	oplotter pltr;			/* open plotter descriptor	*/
char	plstr[SZ_PLSTR+1];		/* save zopnpl argument		*/
int	pltr_inuse = NO;		/* set if plotter is open	*/


extern  int ZOPNBF (), ZCLSBF (), ZOSCMD (), ZFDELE (), ZARDBF ();
extern  int ZAWRBF (), ZAWTBF (), ZSTTBF ();



/* ZOPNPL -- Open a plotter device for binary file i/o.  If we can talk
 * directly to the plotter, do so, otherwise open a spoolfile which is
 * to be sent to the plotter when ZCLSPL is later called.
 */
int
ZOPNPL (
  PKCHAR  *plotter,		/* plotter device descriptor		*/
  XINT	  *mode,		/* file access mode			*/
  XINT	  *chan 		/* UNIX file number (output)		*/
)
{
	register char *ip;
	static char delim;
	int fd;

	/* We do not see a need to have more than one plotter open at
	 * a time, and it makes things simpler.  We can easily generalize
	 * to multiple open plotter devices in the future if justified.
	 */
	if (pltr_inuse == YES) {
	    *chan = XERR;
	    return (XERR);
	} else
	    pltr_inuse = YES;
	
	/* Parse the plotter string into the name, spoolfile, and dispose
	 * strings.
	 */
	strncpy (plstr, (char *)plotter, SZ_PLSTR);

	/* Locate NAME field. */
	dpltr.name = plstr;
	for (ip=plstr;  isalnum(*ip);  ip++)
	    ;
	delim = *ip;
	*ip++ = EOS;

	/* Locate SPOOLFILE field. */
	for (dpltr.spoolfile=ip;  *ip && *ip != delim;  ip++)
	    ;
	*ip++ = EOS;

	/* Locate DISPOSE field. */
	for (dpltr.dispose=ip;  *ip && *ip != delim;  ip++)
	    ;
	*ip++ = EOS;

	/* Initialize the open plotter descriptor.
	 */
	pltr.wbytes = 0L;
	pltr.pl = &dpltr;
	strcpy (pltr.spoolfile, dpltr.spoolfile);
	if (dpltr.dispose[0] != EOS)
	    if ((fd = mkstemp (pltr.spoolfile)) >= 0) {
		fchmod (fd, 0644);
		close (fd);
	    }
	
	return ZOPNBF ((PKCHAR *)pltr.spoolfile, mode, chan);
}


/* ZCLSPL -- To close a plotter we merely close the "spoolfile", and then
 * dispose of the spoolfile to the OS if so indicated.
 */
int
ZCLSPL (XINT *chan, XINT *status)
{
	static	PKCHAR	xnullstr[1] = { EOS };
	register char *ip, *op, *f;
	PKCHAR	cmd[(SZ_OSCMD+1) / sizeof(PKCHAR)];
	XINT	junk;

	ZCLSBF (chan, status);
	pltr_inuse = NO;

	/* Dispose of the output file if so indicated.  Do not bother to
	 * check the status return, since we cannot return status to FIO
	 * from here anyhow.  Do not dispose of the file if it is empty.
	 * If the file is disposed of by the OS, we assume that it is also
	 * deleted after printing.  If file is not disposed to the OS, we
	 * delete it ourselves.
	 */
	if (*(pltr.pl->dispose) != EOS) {
	    if (pltr.wbytes > 0) {
		PKCHAR   out[SZ_FNAME+1];

		/* Build up command line by substituting the spoolfile name
		 * everywhere the macro "$F" appears in the "dispose" text.
		 */
		op = (char *)cmd;
		for (ip=pltr.pl->dispose;  (*op = *ip++) != EOS;  op++)
		    if (*op == '$' && *ip == 'F') {
			for (f=pltr.spoolfile;  (*op = *f++) != EOS;  op++)
			    ;
			/* Overwrite EOS, skip over 'F' */
			--op, ip++;
		    }
		strcpy ((char *)out,
		    save_prtype == PR_CONNECTED ? "/dev/tty" : "");
		ZOSCMD (cmd, xnullstr, out, out, &junk);
	    } else
		ZFDELE ((PKCHAR *)pltr.spoolfile, &junk);
	}

	return (*status);
}


/* ZARDPL -- For UNIX, the read and write routines are just the binary file
 * i/o routines.  Note that packing of chars into bytes, mapping of escape
 * sequences, etc. is done by the high level code; our function is merely to
 * move the data to the device.  The read primitive is not likely to be needed
 * for a plotter, but you never know...
 */
int
ZARDPL (
  XINT	 *chan,
  XCHAR	 *buf,
  XINT	 *maxbytes,
  XLONG	 *offset
)
{
	return ZARDBF (chan, buf, maxbytes, offset);
}


/* ZAWRPL -- Write a metafile record to the plotter spoolfile.  We are always
 * called to write metacode; zfiopl is not used to send device codes to the
 * plotter.  Our job is to make the NSPP metacode record passed on to us by
 * WRITEB look like whatever the system metacode translators expect.  On the
 * KPNO system, the metacode translators are Fortran programs, expecting an
 * unformatted binary metacode file as input.  We simulate this file by
 * adding the integer byte count of the record to the beginning and end of
 * each record.
 *
 * N.B.: We ASSUME that the FIO buffer has been set to the size of a metafile
 * record, i.e., 1440 bytes or 720 chars on the VAX.
 */
int
ZAWRPL (
  XINT	 *chan,
  XCHAR	 *buf,
  XINT	 *nbytes,
  XLONG	 *offset 			/* not used		*/
)
{
	static	XINT hdrlen=sizeof(int);
	static	XLONG noffset=0L;
	XINT	status;
	int	reclen;

	/* Write out the integer record header.  Set the file offset to zero
	 * since the file is sequential, and the offsets do not include the
	 * record headers anyhow so are wrong.
	 */
	reclen = *nbytes;
	ZAWRBF (chan, (XCHAR *)&reclen, &hdrlen, &noffset);
	ZAWTBF (chan, &status);

	/* Write the metacode data.
	 */
	pltr.wbytes += *nbytes;
	ZAWRBF (chan, buf, nbytes, &noffset);
	ZAWTBF (chan, &pltr.status);

	/* Write out the integer record trailer.  Set the file offset to zero
	 * since the file is sequential, and the offsets do not include the
	 * record headers anyhow so are wrong.
	 */
	reclen = *nbytes;
	ZAWRBF (chan, (XCHAR *)&reclen, &hdrlen, &noffset);
	ZAWTBF (chan, &status);

	return (status);
}


/* ZAWTPL -- Return the status of the write (we do not read metafiles with
 * the plotter interface).  The status byte count does not include the
 * record header, since that was written with a separate write unbeknownst
 * to FIO, so the status value returned refers only to the metacode data.
 */
int
ZAWTPL (XINT *chan, XINT *status)
{
	ZAWTBF (chan, status);
	if (*status > 0)
	    *status = pltr.status;

	return (*status);
}


/* ZSTTPL -- Get status for the plotter output file.  Plotter output is
 * strictly sequential due to the way metacode records are packaged in
 * ZAWRPL.  Hence we must always return blksize=0 to indicate that the
 * device is a streaming file, regardless of whether or not the output
 * is spooled.
 */
int
ZSTTPL (XINT *chan, XINT *param, XLONG *lvalue)
{
	switch (*param) {
	case FSTT_BLKSIZE:
	    *lvalue = 0L;
	    break;
	default:
	    return ZSTTBF (chan, param, lvalue);
	}
	return (XOK);
}