This section describes the following pSOSystem system services:
The bootpd server in pSOSystem networking utilities is an implementation of the BOOTSTRAP protocol server and is based on RFC 951 and RFC 1395. It provides additional features by implementing: (a) a tag field (ps) in the bootpd configuration database, which identifies the forwarding server to which bootp requests from a specific hardware device can be forwarded; (b) an optional default parent bootpd server address (parentIP) in the bootpd configuration table to which unresolved BOOTP requests can be forwarded.
bootpd creates a daemon task, BTPD, to handle BOOTP requests from clients. When BTPD starts, it reads configuration information from a user-supplied string, which it stores in its hash tables. When a BOOTP request comes in, if there is a match in the BTPD configuration database, BTPD first verifies whether the forwarding server field (ps) is set for the matching address. If it is set, the request is forwarded to the specified server regardless of other fields. Otherwise, BTPD processes the request and may send back a reply packet, if appropriate. If no match is found in BTPD's configuration database and a parent bootpd server is supplied when BTPD starts, BTPD forwards requests to its parent server.
The bootpd server in the pSOSystem operating systemalways ignores the server name field in BOOTP requests.
To use the bootpd server, you must have the following components installed:
In addition, bootpd requires the following system resources:
In order to use bootpd in an application, you need to link the pSOSystem network utilities library. bootpd is started with bootpd_start(bootpdcfg_t *). The following code fragment gives an example of a database string and shows how to start bootpd:
#include <netutils.h>
char *bootp_table =
"scg.dummy:\
sm=255.255.255.0:\
td=3.0:\
hd=/tftpboot:\
bf=null:\
dn=isi.com:\
hn:\n\
subnetscg.dummy:\
tc=scg.dummy:\
gw=192.103.54.14:\
ps=1.2.3.4:\n\
board1:\
tc=subnetscg.dummy:\
ht=ethernet:\
ha=08003E20F810:\
ip=192.103.54.229:\
bf=ram.hex:\
bs=123:\
ps@:\
";
void start_bootpd_server()
{
static bootpdcfg_t bootpd_cfg;
bootpd.priority = 200;
bootpd_cfg.flags = BOOTPD_SYSLOG;
bootpd_cfg.bootptab = bootp_table;
bootpd_cfg.parentIP.s_addr = htonl(0xC0D8E61D);
if (bootpd_start(&bootpd_cfg))
printf("bootpd_start: failed to start\n");
}
The bootpd server requires a user-supplied configuration table, defined as follows:
struct {
unsigned long priority; /* priority of BTPD task */
unsigned long flags; /* optional flags */
char *bootptab; /* bootpd database string */
struct in_addr parentIP; /* parent BOOTP server IP address */
unsigned long reserved[2]; /* reserved for future */
} bootpdcfg_t;
typedef struct bootpdcfg_t bootpdcfg_t;
"hostname:\
tg=value:\
...\
tg=value:\n\
hostname:\
tg=value:\
...\
tg=value:"
The following tags are currently recognized by the bootpd server:
There is also a generic tag, T n, where n is an RFC1084 vendor field tag number. Thus, it is possible to immediately take advantage of future extensions to RFC1084 without being forced to modify bootpd first. Generic data may be represented as either a stream of hexadecimal numbers or as a quoted string of ASCII characters. The length of the generic data is automatically determined and inserted into the proper field(s) of the RFC1084-style BOOTP reply.
The following tags take a white space-separated list of IP addresses: cs, ds, gw, im, lg, lp, ns, rl, and ts. The ip, sa, ps, sw, and sm tags each take a single IP address. All IP addresses are specified in standard Internet ``dot'' notation and may use decimal, octal, or hexadecimal numbers (octal numbers begin with 0, hexadecimal numbers begin with '0x' or '0X').
The ht tag specifies the hardware type code as either an unsigned decimal, octal, or hexadecimal integer, or as one of the following symbolic names: ethernet or ether for 10Mb Ethernet, ethernet3 or ether3 for 3Mb experimental Ethernet, ieee802, tr, or token-ring for IEEE 802 networks, pronet for Proteon ProNET Token Ring, or chaos, arcnet, or ax.25 for Chaos, ARCNET, and AX.25 Amateur Radio networks, respectively. The ha tag takes a hardware address, which must be specified in hexadecimal; optional periods and/or a leading '0x' may be included for readability. The ha tag must be preceded by the ht tag (either explicitly or implicitly; see tc below).
The td tag is used to inform bootpd of the root directory used by tftpd. The hd tag is actually relative to the root directory specified by the td tag. For pHILE+ files, the td tag should always be there to include the volume name. For Sun files, the td tag is optional. For example, if your BOOTP client bootfile is /tftpboot/bootimage on volume 3 in your system, then specify the following in the bootptab string:
:td=3.0:hd=/tftpboot:bf=bootimage:
The hostname, home directory, and bootfile are ASCII strings that may be optionally surrounded by double quotes ("). The client's request and the values of the hd and bf symbols determine how the server fills in the bootfile field of the BOOTP reply packet.
If the client specifies an absolute pathname (an absolute pathname in the pHILE+ file system manager begins with a volume name followed by a complete path) and that file exists on the server machine, that pathname is returned in the reply packet. If the file cannot be found, the request is discarded; no reply is sent. If the client specifies a relative pathname, a full pathname is formed by prepending the value of the hd tag and testing for existence of the file. If the hd tag is not supplied in the configuration file or if the resulting boot file cannot be found, then the request is discarded.
Clients that specify null boot files always elicit a reply from the server. The exact reply depends again upon the hd and bf tags. If the bf tag gives an absolute pathname and the file exists, that pathname is returned in the reply packet. Otherwise, if the hd and bf tags together specify an accessible file, that filename is returned in the reply. If a complete filename cannot be determined or the file does not exist, the reply will contain a zeroed-out bootfile field.
In all these cases, existence of the file means that, in addition to actually being present, the file must have read access to public, since this is required by tftpd to permit the file transfer. Also, all filenames are first tried as filename.hostname and them simply as filename, thus providing for individual per-host bootfiles.
The sa tag may be used to specify the IP address of the particular TFTP server you wish the client to use. In the absence of this tag, bootpd tells the client to perform TFTP to the same machine bootpd is running on.
The ps tag may be used to specify the IP address of a peer BOOTP server address to which the BOOTP request will forward.
The time offset to may be either a signed decimal integer specifying the client's time zone offset in seconds from UTC, or the keyword auto, which sets the time zone offset to 0. Specifying the to symbol as a boolean has the same effect as specifying auto as its value.
The bootfile size bs may be either a decimal, octal, or hexadecimal integer specifying the size of the bootfile in 512-octet blocks, or the keyword auto, which causes the server to automatically calculate the bootfile size at each request. As with the time offset, specifying the bs symbol as a boolean has the same effect as specifying auto as its value.
The vendor magic cookie selector (the vm tag) may take one of the following keywords: auto (indicating that vendor information is determined by the client's request), rfc1048 or rfc1084 (which always forces an RFC1084-style reply).
The hn tag is strictly a boolean tag; it does not take the usual equals-sign and value. It's presence indicates that the hostname should be sent to RFC1084 clients. bootpd attempts to send the entire hostname as it is specified in the configuration file; if this will not fit into the reply packet, the name is shortened to just the host field (up to the first period, if present) and then tried. In no case is an arbitrarily-truncated hostname sent (if nothing reasonable will fit, nothing is sent).
Often, many host entries share common values for certain tags (such as name servers, etc.). Rather than repeatedly specifying these tags, a full specification can be listed for one host entry and shared by others via the tc (table continuation) mechanism. Often, the template entry is a dummy host that does not actually exist and never sends BOOTP requests. Note that bootpd allows the tc tag symbol to appear anywhere in the host entry. Information explicitly specified for a host always overrides information implied by a tc tag symbol, regardless of its location within the entry. The value of the tc tag may be the hostname or IP address of any host entry previously listed in the configuration file.
Sometimes it is necessary to delete a specific tag after it has been inferred via tc. This can be done using the construction tag @ which removes the effect of tag. For example, to completely undo an IEN-116 name server specification, use ":ns@:" at an appropriate place in the configuration entry. After removal with @, a tag is eligible to be set again through the tc mechanism.
Host entries are separated from one another by new lines in the configuration string; a single host entry may be extended over multiple lines if the lines end with a backslash (\). It is also acceptable for lines to be longer than 80 characters. Tags may appear in any order, with the following exceptions: the hostname must be the very first field in an entry, and the hardware type must precede the hardware address.
Boot ROMs - Applications for downloading executable images from the host to the target
The pSOSystem Boot ROMs from Integrated Systems support a number of commercial computer boards. Boot ROMs are used for downloading executable images from the host machine to the target system, starting the images, and debugging the downloaded code.
The Boot ROMs are a pSOSystem application that contains the pSOS+ kernel, the pROBE+ debugger, the pNA+ network manager, drivers, and initialization code. The ROMs support serial and Ethernet host-target connections, and they can operate in single and multiprocessor configurations. ISI recommends that first-time users start with the Boot ROMs in a single-processor system, even if the intended configuration is multiprocessor. The source code is supplied as part of the pSOSystem operating system and can be customized for a particular target configuration. For instructions on how to install ROMs on a particular target, see Appendix B of pSOSystem Getting Started. "Board-Specific Information".
Upon first-time powerup, the ROMs must connect to a terminal through an RS-232 connection to allow you to configure setup code for the target. (If the configuration information is stored in non-volatile RAM, reconfiguring is unnecessary upon subsequent power-ups.) If the target has more than one RS-232 port, you can determine the most appropriate port by referring to Appendix B in pSOSystem Getting Started. The characteristics of the terminal (or host machine terminal emulation program) should be: 9600 baud, 8-bit data, 1 stop bit, and no parity. A startup message similar to the following appears on the terminal:
pSOSystem V2.1.3 Copyright (c) 1992 - 1996, Integrated Systems, Inc. --------------------------------------------------------------- STARTUP MODE: Boot into pROBE+ standalone mode NETWORK INTERFACE PARAMETERS: IP Address on LAN is 999.999.99.999 Shared memory interface is disabled HARDWARE PARAMETERS: Serial channels will use a baud rate of 9600 This board's memory will reside at 0x1000000 on the VME bus After board is reset, startup code will wait 60 seconds ---------------------------------------------------------------------- To change any of this, press any key within 60 seconds
If such a message fails to appear, check the following items:
The startup message shows the current ROM configuration parameters while the ROMs wait 60 seconds for input. If no key is pressed within this time, the ROMs proceed to operate according to the parameters in the startup message. If a key is pressed, the following message appears:
(M)odify any of this or (C)ontinue? [M]
Entering the default M starts configuration mode. In configuration mode, the ROMs display a series of prompts for the current configuration settings. The user can accept the system-displayed value at each prompt by pressing [Enter] (or [Return]) or enter a new value at a particular prompt. After the final entry, the ROMs print an updated summary of the configuration and again prompt for an m or a c. Entering a c causes an exit from configuration mode. Configuration mode begins with the following display:
For each of the following questions, you can press <Return> to select the value shown in braces, or you can enter a new value. How should the board boot? 1. pROBE+ standalone mode 2. pROBE+ waiting for host debugger via a serial connection 3. pROBE+ waiting for host debugger via a network connection 4. Run the TFTP Bootloader which one do you want? [1]
Entering a 1 at the configuration mode prompt enables you to use a ROM-resident, standalone pROBE+ debugger to download a pSOSystem executable image and start that image. The pROBE+ debugger downloads the image by executing the DL command and starts the image by executing the GO command. (The pROBE+ User's Manual contains a complete description of the pROBE+ debugger.) Upon exit from configuration mode, the following pROBE+ sign-on banner similar to the one below appears:
pROBE+ V3.0.5 COPYRIGHT 1990 - 1996, INTEGRATED SYSTEMS, INC. ALL RIGHTS RESERVED pROBE+>
Entering a 2 at the configuration mode prompt causes the pROBE+ debugger to exit configuration mode, enter remote debug mode, and wait for a connection request from the SpOTLIGHT debugger over the serial channel. The serial connection you are using for communication to the pROBE+ debugger now needs to be used by the pROBE+ debugger to communicate with the SpOTLIGHT debugger, so if you are using a terminal emulator, such as the UNIX tip utility, exit the emulator at this time so that the SpOTLIGHT debugger can use the connection.
If you have a terminal connected to the target's console port, then this connection must be moved from the terminal to a port that the SpOTLIGHT debugger can connect to on the host system. (Remember to set up the host's port the same way as the terminal was set; that is, baud rate and stop bits).
The SpOTLIGHT User's Guide contains instructions for invoking the SpOTLIGHT debugger on the host system. The pSOSystem Getting Started manual contains a SpOTLIGHT tutorial.
Entering a 3 at the configuration mode prompt puts the pROBE+ debugger in remote debug mode, after which the pROBE+ debugger waits for a connection request from the SpOTLIGHT debugger over the network. Because this mode requires a network interface, the program prompts for additional information about network interfaces, as follows:
Do you want an Ethernet interface? [N]
Enter a y. The pROBE+ debugger responds as follows:
What is this board's IP address on the Ethernet(0.0.0.0 = RARP)? [999.9.999.99]
In most cases, when the target CPU is connected to a host system by Ethernet, the target CPU is added to an existing network. As such, the target CPU must have an IP address that is compatible with that network. Consult your system administrator to obtain a usable IP address. The system administrator may need to modify one or more host system files to make the new IP address known to the host. When an Ethernet IP address becomes available, make it known to the ROMs by entering it at this point. IP addresses are entered as a sequence of four decimal numbers separated by periods, for example: 192.0.10.3
The BOOT ROMs can also obtain their IP address for Ethernet by RARP (Reverse Address Resolution Protocol), in which case a RARP server on the Ethernet assigns the IP address to the ROMs when they initialize. To force the ROMs to use RARP to get their IP address, enter 0.0.0.0 for the IP address.
After an IP address is entered, the following prompt appears:
Do you want to use a subnet mask for the Ethernet interface? [N]
In most cases the answer to this question is no. A y entry causes the ROMs to prompt for a subnet mask to use with the interface. Subnet masks are explained in the pSOSystem System Concepts manual.
The next prompt is
Is there a gateway node on the Ethernet to other networks? [N]
Usually, the host and target systems reside on the same network, in which case the answer to this question is no. In larger installations, however, the host and target systems may exist on two different networks. In such cases, the ROMs must have the IP address of a gateway on their network (to which they direct packets ultimately bound for the host system). A gateway node has access to two or more networks, and can thus transfer packets between them. A y entry in response to the preceding question causes the program to prompt for the IP address of this gateway node.
The next two questions are
Is this CPU the gateway between Ethernet and shared memory? [N] Do you want a shared memory interface [N]
For a single-CPU system, the answer to both these questions should be no, so press [Return] twice.
Next, the ROMs step through the Hardware Configuration parameters, which probably won't need to change. Upon exit from Configuration Mode, no further console output appears because the target CPU is waiting for a connection from the SpOTLIGHT debugger.
Invoke the SpOTLIGHT debugger on the host system by following the instructions given in the SpOTLIGHT User's Guide. Be sure to specify use of Ethernet and designate the target CPU's IP address. the SpOTLIGHT debugger is now ready for use. The SpOTLIGHT User's Guide contains a brief introduction to the SpOTLIGHT debugger, and the pSOSystem Getting Started manual contains a short tutorial demonstrating its use.
The following is an example of a complete startup sequence:
pSOSystem V2.1.3 Copyright (c) 1992 - 1996, Integrated Systems, Inc. ---------------------------------------------------------------------- STARTUP MODE: Boot into pROBE+ standalone mode NETWORK INTERFACE PARAMETERS: IP Address on LAN is 999.999.99.999 Shared memory interface is disabled HARDWARE PARAMETERS: Serial channels will use a baud rate of 9600 This board's memory will reside at 0x1000000 on the VME bus After board is reset, startup code will wait 60 seconds ---------------------------------------------------------------------- To change any of this, press any key within 60 seconds (M)odify any of this or (C)ontinue? [M] m For each of the following questions, you can press <Return> to select the value shown in braces, or you can enter a new value. How should the board boot? 1. pROBE+ standalone mode 2. pROBE+ waiting for host debugger via a serial connection 3. pROBE+ waiting for host debugger via a network connection 4. Run the TFTP Bootloader which one do you want? [1] 3 NETWORK INTERFACE PARAMETERS: Do you want a LAN interface? [N] y This board's LAN IP address(0.0.0.0 = RARP)? [000.000.00.000] 000.000.00.000 Use a subnet mask for the LAN interface? [N] Do you want a shared memory network interface? [N] Should there be a default gateway for packet routing? [N] HARDWARE PARAMETERS: Baud rate for serial channels [9600] Bus address of this board's dual-ported memory [1000000] How long (in seconds) should CPU delay before starting up? [60] 5 ---------------------------------------------------------------------- STARTUP MODE: Boot into pROBE+ and wait for host debugger via a network connection NETWORK INTERFACE PARAMETERS: IP address on LAN is 000.000.00.000 Shared memory interface is disabled HARDWARE PARAMETERS: Serial channel will use a baud rate of 9600 This board's memory will reside at 0x1000000 on the VME bus After board is reset, startup code will wait 5 seconds --------------------------------------------------------------------- (M)odify any of this or (C)ontinue? [M] c
Entering a 4 at the configuration mode prompt selects the TFTP bootloader. It provides a mechanism whereby the BOOT ROMs, following a power-on/reset, can automatically download and initiate execution of a pSOSystem executable image without user intervention. The bootloader uses the TFTP protocols and can be used with any host system that supports TFTP. The SpOTLIGHT debugger is not required.
The TFTP bootloader in the ROMs has been designed for ease of use. In configuration mode, the user specifies the name of the S-record file that contains the executable image and the IP address of the host system on which it resides. When the ROMs exit configuration mode, the bootloader begins operating and loads the image into memory. When the image has been loaded, the bootloader transfers control to the entry point of the newly-loaded code.
When the TFTP bootloader has been selected as the operating mode, the ROMs prompt for additional information after the Network Interface Parameters questions. (Refer to ``SpOTLIGHT - Ethernet Connection,'' on page 2-12 for a discussion of these.) First, a prompt for the IP address of the host system appears:
IP address of the TFTP Boot server to boot from? [000.000.00.000]
Enter the IP address of the host system. The next question prompts for the name (possibly including a pathname) of the file to be loaded and started:
What is the name of the file to be loaded and started? [ram.hex]
This should be the name of the S-record file (not the IEEE or a.out file) that contains the pSOSystem executable image intended for the current board. Rules that govern pathnames can vary between TFTP server implementations, but usually relative pathnames (no leading /) are interpreted relative to the /tftpboot directory. In this case, the default answer ram.hex would cause file /tftpboot/ram.hex to be loaded and started.
The ROMs contain a shared memory network interface, which allows target CPU's that share common memory to communicate with each other by packets that are passed in memory. The shared memory subsystem constitutes an IP network. The system board that serves as the gateway has access to both the shared memory and Ethernet networks. The board is a gateway because it routes packets between the two networks.
If the ROMs are intended to run on multiple target boards in this configuration, first set up and test the CPU that has the Ethernet connection (the gateway), as explained in the previous subsections. Then start the other CPUs as explained in the following subsections.
Select one of the CPU's to be the gateway. The gateway has access to both the Ethernet and the shared memory, and thus needs two different IP addresses (one on each network). The IP address for the Ethernet can be the same address used for setup of the single-processor system.
The shared memory system is a separate network and must have its own network address. Consult with the system administrator when selecting a network address for the shared memory network, since it must be compatible with the rest of the system. When a network address for the shared memory system becomes available, assign host ID 1 to the gateway. For example, if the shared memory network address is 000.0.000, use 000.0.000.0 for the gateway.
For the remaining nodes in the system, assign IP addresses from the range 2 through 8 for each non-gateway CPU. In a 3-CPU system, for example, assign IP addresses 000.0.000.0 and 000.0.000.0 for the non-gateway CPU's.
To configure the gateway CPU in a multiprocessor system, select 3 or 4 from the menu, depending whether you want to use the SpOTLIGHT debugger or TFTP over the network. The following prompt appears:
NETWORK INTERFACE PARAMETERS: Do you want a LAN interface? [N] y
Respond with a y to this question, because this system will have a connection to the physical network to which the boot server is connected.
As in the case of a single processor system, next you must enter the IP address of this target:
This board's LAN IP address(0.0.0.0 = RARP)? [000.000.00.000] Use a subnet mask for the LAN interface? [N]
In this example, it is also assumed that there is no subnet mask. The next prompt asks for the IP address for a shared memory network:
IP address for shared memory? [000.00.000.0] 000.000.0.0
Enter the address of the network as discussed under ``Initial Planning.'' You may also have a subnet mask for the shared memory interface. In this example, it is assumed that there is no subnet mask:
Use a subnet mask for the shared memory interface? [N]
The next question asks what node number this system will have in the multiprocessor system. Respond with the node number you are assigning to this target. Node number 1 is used in this example.
Which node number in the shared memory system is this? [1]
The shared memory system needs an area of memory to store a directory that all nodes can access. If you use the same memory map as the pSOSystem operating system, then that area is the reserved area at the base address plus 700. In this example 40000700 is used, which is the address of this board's dual-ported memory (its base address in the shared memory system) plus 700.
Bus address of the SMNI directory? [1000600] 40000700
Note that this is the same address for all non-gateway targets in the system.
The following question depends on whether your SpOTLIGHT host or TFTP is on different network than this target system:
Should there be a default gateway for packet routing? [N]
In this example the host is on the same network, so the answer is no
The remaining questions are answered in the same way you would as with a single processor system, with the exception of the following question:
How many nodes will be using this as a gateway for bootloads? [1]
You need to tell the gateway node how many other nodes will be using it to boot through, so that it can synchronize the multi-CPU boot.
The printout of the configuration should look something like this:
----------------------------------------------------------------- STARTUP MODE: Run the TFTP Bootloader NETWORK INTERFACE PARAMETERS: IP address on LAN is 000.000.00.000 IP address on shared memory is 000.000.1.0 Bus address of SMNI directory is 0x40000700 This is node number 1 in the shared memory system HARDWARE PARAMETERS: Serial channels will use a baud rate of 9600 This board's memory will reside at 0x40000000 on the VME bus TFTP BOOTLOADER PARAMETERS: IP address of the TFTP host is 000.000.00.000 The file to download and start is ram.hex There will be 1 other nodes booting through this gateway After board is reset, startup code will wait 5 seconds ---------------------------------------------------------------- (M)odify any of this or (C)ontinue? [M]
The other CPUs that will use the shared memory network are non-gateway nodes; these need to be configured as follows:
Do you want a LAN interface? [Y] n Do you want a shared memory network interface? [Y]
You can have a LAN interface and a shared memory network interface, but to make this example simpler, a LAN interface is assumed not to exist. You do need to answer yes to the shared memory network interface question.
As in the case of the gateway node, you need to supply an IP address. This address must consist of the same shared memory network address, plus a unique number from 1 to 8 for this target's node. For example:
IP address for shared memory? [000.000.0.0] 000.000.0.0
Next, answer no to the question on the subnet mask for the shared memory interface:
Use a subnet mask for the shared memory interface? [N]
Now you need to give the node number that you have assigned to this target:
Which node number in the shared memory system is this? [1] 2
The next question on the SMNI directory must be answered the same as for the gateway node:
Bus address of the SMNI directory? [40000700]
Next, give the IP address of the Gateway Node:
What is its IP address? [0.0.0.0] 000.000.0.0
The remaining questions are the same as for a single processor. The printout of the configuration should look something like this:
----------------------------------------------------------------- STARTUP MODE: Run the TFTP Bootloader NETWORK INTERFACE PARAMETERS: LAN interface is disabled IP address on shared memory is 000.000.0.0 Bus address of SMNI directory is 0x40000700 This is node number 2 in the shared memory system IP address of default gateway to other networks is 199.109.1.1 HARDWARE PARAMETERS: Serial channels will use a baud rate of 9600 This board's memory will reside at 0x50000000 on the VME bus TFTP BOOTLOADER PARAMETERS: IP address of the TFTP host is 000.000.00.000 The file to download and start is ram.hex After board is reset, startup code will wait 5 seconds ---------------------------------------------------------------- (M)odify any of this or (C)ontinue? [M]
When interacting with the non-gateway nodes on the host system, the SpOTLIGHT debugger and/or the TFTP server daemon call the host system OS to send packets to IP addresses on the shared memory network. However, this network is unknown to the host system OS. Therefore, before attempting to communicate, the host OS must be able to detect the existence of the network and where to send the packets whose ultimate destination is on the network. On many UNIX systems (Sun, HP, and so on), the route command is used to give this information to the OS:
route -n add 000.0.000.0 000.0.000.000 0
This informs the OS that network 000.0.000 (the shared memory network) can be accessed by directing packets to IP address 000.0.000.000 (the Ethernet IP address of the gateway CPU). The final parameter indicates the number of hops, in this case, 1. Use of the route command requires super user privileges.
FTP Client - Transfer files to and from a remote system
The FTP (File Transfer Protocol) Client transfers files to and from a remote system. The remote system must run an FTP server program that conforms to the ARPANET File Transfer Protocol. The FTP Client runs as an application under pSH and is invoked with the following command:
pSH> ftp [ remote_system ]
where remote_system is a remote system IP address.
If no arguments are given, FTP Client enters command mode (indicated by the ftp> prompt). In command mode, FTP accepts and executes commands described under "FTP Commands" on page -21.
If the command contains arguments, FTP executes an open command with those arguments. See ``FTP Commands'' for a description of open and the other FTP commands.
The normal abort sequence, [CTRL]-C does not work during a transfer.
The FTP Client requires the following:
pSH starts FTP Client by calling ftp_main(). The pSOSystem operating system includes a pre-configured version of pSH and FTP Client, but to add FTP Client to pSH, an entry for it must be made in the pSH list of user applications. The following shows an example of a user application list containing FTP and Telnet:
struct appdata_t appdata[] = {
{ "ftp", "file transfer application", ftp_main, "ft00", 250,
4096, 4096,1, 0 },
{ "telnet", "telnet application", telnet_main, "tn00", 250,
4096, 4096, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
You can define the other elements in the preceding example ("ft00", and so on).
The following commands can be entered at the FTP prompt (ftp>). File naming conventions and descriptions of transfer parameters follow these command descriptions.
mls remote _files -
ascii for network ASCII
binary or image for image
tenex for local byte size of eight bits (used to talk to TENEX machines).
A command argument can have embedded spaces if the argument is enclosed in quote marks (").
If a required command argument is absent, ftp prompts for that argument.
Arguments for some commands in the preceding list can be local files. Local files specified as arguments to FTP commands are processed according to the following rules:
FTP command specification (described in the preceding pages) includes three parameters that can affect a file transfer. The three parameters are the representation type, the file structure, and the transfer mode. The representation type can be one of the following:
The network ASCII and EBCDIC types also have a subtype. This subtype specifies whether vertical format control ([NEWLINE] characters, form feeds, and so on) are to be processed in one of the following ways:
FTP supports the network ASCII (subtype non-print only) and image types.
Next, the file structure can be one of file (no record structure), record, or page. FTP supports only file.
Lastly, the transfer mode can be either stream, block, or compressed. FTP supports only stream.
Correct execution of many commands depends on correct operation by the remote server. An error in the treatment of carriage returns in the 4.2 BSD code handling transfers with a representation type of network ASCII has been corrected. This correction can result in incorrect transfers of binary files to and from 4.2 BSD servers using a representation type of network ASCII. Avoid this problem by using the image type.
FTP Server - Allow remote systems running FTP to transfer files to/from a pHILE+ device
FTP Server allows remote systems that are running the ARPANET File Transfer Protocol to transfer files to and from a pHILE+ device. FTP Server is implemented as a daemon task named ftpd. The ftpd daemon listens for connection requests from clients and creates server tasks for each FTP session that a client establishes.
FTP Server requires the following:
The user-supplied FTP Server Configuration Table defines application-specific parameters, and the following is a template for this table. This template exists in the include/netutils.h file.
struct ftpcfg_t {
long task_prio; /* priority for ftpd task */
long max_sessions; /* max # of concurrent sessions */
char *vol_name; /* name of the login volume */
char **hlist; /* list of trusted clients */
struct ulist_t *ulist; /* list of permitted users */
long reserved[2]; /* must be 0 */
};
Definitions for the FTP Server Configuration Table entries are as follows:
struct ulist_t {
char *login_name; /* user name */
char *login_passwd; /* user password */
long reserved[4]; /* must be 0 */
};
struct ulist_t ulist[] {
{ "guest", "psos0", 0, 0, 0, 0 },
{ "scg", "andy0", 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0 }
}
FTP Server comes as one object module and must be linked with a user application. Calling the function ftpd_start(ftpdcfg) at any time after pSOSystem initialization (when ROOT is called) starts it. The parameter ftpdcfg is a pointer to the FTP Server Configuration Table. If FTP Server starts successfully, ftpd_start() returns 0, otherwise it returns a non-zero value.
The following code fragment shows an example configuration table and the call that starts FTP Server. The complete example code exists in the apps/netutils/root.c file.
#include <netutils.h>
start_ftp_server() {
/* FTP server configuration table */
static ftpcfg_t ftpcfg =
{
250, /* priority for ftpd task */
4, /* max # of concurrent sessions */
"4.0", /* name of the login volume */
0, /* list of trusted clients */
0, /* list of permitted users */
0, 0 /* must be 0 */
};
/* start the FTP server */
if (ftpd_start(&ftpcfg))
printf("ftpd_start: failed to start\n");
}
Loader - Allow run-time target loading and unloading of application programs
The pSOSystem loader provides a programmatic interface for controlling run-time target loading and unloading of application programs from a variety of I/O interfaces. The loader is supplied as a library of functions that can be called from a user application.
Powerful loader applications can be written using just three functions (load, unload, and release). The loader library has been designed to depend only on pSOS+ system services; it does not depend on any other components. However, you may need to include other components like the pHILE+ file system manager and the pNA+ network manager, depending on the type of I/O interface being used to load applications.
The loader supports the loading of object files residing on pHILE+ media (pHILE+ volumes, MS-DOS volumes, or remote file systems mounted through NFS). The loader also supports loading from any device driver that conforms to the interface standard defined by the pREPC+ library. Additional requirements for device drivers are described in ``Interfaces and Drivers.'' A pseudo device driver that uses TFTP (Trivial File Transfer Protocol) to transfer files from a remote host is also provided with the pSOSystem operating system. You can use the TFTP device driver in conjunction with the loader.
The loader can load object files that are either in Motorola S-record (SREC) format or in the ELF format generated by pRISM compiler tools. The following types of object files are supported by the loader:
The term relocatable refers to object files that contain relocation information. Such object files are produced as intermediate files during the compilation/linking process. The relocatable object (.o) files are produced by various pRISM tools, as follows:
The ability to load relocatable files with the loader provides extra flexibility. For example, you can generate position-dependent code but defer the decision of where to place the code in target memory until runtime. However, note that relocatable files must not contain unresolved external symbol references.
The loader should be installed under the pSOSystem directory structure. Upon successful installation, the following files and directories are created under the pSOSystem root directory:
The loader contains two user-configurable modules. One supports the loading of Motorola S-records and the other supports the loading of ELF object files. It is possible to generate a loader application that contains any one or both of the modules. By default, both of the modules are enabled. The apps/loader/sys_conf.h file contains the following two #defines:
#define LD_SREC_MODULE YES /* Motorola S-record support */ #define LD_ELF _MODULE YES /* ELF support */
To exclude a particular module from getting linked to the loader application, change YES to NO for the module you want to exclude.
sys_conf.h also contains the following #define, which determines the maximum number of loading operations that can be handled simultaneously by the code in the loader library:
#define LD_MAX_LOAD 8 /* Max number of simultaneously active load */
You must make any necessary changes to LD_SREC_MODULE, LD_ELF_MODULE, or LD_MAX_LOAD by modifying sys_conf.h before generating the loader application.
In addition to the files listed above, a host-level utility called ld_prep gets installed under the various bin/<host> subdirectories in the pSOSystem directory tree. You must include the proper subdirectory in your PATH, depending on the host environment you are using for pSOSystem application development.
For example, if using a Sun SPARCstation as the development platform, modify your path as follows:
set path = ( $path $PSS_ROOT/bin/sparc ) # if csh is the working shell
or
PATH=$PATH:$PSS_ROOT/bin/sparc # if sh or ksh is the working shell
where PSS_ROOT is an environment variable specifying the pathname of the pSOSystem root directory.
After installation, copy the files under the apps/loader directory to a working directory of your choice before making any modifications or generating the sample application. (The UNIX cp -r or MS-DOS xcopy commands can be used for this purpose.) The README file contains detailed information about the sample application. It also contains instructions for generating and running this application. You must follow these instructions to compile and run the sample loader application. Run this application and play around with the sample code to help familiarize yourself with the loader.
The loader is useful in situations where you are dealing with multiple applications (running simultaneously on a target), and they can be partitioned so that no two applications share symbol references with each other. There can be many reasons for partitioning applications into multiple executable files and/or using dynamic loading. Some of these are as follows:
Typically, you will make the loader run as part of the root task. This task remains resident on the target and loads other applications as and when needed. This is one of the suggested approaches and, as demonstrated by some of the sample applications, the loader functions can be used in many other ways.
For ease of explanation, assume the presence of a single task called the loader task, which takes care of loading other application tasks, called loadable applications. The loader task is linked with the pSOSystem operating system and gets loaded on the target system using the standard method for bootstrapping the system. First, an outline is provided of a simple method for writing the loader task using the functions provided by the loader library, loader.olb.
The load() function is provided for loading loadable applications. These applications may remain resident on the target forever, or only temporarily. Loadable applications can be unloaded using the unload() function. A call to unload() frees up any memory allocated by load() for the run-time image of a loadable application; it also frees up any state information associated with the loadable application [saved by the loader library during the call to load()].
If the loadable application is to remain resident on the target forever, the release() function must be called to free up any state information associated with the loadable application. A call to release() does not free up the memory occupied by the run-time image of the loadable application, and the application can keep running without any hindrance. A detailed description of these functions is provided later in this section.
You open the file containing the loadable application using either the pHILE+ open_f() call or the de_open() function, which opens the device driver through which the loadable application will be read. The file descriptor returned by open_f() or the device number of the device driver must be passed to the load() function as the first argument (fd). You must also specify whether the first argument refers to a pHILE+ file descriptor or a device number. This is done by setting either LD_DESC_PHILE or LD_DESC_DEV in the second argument (flags) passed to load().
The load() function reads in the loadable application using either the pHILE+ read_f() function or the de_read() function, whatever the case may be. It determines the object file format of the loadable application and invokes the appropriate module (SREC or ELF ) to convert the object file into a binary image suitable for execution. The exact behavior of load() depends on the type of code (position independent, absolute, or relocatable), as follows:
Loading Absolute Code
Any object files containing absolute code (that is, position-dependent
and non-relocatable code) are loaded at the address specified at the time
of linking. The load() function does not allocate any memory for loading
the run-time image. It is the responsibility of the calling task to make
sure that it is safe to load the application at the address to which it
was linked. You cannot override the default addresses, as it does not make
sense to load absolute code at a location to which it was not linked.
Loading absolute code is a one-step process. Similarly, loading position-independent or relocatable code at the default load address chosen by the loader is also a one-step process. You simply call load() with the LD_LOAD_DEF flag set in the flags argument.
If for some reason you want to control where the various parts (sections) of an object file get loaded into target memory, a two-step process must be followed:
Once the load() call returns, you are free to close the object file (or device driver) by calling close_f() (or de_close()). At this point the binary image of the loadable application has been loaded into memory. If the binary image corresponds to a pSOS+ task, you can create and start the task at any time. In most cases, the entry point to the task can be obtained from the object file information returned by load(). If the entry point is not known, it is set to zero by load(). You must call the t_create() and t_start() system services of the pSOS+ kernel with appropriate arguments to create and start the task, respectively.
Once the task is running there are two possibilities, as explained earlier:
Following is a template for the three data structures used by the pSOSystem loader. The first is the OF_INFO structure, a pointer to which is returned by load() and also gets passed to unload() and release(). The second is the SECN_INFO structure, which is contained in the OF_INFO structure. The third is the TASK_INFO structure, which is also contained in the OF_INFO structure. These structures are defined in the <include/loader.h> file.
typedef struct OF_INFO{
int desc; /* Object file descriptor */
char format[5]; /* Object file format */
char code_type; /* Code Type (Absolute/Relocatable/PIC) */
int nsecns; /* Number of sections */
SECN_INFO *secn_info; /* Section information */
TASK_INFO task_info; /* Info needed to create & start task */
} OF_INFO;
The second structure, SECN_INFO, contains information regarding the individually loadable sections of an object file and is defined as follows:
typedef struct secn_info{
char name[LD_SECNAMELEN]; /* Name of the section */
unsigned long type; /* Type of the section */
unsigned long size; /* Size of the section */
unsigned long base; /* Section load address */
} SECN_INFO;
The name and type field describe the name and type of the section, respectively. These fields are compiler dependent and are supplied only for your information. The loader does not make use of these fields. The size field specifies the size of the section in bytes, and base specifies the address in memory where this section gets loaded.
You can modify base, as explained in the description of the load() function later in this section, to control the placement of the section in memory if the code_type is LD_RELOCATABLE. Modifications done to any other fields of this structure in between any two loader calls are ignored by the loader.
The third structure, TASK_INFO, contains information necessary to create and start a task using the pSOS+ t_create() and t_start() system services. This information is obtained from the object file by load() and can be stored in the object file by running ld_prep on the object file and specifying the appropriate values for various task-specific parameters (see the man page for ld_prep for further details). TASK_INFO is defined as follows:
typedef struct task_info{
char name[4]; /* Name of the task to be created */
unsigned long priority; /* Task priority */
unsigned long sstack_sz; /* Supervisor stack size */
unsigned long ustack_sz; /* User stack size */
unsigned long create_flags; /* Flags used by t_create() */
unsigned long start_mode; /* Mode used by t_start() */
void (*entry) (); /* Task entry point */
} TASK_INFO;
load() is defined as follows:
#include <loader.h>
unsigned long load (
unsigned long fd,
unsigned long flags,
OF_INFO **of_info
);
load() reads an object file from an open file descriptor fd and converts the incoming stream of data into a binary image ready for execution. The information about the object file is read and a pointer to it is returned in the location pointed by of_info. The fd is either a file descriptor returned by a call to the pHILE+ open_f() routine or it is the device number of a pREPC+-compatible device driver. You must set the LD_DESC_PHILE or LD_DESC_DEV fields in the flags argument to specify whether fd is a file descriptor returned by open_f() or a device number.
The exact behavior of load() is controlled by the load type specified by the flags argument. You can specify one of three load types (LD_GET_INFO, LD_LOAD_DEF, LD_LOAD_MOD) by bitwise OR-ing one of the three values in the flags argument.
If LD_LOAD_DEF is specified, load() reads the object file and loads the binary image into target memory, using the default load address specified by the object file header. The values used to load the file are stored in an OF_INFO structure, and a pointer to this structure is returned through of_info.
If LD_GET_INFO is specified, load() reads the object file header information and returns a pointer to it through of_info. No binary image of the object file is loaded in target memory.
You can modify certain values returned in the OF_INFO structure and call load() to load the binary image by specifying the load type as LD_LOAD_MOD.
load() can handle both absolute and relocatable object files. The term relocatable also covers the position-independent code generated by Green Hills compiler tools.
If the object file is absolute, it is always loaded at the address specified by the object file header, and you may not be able to modify these values. Also, it is assumed that it is safe to load an absolute object file at the address specified by the object file header. If the object file is relocatable, then the memory needed to load the object file is automatically allocated by load().
However, for relocatable object files, you can control the loading of file on a per-section basis by modifying the relevant fields in the OF_INFO structure returned by calling load() with load type LD_GET_INFO and then passing the modified structure to load() with load type LD_LOAD_MOD.
On success, load() returns 0; otherwise, it returns a non-zero error number.
The following errors are returned by load():
Other errors may be returned due to the failure of either a pSOS+ system call or a call made internally by the loader to the pHILE+ file system manager or a device driver.
#include <loader.h>
OF_INFO *my_of_info;
unsigned long fd, flags;
...
...
load (fd, flags, &my_of_info);
...
...
unload() is defined as follows:
#include <loader.h>
unsigned long unload (
OF_INFO *of_info
);
This function unloads an executable file image from the target memory, where it was loaded previously using load(). of_info points to the object file information returned by a previous call to load().
If the type of executable being unloaded is LD_ABSOLUTE, the unload() function does nothing to free the memory associated with the executable - it is the responsibility of the caller to free up the memory (if any) that it allocated previously.
If the type of executable is LD_RELOCATABLE, this function frees up any memory allocated earlier for loading the executable. However, it does not free any memory for sections of executable files that were allocated by the caller. Those must be taken care of by the caller.
unload() frees up any state information associated with of_info and preserved internally by the loader. It also frees up the object file information pointed to by of_info, and it must not be referred to subsequently by the caller.
The unload() function must be called only after the task(s) associated with the loaded executable have been deleted, since all of the memory allocated to load executable code and data is returned to the free storage pool by unload() and can be re-used for any purpose at any time.
On success, unload() returns 0; otherwise, it returns a non-zero error number.
The following errors are returned by unload():
Other errors may be returned that can be due to the failure of a pSOS+ system call made internally by the loader.
release() is defined as follows:
#include <loader.h>
unsigned long release (
OF_INFO *of_info
);
This function frees up the object file information pointed to by of_info, and also any state information associated with of_info and preserved internally by the loader. It must be called in one of the following situations:
The object file information pointed to by of_info must not be referred to subsequently by the caller.
On success, release() returns 0; otherwise, it returns a non-zero error number.
The following errors are returned by release():
Other errors may be returned that can be due to the failure of a pSOS+ system call made internally by the loader.
The syntax for ld_prep is as follows:
ld_prep {-a|-i|-r} [-v] [-d defaults_file ] [-n task_name ]
[-p priority ] [-c create_flags ] [-m task_mode ]
[-e entry_point ] [-s supv_stack_size ]
[-u user_stack_size ] [-o out_file ] in_file
ld_prep is a post-processor that must be run on an object file in_file before it can be loaded by the pSOSystem loader. The object file can be in either Motorola SREC format or ELF format. ld_prep analyzes the input object file, prepends a header to it, and writes the file to a user-specified output file out_file (or to a file out.ld by default). The header contains certain information about the object file that is used by the loader.
You must specify whether the input object file has to be loaded at the absolute address specified at link time or whether it can be relocated by the loader to any address of its choosing. You must specify whether the input object file is absolute or relocatable.
Additionally, if the file being loaded corresponds to a task that will be created and started eventually by the user, it is possible to specify all of the task-specific information using ld_prep. This information is passed to the loader application via the TASK_INFO sub-structure of the OF_INFO structure, the pointer to which is returned by load(). This information typically consists of the task name, the priority at which it runs, the sizes of the user and supervisor stacks, the task entry point, and various other task attributes that get passed to t_create() and tstart().
You must run ld_prep on an object file that needs to be loaded by the loader or else an error will be flagged by the loader at runtime.
The following options are provided:
The G flag specifies that the task is global and addressable by external tasks residing on other nodes. If this flag is omitted, the task is assumed to be local.
The F flag specifies that the task uses floating point units. If this flag is omitted, the task is assumed not to use floating point units.
A
specifies that the task's ASRs are disabled. If this flag is omitted,
the task's ASRs are assumed to be enabled.
N
specifies that the task is non-preemptible. If this flag is omitted,
the task is assumed to be preemptible.
T
specifies that the task can be timesliced. If this flag is omitted,
it is assumed that the task cannot be timesliced.
S
specifies that the task runs in supervisor mode. If this flag is omitted,
the task is assumed to run in user mode.
If you specify a defaults file using the -d option, it is parsed first to pick up the defaults. Next, ld_prep parses any command line options. Options specified on the command line override values specified in the defaults file
In most cases, when an option is specified neither in the defaults file nor on the command line, the corresponding parameter is set to 0. When detecting the 0 values, the loader application must determine the appropriate values to use. Note that you must specify either the -a or -r option, either in the defaults file or on the command line; otherwise, an error is flagged by ld_prep.
ld_prep exits with status 0 upon successful execution; otherwise, it exits with exit status 1 and an error message is printed to stderr. The error messages are self explanatory.
ld_prep -r -o app.ld app.x ld_prep -a -v -p 180 -n NApp -cF -mAT -e 0x3c0000 -s 512 -o napp.ld newapp.x
is the same as
ld_prep -d task.defs -o napp.ld newapp.hex
where the file task.defs contains the following line:
-a -v -p 180 -n NApp -cF -mAT -e 0x3c0000 -s 512 -o app.ld
Note that a command line option overrides the options specified in the defaults file (-o in the above example).
If an option is specified more than once on the command line, the last (rightmost) such definition takes precedence over any previous definition. However, if an option is specified more than once in the defaults file, the behavior of ld_prep is undefined.
A warning is issued if the defaults file contains the -d option and the option is ignored.
The ld_prep utility is provided for Sun SPARCstations and machines running MS-DOS.
The procedure for compiling and running applications using the loader is as follows:
As stated earlier, a device driver that interfaces with the loader must meet the interface requirements set by the pREPC+ library. See the guidelines for writing device drivers in Section 3, ``Interfaces and Drivers.'' The loader calls only the de_read() function internally. It passes an I/O parameter block with the following format:
."typedef struct {
unsigned long count; /* Number of bytes to read */
void *address; /* Address of data buffer */
} iopb;
The loader needs the device driver to be capable of skipping data (i.e. seeking in the forward direction). To seek in the forward direction, the loader calls de_read() with the count field in the iopb structure set to the number of bytes to skip, and with the address field in the iopb structure set to (void *)NULL.
The device driver read function, on receipt of an iopb structure with address field set to NULL, reads count number of bytes from the device and discards those. Thus, this case is treated the same as any other case, except that the driver does not copy the data. This is the only additional requirement set by the loader, and it is very easy to implement. For example, you can refer to the TFTP pseudo device driver sources that are provided with the pSOSystem operating system in the drivers directory.
NFS Server - Allow systems to share files in a networked environment
NFS Server allows systems to share files in a networked environment. It permits NFS clients to read and write files transparently on pSOSystem disks that the pHILE+ file system manager manages.
NFS Server is implemented as two application daemon tasks. The mntd task is the mount daemon. It processes requests for mounting and listing exported directories. The nfsd task processes all other NFS requests after exported directories have been mounted.
NFS Server requires:
The user-supplied NFS Server Configuration Table defines application-specific parameters. A template for this configuration table (shown below) exists in the include/netutils.h file.
struct nfscfg_t
{
long task_prio; /* priority for nfsd task */
long unix_auth; /* UNIX authentication-required flag */
long error_opt; /* error reporting option */
long vol_blksize; /* system-wide volume block size */
char *def_vol_name; /* name of the default volume */
nfselist_t *elist; /* ptr to the list of exported directories */
long reserved[4]; /* must be zero */
};
Definitions for the NFS Server Configuration Table entries are as follows:
struct nfselist_t
{
char *dir_path; /* export list */
char *hlist; /* list of trusted clients*/
};
struct nfselist_t nfselist[] =
{
{"4.0/", "000.000.00.000", 000.000.00.000"},
{"5.0/etc", 0 },
{0, 0}
};
NFS Server comes as one object module and must be linked with a user application. Calling the function nfsd_start(nfscfg) any time after pSOSystem initialization (by calling ROOT) starts NFS Server. The parameter nfscfg points to the NFS Server Configuration Table. If NFS Server is started successfully, nfsd_start() returns 0.
The following code fragment shows an example configuration table and the call that starts NFS Server. The complete example code exists in the apps/netutils/root.c file.
#include <netutils.h>
start_nfs_server()
{
/* NFS server configuration table */
static nfscfg_t nfscfg =
{
250, /* task priority for nfsd task */
1, /* requires "root" UNIX client to mount */
0, /* no error reporting */
512, /* system-wide volume block size */
"4.0", /* default volume name */
0, /* everything exported */
0, 0, 0, 0 /* zeros for all reserved entries */
};
/* start the NFS server */
if (nfsd_start(&nfscfg))
printf("nfsd_start: failed to start\n");
}
The following features are not supported in the current version:
On the other hand, the following parameters do apply:
pSH - Interactive command line shell
pSH provides an interactive, command line shell. pSH consists of two parts:
pSH is provided as part of the system utilities object library (sys/libc/netutils.lib). pSH contains a set of built-in commands. Commands or complete applications that will be spawned as separate tasks can be added to pSH.
pSH requires the following components:
The user-supplied pSH Configuration Table defines application-specific parameters. The following is a template for this configuration table. The template exists in the file include/netutils.h:
struct pshcfg_t {
long flag; /* services options */
long task_prio; /* priority for each shell task */
char *def_vol_name; /* default login volume name */
struct ulist_t *ulist; /* list of permitted users */
appdata_t *app; /* ptr to the list of user apps */
cmddata_t *cmd; /* ptr to the list of user cmds */
long reserved[4]; /* must be 0 */
};
Definitions of the pSH Configuration Table entries are as follows:
struct ulist_t
{
char *login_name; /* user name */
char *login_passwd; /* user password */
long reserved[4]; /* must be 0 */
};
struct ulist_t ulist[] = {
{ "guest", "psos0", 0, 0, 0, 0 },
{ "scg", "andy0", 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0 }
};
struct appdata_t
{
char *app_name; /* application name */
char *app_help; /* help string */
void (*app_entry)(); /* entry point */
char *app_tname; /* task name */
long app_tprio; /* task priority */
long app_sssize; /* system stack size */
long app_ussize; /* user stack size */
short app_reentrant_flag; /* reentrant flag */
short app_reentrant_lock; /* reentrant lock */
};
struct appdata_t appdata[ ] = {
{ "ftp", "file transfer application", ftp_main,
"ft00", 250, 2048, 2048,1, 0 },
{ "telnet", "telnet application", telnet_main, "tn00",
250, 2048, 2048, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
struct cmddata_t {
char *cmd_name; /* command name */
char *cmd_help; /* help string */
void (*cmd_entry)(); /* entry point */
short cmd_reentrant_flag; /* reentrant flag */
short cmd_reentrant_lock; /* reentrant lock */
};
struct cmddata_t cmddata[] = {
{ "type", "list content of a file", type_main, 1, 0 },
{ "volume", "show current working volume",
volume_main, 1, 0 },
{ 0, 0, 0, 0, 0 }
};
Making the psh_start(pshcfg) system call from the application starts pSH. The parameter pshcfg is a pointer to the pSH Configuration Table. If pSH is started successfully, psh_start() returns 0; otherwise, it returns a non-zero value.
The pSH configuration table is defined as follows:
long flag; /* services options */
long task_prio; /* priority for pshd task */
char *def_vol_name; /* name of the default login volume */
ulist_t *ulist; /* ptr to the list of trusted users */
appdata_t *app; /* ptr to the list of applications */
cmddata_t *cmd; /* ptr to the list of commands */
unsigned long console_dev; /* psh console device number */
long reserved[3]; /* reserved for future use, must be 0 */
The following code fragment shows an example configuration table and the call that starts pSH. The complete