aboutsummaryrefslogtreecommitdiff
path: root/sys/etc/oscmd.x
blob: 78b723c2374cb8564d5293af65d86f408cff6328 (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
# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.

include	<ctype.h>
include	<clset.h>
include	<error.h>
include	<knet.h>

# OSCMD -- Send a (machine dependent) command to the host operating system.
# Try to spool the standard output and error output in the named files if
# nonnull names for the files are given.  OK is returned if the command
# executes successfully.

int procedure oscmd (cmd, infile, outfile, errfile)

char	cmd[ARB]		# host command
char	infile[ARB]		# name of host command input file
char	outfile[ARB]		# name of file to receive output
char	errfile[ARB]		# name of file to receive error output

int	status, ip, ch
pointer	sp, cmdbuf, osin, osout, oserr, ostmp, op
errchk	fmapfn, mktemp, fclobber, flush, putline
int	clstati(), getci()
bool	fnullfile()

begin
	call smark (sp)
	call salloc (cmdbuf, SZ_COMMAND, TY_CHAR)
	call salloc (osin, SZ_PATHNAME, TY_CHAR)
	call salloc (osout, SZ_PATHNAME, TY_CHAR)
	call salloc (oserr, SZ_PATHNAME, TY_CHAR)
	call salloc (ostmp, SZ_PATHNAME, TY_CHAR)

	# If we are called from the root process, e.g., the CL, the ZOSCMD
	# primitive is called directly to transmit the host command, otherwise
	# the OS command is sent up to the parent (root) process which calls
	# ZOSCMD.  This is necessary because the ZOSCMD primitive will not
	# work from a subprocess on some systems, due to difficulties trying
	# to spawn the host command interpreter.

	if (clstati (CL_PRTYPE) != PR_CONNECTED) {
	    # Root process: send command directly to the host command
	    # interpreter.
		
	    # Pack command string and get OS versions of the filenames.
	    call strpak (cmd, Memc[cmdbuf], SZ_COMMAND)
	    if (infile[1] == EOS)
		call strpak ("", Memc[osin], SZ_PATHNAME)
	    else
		call fmapfn (infile, Memc[osin], SZ_PATHNAME)

	    # If output is directed to dev$null, save in temp file and delete.
	    if (fnullfile(outfile) || fnullfile(errfile))
		call mktemp ("tmp$null", Memc[ostmp], SZ_PATHNAME)
	    else
		Memc[ostmp] = EOS

	    if (outfile[1] == EOS)
		call strpak ("", Memc[osout], SZ_PATHNAME)
	    else if (fnullfile (outfile))
		call fmapfn (Memc[ostmp], Memc[osout], SZ_PATHNAME)
	    else {
		call fclobber (outfile)
		call fmapfn (outfile, Memc[osout], SZ_PATHNAME)
	    }

	    if (errfile[1] == EOS)
		call strpak ("", Memc[oserr], SZ_PATHNAME)
	    else if (fnullfile (errfile))
		call fmapfn (Memc[ostmp], Memc[oserr], SZ_PATHNAME)
	    else {
		call fclobber (errfile)
		call fmapfn (errfile, Memc[oserr], SZ_PATHNAME)
	    }

	    # Execute the command and wait for completion.
	    call zoscmd (Memc[cmdbuf], Memc[osin], Memc[osout], Memc[oserr],
		status)

	    # Discard output directed to dev$null.
	    if (Memc[ostmp] != EOS)
		iferr (call delete (Memc[ostmp]))
		    call erract (EA_WARN)

	} else {
	    # Connected subprocess.  Send the command to the parent process to
	    # be processed as a system directive by the pseudofile i/o system
	    # in the parent process.  Synchronous execution is desired, so wait
	    # for a status return from the parent process before returning.
	    # The redirection files are ignored in this mode.

	    call flush (CLOUT)

	    # Send command.
	    Memc[cmdbuf] = '!'
	    op = cmdbuf + 1
	    for (ip=1;  cmd[ip] != EOS && cmd[ip] != '\n';  ip=ip+1) {
		Memc[op] = cmd[ip]
		op = op + 1
	    }
	    Memc[op] = '\n'
	    Memc[op+1] = EOS
	    call putline (CLOUT, Memc[cmdbuf])
	    call flush (CLOUT)

	    # Get the return status, encoded as a nonnegative decimal integer.
	    for (status=0;  getci (CLIN, ch) != EOF;  )
		if (ch == '\n')
		    break
		else
		    status = status * 10 + TO_INTEG(ch)
	}

	call sfree (sp)
	return (status)
end