#-h- intro.fmt 4211 asc 25-mar-82 10:05:30 v1.1 (sw-tools v1.1) .pl 60 .in 0 .rm 70 NAME .ti +4 Intro - introduction to software tools primitives .sp 20 .ce A (Not So) Primitive Document .sp 5 .ce 100 Joseph Sventek Computer Science & Applied Mathematics Lawrence Berkeley Laboratory Berkeley, CA 94720 .ce 0 .sp 5 .in 15 .rm 55 A complete writeup of the syntax and semantics of the primitive functions upon which the LBL Software Tools Virtual Operating System is based. .bp 1 .rm 70 .in 0 .he 'Intro (2)'11/17/80'Intro (2)' .fo ''-#-'' .fi Basic assumptions of the tools concerning data types: .in +5 `character' is a signed integer data type of at least eight-bit accuracy. The internal representation of characters within the programs is the 7-bit ASCII code, with EOS being traditionally defined as 0 (NULL). This leaves 128 negative values for special flags such as EOF, ERR etc. Msg assumes that it can use 200(8) (NULL with the high bit set) to pad NEWLINES in raw terminal I/O. Integers and characters are freely assigned to each other. Since the above assumption is made, normal FORTRAN compilers should perform this without any side effects. The data type `linepointer' should be defined as an intrinsic FORTRAN data type large enough to hold the address of a record in a file. No arithmetic or assignments are done on linepointers, with all activities on these entities embodied in the routines `note', `seek', `ptreq', `ptrcpy', `ptrtoc' and `ctoptr'. It is also assumed that a defined symbol NULLPOINTER exists and is different from any possible valid linepointer value. .ti -5 Basic assumptions of the ratfor runtime system I/O redirection flags are interpreted (and removed from the argument list) before the tool's main routine is called. In order to be able to pass arguments to the utility which start with the special characters '<', '>', or '?', quoted string arguments are not scanned when determining io redirection. The primitives, as currently defined, only handle character files, with the exception that `gettyp' expects to be able to determine whether a file is BINARY or ASCII. It is expected that the primitives will be extended in the near future to handle ASCII, LOCAL and BINARY files unambiguously. `getarg(0)' should return the name by which the process was invoked. This is useful if your system supports UNIX-style links, thus allowing an image to act differently depending upon which alias was used for its invocation. None of the tools currently use this capability. The first routine to be executed is named subroutine main It is assumed that all I/O redirection and command line fetching have been completed before `main' is called. Upon completion, `main' simply returns, which causes a return to the Tools runtime system. In order to implement this feature, `ld' is set up to extract a module from the library which is the FORTRAN main program, and usually consists of the following lines: .nf call initst call main call endst(OK) end .fi If such library extraction is not possible on a system, the above four line routine will have to be added to each tool. .ti -5 Basic assumptions concerning RAW terminal I/O The routine `stmode' is supplied to permit the use of RAW terminal I/O. In actuality, three modes are defined, RAW, RARE and COOKED. COOKED io implies that the system applies its own semantics concerning the control characters emitted by the terminal, and performs the echo of the characters for the user. RARE and RAW assume that all reads are done a character at a time, with no echo. RARE io assumes that there are certain control characters which the operating system will not relinquish its control of. These probably include XON, XOFF, terminal interrupt characters, etc. RARE is the mode of io used by all of the tools currently using RAW io, since they usually only wish to apply their own semantics to the actual printing characters. RAW io is handy if one wishes to write network control programs over asynchronous lines in ratfor (Don't laugh, it's being done!). With RAW io, it is assumed that the terminal driver is totally bypassed. On many systems, this capability requires enormous privilege and other funky resources, so none of the commonly available tools use it. .in -5 #-h- amove.fmt 1019 asc 25-mar-82 10:05:32 v1.1 (sw-tools v1.1) .so ~bin/manhdr .hd Amove (2) 18-Aug-81 move (rename) file1 to file2 .sy integer function amove(name1, name2) character name1(ARB), name2(ARB) .ds `amove' moves the contents of the file specified by `name1' to the file specified by `name2'. It is essentially a renaming of the file. Both file names are character strings representing pathnames or filenames in whatever format is expected by the local operating system. The names are passed as character arrays terminated with an EOS character. The files need not be opened by (connected to) the running program to be renamed. The function value returned is OK is successful or ERR if not. .im `amove' could be easily implemented by opening the first file, creating the second, copying the first to the second, and then removing the first file. Alternatively, if possible, it could be implemented with a native system call to rename the file. .sa remove(2) .di If the rename fails for any reason, ERR is returned. `name1' is removed only if the rename succeeds. #-h- assign.fmt 1020 asc 25-mar-82 10:05:33 v1.1 (sw-tools v1.1) .so ~bin/manhdr .hd Assign (2) 18-Aug-81 open a file on the specified unit .sy integer function assign(name, fd, access) character name(FILENAMESIZE) filedes fd integer access .ds `assign' is the equivalent of `open' or `create' on a particular ratfor I/O unit. If a file is currently open on `fd', `assign' closes it first. If `access' has the value of READ, `assign' then performs an `open' on the specified unit. If `access' has the value of WRITE, READWRITE or APPEND, `assign' performs a `create' on the specified unit. The function value returned is either the value of `fd' if successful, or ERR. .im There has been much debate whether `assign' should still be in the primitive set. The only tool which relies upon it is `sort', since is does some fairly complex file manipulation during the external merge phase. .sa open(2), create(2), close(2) .di If the file could not be opened or created for any reason, the value ERR is returned. In this case, the previous file associated with `fd' remains closed. #-h- brdcst.fmt 720 asc 25-mar-82 10:05:34 v1.1 (sw-tools v1.1) .so ~bin/manhdr .hd Brdcst (2) 12-Mar-82 broadcast message to one or all terminals .sy integer function brdcst(msg, dev) character msg(ARB), dev(ARB) return(OK/ERR) .ds `brdcst' broadcasts the message in `msg' to the terminal specified by the `dev' argument. If `dev' is the string "all", the message is broadcast to all logged in terminals on the system. .im `brdcst' is heavily dependent upon whether the operating system supports such a notion. In addition, some systems support broadcasts only for very privileged users. This routine is only used by `sndmsg' and `mail' to notify users of mail delivery, and can safely be implemented as a stub. .sa trmlst(2) .di Returns ERR if the message cannot be broadcast. #-h- chmod.fmt 780 asc 25-mar-82 10:05:35 v1.1 (sw-tools v1.1) .so ~bin/manhdr .hd Chmod (2) 12-Mar-82 change protection mode on file .sy integer function chmod( name, mode) character name(ARB) integer mode return(OK/ERR) .ds `chmod' attempts to change the protection on the file `name' to the value specified in `mode'. It returns the value OK/ERR reflecting the degree of success in the operation. .im The only current use of `chmod' is in the `rm' tool using the `-f' flag. In that situation, `mode' is passed as an integer of all ones. Before `chmod' can become generally useful, some system-independent way of specifying the protection on a file needs to be devised. It is totally permissible to implement this as a stub always returning the value ERR. .sa rm(1) .di Return a value of ERR if the mode change could not be performed. #-h- closdr.fmt 416 asc 25-mar-82 10:05:35 v1.1 (sw-tools v1.1) .so ~bin/manhdr .hd Closdr (2) 18-Aug-81 close an opened directory .sy subroutine closdr(fd) filedes fd .ds `closdr' closes the directory that is currently opened and associated with the internal descriptor `fd', which was returned by the `opendr' function. .im .sa opendr(2) .di If `fd' is an invalid descriptor, or if no opened directory is currently associated with `fd', `closdr' returns with no error message. #-h- close.fmt 803 asc 25-mar-82 10:05:36 v1.1 (sw-tools v1.1) .so ~bin/manhdr .hd Close (2) 18-Aug-81 close (detach) a file .sy subroutine close(fd) filedes fd .ds `close' closes the connection between a file and the running program. Any write buffers are flushed and the file is rewound. `fd' is an internal file descriptor as returned from an `open' or `create' call. .im `close' breaks the connection between the program and a file accessed via `open' or `create'. If necessary, the file's write buffer is flushed and the end of the file is marked so that subsequent reads will find an EOF. If a file has been opened multiple times (that is, more than one internal descriptor has been assigned to a file), care is taken that multiple closes will not damage the file. .sa open(2), create(2) .di If the file descriptor is in error, the routine simply returns. #-h- create.fmt 1164 asc 25-mar-82 10:05:37 v1.1 (sw-tools v1.1) .so ~bin/manhdr .hd Create (2) 20-Aug-81 create a new file (or overwrite an existing one) .sy filedes function create( name, access) character name(ARB) integer access .ds `create' creates a new file from within a running program and connects the external name of the file to an internal identifier which is then usable in subsequent subroutine calls. If the file already exists, the old version will be overwritten. In this case, the file should be truncated immediately by `create'. `name' is a character string representing a pathname or filename in whatever format is used by the local operating system. It is passed as a character array terminated by an EOS character. `access' is a integer descriptor for the type of access desired - WRITE, READWRITE or APPEND. The value returned is a "filedes" internal descriptor to be used in subsequent I/O calls on this file. .im `create' is similar to `open' except that `create' generates a new file if it does not already exist, whereas `open' returns an error on such occasions. .sa open(2), close(2) .di The function returns ERR if the file could not be created or if there are already too many files open. #-h- ctoptr.fmt 449 asc 25-mar-82 10:05:38 v1.1 (sw-tools v1.1) .so ~bin/manhdr .hd Ctoptr (2) 20-Aug-81 convert character string into linepointer .sy subroutine ctoptr(buf, i, ptr) character buf(ARB) integer i linepointer ptr .ds `ctoptr' converts the characters starting at location `buf(i)' into a linepointer value and stores the value in the variable `ptr'. The value of `i' is incremented to point to the next available location in `buf'. .im .sa ptreq(2), ptrcpy(2), note(2), seek(2), ptrtoc(2) .di none #-h- cwdir.fmt 664 asc 25-mar-82 10:05:39 v1.1 (sw-tools v1.1) .so ~bin/manhdr .hd Cwdir (2) 20-Aug-81 change current working directory .sy integer function cwdir(name) character name(FILENAMESIZE) .ds `cwdir' changes the current working directory to that specified by `name'. `name' is a character string representing a pathname or whatever format is expected by the local operating system. `name' is passed as a character array terminated by an EOS character. The return value is either OK or ERR depending upon the success of the operation. If the operation fails, the current working directory should be restored to the previous value. .im .sa gwdir(2) .di A value of ERR is returned if the operation is unsuccessful. #-h- delarg.fmt 538 asc 25-mar-82 10:05:40 v1.1 (sw-tools v1.1) .so ~bin/manhdr .hd Delarg (2) 20-Aug-81 mask the existence of specified command line argument .sy subroutine delarg(n) integer n .ds `delarg' masks the existence of the command line argument number `n' so that subsequent calls to `getarg' do not see it. .im `delarg' works in conjunction with `getarg'. It generally re-orders indices to an array holding the command line arguments fetched by `makarg'. `delarg' is currently only used by the shell. .sa getarg(2), initst(2) .di If argument `n' does not exist, `delarg' simply returns. #-h- enbint.fmt 1176 asc 25-mar-82 10:05:42 v1.1 (sw-tools v1.1) .so ~bin/manhdr .hd Enbint (2) 20-Aug-81 enable trapping of terminal interrupts .sy subroutine enbint .ds `enbint' is used by the shell to trap interrupt characters typed by the user at the terminal. `enbint' assumes that there will be a routine named `intsrv' which will be called whenever a terminal interrupt is typed. The canonical semantics of `intsrv' is to kill all sub-processes of the current process and return. This generally results in the return of error notifications to `spawn', which returns the error to the shell, after which the shell prompts for another command. .im `enbint' has been implemented on only three machines, and is not very well defined. In all of the implementations to date, `enbint' checks to make sure that the caller is the top shell in the process tree associated with the user. This prevents `enbint' from being generally called from other programs. It is hoped that a firmer specification for this routine will be available in the near future. If this routine is difficult to implement, it may be left as a stub. .sa intsrv(2) .di If the enabling of the interrupt cannot be performed, the current implementations simply return. #-h- endst.fmt 566 asc 25-mar-82 10:05:43 v1.1 (sw-tools v1.1) .so ~bin/manhdr .hd Endst (2) 20-Aug-81 perform system-dependent cleanup and terminate ratfor program .sy subroutine endst(status) integer status .ds `endst' is normally implicitly called when the `main' subroutine executes a return. `endst' closes all open files, performs any necessary system-dependent cleanup and terminates the program's execution. If it is possible, endst should communicate the termination status (OK/ERR/CHILD_ABORTED) to the outside world. `endst' is also called by `error' to terminate the program. .im .sa close(2), initst(2) .di none #-h- filnfo.fmt 431 asc 25-mar-82 10:05:44 v1.1 (sw-tools v1.1) .so ~bin/manhdr .hd Filnfo (2) 20-Aug-81 determine filename and access on open unit .sy integer function filnfo( fd, file, access) filedes fd integer access character file(FILENAMESIZE) .ds `filnfo' returns the name and access of the file open on `fd' to the user. If the unit is open, `filnfo' returns OK as its value, otherwise it returns ERR. .im .sa .di If the file specified by `fd' is not open, a value of ERR is returned. #-h- gdraux.fmt 1998 asc 25-mar-82 10:05:46 v1.1 (sw-tools v1.1) .so ~bin/manhdr .hd Gdraux (2) 20-Aug-81 get auxiliary information about a file .sy subroutine gdraux( fd, file, aux, date, fmtstr) character file(FILENAMESIZE), aux(MAXLINE), date(TCOLWIDTH) character fmtstr(ARB) filedes fd .ds `gdraux' retrieves auxiliary information on a particular file in a directory. `fd' is the directory descriptor returned from an `opendr' call and `file' is a filename returned from a `gdrprm' call. The auxiliary information is returned in the character array `aux', while `date' receives a "sortable" date string of size (TCOLWIDTH-1) which can be used to sort files by significant date. .sp The information placed into `aux' is dependent upon the format string passed in `fmtstr'. The format string specifies the output information as follows: .sp .in +3 .ti -2 b size of file in blocks (normally 512 characters) .sp .ti -2 c size of file in characters .sp .ti -2 m modification date and time (dd-mmm-yy hh:mm:ss) .sp .ti -2 n filename .sp .ti -2 o file owner's username .sp .ti -2 p protection codes .sp .ti -2 t file type (asc|bin|dir) .in -3 .sp The `b', `c', `n' and `o' options accept an integer prefix which specifies the field width to be used. .im This is admittedly a stop-gap measure until a more useful and penetrating primitive is devised to permit the retrieval of extra information about a file. The only utility which uses `gdraux' currently is `ls', the directory lister. The sortable date field can be anything that the primitive implementor desires, but it is strongly suggested that it be a sortable version of whatever significant date the operating system keeps on the file, so that the "-t" flag in `ls' performs up to specification. .bp .ex The verbose option of `ls' uses the format string "17n p m 6b o". .sa opendr(2), gdrprm(2) .di If the auxiliary information cannot be obtained for a particular file, a message to that effect is returned in `aux', and `date' is given a value such that it will sort out first when sorting by date. #-h- gdrprm.fmt 882 asc 25-mar-82 10:05:48 v1.1 (sw-tools v1.1) .so ~bin/manhdr .hd Gdrprm (2) 20-Aug-81 get next filename from directory .sy integer function gdrprm( fd, file) character file(FILENAMESIZE) filedes fd .ds `gdrprm' retrieves the next sequential filename from the open directory associated with `fd' and places it in the character array `file' as an EOS-terminated string. If there is an error reading the directory or no more filenames are contained in the directory, a value of EOF is returned; otherwise, OK is returned. The filenames are retrieved sequentially, with no particular order (alphabetic, by date, etc.) guaranteed. .im If there are lots of noise characters (version numbers, null extensions, etc.), these are often stripped from the filename before it is returned. .sa gdraux(2), opendr(2) .di A value of EOF is returned whenever there are no more directory entries or an error reading the directory is detected. #-h- getarg.fmt 1918 asc 25-mar-82 10:05:50 v1.1 (sw-tools v1.1) .so ~bin/manhdr .hd Getarg (2) 20-Aug-81 get command line arguments .sy integer function getarg( n, array, maxsiz) character array(maxsiz) integer n, maxsiz .ds `getarg' gets command arguments from the command line or control card and copies the `n'th command line argument into the character array `array', terminating it with an EOS character. `maxsiz' is passed as the maximum number of characters `array' is prepared to deal with (including the EOS character); `getarg' truncates the argument if necessary to fit into the space provided. The number or characters in the argument (not including the EOS character) is returned in the functional call. If there are less than `n' arguments, EOF is returned. Calling `getarg' with `n' having the value of 0 should result in the return of the name by which the image was invoked. .im The implementation of 'getarg' may be quite different on different operating systems. Some systems allow only upper case (or lower case) on the command line; they may limit size; they may not even provide access at all without considerable contortions. When implementing `getarg', the designer should keep in mind that a `delarg' will also be needed. One possible design would be to create a routine `makarg', which would pick up the arguments from the system, convert them to ascii strings, handle any upper-lower case escape conventions, and store them in an array. `getarg' could then access this array, stripping off any quoted strings surrounding the arguments, and passing them along to the user. `delarg' could also access this array when removing reference to arguments. If it is absolutely impossible to pick up command line arguments from the system, `getarg' could be taught to prompt the user for them. When the shell is implemented, `getarg' (or perhaps `makarg') may have to be altered to read arguments as passed from the shell. .sa initst(2), delarg(2) .di none #-h- getch.fmt 912 asc 25-mar-82 10:05:51 v1.1 (sw-tools v1.1) .so ~bin/manhdr .hd Getch (2) 20-Aug-81 read character from file .sy character function getch( c, fd) character c filedes fd .ds `getch' reads the next character from the file specified by `fd'. The character is returned in ASCII format both as the functional return and in the parameter `c'. If the end of a line has been encountered, NEWLINE is returned. If the end of the file has been encountered, EOF is returned. If the unit `fd' is a RAW or RARE terminal unit, then getch actually gets the next character from the terminal WITH NO ECHO. .im Interspersed calls to `getch' and `getlin' should interleave properly. A common implementation is to have `getlin' make repeated calls to `getch'. If the input file is not ASCII, characters are mapped into their ASCII equivalent. .sa getlin(2), putch(2), putlin(2), stmode(2) .di If an error occurs during the reading of the file, the value ERR is returned. #-h- getdir.fmt 929 asc 25-mar-82 10:05:52 v1.1 (sw-tools v1.1) .so ~bin/manhdr .hd Getdir (2) 26-Oct-81 get directory string for known Tools directory .sy subroutine getdir( key, dtype, name) character name(FILENAMESIZE) integer key, dtype .ds `getdir' returns the directory string for any of the known Tools directories. The directory string is returned as a character array terminated by an EOS character. The format of `name' is determined by the value of `dtype', with LOCAL generating a string in local format, and PATH causes a pathname directory string to be returned. The valid values of `key' and their corresponding directories are: .nf .in +10 BINDIRECTORY ~bin/ USRDIRECTORY ~usr/ TMPDIRECTORY ~tmp/ LPRDIRECTORY ~lpr/ MSGDIRECTORY ~msg/ MANDIRECTORY ~man/ SRCDIRECTORY ~src/ INCDIRECTORY ~inc/ LIBDIRECTORY ~lib/ .in -10 .fi If an invalid key is specified, a null string is returned. .im .sa .di If an invalid key is specified, a null string is returned. #-h- getlin.fmt 1743 asc 25-mar-82 10:05:53 v1.1 (sw-tools v1.1) .so ~bin/manhdr .hd Getlin (2) 21-Aug-81 get next line from file .sy integer function getlin( line, fd) character line(MAXLINE) filedes fd .ds `getlin' copies the next line from the file specified by the internal identifier `fd' into the character array `line'. Characters are copied until a NEWLINE character is found or until MAXLINE-1 characters have been copied. The characters are returned with the character array terminated by an EOS character. `getlin' returns EOF when it encounters an end-of-file, otherwise it returns the line length (including NEWLINE, excluding EOS). Interspersed calls to `getlin' and `getch' are permitted and should work properly. .im If the external representation of characters is not ASCII, the characters are mapped into their ASCII equivalents. `getlin' assumes a maximum size (MAXLINE) of the array `line'. If the input line exceeds the limit, only the first "limit-1" characters are returned, with the remainder of the line either being ignored or returned on the next `getlin' call. A common implementation is to have `getlin' call getch until a NEWLINE character is found (or the buffer size is exceeded or EOF is reached). If the underlying disk structure is record oriented (as opposed to stream oriented), it may be more efficient to have `getlin' get the next record in the same way that `getch' does, to avoid the overhead of repeated calls to `getch'. Use of `getlin' on RAW terminal units is of questionable utility, since the repeated `getch' calls perform a READ WITH NO ECHO, and would only terminate when the user types a CTRL/J (LINEFEED) character. All utilities which use RAW I/O have their own line gathering routines. .sa getch(2), putch(2), putlin(2), stmode(2) .di none #-h- getnow.fmt 1114 asc 25-mar-82 10:05:54 v1.1 (sw-tools v1.1) .so ~bin/manhdr .hd Getnow (2) 20-Aug-81 determine current date and time .sy subroutine getnow (now) integer now (7) .ds 'Getnow' is used to query the operating system for the current date and time. The requested information is returned in a seven-word integer array, where: .in +5 .nf word 1 contains the year (e.g. 1980); word 2 contains the month (e.g. 9); word 3 contains the day (e.g. 25); word 4 contains the hour (e.g. 13); word 5 contains the minute (e.g. 39); word 6 contains the second (e.g. 14); word 7 contains the millisecond (e.g. 397). .in -5 .fi The information returned by 'getnow' may be used as-is or further useful processing may be done by 'fmtdat' or 'wkday'. .im Operating systems generally have some mechanism for picking up the current date and time. If yours has one, use it. Getnow is not critical to the implementation of the tools and can be left as a stub if the operating system cannot supply the needed information. .am now .bu Some systems cannot obtain all the time information described. Array elements that cannot be filled default to zero. .sa fmtdat(3), wkday(3), date(1) #-h- gettyp.fmt 1403 asc 25-mar-82 10:05:56 v1.1 (sw-tools v1.1) .so ~bin/manhdr .hd Gettyp (2) 20-Aug-81 get type of file .sy integer function gettyp( fd, type) filedes fd integer type .ds `gettyp' determines whether the file opened on unit `fd' is ascii characters (ASCII), local characters (LOCAL, if different from ASCII) or binary(BINARY). The type is returned as the value of the function and as the value of the parameter `type'. If the file is empty or new, ASCII is returned. `fd' is the file identifier returned from an `open' or `create' call. .im When a file is opened (via a call to `open' or `create'), an internal flag is usually set which specifies the file type. `gettyp' then simply reads the flag. The file type may have been determined by locating system information about the file or by actually reading part of it and making a reasonable guess. `gettyp' is called by the archiver to store a file's type in the archiver header. The shell also uses `gettyp' to determine whether a command verb given by the user represents a script file or an image file. If the verb corresponds to a character file, the shell spawns itself with the file as input. If `gettyp' cannot be implemented on a particular system, a stub returning BINARY should be placed in the library, which will force the user to execute script files in the following manner: .sp % sh