1 Introduction
2 Ground Rules
Building a File System
3 File Systems
4 File Content Data Structure
5 Allocation Cluster Manager
6 Exceptions and Emancipation
7 Base Classes, Testing, and More
8 File Meta Data
9 Native File Class
10 Our File System
11 Allocation Table
12 File System Support Code
13 Initializing the File System
14 Contiguous Files
15 Rebuilding the File System
16 Native File System Support Methods
17 Lookups, Wildcards, and Unicode, Oh My
18 Finishing the File System Class
The Init Program
19 Hardware Abstraction and UOS Architecture
20 Init Command Mode
21 Using Our File System
22 Hardware and Device Lists
23 Fun with Stores: Partitions
24 Fun with Stores: RAID
25 Fun with Stores: RAM Disks
26 Init wrap-up
The Executive
27 Overview of The Executive
28 Starting the Kernel
29 The Kernel
30 Making a Store Bootable
31 The MMC
32 The HMC
33 Loading the components
34 Using the File Processor
35 Symbols and the SSC
36 The File Processor and Device Management
37 The File Processor and File System Management
38 Finishing Executive Startup
Users and Security
39 Introduction to Users and Security
40 More Fun With Stores: File Heaps
41 File Heaps, part 2
42 SysUAF
43 TUser
44 SysUAF API
Terminal I/O
45 Shells and UCL
46 UOS API, the Application Side
47 UOS API, the Executive Side
48 I/O Devices
49 Streams
50 Terminal Output Filters
51 The TTerminal Class
52 Handles
53 Putting it All Together
54 Getting Terminal Input
55 QIO
56 Cooking Terminal Input
57 Putting it all together, part 2
58 Quotas and I/O
UCL
59 UCL Basics
60 Symbol Substitution
61 Command execution
62 Command execution, part 2
63 Command Abbreviation
64 ASTs
65 Expressions, Part 1
66 Expressions, Part 2: Support code
67 Expressions, part 3: Parsing
68 SYS_GETJPIW and SYS_TRNLNM
69 Expressions, part 4: Evaluation
UCL Lexical Functions
70 PROCESS_SCAN
71 PROCESS_SCAN, Part 2
72 TProcess updates
73 Unicode revisted
74 Lexical functions: F$CONTEXT
75 Lexical functions: F$PID
76 Lexical Functions: F$CUNITS
77 Lexical Functions: F$CVSI and F$CVUI
78 UOS Date and Time Formatting
79 Lexical Functions: F$CVTIME
80 LIB_CVTIME
81 Date/Time Contexts
82 SYS_GETTIM, LIB_Get_Timestamp, SYS_ASCTIM, and LIB_SYS_ASCTIM
83 Lexical Functions: F$DELTA_TIME
84 Lexical functions: F$DEVICE
85 SYS_DEVICE_SCAN
86 Lexical functions: F$DIRECTORY
87 Lexical functions: F$EDIT and F$ELEMENT
88 Lexical functions: F$ENVIRONMENT
89 SYS_GETUAI
90 Lexical functions: F$EXTRACT and F$IDENTIFIER
91 LIB_FAO and LIB_FAOL
92 LIB_FAO and LIB_FAOL, part 2
93 Lexical functions: F$FAO
94 File Processing Structures
95 Lexical functions: F$FILE_ATTRIBUTES
96 SYS_DISPLAY
97 Lexical functions: F$GETDVI
98 Parse_GetDVI
99 GetDVI
100 GetDVI, part 2
101 GetDVI, part 3
102 Lexical functions: F$GETJPI
103 GETJPI
104 Lexical functions: F$GETSYI
105 GETSYI
106 Lexical functions: F$INTEGER, F$LENGTH, F$LOCATE, and F$MATCH_WILD
107 Lexical function: F$PARSE
108 FILESCAN
109 SYS_PARSE
110 Lexical Functions: F$MODE, F$PRIVILEGE, and F$PROCESS
111 File Lookup Service
112 Lexical Functions: F$SEARCH
113 SYS_SEARCH
114 F$SETPRV and SYS_SETPRV
115 Lexical Functions: F$STRING, F$TIME, and F$TYPE
116 More on symbols
117 Lexical Functions: F$TRNLNM
118 SYS_TRNLNM, Part 2
119 Lexical functions: F$UNIQUE, F$USER, and F$VERIFY
120 Lexical functions: F$MESSAGE
121 TUOS_File_Wrapper
122 OPEN, CLOSE, and READ system services
UCL Commands
123 WRITE
124 Symbol assignment
125 The @ command
126 @ and EXIT
127 CRELNT system service
128 DELLNT system service
129 IF...THEN...ELSE
130 Comments, labels, and GOTO
131 GOSUB and RETURN
132 CALL, SUBROUTINE, and ENDSUBROUTINE
133 ON, SET {NO}ON, and error handling
134 INQUIRE
135 SYS_WRITE Service
136 OPEN
137 CLOSE
138 DELLNM system service
139 READ
140 Command Recall
141 RECALL
142 RUN
143 LIB_RUN
144 The Data Stream Interface
145 Preparing for execution
146 EOJ and LOGOUT
147 SYS_DELPROC and LIB_GET_FOREIGN
CUSPs and utilities
148 The I/O Queue
149 Timers
150 Logging in, part one
151 Logging in, part 2
152 System configuration
153 SET NODE utility
154 UUI
155 SETTERM utility
156 SETTERM utility, part 2
157 SETTERM utility, part 3
158 AUTHORIZE utility
159 AUTHORIZE utility, UI
160 AUTHORIZE utility, Access Restrictions
161 AUTHORIZE utility, Part 4
162 AUTHORIZE utility, Reporting
163 AUTHORIZE utility, Part 6
164 Authentication
165 Hashlib
166 Authenticate, Part 7
167 Logging in, part 3
168 DAY_OF_WEEK, CVT_FROM_INTERNAL_TIME, and SPAWN
169 DAY_OF_WEEK and CVT_FROM_INTERNAL_TIME
170 LIB_SPAWN
171 CREPRC
172 CREPRC, Part 2
173 COPY
174 COPY, part 2
175 COPY, part 3
176 COPY, part 4
177 LIB_Get_Default_File_Protection and LIB_Substitute_Wildcards
178 CREATESTREAM, STREAMNAME, and Set_Contiguous
179 Help Files
180 LBR Services
181 LBR Services, Part 2
182 LIBRARY utility
183 LIBRARY utility, Part 2
184 FS Services
185 FS Services, Part 2
186 Implementing Help
187 HELP
188 HELP, Part 2
189 DMG_Get_Key and LIB_Put_Formatted_Output
190 LIBRARY utility, Part 3
191 Shutting Down UOS
192 SHUTDOWN
193 WAIT
194 SETIMR
195 WAITFR and Scheduling
196 REPLY, OPCOM, and Mailboxes
197 REPLY utility
198 Mailboxes
199 BRKTHRU
200 OPCOM
201 Mailbox Services
202 Mailboxes, Part 2
203 DEFINE
204 CRELNM
205 DISABLE
206 STOP
207 OPCCRASH and SHUTDOWN
208 APPEND
Glossary/Index
Downloads
|
RUN
The RUN command is used to execute a program in the context of the current process.
Unlike DCL, parameters can be passed to the program. We will discuss the execution
path and order of execution for file extensions in a future article.
Here is the user documentation for the RUN command:
RUN
Executes a program in the context of the current process.
Format
RUN {qualifiers} filespec {parameters...}
Parameters
filespec
Indicates the name of the program file to execute. Programs can be run without
prefixing them with RUN if the program name isn't a UCL command, unless the program name is
prefixed with a path. For instance the following program must be executed by RUN: if.exe.
The following rules determine which program is executed if the path and/or extension
are omitted:
- If a path isn't specified, the program must exist in the user's execution path.
- The first instance of the program found in the execution path is the one that is executed, so
if programs with the specified name exist in multiple directories in the execution path, you
must specify the directory to execute one that is later in the path.
- If a file extension is not provided and multiple matching programs are found in
a given directory, the one executed depends upon the current order of execution for
file extensions.
parameters
Indicates zero, one, or more parameters to pass to the program when execution begins.
Description
This command executes the specified program in the current process. The current process
privileges are used when running the program, unless the program has privileges assigned
to it. You must have Read or Execute access to the program to execute it.
If any qualifier other than /{NO}DEBUG, /USER, or /DETACH is specified, the process
is run as a subprocess. /DEBUG is incompatible with programs run in subprocesses.
Qualifiers
/ACCOUNTING (default)
/NOACCOUNTING
/NOACCOUNTING requires the ACNT privilege. /NOACCOUNTING turns off resource tracking
for the program.
/AST_LIMIT=quota
Specifies the AST quota for the subprocess. This cannot exceed the current process
quota unless the user has the EXQUOTA privilege.
/AUTHORIZE
/NOAUTHORIZE (default)
The IMPERSONATE privilege is required use /NOAUTHORIZE. Programs run with /NOAUTHORIZE
use the system logged-out quotas rather than the current user.
/BUFFER_LIMIT=quota
Specifies the BIOLM quota for the subprocess. If the quota exceeds that of the user,
the EXQUOTA privilege is required.
/DEBUG
/NODEBUG (default)
Runs the program in the debugger, if debugging is enabled for the program.
/DELAY=delta-time
The subprocess will be hibernated for the specified time before it begins execution.
/DETACHED
Specifies that the program will be run in a subprocess.
/DUMP
/NODUMP (default)
If /DUMP is specified, a dump file will be created if the program ends abnormally.
/ENQUEUE_LIMIT=quota
Specifies the maximum number of locks the subprocess can have. If this exceeds the
ENQLM quota of the current process, the EXQUOTA privilege is required.
/ERROR=filespec
Specifies the subprocess' SYS$ERROR value.
/EXTENT=quota
Specifies the maximum WSEXTENT value of the subprocess. If the quota exceeds that
of the process owner, the EXQUOTA privilege is required.
/FILE_LIMIT=quota
Specifies the FILLM value of the subprocess. If the quota exceeds that
of the process owner, the EXQUOTA privilege is required.
/INPUT=filespec
Specifies the subprocess' SYS$INPUT value.
/INTERVAL=delta-time
Indicates the interval between the subprocess being regularly hibernated and awakened.
/IO_BUFFERED=quota
Indicates the BIOLM quota of the subprocess. If the quota exceeds that of the process
owner, the EXQUOTA privilege is required.
/IO_DIRECT=quota
Indicates the DIOLM quota of the subprocess. If the quota exceeds that of the process
owner, the EXQUOTA privilege is required.
/JOB_TABLE_QUOTA=quota
Indicates the quota for a detached process' job symbol table. This is ignored for
subprocesses. A value of 0 means an unlimited table size.
/MAILBOX=unit
Indicates the mailbox to be notified when the program completes. If not specified,
no process is notified when the subprocess or detached program completes.
/MAXIMUM_WORKING_SET=quota
Indicates the WSLIMIT quota of the subprocess. If the quota exceeds that of the process
owner, the EXQUOTA privilege is required.
/OUTPUT=filespec
Specifies the subprocess' SYS$OUTPUT value.
/PAGE_FILE=quota
Indicates the PGFLQUOTA quota of the subprocess. If the quota exceeds that of the process
owner, the EXQUOTA privilege is required.
/PRIORITY=priority
Specifies the subprocess' priority. If this is greater than the priority of the current
process, the ALTPRI privilege is required.
/PRIVILEGES=(privilege{,...})
Specifies the subprocess' privilege(s). To specify privileges you do not have, you
must have the SETPRV privilege. If not specified, the subprocess is given the same
set of privileges as the current privileges of the current process. If the privilege
specified is "NOSAME", the subprocess will have no privileges.
/PROCESS_NAME=name
Specifies the subprocess' name. If not specified, the subprocess will have a null
name.
/QUEUE_LIMIT=quota
Indicates the TQELM quota of the subprocess. If the quota exceeds that of the process
owner, the EXQUOTA privilege is required.
/RESOURCEWAIT (default)
/NORESOURCEWAIT
If /RESOURCEWAIT is specified, the subprocess will hibernate until any requested resource
becomes available. Otherwise an error is caused if a resource is unavailable.
/SCHEDULE=absolute-time
If specified, the subprocess will hibernate until the specified time.
/SERVICE_FAILURE
/NOSERVICE_FAILURE (default)
If /SERVICE_FAILURE is not specified, the subprocess will receive an error code when
any system service call fails. Otherwise, all system services calls return a success
code.
/SUBPROCESS_LIMIT=quota
Indicates the MAXJOBS quota of the subprocess. If the quota exceeds that of the process
owner, the EXQUOTA privilege is required.
/SWAPPING (default)
/NOSWAPPING
/NOSWAPPING indicates that the subprocess cannot be swapped out of memory. Specifying
this requires the PSWAPM privilege.
/USER=username
Indicates that the program is to execute in the context of the specified user. If the
user is a different user, the IMPERSONATE privilege is required.
/WORKING_SET=quota
Indicates the WSQUOTA quota for the subprocess. If the quota exceeds that of the process
owner, the EXQUOTA privilege is required.
/TIME_LIMIT=quota
Indicates the CPULIMIT quota of the subprocess. If the quota exceeds that of the process
owner, the EXQUOTA privilege is required.
Examples
$ RUN SYS$SYSTEM:LOGOUT.EXE
$ RUN MYPROG/DETACH
if( Sym = 'run' ) then
begin
Process_Run ;
end else
This code is added to the Process routine to handle the RUN command.
end else
begin // Command...
I := Starlet.Run( Sym, Parser.Grab_Line ) ;
if( I = 0 ) then
begin
exit ;
end ;
Parser.Command := '' ;
Exception( UCL_IVVERB, Sym ) ;
Handle_Exception ;
continue ;
end ;
This code is added to the end of the end of the Process routine if the user types an unrecognized
command. VMS uses a command line facility (CLI) to define new commands. UCL works more like Windows - if UCL
doesn't recognize the command it looks for a program whose name matches the typed command. This allows users to
define their own "commands", rather than requiring them to use a CLI-like facility. As mentioned above, if
the program name matches a command name, the program can only be run by using the RUN command.
procedure Process_Run ;
var Accounting, Authorize, Debug, Dump, Detach : boolean ;
ASTLM, BIOLM, Delay, ENQLM, WSEXTENT : integer ;
I : integer ;
Res : int64 ;
Switches : TStringList ;
Error, S, Temp : string ;
begin
// Setup...
Accounting := True ;
Authorize := False ;
Debug := False ;
Detach := False ;
Dump := False ;
ASTLM := -1 ;
BIOLM := -1 ;
Delay := -1 ;
ENQLM := -1 ;
WSEXTENT := -1 ;
Error := '' ;
Switches := Parse_Switches ;
// Process switches...
for I := 0 to Switches.Count - 1 do
begin
S := lowercase( Switches[ I ] ) ;
Temp := '' ;
if( Switch_Match( S, 'accounting', 2, Temp ) ) then
begin
Accounting := True ;
if( Temp <> '' ) then
begin
Exception( UCL_NOVALU, Switches[ I ] ) ;
Switches.Free ;
exit ;
end ;
end else
if( Switch_Match( S, 'ast_limit', 2, Temp ) ) then
begin
if( Temp = '' ) then
begin
Exception( UCL_VALREQ, Switches[ I ] ) ;
Switches.Free ;
exit ;
end ;
ASTLM := strtoint( UCL_Strtoint( Temp ) ) ;
Detach := True ;
end else
if( Switch_Match( S, 'authorize', 2, Temp ) ) then
begin
Authorize := True ;
if( Temp <> '' ) then
begin
Exception( UCL_NOVALU, Switches[ I ] ) ;
Switches.Free ;
exit ;
end ;
end else
if( Switch_Match( S, 'buffer_length', 1, Temp ) ) then
begin
if( Temp = '' ) then
begin
Exception( UCL_VALREQ, Switches[ I ] ) ;
Switches.Free ;
exit ;
end ;
BIOLM := strtoint( UCL_Strtoint( Temp ) ) ;
Detach := True ;
end else
if( Switch_Match( S, 'debug', 3, Temp ) ) then
begin
Debug := True ;
if( Temp <> '' ) then
begin
Exception( UCL_NOVALU, Switches[ I ] ) ;
Switches.Free ;
exit ;
end ;
end else
if( Switch_Match( S, 'delay', 3, Temp ) ) then
begin
if( Temp = '' ) then
begin
Exception( UCL_VALREQ, Switches[ I ] ) ;
Switches.Free ;
exit ;
end ;
Delay := strtoint( UCL_Strtoint( Temp ) ) ;
Detach := True ;
end else
if( Switch_Match( S, 'detached', 3, Temp ) ) then
begin
Detach := True ;
if( Temp <> '' ) then
begin
Exception( UCL_NOVALU, Switches[ I ] ) ;
Switches.Free ;
exit ;
end ;
end else
if( Switch_Match( S, 'dump', 3, Temp ) ) then
begin
Dump := True ;
if( Temp <> '' ) then
begin
Exception( UCL_NOVALU, Switches[ I ] ) ;
Switches.Free ;
exit ;
end ;
end else
if( Switch_Match( S, 'enqueue_limit', 2, Temp ) ) then
begin
if( Temp = '' ) then
begin
Exception( UCL_VALREQ, Switches[ I ] ) ;
Switches.Free ;
exit ;
end ;
ENQLM := strtoint( UCL_Strtoint( Temp ) ) ;
Detach := True ;
end else
if( Switch_Match( S, 'error', 2, Error ) ) then
begin
if( Temp = '' ) then
begin
Exception( UCL_VALREQ, Switches[ I ] ) ;
Switches.Free ;
exit ;
end ;
Detach := True ;
end else
if( Switch_Match( S, 'extent', 2, Temp ) ) then
begin
if( Temp = '' ) then
begin
Exception( UCL_VALREQ, Switches[ I ] ) ;
Switches.Free ;
exit ;
end ;
WSEXTENT := strtoint( UCL_Strtoint( Temp ) ) ;
Detach := True ;
end else
if( Switch_Match( S, 'noaccounting', 4, Temp ) ) then
begin
Accounting := False ;
if( Temp <> '' ) then
begin
Exception( UCL_NOVALU, Switches[ I ] ) ;
Switches.Free ;
exit ;
end ;
end else
if( Switch_Match( S, 'noauthorize', 4, Temp ) ) then
begin
Authorize := False ;
if( Temp = '' ) then
begin
Exception( UCL_VALREQ, Switches[ I ] ) ;
Switches.Free ;
exit ;
end ;
end else
if( Switch_Match( S, 'nodebug', 4, Temp ) ) then
begin
Debug := False ;
if( Temp <> '' ) then
begin
Exception( UCL_NOVALU, Switches[ I ] ) ;
Switches.Free ;
exit ;
end ;
end else
if( Switch_Match( S, 'nodump', 4, Temp ) ) then
begin
Dump := False ;
if( Temp <> '' ) then
begin
Exception( UCL_NOVALU, Switches[ I ] ) ;
Switches.Free ;
exit ;
end ;
end else
begin
Exception( UCL_IVQUAL, S ) ;
Switches.Free ;
exit ;
end ;
end ; // for I := 0 to Switches.Count - 1
Switches.Free ;
S := Get_Filename ;
if( Detach ) then
begin
.
.
.
end else
begin
Res := PasStarlet.Run( S, trim( Parser.Grab_Line ), Accounting, Authorize, Debug, Dump ) ;
if( Res = 0 ) then
begin
exit ;
end ;
end ;
Exception( UCL_FNF, S ) ;
end ; // Process_Run
This routine follows the general pattern of previous UCL command processing code.
When the command is parsed and validated, the Run routine is
called to execute the program. For clarity, we will skip the handling of detached
processes for now. Note that the use of certain switches implies /DETACH.
function Get_Filename : string ;
begin
Result := Get_Token ;
if( copy( Result, 1, 1 ) = '"' ) then // Quoted filename
begin
// Trim quotes...
Result := copy( Result, 2, length( Result ) ) ;
if( copy( Result, length( Result ), 1 ) = '"' ) then
begin
setlength( Result, length( Result ) - 1 ) ;
end ;
exit ;
end ;
// Make sure entire file spec is pulled from token stream...
while( ( Parser.Peek_Char <> ' ' ) and ( Parser.Peek_Char <> '' ) ) do
begin
Result := Result + Get_Token ;
end ;
end ;
This routine is used to retrieve a filename from the token stream. We can't simply
use Get_Token , because tokens terminate with colons, etc. Thus, if we
only use Get_Token , we'd only retrieve the node or device of a file specification.
If the filename is enclosed within quotes, the entire string is returned by the
parser (and if so, we trim the quotes and return the filename), but it not, we need
to append all tokens until we run into a space or the end of the line.
In the next article, we will look at the LIB_Run routine.
Copyright © 2021 by Alan Conroy. This article may be copied
in whole or in part as long as this copyright is included.
|