Survey
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
* Your assessment is very important for improving the workof artificial intelligence, which forms the content of this project
Jeeves 24 June 2017 System Manual 1 Introduction Jeeves can be thought of as a typical, interrupt-driven server system, although it is completely simulated. Jeeves seems to have the usual complement of hardware, although some of it runs slower than is typical today and some is smaller in capacity than is typical today. Nevertheless, Jeeves functions like a modern server system in most respects. Generally, the slow speed and small sizes are there only to keep the simulation reasonable. From this point on, Jeeves will be described as if it were a real machine (with a few minor exceptions to describe aids that the simulator provides which would not be present on a real machine). The basic hardware components for Jeeves are as follows: Clock The internal clock speed is only 100 KHz. So, there is a clock tick every 10 microseconds. Most CPU instructions take fewer than 3 clock ticks. The clock value is kept in the clock register and may be accessed whenever needed. When the simulation begins, the clock register is set to time 1; it is then advanced for each tick. The very slow clock and execution speed allow the scripting to be done without dealing in 9-digit numbers. CPU There is a single CPU that can run in either supervisor mode or user mode. In supervisor mode, activity at the CPU can proceed without possibility of being interrupted from the system devices - all interrupts and traps are masked when this mode is in effect. The operating system and the system programs (daemons) execute in supervisor mode. In user mode, any event requiring attention at any of the devices or processes halts the CPU activity with an interrupt or trap that must be addressed by the operating system. User programs execute in this mode. The CPU also has a collection of registers Jeeves 24 June 2017 System Manual 2 which the operating system needs to access and control the hardware actions see later discussion. Timer There is a timer (alarm clock) which may be set on Jeeves. It is used to control execution time of user programs. To use it, the operating system sets the timer register to some future time (measured in ticks). When that time is reached, a Time_Out interrupt is generated. Memory There are considerably more than 128 K bytes of memory; however, only 128 K bytes are available for user programs and buffers - this is the memory that the operating system must manage. The operating system (OS from now on) kernel and the daemons reside in additional, separate memory. The 128 K memory is byte addressable but is organized into sixty-four 2048-byte page frames. Jeeves is a virtual memory machine - the 128 K of physical memory has addresses from 0 to 131071, with page frames beginning at addresses 0, 2048, 4096, 6144, etc. The memory is referred to in some places by physical page frame number, so page frames beginning at 0, 2048, 4096, 6144 would be in frames numbered 0, 1, 2, and 3. Disk Jeeves has a single 3-platter hard disk; so there are 6 available surfaces (numbered 0-5). Each surface has 128 tracks numbered (0-127); and each track has 32 sectors (numbered 0-31). Each sector holds 512 bytes. Thus, the total capacity of the disk is 12582912 bytes (12 MB). The disk is normally accessed for reading or writing 4 sectors (a cluster) at a time; however, any contiguous group of sequentially numbered sectors in a single track can be accessed in one disk action. The use of the storage on the disk is tightly controlled by the structure of the file system - see later discussion. The disk spins at 7200 rpm giving it an access time of 3 ms to 14 ms (average access Jeeves 24 June 2017 System Manual 3 time is 8.25 milliseconds - 825 clock ticks). Console This really consists of three devices which are physically attached to the other components of Jeeves. Keyboard the standard one found on PCs - each keystroke causes an interrupt. Keystroke frequency depends on typing speed. Screen mostly character-oriented, although it can accept one or more lines of output for display in a single operation. The display rate for the screen is approximately 10K bytes per second; up to 2048 bytes can be accepted for display at once. The screen is treated as an output device involving interrupts; it is not memory mapped. Mouse with a roller ball to control a pointer and a single button to initiate action; not used for the project. Communications Interface This is the connection to the network. A TCP/IP-like protocol is used with the packets sent and received over the network. Clients at other IP addresses can use the services that Jeeves provides by establishing connections with the server (Jeeves' IP address is 144.201.193.179). The services available from Jeeves are Telnet and FTP. (For Telnet clients, Jeeves also acts as a printer server; it is not a general printer server.) The interface has a one Mb connection to the outside world, allowing packets to be sent or received at the rate of about one byte each 10 microseconds (approximately one byte each clock tick). Jeeves is one server on a LAN with a bus topology. Consequently, Jeeves receives some packets that are intended for other servers; as in real life, these packets are to be ignored. Only packets destined for Jeeves should be processed by Jeeves. Jeeves 24 June 2017 System Manual 4 Printer Jeeves uses a typical buffered printer but with a small buffer. It can buffer up to 8K bytes; so when printing a file, often only part of the file can be sent to the printer before it must print. Transmission of data from memory to the buffer occurs at approximately one byte per microsecond (10 bytes per clock tick). Once it is signaled to print, the printer prints the contents of its buffer at a rate of 16 K bytes per second (so a full buffer takes 50000 ticks to print). Ejecting a page on the printer takes up to 0.05 seconds (5000 clock ticks). Interrupts Jeeves is driven by the occurrence of interrupts and traps. An interrupt is regarded as a signal from some system element (hardware) away from the CPU which indicates the need for the operating system's attention. A trap is regarded as a signal from the executing program which indicates the need for the operating system's attention. When an interrupt or trap occurs, the hardware does the following: 1. Changes to supervisor mode (if it is not there already). 2. Puts an interrupt code in the icode register. The code indicates what type of event has occurred or what type of attention is needed. The interrupt code is a number between 1 and 13. 3. If the interrupt is from a device (keyboard, screen, printer, disk, comm interface, mouse), the hardware puts the device number into the device register. If the interrupt is from booting up or powering down or if it is a trap, nothing is put in the device register. Jeeves 24 June 2017 System Manual 4. 5 Calls the function OpSys() which is expected to be the entry point to the operating system for all interrupt and trap handling. The following tables lists the interrupt and trap codes that Jeeves uses. Associated with each code is a name (used to refer to the specific interrupt/trap in subsequent descriptions) and a cause that gives a basic explanation of what caused the exception. Code 1 Common Name Type Cause Boot_Done Interrupt Machine has been powered up and the operating system has been loaded into memory by the program in PROM. 2 Power_Down Interrupt Person at console has pushed the button to turn power off. 3 Device_In Interrupt Input has been received from some source: key from keyboard, packet from interface, cluster from disk, mouse movement. 4 Device_Out Interrupt Output has been delivered to some destination: text to the screen, data to the printer, cluster to the disk, packet to the interface. 5 Device_Enable Interrupt The printer has come on line; it was previously disabled for some reason. The printer always starts online. 6 Device_Disable Interrupt The printer has gone off line; it will reenable at some point. 7 Control_Done Interrupt A device has completed a control action: seek on a disk or eject on a printer 8 Block_Self Trap A system program has completed its task Jeeves 24 June 2017 System Manual 6 and needs to be moved to a blocked state. 9 Time_Out Interrupt The time set in the timer has been reached or exceeded. 10 User_Pgm_Input Trap A user program has requested to read some data from a file. 11 User_Pgm_Output Trap A user program has requested to write some data to a file. 12 User_Terminate Trap A user program has reached a successful conclusion. 13 User_Abort Trap A user program has attempted some action that is not allowed and must be terminated. Each device on the system is referred to by its device number. When interrupt codes 3, 4, 5, 6 or 7 occur, it is vital to distinguish which device the interrupt code should be associated with. Following is a list of the device numbers used on Jeeves: Device Device Number Comm Interface 20 Disk 19 Keyboard Mouse 9 51 Printer Screen 23 16 How It All Gets Started Jeeves 24 June 2017 System Manual 7 The simulator works with two (or three) data files: one contains the information for Jeeves' disk; a second contains a script of events to exercise your operating system. The optional one is used for tracing purposes, see later description. To start the simulator, your program must call BootStrap() in main; BootStrap then does the following: 1. It sets up a simulation with the specified disk and script files. 2. It acts as if memory is being checked and your operating system and its system processes are being loaded from the disk. The disk already holds the bootstrap program, the operating system, a starter file system and some user authentication information. The simulator notifies you if any problems occur during this the setup. (This step is completely fake - your OS is not really on the disk, neither are the system processes. 3. It then issues a Boot_Done interrupt to give your operating system control, by calling OpSys with the interrupt code set to 1. At that point, your operating system should take over. You may assume that all of the standard devices (console, comm interface, disk, and printer) are available at that time. Your operating system should set up its data base of information about the devices, the users, the processes (it should create six system processes initially) and the threads. The OS should then begin thread scheduling. When you run the simulator, it prompts you for two pieces of information. It asks for a script file name and a disk name. The script file contains a script of mostly input interrupts (keystrokes and Comm Input messages) and a few other events (Boot_Done, Device_Enable, and Device_Disable interrupts). The disk is actually kept in a file also. The disk file contains Jeeves 24 June 2017 System Manual 8 the information held on the simulated disk. Below is a display of exactly what appears when the simulator executed for one script; naturally, the number of bytes varies from script to script. The elements in bold are the entries specified for a simulation run (by you). Enter script file name: comm1.scr 133 byte script ready. Memory OK Peripherals present: Console, Comm Interface, Printer Console elements: Keyboard, Screen, Mouse Enter disk name: thedisk Disk is ready. All other hardware is ready. Operating system loaded -- Transferring control to it. If your OS does not cause any errors, this may be all the output to the screen that you see during a simulation. Other possible outputs to the screen and other files are described later. Registers Jeeves has a collection of registers that are used by the operating system to direct the devices and by the devices to communicate information to the operating system. Nearly all of these registers can hold 32-bit integer values. These registers are described in three groups based on their function. Below is a list of the general registers and what they are used for. Each of these registers is referred to in your OS as R.registername Jeeves 24 June 2017 System Manual 9 General Registers Name Purpose clock Keeps the system time (measured in units of 10 microseconds). The OS may get value of clock anytime, but it cannot change it. timer Holds a system time at which to raise an alarm (interrupt code 9). The OS may set this to any system time. If timer <= clock, a Time_Out interrupt is raised unless timer is set to -1 (its "off" value). icode Interrupt code number. The OS can get this value; but it cannot set it. device Interrupt/command device number. The OS can get the value here when an interrupt occurs to determine which device needs attention. The OS must set the value of this register in conjunction with checking the status of a device, with resetting a device or with issuing a command to a device. state Contains a status code for a device which was just interrogated with the GetStatus instruction. The state must indicate a device is "ready" before an I/O command can be issued to the device. The possible state codes are 0 to indicate "ready", 1 to indicate "busy", 3 to indicate "locked", 4 to indicate "disabled", 7 to indicate "unstable", and 9 to indicate "unknown". pc Holds the relative (virtual) memory address of the next instruction to execute for the executing process. This is the program counter. genpur[8] This is the collection of general purpose registers that are used for running any program. oserror This would not be a register on any real machine. When the simulator detects an error that your OS has made, it displays an error message and puts an error code in this register. In this way, the OS can determine if an action that it attempted failed; a value of zero in this register indicates "no error." In addition to the general registers (useful for many actions), there are two groups of special Jeeves 24 June 2017 System Manual 10 use registers. The first of these is for control of input and output. The registers in this group are referred to as R.io.registername in your OS; each is described below. I/O Registers Name Purpose address Physical memory address of the beginning of an area to be used in a data transfer. The OS must set this register prior to issuing a command that is expected to result in data being transferred from memory (and to memory in the case of the disk). For I/O involving disks and printers, the address must be a multiple of 2048 - disk I/O and printer output must begin on a page frame boundary. datasize Number of bytes to be transferred to or from the memory area whose beginning is specified in address. The OS must set this register prior to issuing a command that is expected to result in data being transferred from memory (and to memory in the case of the disk). packetin Holds the physical memory address of where the next packet to arrive over the communications interface is to be placed. mousein Holds the physical memory address of where the information about the next mouse action is to be placed. keyin Holds the physical memory address of where the next character from the keyboard is to be placed. surface The surface number of where to access the disk. track The track number within the surface to access. sector The sector number within the track at which to begin the access. Most disk accesses are expected to access 4 consecutive sectors (a cluster); the exact number of sectors is determined by the datasize register. The datasize must be a multiple of 512 (the number of bytes in a sector). The sector value is Jeeves 24 June 2017 System Manual 11 usually a multiple of 4. action The action to take (a char): R to read from the disk to memory, W to write from memory to the disk, S to seek only on the disk, B to write from memory to the printer buffer, P to print the contents of the printer buffer, or E to eject a page on the printer. This character must be in uppercase. bufferaddr The printer buffer address to which a transfer from memory is to be made, beginning at R.io.address. The second group of special purpose registers is for process and thread control actions. For all but two of these registers, it is necessary for the OS to set specific values into them before trying to execute a process. The two exceptions are registers that are set by user programs when requesting the OS to perform some I/O. The process control registers are referenced in the OS as R.process.registername each is described below. Process Registers userid The user identification number of the user who owns this process. This number is found in the password file and is permanently associated with a user. This is useful when executing user programs. processid This number is assigned by the OS. Each process gets a processid when it is created. The system processes have special processids that must be assigned: the DiskScheduler must have processid == 1, the ProtocolHandler must have processid == 2, the Login handler must have processid == 3, the Shell must have processid == 4; the Unspooler must have processid == 5; and the Transmitter must have processid == 6. User processes are assigned processids on an as needed basis - these processids must be > 10 (so, the first user process should have processid == 11). thread This number is used to allow a user program or system process to be used in a reentrant manner; it is a number that is distinct for each executable element Jeeves 24 June 2017 System Manual 12 (each communication session or console login). If user xyz was logged in three times from separate client machines and was executing the same process (e.g. Shell) on each of them, the thread would distinguish the three instances. If the user logs in, does something, logs out, and then logs in again from the same IP address, these are separate threads. Thread numbers begin at 101 and are allocated sequentially as each session's SYN is received. Generally, a thread number should be maintained throughout the life of a session, regardless of which process (system or user) is executing. ipaddr The IP address of the client responsible for this thread. pgmioaddr The relative memory address at which a user program wants input read into or output written from. In each case, a data record is being transferred. System processes do not use this register. pgmiosize The number of bytes to be transferred in a user program I/O action. For input, pgmiosize is the maximum number of bytes allowed for reading - each read generally reads one record of a file; for output, pgmiosize is the actual number of bytes to write. System processes do not use this register. pagemap[16] This provides a hardware page map for translating virtual memory addresses to physical memory addresses. Each element of this array is a page map entry; each entry is four bytes long. A page map entry has three named components: resident: Residency flag - 1 resident in memory, 0 not resident; referred to a R.process.pagemap[x].resident for the xth pagemap entry valid: Validity flag - 1 refers to part of the program, 0 does not refer to the program (or its data) pageframe: Page Frame Number - used for address translation of virtual to physical addresses To execute a user program, the OS must assign it to available page frames in Jeeves 24 June 2017 System Manual 13 memory and then copy the program into them. The assigned page frames determine what values to place in the pagemap. For small user programs, many of the pagemap entries will have valid == 0 and resident == 0 System processes use only pagemap[0]; the pageframe value used for these are always the same: DiskScheduler 91, ProtocolHandler 92, Login 93, Shell 94, Unspooler 95, and Transmitter 96, respectively. Naturally, the valid and resident values for the system processes are 1 for pagemap[0]. Privileged Instructions There are 8 privileged instructions on Jeeves. Today, every system has some instructions built into it that only the operating system (kernel or daemons) may use; i.e., instructions that can be executed only in supervisor mode. For Jeeves, your OS uses these instructions in a form that looks like a call to a function which has no arguments and returns no values. Three of the privileged instructions are used for setting up, initiating and acknowledging I/O actions; the other five are for relinquishing control of the CPU in various ways. Each is described below. GetStatus() Requires that R.device be set to a valid device number. Returns in R.state the status of the specified device - see R.state for an explanation of the state values (codes). StartAct() Requires that R.device be set to a valid device number, that R.io.address and R.io.datasize be set to the starting location and number of bytes to be transferred, respectively. In addition for printers and disks, R.io.action must specify the operation; for the disk, the disk location registers must be set; and for the printer the R.io.bufferaddr register sometimes must be set. StartAct Jeeves 24 June 2017 System Manual 14 causes the I/O operation to get started. StartAct does not change any register. Clear() Requires that R.device be set to a valid device number. This instruction resets an input device that spontaneously interrupts (i.e., not the disk or the printer) so that subsequent input will cause an interrupt. For example, after a keystroke or a packet arrival, the OS must issue a Clear so that subsequent keystrokes or packets can arrive. Clear changes R.state to zero. RunUser() Requires that the R.process registers be set to the specifications of the user thread to execute (user id, process id, thread number, IP address, and pagemap), that R.pc be set to the program counter of where the thread last stopped (or to zero if the thread is just starting) and that R.genpur[] registers be set to the values in the general purpose registers when the thread last stopped (or to zero if the thread is just starting). When the OS uses this instruction, Jeeves enters user mode and the specified thread resumes/starts execution. RunSys() Requires that R.process.userid, R.process.processid, R.process.thread, and R.process.ipaddr be set to the specifications of a system process. The six system processes that you must have are described later. When a system process runs, Jeeves is in supervisor mode. Block() No setup is required. Only a system process can issue this instruction, without causing a possible infinite loop in the OS. When a system process has finishes executing for a thread, it must use Block to notify the OS that it wants to stop executing and have the thread placed in a blocked state or associated with a different process. This instruction causes a Block_Self trap to occur to give control to the OS kernel. The OS should then perform the appropriate action Jeeves 24 June 2017 System Manual 15 on the system process and resume kernel actions. Jeeves remains in supervisor mode throughout. Wait() No setup is required. Makes the CPU idle and changes to user mode. Nothing uses the CPU until an interrupt occurs; devices which have been given commands continue to work on their assigned actions. Halt() No setup is required. Terminates the simulation and causes the analysis report to be displayed. How Do You Use All This? At this point, the long list of hardware components, types of interrupts, registers and privileged instructions might seem to be lacking in one thing - an explanation of what to do with it all. That, of course, is what an operating system does; it controls the hardware on behalf of the users of the system - in this case the clients of this server. Following is a general description of how your operating system would use the hardware. It is general because you are allowed to design your operating system in any manner you want as long as it meets certain requirements - see a later section. Consider how a server system is supposed to behave. When it is booted (when a Boot_Done interrupt occurs), the OS must take control and be ready to serve the clients who are out there somewhere at some IP addresses and want to have the server do things for them. The server system you are making can provide two types of service: Telnet - allowing users to log in and give commands (just as if they were at the console) and FTP - allowing users to transfer files to and from the server. The clients may be on the same LAN as Jeeves or anywhere else in the Internet world. Jeeves 24 June 2017 System Manual 16 So, at the Boot_Done interrupt, the OS must prepare for the onslaught of client messages from the Comm Interface, as well as possible activity from the console. To manage authentication and the handling of clients and their files, the OS must set up a collection of information about the Interface, the console, the printer, the disk, the clients, their processes and threads, various system processes that will be needed, the messages that are being used, and the memory. This collection of information is often called the OS database. This is not a database in the COSC 341 sense; there are no relations or attributes or queries, although there are some similarities in terms of conflict with a normal database. The OS database is the collection of data structures or objects that the OS uses to control what is going on. At the Boot_Done interrupt, the OS should begin to build its database. Some information is available from the disk; it already has a file structure on it. Your OS should start reading in critical information from the disk, such as the disk bit map, the root directory, the password file, perhaps the users directory - these are described in a later section. The OS should also make the console ready by prompting for a login. Normally, only the root user might be allowed to login to the console; but for Jeeves, any user is allowed to login at the console. This user would want to be able to do any of the commands that a Telnet client could do; if the user is root, even more capability than normal clients is expected. Getting information from the disk involves reading it. ALL OS initiated device operations occur in the following sequence. 1. The OS must verify that the device to be involved is ready. Your OS would do this by using the GetStatus privileged instruction; this instruction places the status of the specified device in the R.state register. If the returned state is 0 (Ready), the OS can proceed to the next step. If the state is 7 (Unstable), an electronic anomaly has Jeeves 24 June 2017 System Manual 17 occurred - these are fleeting; normally by simply getting the status again, a regular status is returned. If the state is anything else (1 Busy, 3 Locked, 4 Disabled, 9 Unknown), the OS should not have done the GetStatus. The OS should be keeping track of the device state; the act of doing a GetStatus should be a formality; the OS should be expecting Ready every time it does GetStatus. If the OS doesn't expect a Ready state, it isn't paying attention. . . . When a device is ready, 2. Set the appropriate registers - these always include the R.io.address and R.io.datasize registers; for disks, these include the location and action registers; and for printers, they include the action and buffer address registers. 3. Then, the OS must use the StartAct privileged instruction. There is nothing more the OS can do until the device completes the action and causes an interrupt. 4. The OS must either run a user process (RunUser), a system process (RunSys) or do nothing (Wait)until the device is done. A disk takes an average of 825 ticks to complete; for the screen, the printer or output to the Interface, the time required for an action is also variable, based on the amount of data being transferred. When a device completes a directed action, either a Device_In, a Device_Out or a Control_Done interrupt occurs; i.e., one of these codes is in R.icode. When any of these occurs, the R.device register holds the number of the device causing the interrupt. The OS must use the R.device and R.icode values (and other information maintained in the database) to know whose action has just completed and how to respond. There are also interrupts that occur with no command coming from the OS. As examples, the user at the console can press a key or move or click the mouse; a client can initiate a connection or a command that appears to the server in the form of a message Jeeves 24 June 2017 System Manual 18 packet. Because the OS has no idea when these interrupts might occur; it must be ready for them any time the system is in user mode. When a keystroke, or a message or a mouse action occur, the OS must have provided an appropriate size buffer area in memory to hold the data arriving from the device. The OS prepares to do this by setting the R.keyin, R.mousein and R.packetin registers with the addresses of the buffer areas as part of its preparations at the Boot_Done interrupt. When one of these interrupts occurs, the hardware puts the device number into R.device, a 3 into R.icode and the data into memory. The OS must make provisions for another such interrupt by moving the data from the buffer or making one of the registers point somewhere else. The OS must also clear the device so the device can issue another interrupt - this is done with the Clear privileged instruction. When any uninitiated interrupt occurs on a device, the device's state becomes "Locked" (R.state is 3). The Clear instruction restores a ready state to the device, thereby allowing more input (and in the case of the Comm Interface, more output). The Device_Enable and Device_Disable interrupts are limited to occurring at the printer and like keystrokes, mouse actions and packet arrivals, can occur at any time. The printer is initially enabled when the system starts. If it sends a Device_Disable interrupt, it is saying that it cannot accept commands, at least not until it signals again with a Device_Enable. If the OS issues a command to a printer and that printer sends a Device_Disable instead of a Device_Out or Control_Done interrupt (which would indicate completion), the OS must reissue the command after the printer sends a Device_Enable. If the printer is not busy when it sends a Device_Disable, the OS must simply delay issuing any commands to it until it sends a Device_Enable. You may assume that the printer will always send a Device_Enable; you just cannot be sure when that will happen. When a packet arrives at the Comm Interface, the OS must perform several tasks in addition to the "device driver" actions of clearing the interface and manipulating buffers. These actions include: 1) make sure the message is valid and intended for Jeeves, 2) Jeeves 24 June 2017 System Manual 19 identify the source IP and associate that with a thread on the server (or create a new thread), 3) determine the nature of the message (part of authentication or a command), 4) perform authentication or parse the command, and 5) if it is a valid command, begin to perform the requested action. All of these actions are handled by system processes - described in a later section. Sometimes a client issues a run command to execute a program on the server. The run command specifies a file containing the executable program, a file containing the input, and a file to contain the output. To accomplish reading of the input, writing of the output and program termination, several trap actions come into play. To execute a user program, the OS must load the program file into memory, set up the R.process registers, including the R.process.ipaddr and R.process.pagemap[] registers, and do a RunUser privileged instruction. At that point, the system goes into user mode and the user program begins to execute. Soon the program starts generating traps that the OS must deal with. There are four types of traps generated by user programs: User_Pgm_Input requests the logical reading of a record (line) from its input file - the OS response is to do whatever it takes to get the record to where the program wants it. User_Pgm_Output requests that an output record (line) which the program has produced be logically appended to the output file the OS response is to do whatever it takes to get the record from where the program is holding it to the output file. User_Terminate and User_Abort announce that the program has come to an end (successfully or not) - the OS response is the same in either case - finish output to and close the output file and release the resources (memory and files) the program is using. More details later. The OS may choose to use the R.timer register to provide additional control of the user program' actions (highly recommended). Prior to starting/resuming a user program with a RunUser instruction, the OS can set the R.timer register to some future clock time. When that Jeeves 24 June 2017 System Manual 20 time is reached, a Time_Out interrupt is generated. This gives the OS an opportunity to stop the executing user program and allow another process to execute. Note: When a Time_Out interrupt occurs, R.timer must be set to another future time or be turned off (set to -1). If neither of these is done, Time_Out interrupts are generated continuously. How is the OS Structured? You have considerable flexibility in deciding exactly how components are arranged; however, the overall structure of the OS must fit the following model. Kernel The OS kernel (central part) must contain the code to handle Database Setup, an Interrupt Direction Mechanism, Device Drivers, and the CPU scheduler. These elements must be direct or indirect parts of OpSys(). The first three of these tasks have been addressed in the previous section; CPU scheduling is covered below. To handle the other key tasks, the OS can rely on six system service processes (sometimes called daemons). Auxiliary tasks may be taken care of in any place that you (the designer) wish. You may not have recognized the Interrupt Direction Mechanism and the Device Drivers in the previous discussion. When the hardware calls OpSys(), it already has various registers set to indicate the nature of the interrupt or trap. The kernel must react to the exception by performing an appropriate Interrupt Service Routine (ISR). The Direction Mechanism is the decision making necessary to get to the ISR. Device Drivers handle the details associated with a device - for a Keystroke or a Comm Input, that includes storing the data and perhaps clearing the device status; for output to anything, it includes setting the registers and initiating the act. There is more discussion about output later. Jeeves 24 June 2017 System Manual 21 Your OS is expected to schedule threads to use the CPU. A thread is usually defined as a unique instance of an execution of a program. A process is a program in execution. So, if two clients both execute the same program, there are always two threads involved because there are two instances of execution; however, there may be one or two processes, depending on whether the program is loaded into memory once or twice. On Jeeves, each client is expected to have his/her thread of execution identified by a number (starting at 101). Then, regardless of which program the client is executing, that client's thread has the same assigned number. Two system processes (Login and Shell) are expected to allow multiple simultaneous threads, more than one thread executing the same copy of the process. All other system processes and all user program processes are limited to one thread at a time. To schedule the CPU, the OS must establish the context of the thread to be executed. The context consists of the settings of the R.pc, R.genpur, and all R.process registers. These values must be restored to whatever they were when the thread last executed so that the thread can resume execution exactly where it left off. Setting of the context is required whether the CPU is to be executing a system or a user process. Your OS must allow all ready threads to have an opportunity to execute; it must be fair in selecting the next thread to execute; it must not allow threads to wait indefinitely to execute. Consequently, the OS must have one or more mechanisms for changing the executing thread. System processes are always resident in memory; but user processes must be loaded into memory and require more elaborate support. To execute a user process thread, the OS must reserve enough page frames in memory to hold the entire program, plus one additional page frame to hold the program's data. It must read the program into the page frames and set up the page map. It must reserve one page frame as an input-file buffer and another page frame as an output-file buffer. And the OS must support the unblocking of input records and the blocking of output records to allow the user process threads to function normally. Jeeves 24 June 2017 System Manual 22 Daemons (System Processes) The task of directing incoming packets to the appropriate receiver is performed by the ProtocolHandler daemon. The task of directing outgoing packets to the appropriate client is performed by the Transmitter daemon. The task of authenticating clients is performed by the Login daemon. The task of responding to client commands (entered via Telnet or FTP) is performed by the Shell daemon. The task of scheduling the use of the disk is performed by the DiskScheduler daemon. The task of getting files printed on the printer is performed by the Unspooler daemon. By modularizing the OS and separating out several of the tasks, the design and construction or your OS should go more smoothly. Some tasks (conflict resolution, memory management, file management, etc.) may be distributed throughout the OS or may be centralized, as you choose. Although you are required to write them, the six system processes are a part of your OS that you are NOT allowed to use directly. They are processes whose threads must be scheduled to use the CPU; each system process thread must be executed when necessary by using the RunSys instruction (with R.process.processid indicating which process to run). In addition, each of the processes must appear as a single void function with no arguments in your OS (although they are permitted to call any other functions that you have in your OS). The processes functions must be named DiskScheduler(), ProcotolHandler(), Login(), Shell(), Unspooler(), and Transmitter(). The functions have a form requirement: At the end of each one, the Block instruction must be used to tell the kernel that the thread is done for the moment. ProtocolHandler Although Jeeves does not use the complete 7-layer OSI network model for communications, there are elements of four layers that your OS must deal with. The data link Jeeves 24 June 2017 System Manual 23 layer, which deals directly with the hardware, is handled very simply with interface input and output device drivers. Here your OS must respond to the interrupt caused by receiving a message and pass the packet to the network layer for validation and authorization. The network layer examines the IP header to check the IP addresses, to determine that the message is in tact, to find the size of the data, to assemble messages that are sent in pieces, etc. After passing these tests, the whole message is taken by the transport layer which uses the TCP header to determine the application that is to act on the contained data. Here the sequence number is also noted so that communications can be kept organized. The application layer (represented by the Login and Shell processes) acts on the messages once it receives them. The ProtocolHandler and the input device driver must handle all the preliminary action to get valid messages to Login and Shell. The real Telnet and FTP use the TCP/IP protocol suites; Jeeves' Telnet and FTP use message forms and methods that are similar to the real thing. To understand the actions of the ProtocolHandler (and the Comm Interface device drivers), you need to know about the message form and the use of the message elements. Every packet that comes in or goes out the Comm Interface has three parts: an IP header that contains 20 bytes, a TCP header that contains 12 bytes, and a data area that may contain from 0 to 512 bytes. Each of these forms is described below, beginning with the IP Header Form (The Size column shows the number of bytes used to represent the content information.) Size Form Contents 1 char Version number - this is always 4 (binary 00000100, ASCII Ctrl-D) 1 char IP Header length, measured in units of 32 bits - this is always 5 (Jeeves uses IP headers of 20 bytes exclusively) 2 short Data length, measured in bytes. Because the TCP header follows the IP header, its bytes are counted as part of the data length. So this value is never less than 12 and may be as large as 524. Jeeves 24 June 2017 System Manual 2 short 24 Fragment number. For most messages, this is 0. When data larger than 512 bytes needs to be sent, the OS must break it into parts and send two or more message fragments. Then, this element of the message is a number indicating which fragment this packet is; for example, 1500 data bytes would be sent in 3 fragments with fragment numbers 1, 2, and 3. When incoming data is larger than 512 bytes (as in a file transfer), the client computer sends fragmented messages to Jeeves in this same way. 1 char Fragment total. When messages are fragmented, this field holds the total number of fragments for the message. For the 1500 data bytes above, this field holds 3 on all three fragment packets. 1 char Transport protocol used - this is always 'T' meaning TCP. 2 char Time to live; the number of hops the message is allowed to take to reach the client - this is always 64. 2 u short Standard 16-bit cyclic redundancy check value for the header; it is a 16-bit unsigned short value. This is calculated by setting it to zero, passing the entire header to the CRC function (provided to you) and storing the returned result in this element. This value is used for error detection in the header. 4 ip addr Source IP address for the message, stored in standard class B address form where the subnet mask is always 255.255.255.0. That is, each component of the address is one byte in size. For example, the IP address for Jeeves is 144.201.193.179 where 144 and 201 specify the domain, 193 is the subnet and 179 is the host. 4 ip addr Destination IP address in the same form as the source. From the IP header, the OS can determine all of the following from incoming messages: 1) where to put the next incoming message which may come in at any time - Jeeves 24 June 2017 System Manual 25 based on the size of this one; 2) whether there was any error in communicating the message - recalculate CRC and see if it matches the one in the message; 3) whether the message is intended for Jeeves; 4) what the source IP address is - if it is an IP address on which there is no active session, a new thread usually needs to be created; 5) what the data length is to see how much to pass on to the next stage of processing. Usually, the device driver for the interface input handles action 1), while the ProtocolHandler handles 4) and 5), with 2) and 3) being done by either. The ProtocolHandler must have access to information about what threads are active so it can determine whether or not to create a new thread in response to an incoming SYN message. There are four message types that are used to establish, maintain and sever a connection between a client and the server. These message types are part of the TCP header. We need to look at its 12 bytes next. Size Form Contents 2 short Source port number. There are 65536 port numbers; Telnet and FTP use standard ports: Telnet always uses 23 and FTP uses 20 and 21. So, for Jeeves Telnet, this is always 23; for Jeeves FTP, this is always 20 - Jeeves does not use port 21. 2 short Destination port number - again the standard for Telnet is 23 and for FTP is 20 or 21; here always 23 for Telnet and 20 for FTP. 4 long Message sequence number. When a client initiates a connection it begins sending messages and associates a sequence number with each of them so that the client and server can determine whether messages have gotten out of order. Most messages that are received require an acknowledgment; the OS should copy the sequence number from the incoming message into the response message(s) that it sends back so that the client knows what has been received. Jeeves 24 June 2017 System Manual 26 1 char TCP header length measured in bytes - this is always 12 1 char Message type: 'S' indicates SYN - used to initiate a connection, first message a client sends, has sequence number 1; 'A' indicates ACK used to acknowledge a previous message (and often to include response data); 'P' indicates PSH - used to send data to the server (a command from a Telnet client); and 'F' indicates FIN - used to abruptly terminate the connection, may be sent by client or server, no acknowledgment is sent. Note: real TCP messages can have multiple types, e.g. 'A' and 'P' to send an ACK that includes data - your OS should simple use 'A' or 'P' message types to do this. An illustration is given later. 2 char Application indicator; for Jeeves this is essentially just used to distinguish what type of service is to be provided and therefore what client commands are valid. Jeeves uses 'TN' for Telnet, 'FP' for FTP The ProtocolHandler must distinguish the message types, verify that the messages are Telnet or FTP messages, and pass on the data to the appropriate process (Login or Shell) for action (sometimes creating a thread for a new client). The data part of the messages may contain a username, a password, a command, or part of a file, depending on the situation. All of this data is in ASCII character form; there is no message for Jeeves that involves binary data. Login This system process handles all elements of authentication. When the ProtocolHandler receives a SYN from a new client using the Telnet port, it must create a new thread and associate it with the Login process. Login must then create an acknowledgment message that prompts the client to login. For Jeeves, this prompt must be "login please: " including a Jeeves 24 June 2017 System Manual 27 trailing space but without the quotes. When the ProtocolHandler receives a PSH from a client, it needs to know to which process to direct the data. The OS database must maintain information that the Protocol Handler can check to determine this. If the PSH is from a known, authenticated client, the ProtocolHandler passes the data to a thread of the Shell process. If the PSH is from a newly created but not yet authenticated client thread, the ProtocolHandler passes the data to a thread of Login. (Such a message may contain the username.) Login should save the user name and create and acknowledgment message that prompts for a password. When the ProtocolHandler receives the PSH containing the password, it must know to give the information to Login. Login must then verify that the password is correct. This is normally done by matching the user name and encrypted password with the entries in the password file. You are given the use of the encrypt function to encrypt what the client entered as a password. If the user name and encrypted password match, Login should mark the client as "authenticated" and should associate the client thread with the Shell system process for subsequent packet processing. If there is no match, Login must generate a FIN message with an error statement in the data and send it to the client to terminate the client's connection. Shell When the Shell first gets a thread, it sends an ACK message containing the system prompt to the client. The system prompt is "Jeeves> " with a trailing space. Shell's job is to accept Telnet and FTP commands from client threads, parse them (based on the service being used) and, if they are valid, start to perform them. If they are not valid, Shell should construct an ACK with an error message to send to the client. Shell contains the code to perform most client requests, except for two commands. The run command leads to Jeeves 24 June 2017 System Manual 28 executing a user program which was briefly described previously; and the print command leads to Unspooler action to control the actual printing, described later. This was a very brief description. The Shell is a key element in directing the tasks that the clients want to have performed. See the Suggested Handling of show to appreciate its central role. DiskScheduler This system process should be activated whenever there is some disk I/O to do (and the disk is not already busy). There may be many reasons for such I/O. To set up the database, the DiskScheduler must be used to read information from the disk. When a client logs in, if the database does not contain an up-to-date copy of the password file information, then the DiskScheduler must be used to read the password file. As clients give commands, the DiskScheduler is needed to handle the associated disk I/O - consider such commands as "copy a file", "add a user", "print a file", "change file access". As user programs execute, they need to access the input and output files; the DiskScheduler is used to read and write data, respectively. And, as files are printed, the Unspooler must request the DiskScheduler to read in spooled files. This process is called a scheduler because with all these possible sources of requests and the fact that the disk can do only one operation at a time, some component must choose which request to satisfy next, as well as keep the disk busy as long as there are requests. Transmitter The Shell and Login processes may be dealing with many client threads at once. Consequently, they may generate many output messages during the time that one message is being transmitted. Some of these messages may contain multiple fragments. Some Jeeves 24 June 2017 System Manual 29 component must be able to handle requests to send many messages and the fact that the Comm Interface can really receive or send only one message at a time. The Transmitter must keep the messages to be sent going out to the clients as rapidly as the Comm Interface will allow. Remember all clients (except perhaps the one at the console) are gaining access through the Comm Interface. The more of them that there are and the more actions they take, the more messages that need to go through the Interface. Unspooler The Unspooler deals with the print queue. When a client enters a print command, the Shell must take care of copying the file to the spooling area of the disk and putting an entry in the print queue. At that point, the command is considered complete from the client's point of view. Consequently, the client should be sent a prompt and the client's Shell thread should be ready to process the next incoming command. The Unspooler handles the print request, once it is in the print queue. The Unspooler schedules the print images (spooled copies of files) to be sent to the printer and, along with the printer driver, issues the commands to the printer to get the printing done. The Unspooler works with the DiskScheduler to read the spooled files from the disk. After each disk cluster is read, the Unspooler must initiate a transfer of the cluster to the printer's buffer. This is done until the buffer is full or all of the data in the file has been transferred. When either of these happens, the Unspooler or printer driver must tell the printer to print the contents of its buffer (thus, emptying the buffer). If more of the file is yet to print, the cycle of disk read buffer transfer - print continues. After the last data of the file is printed, the Unspooler or printer driver must issue an eject command to the printer so that it advances the paper to the top of the next page. When the printer completes this action, the printing of the file is complete. The Unspooler can then focus on any additional print requests that the print queue may contain. Jeeves 24 June 2017 System Manual 30 There is one complication with printing. The printer is the only device which may become temporarily disabled (unable to perform any action). When the printer becomes disabled, it issues a Device_Disable interrupt. If this occurs between the time that the printer has been issued a command and the time it completes that command, the command is lost. You are guaranteed that the printer will become enabled soon after it disables; but you don't know exactly when this will happen. Consequently, your OS must be prepared to re-issue the last command it gave the printer, if that command was lost. Of course, if the printer disables during a time in which it is inactive, there is no command to reissue; any unspooling action which is needed while the printer is disabled must be delayed (not abandoned) if such an event occurs. Suggested Handling of show One of the commands that clients can request via Telnet is to show a file. This command requests that the contents of a file be sent back to the client, presumably so the client can view them. It would be like a cat command in Unix or a type command for VMS or MS-DOS. To illustrate how the system processes interact to get a task done, a suggested method of implementing show is outlined below. In addition to the system processes, this implementation also mentions the roles of the kernel and device drivers. Let's assume that some client has successfully logged in from IP 1.2.3.4. When this client sends a packet containing the command: show ./simple.one it causes a Device_In interrupt at the Comm Interface. Based on the device causing the interrupt, OpSys should call the Comm Input Driver to handle the incoming packet. Jeeves 24 June 2017 System Manual 1. 31 The Driver should put the packet in a queue for processing by the ProtocolHandler and make the ProtocolHandler process/thread ready to execute (if it is not already). Note that it is enntirely possible that the driver may need to do this for many packets before the ProtocolHandler executes. The Driver must also clear the interrupt. 2. The ProtocolHandler may not be the next process to execute - that depends on the CPU scheduling algorithm and whether or not there are other processes that are ready. However, if the CPU scheduler is working properly, the ProtocolHandler will be selected to execute at some point. 3. When the ProtocolHandler executes, it should process all the packets in its queue by directing them to the next level of service. The ProtocolHandler must recognize that the packet from 1.2.3.4 is from a known IP address and must associate it with the appropriate next step. The OS must maintain information about all threads in the system so the ProtocolHandler can determine that this command should be directed to the attention of a thread of the Shell process. The ProtocolHandler should then make that thread ready to execute. The last act of the ProtocolHandler (after handling everything in the queue) is to block itself with the Block instruction. 4. As with the ProtocolHandler, there is no certainty as to when this thread of the Shell will execute; however, when it does, it should try to start or continue the task presented to it by a client. For the client at 1.2.3.4, Shell should realize that this is a fully authenticated client and that it is presenting a Telnet command. Shell should parse the command to make sure it is valid. The command is asking to show the contents of the file sample.one in the client's own directory (the ./ part) on Jeeves. If there is any problem with the command (e.g., if sample.one did not exist), the Shell thread should generate an error message (an ACK) and enqueue the message for the Transmitter to send to the client. But, this is a valid command, so the Shell thread Jeeves 24 June 2017 System Manual 32 begins to do the command - it must begin to read the file. 5. The Shell thread assigns memory buffer space for the file, puts a request to read a cluster of sample.one in the disk queue, and makes the DiskScheduler ready. Note: we are assuming that the Shell thread already has access to the client's directory and therefore can look up the file's directory entry and get the disk location of the first cluster. If the OS is not maintaining directory information for this client, the Shell thread must first request a read of the client's directory (to get the file's directory entry), before trying to read the file. After addressing the command, the Shell thread uses the Block instruction. 6. As with the other system tasks, it is not certain when the DiskScheduler thread will execute; but when it does, it takes the first entry from the disk queue and issues a command to the disk to perform the appropriate action. The request for client 1.2.3.4 may not be first in the disk queue; in this case, the action for the client is delayed. The DiskScheduler must block after starting each disk operation. 7. At some point, the disk completes the read action for a cluster of the file needed by client 1.2.3.4. It signals this fact with a Device_In interrupt. When OpSys receives this interrupt, it directs control to the Disk Driver. The Disk Driver must be able to realize that this interrupt signals the completion of the reading of a file cluster for some client. The Driver should then make the appropriate thread of Shell ready to deal with the newly arrived data from the disk. 8. At some point the Shell thread will be scheduled to execute again for client 1.2.3.4. The thread must realize that the first cluster is now in memory. It should use this data to build message packets to be sent to the client. Since a cluster contains up to 2048 bytes of data and a message packet can hold no more than 512 data bytes, the Shell Jeeves 24 June 2017 System Manual 33 will almost always have to build multiple message packets (fragments) to hold the disk data; these need to be sent to 1.2.3.4. The packets are placed in the queue for output through the interface. The Shell thread then makes the Transmitter ready so it can be scheduled and handle the packets. The Shell thread blocks after generating the packets from the cluster. 9. At some point the Transmitter thread will be scheduled to execute. It will take the first packet on its queue and send it out through the Comm Interface (the packet may be for any client). Other packets cannot be sent until the Interface completes sending the current packet. So, the Transmitter thread blocks. 10. At some point the Comm Interface completes sending a packet to 1.2.3.4 and signals with a Device_Out interrupt. When OpSys receives this interrupt, it directs the response to the Comm Output Driver. This Driver should then either notify the Transmitter thread, so the next packet can be sent, or the Shell thread, so the next disk cluster can be read, or both. If we assume that sample.one has 3072 bytes, then, the Transmitter would still have three more packets for the client at 1.2.3.4 in its queue; so, the Driver should make the Transmitter thread ready. If this is the last packet for the client at 1.2.3.4, the Driver should make the Shell thread ready to deal with the next cluster. If it is the last packet for the client at 1.2.3.4 and there are other packets in the queue (from other clients), the Driver should make the Transmitter thread ready also. 11. When the Shell thread gets to execute again, it should recognize that it needs to get the next cluster for the client command (i.e., resume at step #5 above, except that the same memory may be used as a buffer). When step #11 is reached and the Shell thread realizes that there are no more clusters to read and no more output for the client, the thread should construct a prompt message packet for output and make the Jeeves 24 June 2017 System Manual 34 Transmitter thread ready. The Shell thread also needs to mark the client command as complete. There are many administrative details that were omitted in describing this process, such as verifying that access to the file is allowed, keeping track of how far along the task is, handling device independence, etc. You must find a way with your OS to allow the system processes to coordinate their activities when dealing with client commands. Some commands from the clients can be handled with a single message or disk action; the show command is described here because it requires multiple coordinated actions and gets four of the six system processes involved. The 11 steps above are NOT the only way to implement the handling of the show command; you may see some alternatives as you read it. You are not required to implement show in exactly this way - you are required only to implement it in a way that works. Client Actions Jeeves is expected to serve two types of clients, those who want Telnet service (this includes the client at the console) and those who want FTP service. For both of these services, a client is expected to make a series of requests through a "session". Each session consists of a series of messages sent from and to the client. Below are sketches of Telnet and FTP sessions; in each case, the message is described briefly. Telent FTP Client: Sends SYN Sends SYN Server: Prompts with login please: Prompts with login please: Client: Sends username Sends username Server: Prompts with password: Prompts with password: Jeeves 24 June 2017 System Manual 35 Client: Sends password Sends password Server: * Sends prompt Jeeves> * Sends prompt Jeeves> Client: Sends Telnet command Sends FTP command Server: Responds with results Responds with results Server: Repeat at * Repeat at * . . . until either . . . until either Client: Sends logout Server: Sends FIN with message Sends quit Sends FIN with message or or Client: Sends FIN Sends FIN Server: -- No response -- -- No response -- As you can see, the sessions for the two services are remarkably similar. As a consequence, your OS should be able to handle both services with a single Shell process to deal with the commands of the clients. On a real system, there would be separate processes parsing and implementing the commands; that is, there would be a Telnet Shell and an FTP Shell to deal with. For Jeeves, you can actually gain a considerable advantage by combining the services in a single Shell. Also, note that a session can end either by the client logging out (quitting) or by the client sending a FIN (termination message). For Jeeves, you may assume that all commands arrive contained in a single message. Thus, your OS does not need to assemble commands by piecing together parts of several messages. You may assume that your OS does not need to echo the commands themselves back to the client; assume that the echoing is being done on the client's local machine. Also, you may assume that clients do not use typeahead - that is, they do not issue another command until the previous command is completed and a prompt is sent back. None of these assumptions could be made on a real server; however, for you to handle these possibilities for Jeeves, your OS would increase in size by a considerable amount. Jeeves 24 June 2017 System Manual 36 Telnet Commands Here is a description of the form of each of the Telnet commands that Telnet clients (and the console user) are allowed to use. Your OS needs to allow for a few possible errors on the part of the clients in entering these commands. Your OS is not expected to do fancy parsing or elaborate error checking. Those errors for which your OS is required to check are described below. Whenever your OS detects one of these specified errors, it is required to send the client a specific error message, see the list later. The system prompt for Jeeves must be space after the angle bracket. Jeeves> where there is one The OS must send a prompt to each client to indicate readiness to accept a command; it must be sent prior to every command once the client has been authenticated. All Telnet commands are entered in lowercase; there are no command abbreviations; and the different parts of the command are separated by a single space (or a slash in some cases). As they appear in the message packets, commands contain a null character after their end; that is, commands have the form of c-strings. Several commands refer to files; such references always have the form: folder/filename where a slash separates the folder from the filename There are no implied or current folders; so every file reference must have both parts. There is only one concession to directory structure - if the client is referring to a file in his/her own folder (directory), s/he may use a reference such as substitute for the client's own directory name. ./filename where the . is a Thus, for client jwolfe, the reference to ./whatever is the same as the reference jwolfe/whatever Jeeves 24 June 2017 System Manual 37 Below each of the valid Telnet command forms and their uses are described. Note: when using the Telnet service, a client cannot enter FTP commands (they should be regarded as error entries). access code folder/filename This command is used to change the access (protection) codes for a file. The command is restricted to use by the file's owner. Your OS should locate the directory entry for the file and change its access pairs. The code is a 6-character sequence to specify all three access pairs. For example, the code RWRWX- indicates that privileged users and the owner both have full read and write access, while the world has only execute access to the file. Here is a sample to change a library file: access RWRWX- library/spacy add userid username password This command is restricted to use by the root. No other user, privileged or not, may use this command. It is used to add another user to the system. Your OS should encrypt the password and add an entry to the password file. It should also create a directory entry for the new user in the users directory/folder, specifying no files. Note: although a new user has no files, one cluster is allocated to the user's directory to hold directory entries as soon as they are created. The userid is a 4-digit number and must be greater than 1000. The username may consist of up to eight characters. The password must consist of at least 6 characters with no spaces. If the userid or username already exists, the OS should send an error message, rather than add the user. If the password is too short, the OS should also send an error message. Here is a sample command to add user bozo: add 3099 bozo theclown copy folder1/filename1 folder2/filename2 Jeeves 24 June 2017 System Manual 38 This command is used to copy the contents of filename1, which is in folder1, to filename2 in folder2. The client must have at least read access to folder1, at least read access to filename1, and at least create access to folder2 (or write access if filename2 already exists in folder2). If any of these requirements are not met, your OS should send an appropriate error message to the client. It should also send an error message if folder1 or filename1 or folder2 do not exist. example: If filename2 does exist in folder2, your OS should replace it. Here is an copy library/spacy ./mine delete folder/filename This command is used to get rid of a file. The client must have write access to the folder and file in order to do a delete. If this requirement is met, your OS should take back the file's disk storage, remove its directory entry from the folder (rewriting the folder), update the higher-level directory entry which is for the folder of the file being deleted, and update the bit map. Here is an example: delete common/mess.txt list folder This command is used to provide a listing of the entries in a folder (directory). For each directory entry, the information to be listed consists of the access pairs, the file size in bytes, the owner (ID of the user who created the file), the file type, and the filename. The folder may be a named one or . to mean the owner's folder. Below is a sample listing produced from the command list . RWRW-RWRW-RWRW-RWRW-- given by client wlewis. 3715 3312 23225 677 wlewis wlewis wlewis wlewis D P D D simple.one dosomething another tiny.one Jeeves 24 June 2017 System Manual 39 This listing must be packaged in a message or messages and sent to the client. If the client is not allowed to access the specified folder, the OS should respond with an error message rather than a listing. logout This command is used to terminate a Telnet session. Your OS should respond to this command by sending a FIN message with a logout acknowledgement that looks like this: End Session at tttttt where tttttt is the current clock time. now This command is used to produce a listing of which clients are currently logged in and what they are doing. It is sort of a cross between who and ps on Unix or a cross between show users and show system on VMS. For each client that is logged in at the time of the command, your OS should list the client's thread number, IP address, the command currently being done (or last done), and the client's username. Here is a sample of the command being given by client richie. 101 102 103 104 144.201.193.179 144. 80.128. 13 24. 43.159.183 24. 77.159. 95 Logging Valid list now dwagner wlewis jwolfe richie The extra spaces in the IP address serve to keep the display lined up, also true for the names of the commands. The command named "Logging" is used as a placeholder for a client who is still logging in and has not yet been authenticated. The command named "Valid" is used as a placeholder for a client who has been authenticated but has not yet given any commands. Jeeves 24 June 2017 System Manual 40 print folder/filename This command is used to cause the specified file to be printed. Your OS must use a Shell thread to copy the file to the spooling area on the disk and then use the Unspooler thread to print the file. If the folder or the file do not exist or if the client is not allowed access to either, your OS should respond with an error message, rather than print the file. remove username This command is restricted to the root. No other user, privileged or not, may use this command. It is used to eliminate a user from the system. Eliminating a user requires that all of the user's files be removed, that the user's directory entry be removed from the users directory, that the user's entry in the password file be wiped out, and that the higher-level directory for the users directory (i.e., the root directory) be adjusted. If the username does not exist, the OS should send an error message, rather than remove the user. run folder1/filename1 folder2/filename2 folder3/filename3 This command is used to execute a user program. Folder1 and filename1 specify the executable file (containing the program to run). Folder2 and filename2 specify the data input for the program - this file is read by the executing program. Folder3 and filename3 specify the output for the program - this file is created by the executing program as it generates output. Your OS must verify the existence of the files and that the required access is allowed; it must then manage the execution of the user program - described in a later section. show folder/filename This command is used to examine the contents of a file. Your OS should read the file from disk, package the contents into messages, and send the messages to the client. This must Jeeves 24 June 2017 System Manual 41 be done one disk cluster at a time (because of requirements on your OS). The OS must verify the existence of the folder and filename and that read access is allowed. users This command is used to produce the complete list of users known to the system. Your OS should display the userid and username for every user, regardless of whether that user is logged in. The order is not critical; it is probably easiest to list the users in the order they appear in the password file. Here is a partial list of what this command produces. 999 root 1013 dcomer 1020 nhorvath 1035 jwolfe 1121 wlewis FTP Commands Because FTP has a much more limited purpose than Telnet, there are fewer commands to contend with. Nevertheless, the same restrictions on their form and error checking apply. Also, when using the FTP service, a client cannot enter a Telnet command (it should be regarded as an error entry). The valid FTP command forms are shown below; the FTP prompt is also Jeeves> dir folder This command is used to provide a listing of the entries in a folder (directory). For each directory entry, the information to be listed consists of the access pairs, the file size in bytes, the owner, the file type, and the filename. The folder may be a named one or . to represent the owner's folder. Below is a sample listing produced from the command dir . given by client wlewis. Jeeves 24 June 2017 System Manual RWRW-RWRW-RWRW-RWRW-- 3715 3312 23225 677 42 wlewis wlewis wlewis wlewis D P D D simple.one dosomething another tiny.one This listing must be packaged in one or more messages and sent to the client. If the client is not allowed to access the specified folder, the OS should respond with an error message rather than a listing (the same error message as would be used for a similar problem on the Telnet list command). get folder/filename This command is used to transfer a copy of a file that resides on the server in the specified filename of the specified folder to the client. Your OS should verify the existence of the folder and filename and that access is allowed. The OS should then read the file contents from the disk, package it into messages, and send them to the client. put folder/filename This command is used to transfer a copy of a file from the client to the server and create a file named filename in the specified folder. The OS should verify the existence of the folder and its accessibility. The client then sends messages containing the contents of the file being transferred. To determine roughly how large a file the client may be sending, your OS can check the total number of fragments in the incoming messages. The client always sends maximum size fragments, except possibly the last; so if the total fragment count is 6 for example, the file size must be between 2561 and 3072 bytes. The new file that the OS creates must have type T to indicate that it was transferred to Jeeves; see the File System section. quit This command is used to terminate an FTP session. The OS should respond to it by sending Jeeves 24 June 2017 System Manual 43 a FIN message with an acknowledgment message that looks like this: where tttttt is the current clock time. End Session at tttttt Error Messages to Clients The following situations and error messages are the only parsing and logical errors that your OS needs to deal with. In each case, a specific error message is shown. Your OS must use these exact message forms. Do not make up your own messages for these conditions and do not add messages for situations that you are told are not allowed to happen. If a folder is specified as part of a command and that folder does not exist, the OS should send a message of the form: Folder does not exist: dddd where dddd is the folder's name. If a folder is specified as part of a command and that folder does exist but the client is not allowed the required access, the OS should send a message of the form: Access not allowed to folder: where dddd is the folder's name. dddd If a filename is specified as part of a command and that file is to be used for input or execution but the file does not exist, the OS should send a message of the form: File does not exist: ffff where ffff is the filename. If a filename is specified as part of a command and the client is not allowed the required access, the OS should send a message of the form: Access not allowed to file: ffff where ffff is the filename. Jeeves 24 June 2017 System Manual 44 If a filename is specified as part of a command and the file is to be used for a purpose that conflicts with the file's current use by other client(s), the OS should send a message of the form: Conflict over file: ffff where ffff is the filename. If on a login attempt, the client cannot be authenticated, the OS should send a message of the form: Invalid attempt to login If on a remove command, the username specified does not exist, the OS should send a message of the form: No such user: uuuu where uuuu is the username. If on an add command, the username or userid already exists in the password file, the OS should send a message of the form: Username or ID already exists If on an add command, the password contains fewer than six characters, the OS should send a message of the form: Password is too short If on an add or remove command, the client is not root, the OS should send a message of the form: Command restricted to root If a command is given that is not one of the listed valid commands, the OS should display a message of the form: Unknown command: cccc where cccc is the given command. Note about the origin of commands: Commands that come in from remote clients (Telnet or FTP) are guaranteed to arrive in one packet (message). Each of these commands ends with a null character; there is no new line character ('\n') at the end of the command. This was mentioned before. Commands that come in through the console arrive one character Jeeves 24 June 2017 System Manual 45 at a time, because of the nature of the keyboard; and each such command does end with '\n' (as the client presses the Enter key). There is no null character entered or attached by the hardware. Device Independence Operating Systems tend to have to deal with a wide range of input and output sources. The more that the OS can treat every input source like every other input source (and similarly for output), the simpler things are within the operating system. In your OS, you are expected to use the idea of device independence in handling the console. The console provides command input just as the Comm Interface does, but one character at a time through the keyboard instead of a command at a time, and without all the header information of a packet. The console can also receive command output just as the Comm Interface does, but for display on the screen, rather than transmission to the client; and again no header information is needed. The console has a mouse which gives it a third means of input completely different from keyboard or Comm Interface; however, the mouse is not used in the current system. To make input device-independent, some basic level of the OS (generally the device drivers) must deal with each device's idiosyncracies; but most of the OS should be able to deal with the input in a generic manner. For Jeeves, your OS is required to make all input look like it is coming from the Comm Interface. This is not difficult. Collect the keystrokes as they come in. When a '\n' is received, indicating the end of a command, take the collected characters, form a packet that looks like it came thorugh the Comm Interface, place it in memory where input would normally come from the Comm Interface, and call upon the Comm Input Driver, as if a Device_In interrupt from the Interface just occurred. From that point on, the input can be treated as if it had come in from some distant client. The packets Jeeves 24 June 2017 System Manual 46 that the OS constructs should have Jeeves' IP address as both the source and destination of the message. A similar approach can be taken to make output device-independent. Again, the device drivers must handle the differences; but most of the OS can treat the output generically. So, when there is output to be sent to the console, Login or Shell can construct output messages as usual. When the Transmitter gets the message, it can determine that the output is destined for the console (if nothing else, by examining the destination IP address) and turn the content of such messages over to the Screen Driver for display on the screen, instead of sending the message through the Comm Interface. There is one tricky point in handling the console in this manner - the console has no capacity to send a SYN message to get a session started. But then, the console really should not need to notify the system that it is ready to start a session - it is always ready. From the time the Bootstrap program finishes and gives the OS control, the console is ready. As part of the Bootstrap actions, your OS should create a SYN message (with sequence number 1) for the console and trick the Comm Input Driver into handling it just as described above for commands. This should lead to Login sending out its "login please: " message to the screen so that a console user can then start entering username, password, etc. When a user logs out at the console, a similar situation arises. For remote clients, your OS should send a final FIN message to terminate the session. But for a client at the console, after sending the FIN message, the OS must send out another login please: prompt message to allow the next console user to login. This should be handled by creating another SYN message as with the first console login. This SYN should also have the sequence number 1 (it is the start of a new session). On a system like Unix, device independence is carried much further than you have to Jeeves 24 June 2017 System Manual 47 go with Jeeves. On Unix, every source of input or output is regarded as file-like and much of the internal treatment is then standardized to file actions. You would find that trying to do this with Jeeves would be considerable additional work. Your OS should deal with files using one set of actions and clients using another. Dealing with root The root is a different type of user with more privileges than regular users. It has already been noted that root is allowed to add and remove users on the system. No other user is allowed to do that. In addition, root is allowed access to every directory and every file on the system, as long as root is logged in at the console. When at the console, root is not bound by any of the access pairs that are used to protect files or directories; root always passes the access test when at the console. However, root cannot do absolutely anything. When root is logged in from some place other than the console, the privileged access pair is used to determine access to a directory or file. Thus, users can protect their files from a hacker who may guess the root password by removing priveleged access (setting this access pair to -- instead of the RW default). Also root, regardless of where it is logged in, must abide by the file use restrictions. File use restrictions are based on what is happening with a file. If one client is currently reading a file (for a show or copy or run or print command), other clients are allowed to read that same file simultaneously. This is shared reading and is a commonly provided capability on systems. However, if one client is reading or writing a file, no other client is allowed to write to or delete that file; not even root is allowed to do this. Writing and deleting are file actions that require exclusive access; sharing cannot be allowed with such actions. If root could get around this file use restriction, the system could be seriously Jeeves 24 June 2017 System Manual 48 corrupted accidentally. The "Conflict over file:" error message is to be used when one client, even root, comes into conflict with the file use of another client. Allowing a privileged user on a system is usually a necessity for system management. But, the root user can create headaches for you. Because there is a root user, your OS must provide means for making exceptions for this one user. It also has to maintain information that would otherwise not be needed; for example, if root issues the command list dcomer then, even though dcomer may not be logged in, the OS must read in his directory so that the listing can be made. You will find that it may not be easy to add root capability to your system if you did not plan for it from the beginning. To avoid some complications that can arise in the simulator and your OS, you are hereby guaranteed that no script has the root create any additional files in the root directory. (The directory entry for the root directory appears in two places; this would make updating it awkward.) However, root may create files in any other directory; it has full access to all directories (at least when it is logged in at the console). The only privileged user on Jeeves is root. You are guaranteed that root (the only user who can) does not add another privileged user to the system. The user ID distinguishes privileged users from regular users. Any user with a user ID less than 1000 is considered privileged. Any privileged user has the same access capabilities as root; however, only root can issue an add or a remove command; and to repeat, the only privileged user is root. Requirements of Implementation As you create your OS, you must meet a number of requirements. Failure to meet these requirements results in severe scoring penalties because alternative implementations violate the nature of the project; i.e., they are considered cheating. Jeeves 24 June 2017 System Manual 1. 49 Message packets must be kept in Jeeves' memory. When a packet arrives at the communications interface, it is stored in memory in association with the Device_In interrupt. Your OS is not permitted to copy such a packet to some queue that is contained completely in the OS database (and is therefore separate from Jeeves' 128 KB managed memory). Doing so would eliminate the manage-the-buffer-space element of this project. The packet must be held in managed memory as the ProtocolHandler, Login, or Shell system processes act on its contents, although it may be moved to different portions of managed memory if appropriate. Similarly, when Login or Shell construct packets for output, they must be held in memory for the Transmitter process and the Comm Output device driver. You will definitely need queues or linked lists to keep track of the packets and what element of the system is working on them. However, it would be awkward to have the queue entry contain the packet (because the packet must be in managed memory); instead, the entry should contain a memory reference and packet size or beginning and ending memory references. 2. Disk files must be kept on the disk. Your OS may hold in its database copies of directory information from the disk, i.e., copies of directory entries. However, it is not allowed to hold copies of files in the database. Each time a client needs to access a file, your OS must read or write the disk; it may not simply retrieve the information from somewhere in the database. There is one exception. Your OS is allowed to maintain a copy of the password file in its database; this will facilitate the response to the users command for regular clients and the add and remove commands for the root. However, changes to the password file must be written to disk, even if a copy of the password information is kept in the database. 3. Those elements of the disk that are copied into the database must remain faithful Jeeves 24 June 2017 System Manual 50 copies. That is, if the bitmap, any directory, or the password file change in response to a client command, your OS must issue update commands to cause the disk copy of these elements to agree with the changed database copy. This update must be done as soon as is reasonable after the change to the database. If your OS delays in doing the update, it may never get a chance; Power_Down may occur at any time. 4. Your OS must number the processes and threads in accordance with the guidelines given. System processes must have process ids 1 thru 6; each client session is a thread and must be numbered, starting at 101. The thread numbered 101 must be the console session that is begun at Boot_Done. Numbering of threads is sequential; each client sends a SYN message to initiate the creation of a new thread. User process ids are required to be numbers greater than 10; each time a user executes a run command, it should be assigned the next sequential process id (start at 11). Although each user process is and most system processes are associated with one thread; the Login and Shell processes may be associated with many different threads as they are performing their tasks for different clients. 5. The six system processes must be constructed and used in the manner described previously. Each must be a void function with no arguments; each must issue a Block as its last action; each must be called only indirectly by using RunSys. 6. Your OS must display the client error messages and system prompt as they are given to you. You are not allowed to make up extra or different messages. The simulator depends on several of these messages being as given in order to evaluate what is happening. If you think you have found some situation different from those with specified error messages that requires an additional error message, ask about it before implementing the message. Usually, the situation will involve something that is guaranteed not to happen in any script. Jeeves 24 June 2017 System Manual 7. 51 Your OS must support the execution of user process threads using a model similar to, if not the same as, the support described in the next section. User Process Threads When a client issues a run command, your OS must set up and support the execution of a user process thread. Each valid run command should cause the OS to create the next higher numbered process (starting at 11) and associate the client's thread with it. Verifying that the command is valid requires checking the three files involved. Setup can probably best be done through the use of the Shell and DiskScheduler. Start by determining the size of the executable file (in pages); suppose it is N. Assign N+1 page frames to hold the process. Read the N clusters into the first N of the assigned page frames. The additional page frame holds the data area for the process as it executes. Setup must also include the assignment of one page frame for the input file and one page frame for the output file. Setup may include an anticipatory read of the first cluster of the input file; or this reading may be delayed until the user process actually attempts to read data. Once the setup is complete, the client thread should be associated with the process; and that thread should be put in the ready state so it can be selected for execution. During the thread's execution, it performs three basic types of instructions: 1) "reads" in which the thread wants to read a record (line) of data from the input file into some variable(s) in the data area; 2) "writes" in which the thread wants to write a record (line) of variables from its data area to the output file; and 3) "other" in which the thread is performing some action on the data it has. The first two of these actions require operating system support; all user process thread actions on files use sequential access. Jeeves 24 June 2017 System Manual 52 Reading Your OS must provide for "reads" by reading clusters into the input page frame as needed and transferring records from the input file page frame to the data area designated by the user process. The user process signals that it is reading by causing a User_Pgm_Input trap, with the R.process.pgmioaddr and R.process.pgmiosize registers set appropriately. The address that the process provides is a virtual one - it has no idea where your OS has placed it in memory. The size that the process provides is a maximum - it cannot know the actual size of the next input file record. (There will never be an instance in which the specified size is too small.) The OS must maintain a file pointer so that it knows where reading left off in the input file page; and, from that point, copy the bytes of the next record (up to the \n) to the physical address which corresponds to the virtual address that the process specified (and update the file pointer). It may be that when a "read" is requested, that there is no data in the input page frame (as before execution begins) or that there is only part of a record left in the input page frame (the rest of the record is in the next cluster). In both of these cases, the OS must suspend execution of the thread while it uses the DiskScheduler to read the next input file cluster into the input page frame. During the time that it takes to fetch the file cluster, the thread should be put in a "waiting" state. When the cluster read is finished, the OS must copy the record (or what remains of it) to the user process' data area. The thread can then be made ready again for execution. There is one complication with supporting reading. The OS must always be aware of the size of the input file. If the user process attempts to read beyond the last record of the input file, it must be stopped. This is normal end-of-file processing for operating systems. Your OS must terminate any thread which tries to read beyond the end of file. Jeeves 24 June 2017 System Manual 53 Writing Your OS must support writing by transferring records from the thread's data area to the output page frame; and when the page frame becomes full, writing the page frame as a cluster to the output file. A user process signals a "write" by using a User_Pgm_Output trap with registers R.process.pgmioaddr and R.process.pgmiosize set appropriately. The address refers to the virtual address of the beginning of the output record; the size is the actual number of bytes in the record (including the \n). The OS must maintain a file pointer to the output page frame so that it knows where the data at the implied physical address should be transferred to in the output page frame. If there is enough space in the page frame, the OS must copy the data bytes (including the \n) to the page frame and update its file pointer. If there is not enough space, the OS must fill the buffer with part of the data record and initiate a disk transfer through the DiskScheduler. When a disk write is needed, the OS must put the thread in a "waiting" state until the disk operation is complete, obtain a free disk cluster, and update the output file's directory entry (the in-memory copy). When the transfer is complete, if more of the data record needs to be copied, the OS must move the partial record into the beginning of the output page frame, update the file pointer, and make the thread "ready" again. You are guaranteed that no user process thread will write more records than can fit into a file Time Out You are encouraged to use time slicing to give all threads a fair chance at using the CPU. The time slicing technique is simple to describe: each time a user thread is selected to execute, set R.timer to a future time at which it must give up use of the CPU. When that time is reached, a Time_Out interrupt is generated. Your OS should respond to this interrupt by Jeeves 24 June 2017 System Manual 54 trying to select a different thread from those that are ready (and putting the one that was executing into a "ready" state). In practice, there a few complications involved in time slicing. Your OS must turn the timer off, if the executing user thread is stopped by some interrupt other than Time_Out. For instance, if a message packet arrives from another client, the Device_In interrupt stops the executing user thread. To execute the ProtocolHandler and deal with the packet, the user thread must be made "ready" and the ProtocolHandler must be scheduled. If the timer is not turned off, a Time_Out interrupt will occur at some later time when the user thread may not even be running. If the user thread is not moved to "ready" and some other thread selected to execute, there may be long delays in responding to some interrupts. Also, when a user input or output trap occurs, the OS must decide whether or not to stop the timer. If the request can be satisfied by just accessing the buffer, the user thread can be resumed and there is no need to stop the timer. If the request leads to disk access, the timer needs to be stopped because the user thread must be put into a "waiting" state. Termination When a user process thread terminates, the OS actions are the same, regardless of the reason for termination (there are three possible reasons: User_Terminate, User_Abort, or forced termination for reading too far). The actions are 1) recover the memory space allocated for running the process and for the input file page frame; 2) finish the writing of the output file - the output page frame may be partially full; it must be written; it is also necessary to update the directory holding the file and the directory a level above; recover the memory space being used for these disk transfers (all this can be referred to as closing the output file); 3) close the input file - much easier; 4) remove the process and re-associate the thread with Shell; and 5) prompt the user. Jeeves 24 June 2017 System Manual 55 File System The file system is designed to use the disk in clusters (4 sectors at a time). As with any system, the starting point is the boot record (located in the cluster starting at surface 0, track 0, sector 0 - from now on abbreviated as (0,0,0) and called a disk location or diskloc). The boot record has the following layout. Boot Record Size (bytes) Form 12 Contents char Instruction to start bootstrap program 4 long Number of surfaces on this disk 4 long Number of tracks per surface 4 long Number of sectors per track 4 long Sector size in bytes 4 long Cluster size in sectors 3 diskloc Disk location (surface, track and sector as three unsigned chars) of cluster containing the bit map 3 diskloc Location of the cluster containing the root directory 3 diskloc Location of the cluster where the kernel begins 6 diskloc Locations of the starting and ending clusters of the spooling area the spooling area is all of surface 4. 6 diskloc Locations of the starting and ending clusters of the swapping area the swapping area is all of surface 5. 1992 Bitmap char Bootstrap program Jeeves 24 June 2017 System Manual 56 The bitmap and disk usage information are kept in a cluster whose disk location is specified in the boot record. This cluster has the following form: Size 768 Form Contents char Bitmap - a [6][128] array of char, where each bit of a char represents the availability of one of the 8 clusters in a track. The bit usage is as follows: with bits numbered 76543210, bit n represents sectors 4*n through 4*n+3. A 1 in a bit position indicates the cluster is in use; a 0 indicates the cluster is free. Example: if bit 2 is 1, sectors 8-11 are in use. 3 diskloc Location of the last cluster used by the file system, excluding the kernel and daemons storage which are at the far end of the file space. 1277 char Wasted space. Root Directory The root directory is kept in a cluster whose disk location is specified in the boot record. The disk location for the root directory must stay the same throughout each simulation. This cluster holds the directory entries of the root user. Each directory entry consists of 128 bytes in the following form. Because clusters hold 2048 bytes, each cluster of a directory can hold up to 16 directory entries. Size Form Contents 28 char File/Directory name - up to 27 characters plus null terminator, file/directory names are not allowed to contain any white space characters or the symbol slash (/) Jeeves 24 June 2017 System Manual 57 4 long Number of bytes the file/directory occupies 4 long Number of logical records in the file/directory - for a directory, each record is a directory entry; for a data file, each record is a line of data; for a program, each record is an instruction; for a transfer file, each byte is a record. 6 accesspair An array of three pairs of characters to specify what access is allowed to the file/directory. The first accesspair indicates "Privileged" access, controlling what access privileged users have to this file/directory from non-console locations. If the first character of the pair (input access) is R, reading, listing and executing are allowed; if it is X, executing only is allowed; and if it is -, no input action is allowed. If the second character (output access) is W, updating, appending, creating and deleting are allowed; if it is C, creating only is allowed; and if it is -, no output action is allowed. The second accesspair indicates "Owner" access using the same codes; this pair controls what access the file's owner has. The third pair indicates "World" access - what access all other users have. Only the owner of a file/directory can change the access. 1 char Type of file: F (Folder/directory), P (Program), D (Data), or T (Transfer) - only from FTP. 9 char Null terminated name of the user who owns the file/directory. 1 char The character * always - used by the disk utility program and the simulator. 3 72 char Wasted space. diskloc An array of 24 disk locations referring to the clusters that hold the contents of the file/directory. Unused locations may contain Jeeves 24 June 2017 System Manual 58 garbage. For files of fewer than 24 disk locations, the first n entries must be used, where n is determined by the size of the file. There are 7 directory entries in the root directory. These directory entries are associated with the following folders/directories and files. root Root directory's own directory entry. That is, the root directory contains a directory entry of the root directory itself. kernel The central part of the operating system, stored as a program file. daemons The auxiliary part of the operating system, stored as a program file. password A special data file containing the encrypted user passwords and user identification numbers. library A directory meant to hold files that users can access for reading or executing. All files should have "World" access set to R- when they are created (with privileged user and owner access set to RW). The files here are not meant to be changed or deleted; however, new files may be added to the directory by anyone and the owner can change the access on any file s/he has created. The access to the library itself is RWRWRC to allow anyone to use the files that are there and to create new files in the library. For any file created in the library directory, the accesspairs should be RWRWR- The owner of new library files can change the access. common A directory meant to allow users to share files in any way they wish. All files should have all access pairs set to RW when they are created to allow any user to do anything s/he wishes to any file. The access may be changed later by the file's owner. users The directory for the users. Each user (including root) has a directory entry in this directory. The directory entry for user root is identical to the root Jeeves 24 June 2017 System Manual 59 directory's directory entry for itself. Only the root gets this special treatment. Password File The password file contains data in a format that is different from all other data files. Its contents are coordinated with the user directory. The order of the users in the users directory should match the order of the password file entries; however, this is not an absolute requirement. Each password entry has the following form: Size Form Contents 4 long User Identification Number - unique for each user, assigned at the time the user is added to the system. 9 char User's name stored as a null terminated string of up to 8 characters (plus null). 19 char This user's encrypted password stored as a null terminated cstring 17 characters long (plus null). Data Files All files on the original disk (as well as all files that can be created using Telnet commands) are either normal data files or program files. One FTP command (put) can create a data file on the disk that does not have normal data file form. Normal data files contain ASCII characters arranged into records. Each record ends with a '\n' (new line character); the records all have a similar format but vary widely in their length. The format of a data record is as follows: folder filename nnn sssdata Jeeves 24 June 2017 System Manual 60 That is, a folder name, a space, a file name, a space, a three-digit record number (nnn), a space, a three-digit record length (sss) and the data characters of the record. The data characters are simply the alphabet, repeated as often as necessary. The sss value is the number of alphabet letters that appear; this does not count the folder, filename, record number and spaces. Each record ends with a '\n' character; this character is not counted as part of the record length (sss) either. Here are records 5-7 from file tiny.one in the wlewis folder to illustrate wlewis tiny.one 005 036ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJ wlewis tiny.one 006 040ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMN wlewis tiny.one 007 007ABCDEFG The FTP command put can transfer a text file of almost any form to a Jeeves file. Such files should be flagged as different by making the data type in the directory entry be T, for 'transfer' and the number of logical records for the file should be made equal to the number of bytes in the file. Transfer files can be subsequently copied or printed but not used as data for program executions or displayed with the show command. Program files contain instructions, each 4 bytes long. Consequently, the number of logical records is always 1/4 of the number of bytes in the file (each instruction is a record). An instruction contains an act value (one byte) indicating the operation to perform, an elapse value (one byte) that is used by the simulator, and a reladdr value (two bytes) indicating the relative address of the data that the instruction acts on. Generally, the OS need not be concerned about these instructions. Miscellaneous Thoughts about the File System Overall, the file system can be thought of as being in four levels: 1) the Boot Record Jeeves 24 June 2017 System Manual 61 holds the location of the root directory and bit map (as well as specifications about use and structure of the disk); 2) the Root Directory holds directory entries for the three key directories used by clients (users, common, and library) and entries for the operating system and password files; 3) the Users Directory holds one directory entry for each valid client of the system; and 4) each client directory holds the directory entries for that client's files. Your OS must maintain some semblance of this structure internally (in its database) so it can make changes, find things, etc. Although the bitmap, root directory and the other standard directories and files are at predetermined places on the disk, your OS is expected to read the boot record and extract the necessary disk locations, rather than using your personal knowledge of where the appropriate clusters are and simply reading them in directly. The sample program (shown later) partly illustrates this as it reads the root directory and the user directory. Because each directory entry occupies 128 bytes, it is possible to keep track of 16 files in one cluster of a directory. Although all directories initially have fewer than 16 files in them, your OS should allow the users directory (at least) to have more than 16 files. The directory entry for a directory, just like a directory entry for a file has space for 24 disk locations. Thus, it is possible for a directory to hold entries for 384 files. Each directory entry for a file can refer to 24 clusters of disk storage, for a total size of 48 KB. Some files are near maximum in size (e.g. kernel file or the daemons file); others are very small, occupying less than one cluster. Your OS is allowed to maintain in its database a copy of the bit map, a copy of the root directory, copies of the users directory, library directory and common directory, and a copy of a user's directory for every user. These copies may be used for reference when responding to user commands; however, they MUST remain faithful copies. So, if some action causes the bit map or the root directory or the users directory or a client's directory to Jeeves 24 June 2017 System Manual 62 change, your OS MUST update both the database copy and the disk copy. Failure to do this will have catastrophic consequences when running your OS - the simulator is evaluating the actions your OS takes; it cannot access your OS database; it can access only the disk to determine if actions have been done correctly. If the disk is not updated, the simulator does not have the same view of the file system as your OS might. This can lead the simulator to report bogus error messages or even to crash. Unrealistic Things The Simulator Does The simulator is pretending to be a the hardware of a real server system. However, in a variety of ways, the simulator does not behave as real server would. Partly, this is because the environment that the simulator exists in is not completely realistic. Below is a list of some of the ways in which a real server system would be different. 1. A real server would have to deal with all seven OSI layers or, at least, the four complete TCP/IP layers. In this discussion, OSI layers are referenced with TCP/IP layers in parentheses. By simplifying the data link and physical layers (network interface layer), the issues of actually dealing with the hardware have been glossed over so that a few registers are all that is needed to initiate message transmission and reception. The Ethernet protocol at the data link layer is ignored completely. The elements of retransmission of lost messages and construction of messages from piecemeal datagrams that may possibly be out of order would be the job of the network layer (Internet layer). That task is completely done away with by having message packets contain whole commands and never arrive out of order or requiring retransmission. Layers (application) above the transport layer have been eliminated by keeping the services basic and similar, so that a single Login process and Shell process can easily deal with the incoming messages. Many of the complications Jeeves 24 June 2017 System Manual 63 associated with TCP/IP are eliminated by simplifying the IP and TCP headers and cutting down on the types of message interactions. Also, the IP addresses are all treated as class B even though there is no enforcement of the requirement that the network ID begins with 10. 2. The clock on the server is extraordinarily slow in comparison to many of the other system components. For the most part, you should not notice this. The primary reasons for the slow clock (ticking each 10 microseconds) are to allow the simulator to work with reasonable numbers in trying to sequence the activities (interrupts) that it is generating and to keep the executing user programs small. 3. The simulated clients make only very limited types of errors in the commands they enter. Real clients could screw up in a many, many other ways. The types of errors that your OS must handle are kept restricted so that you do not need to make a complicated parsing element for the Shell. This is a course in operating systems, not command languages; so parsing of the commands is deliberately kept simple. 4. Supervisor mode is used far too much on Jeeves. A real server would greatly restrict the use of this mode because interrupts cannot occur when the system is in this mode. We will discuss in class what happens when the various components of the operating system run in user mode and what it would take to prevent the system processes from conflicting with each other. But for you to implement an OS which allows interrupts while the system processes are running, a great many elements (semaphores or monitors or their equivalent) would need to be added. Also, the simulator would have to have a more complicated structure. 5. The scheduling of threads to use the CPU is slightly different from the way this would be handled on a real system. Real systems commonly have many processes with Jeeves 24 June 2017 System Manual 64 multiple threads, even allowing all processes to have multiple threads. Also, there would be no need to maintain thread numbers across processes; instead, threads would be relative to the process. This level of sophistication would create too many headaches for you and would make the simulators monitoring job much more difficult. 6. The file system that you are required to use is rather crude. Real systems today permit clients to create subdirectories and links, as well as having much larger files with much more complicated directory entries than Jeeves allows. But, if all that is allowed, the task of maintaining the file system grows enormously. 7. There are no execution stacks. User programs are not modular, do not include function calls; so that argument passing and return addresses need not be stored. Also, by not allowing interrupts in supervisor mode, it is not necessary to save and restore state information about OS actions. Guarantees To prevent you from trying to do unnecessary tasks in your OS, the following list of guarantees are provided. For the most part, those things which are not allowed to happen are prevented from happening because they would put more of a burden on you the OS designer; and this burden is considered greater that the benefit of letting you experience a more realistic situation. Because of these guarantees, some elements that you might think you need in your OS are not needed. You are guaranteed that . . . 1. There are no syntax errors in the commands coming from clients. No omission of fields, no extra fields, no invalid numbers, no messed up file specifications. simulated clients are better at typing than you are. The Jeeves 24 June 2017 System Manual 2. 65 There is no need to worry about running out of disk space. Created files will not exceed file storage. Spooled files do not exceed the size of the spooled area, provided your OS actually prints the spooled files and recycles the space. 3. There is no need to worry about running out of memory, provided you recycle. At no time do the clients who are logged in need more memory than what should be available. 4. There is only one privileged user, root. 5. There is no time in any script when more than 12 clients are logged in at the same time. 6. If the printer becomes disabled, it will always become enabled again and with enough time for a reasonable OS to get all of the spooled files printed before the Power_Down occurs. 7. No user attempts to log in on Jeeves until at least two seconds (200000 ticks) into the simulation. Thus, there is plenty of time for your OS to get itself set up before the users start doing anything. 8. No user has more than 30 files in his/her directory at any time during a simulation. 9. No new directories or files are added to the root directory. root always contains seven entries, although the content of those entries may change. 10. No hackers attempts to send Jeeves trick packets to try to confuse it or overload it Jeeves 24 June 2017 System Manual during a simulation. 66 However, some packets not intended for Jeeves are sent to Jeeves because it is on a network with other servers. 11. No user program attempts to read anything but a data file. 12. No client gives a show command for anything but a data file. However, it is perfectly reasonable to use copy or get or delete on any type of file; and it is reasonable to use a print command for a data or a transfer file. 13. No client gives a run command to execute anything but a program file. 14. No more than 20 files are open at any one time by any script. 15. There is no need to echo the commands back to the client. In fact, doing this causes redundant output in various simulator log files. 16. Although all clients are allowed to use either Telnet or FTP services, any client who logs in at the console uses only Telnet. 17. No more than 64 valid users can exist at any one time. 18. At no time does root attempt to remove any user who is currently logged in. 19. No more than one client tries to start a session from one IP address at a time. However, one client may simultaneously start sessions from separate IP addresses; and multiple clients may have sessions sequentially from the same IP address. 20. No data file record in any data file is longer than 150 bytes. Jeeves 24 June 2017 System Manual 21. 67 No user process thread outputs more records that can fit in a file; and every input request from a user process thread specifies a size of 150. 22. Provided the OS does reasonable processing of client commands, no client uses command typeahead - entry of a second command before the first is finished and a prompt is received. 23. The only bogus messages that Jeeves receives are SYN messages directed to other servers on the LAN. There are no PSH, FIN, or ACK messages that are bogus. Auxiliary Simulator Functions In addition to simulating the Jeeves hardware, the simulator provides many other capabilities to the operating system writer, you. It generates a wide variety of outputs, some of which are always produced, and others which are produced for the asking. If you use this output wisely, it can greatly aid you in debugging your OS. It also provides proof that your OS did indeed serve the clients by directing Jeeves in doing the tasks they requested. Every time you execute your OS with the Jeeves simulator, it produces results in five files, jeeves.log, jeeves.report, printer.log, execution.log and xxx.final. jeeves.log records every input or output transfer that is performed during a simulation and shows the time and associated device for the transfer. jeeves.report is a summary of all of the simulation activity. printer.log captures all output to the printer. execution.log records, approximately, the records input and output by user programs. xxx.final holds the disk image after the simulation, assuming xxx is the starting disk image. Jeeves 24 June 2017 System Manual 68 jeeves.log The jeeves.log file shows in chronological order all the significant events of the simulation, with considerable detail. If the script is complicated, this file can be quite long. Below are two segments of a jeeves.log file to illustrate. 481034 Message: 557345 Message: 557383 Message: 557391 Message: 627757 Message: 628609 Begins: 628678 Message: 628712 Message: 628731 Message: 1914262 2339604 2340344 2340438 Comm Out IP: 123.123.123.123 DL: 21 Fg: 0 FT: 0 Ty: A Srv: T Seq: 4 Jeeves> . Comm In IP: 123.123.123.123 DL: 18 Fg: 0 FT: 0 Ty: P Srv: T Seq: 5 users. Comm Out IP: 123.123.123.123 DL: 164 Fg: 0 FT: 0 Ty: P Srv: T Seq: 5 999 root\n1013 dcomer\n1020 nhorvath\n1035 jwolfe\n1121 wl Comm Out IP: 123.123.123.123 DL: 21 Fg: 0 FT: 0 Ty: A Srv: T Seq: 5 Jeeves> . Comm In IP: 123.123.123.123 DL: 28 Fg: 0 FT: 0 Ty: P Srv: T Seq: 6 show ./tiny.one. Disk R Cluster: (0,5,20) Address: 40960 wlewis tiny.one 001 024ABCDEFGHIJKLMNOPQRSTUVWX\nwlewis tiny. Comm Out IP: 123.123.123.123 DL: 524 Fg: 1 FT: 2 Ty: P Srv: T Seq: 6 wlewis tiny.one 001 024ABCDEFGHIJKLMNOPQRSTUVWX\nwlewis tiny. Comm Out IP: 123.123.123.123 DL: 177 Fg: 2 FT: 2 Ty: P Srv: T Seq: 6 JKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJK\nwlewi Comm Out IP: 123.123.123.123 DL: 21 Fg: 0 FT: 0 Ty: A Srv: T Seq: 6 Jeeves> . Screen: Jeeves> Keyboard In: list library Screen: RWRWR1752 jwolfe Screen: Jeeves> P helper\nRWRWR- 21538 dcomer Each transfer begins with the details of the device involved in the transfer. On the first line, we can see the time (481034) of an output message sent to IP 123.123.123.123. The IP header data length (DL) is 21 (12 for the TCP header, 9 for the text); it is fragment (Fg) 0 of a total fragment count (FT) of 0; it is message type (Ty) A for ACK, using service (Srv) T for Telnet; and it is message sequence (Seq) number 4. The content of the message appears on the next line, Jeeves> the system prompt. (The . is the null character after the text; it is counted in determining data length.) The second transfer is an input at the Comm Interface (it is a users command). The third transfer is only partly shown. For long messages (the third one has a data length of 164 bytes), only the first 60 bytes are shown. Jeeves 24 June 2017 System Manual 69 This is the way all large transfers are handled in the log; only the first 60 characters are shown. Note that the newline character is shown as \n rather than allowing it to output normally and cause movement to the next line. This approach keeps the messages more compact, although it does not show multi-line messages as they would appear to the client. The sixth transfer shown (at time 628609) involves the disk. For disk transfers, the log shows the action (R for read, W for write), the cluster number (0,5,20) and the memory address (40960) used for the disk transfer. From the fifth transfer message, we can see that the disk was being read in order to perform a show command (show ./tiny.one). Following the disk information for the sixth transfer, we see the first 60 characters that were read from surface 0, track 5, sector 20. tiny.one is a very small file; its contents can be sent to the client in just two packets. The next two transfers show the output messages for the show command. Note the values of DL, Fg, FT and Seq for these messages. The seventh message is the maximum allowable length (DL is 524); it is the first (Fg=1) of two fragments (FT=2) that are being sent in response to the incoming message with sequence number 6 (Seq). The eighth message is the second fragment. From this information alone, it is possible to infer that tiny.one contains 677 bytes (524 - 12 + 177 - 12). The 12's are subtracted for the TCP headers that are part of each message. The ninth transfer shown also uses sequence number 6. This is the prompt message after completing the show command. So, it is regarded as being part of the response to incoming message 6 which contained that command. Note the message types (Ty values) being used. Incoming client messages are PSHes, as should be expected. Outgoing messages are either ACKs or PSHes. The OS that was executing here uses ACKs for sending prompts and PSHes for other packets sent to the Jeeves 24 June 2017 System Manual 70 client. You may choose whether or not to adopt this strategy in your OS; however, this is the recommended approach. In the second segment from jeeves.log, we can see transfers involving the console. Less information is necessary to show these transfers; so, one line is used for each transfer. Transfers to the screen show only the clock time, the word "Screen:", and the first 60 characters of the transfer (fewer if there are fewer than 60 in the transfer). Transfers from the keyboard show only the clock time, the words "Keyboard In:", and the characters that came in as a command. Null characters are not shown as '.' for either input from the keyboard or output to the screen. Note: if there are any simulator reported errors, they are also recorded in the jeeves.log file. jeeves.report The jeeves.report file is a summary of everything that occurs during a simulation. The report is divided into several sections, most of which simply show the number of times something happened. The report gives the big picture of how your OS responded to the script it was presented. The first section of the report shows the activity on each of the devices. Here is a sample. Status 0 7 21 0 7 0 Clear 0 0 16 26 0 0 Outputs 0 0 20 0 7 0 Inputs 0 7 16 26 0 0 Errors 0 0 0 0 0 0 Device Mouse Disk Comm Keyboard Screen Printer Jeeves 24 June 2017 System Manual 71 The first column shows the number of times the GetStatus instruction was performed on each device. The second column shows the number of times the Clear command was performed on each device. The third shows the number of StartActs for output issued to each device (here disk seeks and printer ejects are considered output actions). The fourth shows the number of inputs from each device - this includes StartActs for the disk or keystrokes for the keyboard or incoming messages for the Comm Interface or spontaneous actions for the mouse. The fifth shows the number of errors associated with each device - it is good to have zeros in this column. The second section of the report collects information about each IP address which was dealt with. Again, the information is tabular. Here is a sample. IP SYN 24. 77.159. 95 1 24. 43.159.183 1 144. 80.128. 13 1 144.201.193.179 1 For other servers 0 ACK 3 4 3 5 PSH 5 7 5 4 FIN 1 1 1 1 Srv T T T T The IP addresses are listed in the reverse order in which they were a part of the simulation, i.e., 24.77.159.95 was the last IP address to be heard from. The table shows the number of SYN messages, ACK messages, PSH messages, and FIN messages for each IP. In this case, each IP had one client in the simulation so there is a single SYN and a single FIN. ACKs are generally from prompt messages; PSHes are generally from data messages. Srv indicates the service; in this case, all clients were using Telnet (T). Note that even the console is shown here - Jeeves' IP address, 144.201.193.179, represents the console and the messages were all used internally to provide device independence. The last line referring to "other servers" is a count of messages that Jeeves received which were intended for other servers. Jeeves 24 June 2017 System Manual 72 The third section is about what each client did. Here is a sample. Username --richie jwolfe wlewis dwagner IP 144.201.193.179 24. 77.159. 95 24. 43.159.183 144. 80.128. 13 144.201.193.179 Thread Srv Pkts Cmds 105 T 1 -2 104 T 5 2 103 T 6 3 102 T 5 2 101 T 5 2 Login 911638 220016 210015 200011 0 End Session -1 522640 601947 497131 911384 Again, the listing is in reverse chronological order based on login time. For each client, we see the client's username, the IP address they used, the thread number that was assigned to the client, the service used (here, all Telnet - T), the number of packets that were exchanged between Jeeves and this client, the number of commands the client entered, the clock time when the client logged in (sent SYN really), and the clock time when the client logged out. Note that dwagner logged in at the console and when he logged out, no one else logged in. This is why two clients are shown for the console IP; and the last one (at the top) is "---" which is used as a placeholder until a client logs in. The fact that the console was unused after dwagner logged out also causes the unusual command count and End Session time for the top entry. The section about user process thread executions may come next. This section appears only if the script contains run commands and the operating system supports those commands. Here is a sample from a script containing two run commands. Execution 102a 103a Inputs 25 15 Outputs 50 45 TimeOuts 10 15 Stops 3 4 End T A Start 413635 416955 Finish 513033 525841 The execution designator identifies the thread (e.g. 102) and the number of executions ('a' indicates the first run command for thread 102; 'b' would indicate the second, and so on). The number of inputs and outputs refer to the executing program's requests. The number of time outs depends on the time slicing. Stops are caused by interrupts that are unrelated to Jeeves 24 June 2017 System Manual 73 the program which occur during execution. The "End" letter indicates termination (T), aborted (A), or unfinished or forced to terminate (?). The execution times are also shown. The next section shows the number of privileged instructions, the number of interrupts and the number of times that system processes were scheduled. Here again is a sample. Count Interrupt/Trap 1 Boot_Done 1 Power_Down 25 Device_In 31 Device_Out 0 Device_Enable 0 Device_Disable 0 Control_Done 92 Block_Self 0 Time_Out 0 User_Pgm_Input 0 User_Pgm_Output 0 User_Terminate 0 User_Abort 150 TOTALS Count 46 12 44 92 57 92 0 1 344 Instruction GetStatus Clear StartAct Block Wait RunSys RunUser Halt TOTALS Count System Process 26 DiskScheduler 13 ProtocolHandler 4 Login 31 Shell 0 Unspooler 18 Transmitter 92 TOTALS These are straightforward counts of how many times each thing occurred. A few examples: the RunSys instruction was used 92 times and each of those times Block was used - this is good. A thread of Shell was scheduled 31 times to deal with pending commands. There were a total of 31 Device_Out interrupts with 44 StartAct instructions. There were 13 disk input operations to account for the difference between the Device_Out count and the StartAct count - each disk input is also preceded by a StartAct. After the counts, there may be a dump of the bit map from the disk. This may be followed by a dump of the directory entries in the root directory and the users directory. These dumps appear only if there were write actions on the disk; they show how the disk has changed. printer.log Jeeves 24 June 2017 System Manual 74 This file contains the output that has been sent to the printer, in the order and form it was sent. If your OS does a paper eject, as it should, when the printing of a file is finished, an "ejection marker" is output at the end of the file. The ejection marker is simply a line of dashes with the word "Eject" and a time embedded in it; this separates the end of one file from the beginning of the next. If Printer Disables and Enables occur, these are also noted in the printer.log file. Below is a sample from a printer.log file showing the beginning of printing of the term.paper file from the library directory. Printer Log based on script print2.scr with disk newfiles 450897 library term.paper CDEFGHI library term.paper CD library term.paper CDEFGHIJKLMNOPQRS library term.paper 001 061ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZAB 002 056ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZAB 003 071ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZAB 004 036ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJ The number at the beginning (450897) is the clock time when the following lines from the printer buffer begin printing on paper. Only part of the printer buffer contents are shown. Note that whole output lines are recorded in the log file, not just the first 60 characters. execution.log This file contains all or part of each input or output record read or written by any user program that runs. Each program input is recorded as an introductory line to state the time, the thread and address involved followed by a line containing up to 75 characters from the input record. Each program output is recorded as an introductory line to state the time, the thread and address involved, followed by a line containing up to 75 characters from the output record. Input records are logged in a delayed fashion (to allow the OS to get information into memory); output records are logged at the time of the trap. Below is a sample of the Jeeves 24 June 2017 System Manual 75 beginning of an execution.log file. 416941 Input to thread 102 at physical address 44575 jwolfe my-first-data-file 001 059ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOP 417553 Output from thread 102 at physical address 44754 jwolfe THREAD.102a 007 055ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVW 418332 Output from thread 102 at physical address 44671 jwolfe THREAD.102a 008 070ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVW 418378 Input to thread 102 at physical address 43631 jwolfe my-first-data-file 002 079ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOP 421062 Output from thread 102 at physical address 44380 jwolfe THREAD.102a 009 015ABCDEFGHIJKLMNO Time out for process 102 at 422546 424478 Output from thread 102 at physical address 44672 jwolfe THREAD.102a 010 016ABCDEFGHIJKLMNOP Notice the filename part of the output records. The simulator generates all program output; but the simulator has no easy way of determining the name of the file being written. Consequently, the simulator puts in place of the filename a name composed of the letters "THREAD", the thread number (102 in this case), and a sequencing letter ("a" in this case). The sequencing letter for a second file created by thread 102 would be "b". Also, note that Time_Out interrupts are logged in the execution log - see the second to last line. xxx.final After the simulation is complete, the simulator copies the contents of the disk to a new file. Because the simulation can be done with a disk file having any name, the simulator records the final disk image in a file whose name is derived from the original disk file; it is not really named xxx.final. So, if the simulation was started on a disk file named thedisk, the final image will be written to a disk file named thedisk.final Tracing Events In addition to the jeeves.log file and the jeeves.report file, the simulator can also Jeeves 24 June 2017 System Manual 76 display other information about what is going on, if you ask for this information. The way to ask is by specifying one or more trace variable values in a file called trace.setup There are nine trace variables; all but one are integers. The idea is that the simulator examines these variables at key points in the simulation and if the variables have a appropriate value, some key piece of information is displayed (on the screen in front of you). This display (a trace) can show you a great deal about how far the simulation went before something went wrong. It often indicates exactly what it is that went wrong. When a simulation begins, the simulator looks for a trace.setup file, if none is found, the trace variables are set to their default values which cause no information to be displayed. If the file is found, the simulator reads in the nine values for each of the trace variables and uses the values you have specified to control the display. The nine values must be in the order shown below, each value separated from the next by whitespace. Following is a description of each variable. T.icode For tracing interrupts and traps. When this variable is set to a non-default value, the simulator displays information about the specified interrupts or traps just BEFORE they occur, i.e., just before OpSys gets to act on them. The value in T.icode uses one bit for each interrupt or trap, like this ------------------------------------------------. . . | |13|12|11|10| 9| 8| 7| 6| 5| 4| 3| 2| 1| ------------------------------------------------So, to get a display for interrupt code 1, you must set the rightmost bit of T.icode to 1; for interrupt code 2, set the next to rightmost bit and so on for each of the interrupt codes. You may set T.icode to trace any combination of interrupts or traps in this way. Here is a practical example; set T.icode to 12 (which in binary is 000000001100) thereby requesting a trace for all Device_In (3) and all Device_Out (4) interrupts. If you set T.icode to 0, ALL interrupts are traced - be careful when doing this except for very simple scripts; Jeeves 24 June 2017 System Manual 77 you may get a lot of output. The default value for T.icode is -1. T.instruction For tracing privileged instructions. When this variable is set to a non-default value, the simulator displays information about each of the specified privileged instruction uses, usually right at the end of the privileged instruction. T.instruction uses one bit for each instruction, like this --------------------------------------. . .| | | |Ht|RU|RS|Wt|Bl|SA|Cl|GS| --------------------------------------So, to display information about GetStatus (GS), set the rightmost bit; to display information about Clear (Cl), set the next to rightmost bit; and so on for StartAct (SA), Block (Bl), Wait (Wt), RunSys (RS), RunUser (RU), and Halt (Ht). You may set T.instruction to trace any combination of privileged instructions in this way. Here is a practical example; set T.instruction to 5 (which in binary is 00000101) thereby requesting a trace of all uses of GetStatus and StartAct. If you set T.instruction to 0, ALL privileged instructions are traced. The default value for T.instruction is -1. T.sysproc For tracing system processes. When this variable is set to a non-default value, the simulator displays information about each execution of specified system processes. T.sysproc uses one bit for each process, like this ---------------------------------. . . | | | |Tr|Un|Sh|Lo|Pr|Di| ---------------------------------So, to display information about the DiskScheduler (Di), set the rightmost bit; to display information about the ProtocolHandler (Pr), set the next to rightmost bit; and so on for Login (Lo), Shell (Sh), Unspooler (Un), and Transmitter (Tr). You may set T.sysproc to trace any combination of system processes in this way. Here is a practical example; set T.sysproc to 32 (which in binary is 100000) thereby requesting a trace of all uses of the Transmitter. If you set Jeeves 24 June 2017 System Manual T.sysproc to 0, ALL system processes are traced. 78 The default value for T.sysproc is -1. T.transfer For tracing data transfers between memory and a device. The information about the transfer is shown when the transfer is complete, just before an interrupt is generated. When this variable is set to a non-default value, the simulator displays information about each specified data transfer (essentially the same information shown in jeeves.log, with one exception). T.transfer uses one bit for each device, like this ---------------------------------. . . | | | |Pr|Sc|Ke|Co|Di|Mo| ---------------------------------So, to display information about the Mouse (Mo), set the rightmost bit; to display information about the Disk (Di), set the next to rightmost bit; and so on for the Comm Interface (Co), Keyboard (Ke), Screen (Sc), and Printer (Pr). You may set T.transfer to trace any combination of data transfers in this way. Here is a practical example, set T.transfer to 18 (which in binary is 010010) to trace all Disk transfers and Screen transfers. As mentioned, this trace looks like the information in jeeves.log except for the Keyboard trace; for the Keyboard, there is a trace shown for each character entered, instead of showing the whole command. If T.transfer is set to 0, all data transfers will be traced. The default value for T.transfer is -1. T.ipaddr For tracing what happens at a specific IP address. This variable attempts to capture exactly what the client would see during a session at some IP address. Actually, what is captured is more detailed than what the client would see each input and output is labeled, with I or O and the clock time. The trace output is not sent to the screen; it is written to a file named captured.ip below is a segment of what was captured for a simulation - you can see the labeling Jeeves 24 June 2017 System Manual 79 of the prompts, commands, and results. O 393942: Jeeves> I 480988: list . O 481026: RWRW-3715 RWRW-3312 RWRW-- 23225 RWRW-677 O 481034: Jeeves> I 557345: users O 557383: 999 root 1013 dcomer 1020 nhorvath wlewis wlewis wlewis wlewis D P D D simple.one dosomething another tiny.one To perform a capture such as this, you must set T.ipaddr to the IP address of the client you want to see. Specify the 4-part IP address in the usual form four numbers separated by periods, for example 24.43.159.95 If the special IP address 0.0.0.0 is specified, the inputs and outputs for all IP addresses are captured simultaneously - this may create a rather jumbled appearance in captured.ip; however, each input and output is labeled with its associated IP address so that you can distinguish who is doing what. Do not embed white space in the IP address that you specify in trace.setup. T.start This value controls the start of tracing. You must set it to the clock time at which you want tracing to begin. This value affects ALL tracing variables. The idea is that tracing does not begin until R.clock >= T.start Of course, if T.start is set to 0, tracing begins as soon as the simulation starts. You should use this variable to focus on a section of time during which a problem occurs. Jeeves 24 June 2017 System Manual 80 The default value of T.start is 600000000. T.finish This value controls the end of tracing. You must set it to a clock time at which you want tracing to stop. This value affects ALL tracing variables. The idea is that tracing continues only while R.clock <= T.finish Of course, if you set T.finish high enough, tracing will continue throughout the simulation. You should use this variable to focus on a section of time during which a problem occurs. The default value of T.finish is 600000000. T.diskdump This value can provide the ability to dump one or more sectors of the disk. You must set it to a clock time at which you want to do the dump - this time must be between T.start and T.finish. When the specified diskdump time occurs, the simulator prompts for the disk location of a sector (not cluster) and then displays the specified sector in the form you specify. This prompting occurs repeatedly, so you can examine multiple sectors. The simulator also asks you to specify a time for the next diskdump. The default value for T.diskdump is -1. Here is a sample of the prompts and responses assuming T.diskdump is 450500 - the bold elements were entered by the programmer. The choices of sector form are the same as are available from the diskutility program, described later. Disk Dump at 450500: Surface (0-5, -1 to stop): 0 Track (0-127): 1 Sector (0-31): 9 Interpretation (Hex, Boot, Map, Folder, ASCII): f Display for disk location (0,1,9) Filename: mycopy Size (in bytes): 1540 Record count: 20 Access settings: RWRW-File type: D Owner: wlewis Clusters occupied: (0,6,28) Surface (0-5, -1 to stop): -1 Jeeves 24 June 2017 System Manual 81 Do you want to Dump Disk at a later clock time (Y/N)? n This dump requests to examine sector (0,1,9) as a folder - one directory entry (for file mycopy) is found in it. Note that only one sector is shown at a time. T.memorydump This value can provide the ability to dump one or more 512-byte blocks of memory. You must set it to a clock time at which you want to do the dump - this time must be between T.start and T.finish. When the specified memorydump time occurs, the simulator prompts for the memory address to begin the dump and then displays the specified block in the form you specify. This prompting occurs repeatedly, so you can examined multiple memory blocks. The simulator also asks you to specify a time for the next memorydump. T.memorydump is -1. The default value for Here is a sample of the dialog, assuming T.memorydump is 611055; again, the forms are the same as those available from diskutility. Memory Dump at 611055: Start Address (-1 to end): 36864 Interpretation (Hex, Boot, Map, Folder, ASCII): a Display of memory starting at address 36864 Offset 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF 0000 CDE.wlewis simple.one 028 062ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHI 0040 JKLMNOPQRSTUVWXYZABCDEFGHIJ.wlewis simple.one 029 060ABCDEFGHIJK 0080 LMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGH.wlewis simple. 00C0 one 030 074ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZA 0100 BCDEFGHIJKLMNOPQRSTUV.wlewis simple.one 031 038ABCDEFGHIJKLMNOPQ 0140 RSTUVWXYZABCDEFGHIJKL.wlewis simple.one 032 020ABCDEFGHIJKLMNOPQ 0180 RST.wlewis simple.one 033 090ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHI 01C0 JKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKL.wlewis s Start Address (-1 to end): -1 Do you want to Dump Memory at a later clock time (Y/N)? n This request is to examine memory locations 36864 through 37375 as ASCII Jeeves 24 June 2017 System Manual 82 characters - undisplayable characters are shown as periods. To do all the tracing shown in the examples, the trace.setup file should have the following values, in order. The values need not be on separate lines. 12 5 32 18 24.43.159.95 300000 1000000 450500 611055 Simulator Detected OS Errors The simulator is checking many of the actions of your OS to make sure it is doing reasonable things. When your OS does something that the simulator regards as wrong, the simulator does three things: it displays an error message on the screen; it records the same error message in the jeeves.log file; and it sets R.oserror to an error code number. By setting R.oserror, the simulator is trying to communicate to your OS (not just to you) that the OS has made a mistake. You would be wise to have your OS check the R.oserror value to be sure it is 0 (the indication of no error) after any action that is questionable. Below is a listing of the errors that the simulator detects along with the associated error code numbers (on the left). Each error message appears on one line. The text beneath them is an explanation of what you might be doing that caused the error. 1. OS has changed R.clock to xxxx it should be yyyy Your OS changed the value in R.clock; but your OS is not allowed to ever change the value in R.clock. Jeeves 24 June 2017 System Manual 2. 83 OS should not be using 'throw' The simulator uses the 'catch' and 'throw' mechanism to simulate interrupts. Your OS contains a 'throw' which it did not catch. 3. OS returned from OpSys; must use priv. instr. Your OS must never simply fall through OpSys and return. It must relinquish control of the CPU by issuing a RunSys, RunUser, Wait, or Halt. 4. Invalid Device: xxxx 1=Status, 2=Clear, 3=StartAct: yyyy The value in R.device (xxxx) is not a valid device number. The detection was made during a GetStatus (1), Clear (2) or StartAct (3) as indicated by yyyy. 5. Device not ready; device: xxxx status: yyyy Device xxxx is not in a ready state when attempting StartAct, instead the device's state is yyyy. 6. Can't StartAct on device: xxxx Your OS is attempting to start IO on device number xxxx; but it is a keyboard or a mouse. 7. Invalid surface: xxxx The disk has surfaces numbered 0 through 5, not xxxx. 8. Invalid track: xxxx The disk has tracks numbered 0 through 127, not xxxx. 9. Invalid sector: xxxx The disk has sectors numbered 0 through 31, not xxxx. 10. Invalid disk action - not R or W or S The disk can only read (R) or write (W) or seek (S); some other character was found in the action register. The action must be in uppercase. 11. Not on page frame start: xxxx is address, device yyyy Disk reads and writes and printer writes must involve transfers to/from a memory address that is the start of a page frame, i.e., a multiple of 2048. xxxx is not such a multiple; yyyy is the device in question. Jeeves 24 June 2017 System Manual 12. 84 Invalid data transfer size: xxxx Disk reads and writes must involve some multiple of the number of bytes in a sector (512). xxxx is not a multiple of 512. 13. No system service with processid: xxxx xxxx is not a system process id; such ids are 1 through 6 14. Process id: xxxx cannot be used with RunSys xxxx is the process id of some user process, not one of the system processes 15. Bad address: xxxx for device yyyy xxxx is not a valid memory address for a StartAct using device yyyy 16. Bad data size: xxxx bytes for device yyyy The number of bytes that can be transferred to device yyyy must be in the range 0 to 2048; it cannot be xxxx 17 Lost input from device xxxx due to locked status Device xxxx was not cleared when input arrived on it. The input was discarded. Your OS did not Clear the device after its previous input. 18. Inappropriate device: xxxx to use Clear on Only devices that can have spontaneous input (Mouse, Keyboard, and Comm Input) require clearing; device xxxx does not 19. Must issue Halt at Power_Down interrupt When a Power_Down interrupt occurs, your OS must issue a Halt. It cannot attempt any other actions. 20. Return from system process xxxx must use Block The last action of every system process must be to Block itself. System processes are not allowed to return; but xxxx did. 21. Invalid use of Block, process xxxx The Block trap can be used only by system processes; however, a Block occurred while the current process id was xxxx (not a system process id) 22. Context not restored for thread xxxx Jeeves 24 June 2017 System Manual 85 When a user program is executing and an interrupt occurs, your OS must save the thread's context (pc and genpur values) so that it can be restored when the thread is next selected for execution. Also, when a system process blocks, your OS must save its context so that it can be restored when the system process is next executed. In this case, your OS did not do this for thread xxxx. 23. Bad CRC16 value, was xxxx should be yyyy for host zzzz The crc16 field of an IP header for an output message is not correct. Your OS is responsible for calculating the crc16 value for all outgoing messages. The message to host zzzz contained xxxx in the crc16 field; it should have had yyyy 24. Bad sequence number, was xxxx should be yyyy for host zzzz The sequence number of every outgoing message should match the sequence number of the incoming message that it is a response to. The last incoming message from host zzzz had sequence number yyyy; the last outgoing message had sequence number xxxx. 25. Client skipped authentication: subnet xxxx host yyyy The client on subnet xxxx, host yyyy tried to use the server without properly starting a session; i.e., did not begin by sending a SYN message. 26. Invalid printer action = not B or P or E The printer can only receive data into its buffer (B), print the contents of the buffer (P), or eject a page (E); some other character was found in the action register. The action must be in uppercase. 27. Invalid data size for printer: xxxx The specified data size (xxxx) is too large; the printer buffer can hold only 8192 bytes. 28. Invalid printer buffer address: xxxx The printer buffer address (place where data is to be transferred to) must be a multiple of 2048; instead, it was xxxx 29. Pagemap[0] invalid for system process: xxxx Every system process should have pagemap[0] set to valid==1, resident==1, and Jeeves 24 June 2017 System Manual 86 pageframe==90+processid In this case, process xxxx does not have that. 30. Invalid opcode at address xxxx thread yyyy The user program instruction found at address xxxx for thread yyyy is not one of the recognized operations. Almost certainly, the pagemap for yyyy is corrupted or R.process.pgmioaddr is invalid. 31. Invalid pagemap entry; address: xxxx thread yyyy A reference was made to address xxxx by thread yyyy; however, the pagemap is not set up to allow such a reference. Below is a sample of what an error message would look like when it appears on the screen. This error message is indicating that the disk is busy at the time (567332) your OS is attempting to issue a StartAct on it. 567332 *** Error code 5 *** Device not ready; device: 16 status: 1 Tools In addition to the simulator program, several program tools are available to help you test and refine your OS. These tools let you custom design a script so that you can test some situation without the distraction that may be created by other client or device actions that are part of one of the official scripts. In this section, these tools are described. scripter scripter is a program that lets you create a script file in whatever way you want. If you want to have a script that has one or more clients log in and do some specific command(s) Jeeves 24 June 2017 System Manual 87 and nothing else, you can make such a script with this program. Execute the scripter program and answer the questions it asks to make the script. The overall design of scripter is such that you are expected to enter the messages from one client's session at once; however, the program is flexible enough to allow you to break the session into pieces if you want to. As you enter commands, be aware of the clock times so that you space the commands out in a realistic way and so that you do not create a typeahead situation or a jumbled command. You can have the session involve any IP address, even Jeeves own if you choose to have the input come from the console. In addition, you can create special events in a script (enabling or disabling printers or generating SYN messages that are really destined for some server other than Jeeves). The following discussion is about each of the prompts that scripter displays; these are shown in the approximate order they would appear when you execute the program. Enter script file name: Here respond with a file name. If the file already exists, scripter assumes you want to append more sessions or events to it; if the file does not exist, scripter starts to create a new script file. Suggestion: use a .scr extension for the name of script files; it makes them easy to recognize. Session (Telnet, FTP, Keyboard, Printer, Bogus or Quit): Here specify what category of events you want to create by entering the first letter of each of the key words. T to create or add to a Telnet session; F to create or add to an FTP session, K to create commands from the keyboard (console), P to enable or disable a printer, B to create messages that should go to some server other than Jeeves, and Q to terminate the program. T and F are handled in much the same way; consider what happens when you enter either of these; you see Enter IP address as four dot-separated numbers: Jeeves 24 June 2017 System Manual 88 Enter some IP address. It may be any valid address, except for Jeeves own address. Do not put spaces in the address. Sample: 144.80.128.7 Message type (SYN, PSH, FIN or Quit): You are responsible for making sure the messages constitute a valid session - begin with one SYN, followed by one or more PSHes, and end with a PSH containing a logout or quit command or a FIN. Enter just the first letter of whatever message type you want (S, P, F, or Q). If you enter S, you see Arrival time: Enter the time (in ticks) when you want the SYN message to arrive. Remember, there are 100,000 ticks per second. Do not choose a time before 200000 so that the OS has time to do whatever it wants in setting up its database. After you enter the time, you are prompted again for a message type. This time enter P and see Arrival time: again. This time you are being asked for the time of the first message with command content. Choose some time after the SYN. scripter then assumes that you will want to enter multiple PSH messages and so does not go back to asking for a message type or arrival time. Instead, you are repeatedly prompted with Text (command) to send: Enter a command that is to go to the server. If this is the first command line, you should enter a username (the server always asks the client to log in before doing any Jeeves 24 June 2017 System Manual 89 of his/her commands). When the prompt appears a second time, enter the client's password. Then at subsequent prompts, enter valid Telnet or FTP commands (depending on what type of session you specified). Usually, the last command you enter is logout (Telnet) or quit (FTP). When prompted after the last command, just press enter alone. For each of the entered messages, scripter is calculating arrival times for them based on what you entered for the first arrival time. When you press enter alone, scripter tells you how far the time reached with a display: Last time reached: xxxxxx It then prompts again for a message type. You may at that point chose P and enter more commands (it asks for a new arrival time). If you choose FIN or Quit, scripter prompts with Enter new IP address (0.0.0.0 to end): You may enter commands for a second session by specifying the IP address of another client or enter 0.0.0.0 if you don't have any more sessions to add. Any IP address other than 0.0.0.0 leads to the message type prompt again (where you should begin with a SYN, as before). Entering 0.0.0.0 causes the session prompt to be displayed again. There is one special situation for FTP sessions; it occurs when the "put" command is used. The "put" command is used by a client to transfer a copy of a file from the client's machine to Jeeves. After this command is entered, the next entry at the Text prompt should specify the file to be transfered, the form is @filespecification filesize This is not a prompt, you must enter this information to tell scripter what file to use as the source for the transfer (this is a real file in your current directory); the filesize is the number of bytes to send. scripter takes the first filesize bytes, packages them into messages of no more than 512 bytes and puts the messages into the script. scripter takes this special action only when the Jeeves 24 June 2017 System Manual 90 command line begins with an @. Whenever you see the "Session" prompt, you may choose any session type so that a single script file can contain any combination of session types. If you choose the K (keyboard) session type, the following prompt appears Command (Enter only to end): Enter a Telnet command (or user ID or password). The first time this prompt appears, you should enter a user name to begin the authentication process. scripter responds by displaying the prompt Start time: Unlike remote Telnet and FTP sessions in which scripter determines the timing of subsequent messages, for the console, you must specify the time for each command line. scripter does assign times to each keystroke that is part of the command. After you specify the time, scripter displays a message such as, Command ends at xxxxxx before prompting for the next command. It does this so you know how far the clock advanced by entering the previous command. When you just press enter at the command prompt, scripter again prompts for the session type. If you choose P for printer, scripter displays the prompt Disable or Enable: Enter a D or E to specify the printer action. scripter then asks for a time Jeeves 24 June 2017 System Manual 91 At what time: Enter the time you want the enable or disable to occur. The session type prompt is then redisplayed. If you choose B for bogus at the session type prompt, scripter prompts with Number of messages: Enter the number of bogus messages that you want scripter to generate. These are SYN messages (no PSH, FIN, or ACK bogus messages are generated) that are coming from some random IP address and are destined to be delivered to another server on the same subnet as Jeeves. messages is not 144.201.193.179 So, the destination IP address in these Such messages are coming to Jeeves' Comm Interface because Jeeves is on a bus network with these other servers. scripter then asks for a Starting time: Enter the time that you want the first bogus message to arrive. scripter also prompts for the approximate time between bogus messages with Rough separation: Again, enter a time of separation between bogus messages. The bogus messages are not exactly separated by this amount; scripter adjusts the true separation. When you choose Q (Quit) at the session type prompt, scripter terminates, writing the script file with the specifications you have given. As indicated at the beginning, you may Jeeves 24 June 2017 System Manual 92 choose to add more sessions or events to a script file later. Unfortunately, there is no tool available to delete or change the contents of events in a script file. So, if you make a mistake in creating the file, you have to start over. Script files are binary and cannot be edited easily. Below is a sample script creation using scripter. The script being made is meant to test the FTP command "put"; the elements in bold are what was typed in. The script has wlewis logging in, giving a put command to transfer 3500 bytes of the sampler.txt file to Jeeves and store it there as the file jumbled.mess in the wlewis directory. wlewis then verifies the transfer by using a dir command. Enter script file name: put.scr put.scr is a brand new script file. Session (Telnet, FTP, Keyboard, Printer, Bogus or Quit): f Enter IP as four dot-separated numbers: 12.34.56.78 Message type (SYN, PSH, FIN or Quit): s Arrival time: 222000 Message type (SYN, PSH, FIN or Quit): p Arrival time: 333000 Text (command) to send: wlewis Text (command) to send: thursday Text (command) to send: put ./jumbled.mess Text (command) to send: @sampler.txt 3500 Text (command) to send: dir . Text (command) to send: quit Text (command) to send: Last time reached: 733660 Message type (SYN, PSH, FIN or Quit): q Enter new IP address (0.0.0.0 to end): 0.0.0.0 Session (Telnet, FTP, Keyboard, Printer, Bogus or Quit): q There are two programs available to view the contents of a script file. Both are useful; one shows a summary of the events in the script - each event is shown on one line; the other shows the complete details of each event. Having these programs means that you do not have to keep a record of what each script file contains after you make it. Jeeves 24 June 2017 System Manual 93 displayscript displayscript displays a summary of the events in a script file. Every event is shown on a single line in the order that they are stored in the file. Note that every event in the file has an associated time and that the file need not be in chronological order. When the simulator reads the script file, it will put the events in chronological order, regardless of the order in which they are in the script file. When you run displayscript, it prompts only for the script file name and then displays the information. Below is an example of what you might see in the display of 1 1 3 200000 F 3 300000 F 3 386641 F 3 445121 F 3 523910 F 3 607856 F 3 430201 T 3 210005 T 3 320005 T 3 370289 T 3 428214 T 3 523260 T 3 601931 T a short script file. 123. 45. 67. 89 123. 45. 67. 89 123. 45. 67. 89 123. 45. 67. 89 123. 45. 67. 89 123. 45. 67. 89 66.247. 7.135 24. 43.159.183 24. 43.159.183 24. 43.159.183 24. 43.159.183 24. 43.159.183 24. 43.159.183 1: SYN 2: wlewis 3: thursday 4: get ./tiny.one 5: dir library 6: quit To 144.201.193.140 1: SYN 2: jwolfe 3: wednesday 4: list library 5: now 6: logout 1: SYN The first line shows the Boot_Done interrupt. scripter always puts this event in every script at time 1. The format of each line is this: Interrupt/Trap code (mostly 3 for Device_In), time of interrupt, service (F for FTP, T for Telnet), IP address of the client, sequence number of the message, and the message itself. The one exception is the bogus message in the middle; for it, the destination IP address is also shown. The script contains two valid sessions; the first is an FTP session; the second is a Telnet session. If the FTP session had contained a put command, the display would show parts of each of the message fragments for the file being transferred. Each of these sessions contains only a couple of commands. Bogus messages are always SYN messages. Notice that the times of the sessions completely overlap. Jeeves 24 June 2017 System Manual 94 analyzescript This program provides a complete analysis of a script file, showing the complete contents of all parts of all messages. The display shows the events in storage order, just as displayscript does. Here is how the first part of the above script is displayed by analyzescript. Code: 1 Device: 0 Time: 1 Size: 0 Code: 3 Device: 20 Time: 200000 Size: 32 IP Header: Version: 4 HdrSize: 5 DataSize: 12 Frag No: 0 Frag Total: 0 Protocol: T To Live: 64 CRC: 5360 Source: 123. 45. 67. 89 Destination: 144.201.193.179 TCP Header: Source Port: 20 Destination Port: 20 Sequence No: 1 Hdr Size: 12 Msg Type: S Application: FP Code: 3 Device: 20 Time: 300000 Size: 39 IP Header: Version: 4 HdrSize: 5 DataSize: 19 Frag No: 0 Frag Total: 0 Protocol: T To Live: 64 CRC: 59317 Source: 123. 45. 67. 89 Destination: 144.201.193.179 TCP Header: Source Port: 20 Destination Port: 20 Sequence No: 2 Hdr Size: 12 Msg Type: P Application: FP Message text: wlewis Notice that this is a great deal more verbose that displayscript. Above are shown only the first three events from the script file. Subsequent FTP and Telnet messages are similar to the second and third messages above. You should be able to match the elements of this display with the components of IP and TCP headers described previously. diskutility With this program you can create a completely new disk for Jeeves to use or modify an existing disk. diskutility has the ability to add or delete users, add or delete files, and display the contents of the disk in a variety of forms. When you start the program, it prompts with Jeeves 24 June 2017 System Manual Disk's file name: 95 You may enter the name of an existing file that contains a disk image or you may enter a new file name. Assume you enter my.disk If diskutility can find my.disk, it displays: Read existing disk named my.disk If it cannot find the file, diskutility displays the message: Making new disk named my.disk and creates a new disk image. A new disk image contains a complete boot record, bit map, and root directory. The kernel, daemons, and password files are created, as are the library, common, and users directories (although two of these directories are empty). The users directory has the root directory entry in it. There is one pre-defined user, root. Its entry is the only one in the password file. After either retrieving a disk image from a file or constructing one, diskutility prompts with its standard command prompt Command: You are then expected to enter one of the six command categories that it recognizes (Dump, File, User, Write, Help or Quit). You need enter only the first letter of the category (upper or lowercase). Each category is discussed below: Dump Here you may specify one sector of the disk and ask to have it displayed in one of five different forms. The prompts that appear are Surface (0-3): Enter the surface number; surfaces 4 and 5 cannot be specified because they do not contain permanent information - being used for swapping and spooling. Track (0-127): Enter the track number. Sector (0-31): Enter the sector number - remember that disk references are in terms of clusters, so disk locations that you will see in directories will always have the sector number as a multiple of 4. Dump is Jeeves 24 June 2017 System Manual 96 going to show you one sector, not one cluster; all sector numbers 0 to 31 are valid. Interpretation (Hex, Boot, Map, Folder, ASCII): Here you choose what interpretation you want made of the sector. You need enter only the first letter of each form. For "Hex", you get a hexadecimal display of each byte. For "Boot", the sector is interpreted as a Boot record, showing number of surfaces, number of tracks/surface, number of sectors/track, sector size, number of sectors/cluster, and the disk locations of the start of the bit map, root directory, kernel, swapping area, and spooling area. For "Map", the sector is interpreted as a bit map showing the used portions of the bit map (in hexadecimal) and a statement of where the last used cluster is. For "Folder", you get a display of up to four directory entries in a standard form; here is a sample directory entry Filename: my-first-data-file Size (in bytes): 3127 Record count: 30 Access settings: RWRW-File type: D Owner: jwolfe Clusters occupied: (0,6,4) (0,6,8) For "ASCII", you get a display of the sector as characters; however, undisplayable characters are shown as periods. File Here you may create new files or delete files from any folder. You can also see a listing of what files are in a folder and get a display of the contents of a file. The prompts are as follows Folder name: You may enter any valid folder name. File action: Add(A), Delete(D), List(L), Show(S): Choose "Add" to create a new file and put it in the folder. The subsequent Jeeves 24 June 2017 System Manual 97 prompts for Add are: File name: Any valid file name is allowed Who owns this file? This prompt appears only if the folder is library or common. For these folders, any user may be the file's owner. You need to specify a valid user name. Data(D) or Program(P): You may create either a data or program file. diskutility asks for parameters of the file; but it generates the contents. For data files, diskutility prompts with Number of records: Enter a reasonable number. There is no specific limit because the records vary in size; you cannot make a file that occupies more than 48 KB. Smallest size of data record: This is the fewest number of characters that can appear in a record, in addition to the folder, file name, sequence number and record size which are a part of every data record. For program files, diskutility prompts with Number of reads (400 max): Enter how many reads you want the program to make (if it runs successfully). Number of writes (800 max): Enter how many writes you want the program to make (if it runs successfully). Speed (1-10, 1=fastest): Programs can be made to execute at different speeds - 1 is the fastest; programs at speed 10 take about 10 times longer than programs at speed 1 (to do the same number of I/O actions). Have Program Terminate (T) or Abort (A): Enter T to cause the program to end normally or A to cause the program to abort. Jeeves 24 June 2017 System Manual 98 If you choose "Delete" at the File Action prompt, diskutility prompts with File name: Whatever file you specify is deleted. If you choose "List" at the File Action prompt, diskutility displays a basic listing of the files in the folder; perhaps, something like this. File Name simple.one problem another mixup.txt list.h P O W Bytes RWRW-- 3715 RWRW-- 2280 RWRW-- 24607 RWRW-- 3672 RWRW-- 7632 Recs 50 570 302 47 7632 Type D P D D T Owner wlewis wlewis wlewis wlewis wlewis If you choose "Show" at the File Action prompt, diskutility prompts with File name: Whatever file you specify is displayed. diskutility examines the file type and handles the adjustment necessary to display data files, program files or transfer files. Folder files cannot be displayed with Show; also, you should not attempt to use Show on the password, kernel, or daemons files. User Here you may create new users, delete existing users, or list the password information about the users. Note, that deletion of a user implies deletion of all files of that user; diskutility handles this automatically. Also, this category contains the only command that you can use which shows the decrypted passwords of the users on the disk. The prompts for this category are Add (A), Delete (D), List (L) Users: Enter the letter which indicates the action you want to perform. If you choose "Add", diskutility prompts with New User Name: Enter the username (8 characters maximum). Jeeves 24 June 2017 System Manual 99 xxxxx's password (no white space): The xxxxx is the user name you specified. The password must be at least 6 characters long. User ID number: Enter a unique ID number (a value greater than 1000). If you choose "Delete" at the User Action prompt, diskutility prompts with User to delete: Whatever username you enter causes that user to be removed totally from the disk. All the user's files are deleted, the user's entry in the users directory is removed and the user's entry in the password file is removed. If you choose "List" at the User action prompt, diskutility displays a table like the following one UID 1020 1035 1121 Write User nhorvath jwolfe wlewis Encrypted Password yZNrzhp4mBk95Rk9b zQd2aDMD9ks.T8t9M otc0QDYLGA69O9t92 Decrypted tuesday wednesday thursday This choice is used to write the changed or created disk image to a file. When you choose this category, diskutility prompts with New Disk file name (Enter only to write xxxxxxx): The xxxxxxx is the name of the file you specified when you started to execute diskutility. If you simply press enter, the xxxxxxx file is written. If you enter some other name, that file is written. In this way, you can create one disk image from another one and still have the original or update the original. diskutility then displays Disk yyyyyyy written + internal update done. Where yyyyyyy is the name of the file actually written (whether it is the original or a new file). Note that the message says "internal update Jeeves 24 June 2017 System Manual 100 done". diskutility does NOT immediately update everything internally as you do add and delete commands; only after you Write are some updates made. diskutility does not terminate upon writing the file; you can still give more commands. Help This displays a brief explanation of each of the command categories and what they are about. Quit This terminates the program. Because termination is independent of writing the disk image, you can make test changes to a disk image and then quit, without ever writing it to a file. File Summary The following files are significant in conjunction with the COSC 432 project. Some of the files are provided to you in the /usr2/fac/jlwolfe/jeeves directory. Some are created when the simulator executes. One is to be created by you, if you want to execute in a controlled way. Files that are in bold are binary; do not try to display or print them. Files in normal font are text files; they may be examined or printed or edited, as you wish. Principal Files answer.* A collection of files from a simulator execution, including the script and all output files produced by the simulator. The script has one client try all Telnet commands. The script is binary; the other answer files are text. analyzescript Exec. Shows the details of all events in a script file. basics.h Inc. Contains struct definitions for all registers, tracers, memory, and Jeeves 24 June 2017 System Manual 101 all message components captured.ip Produced by the simulator, contains a record of all activity at an IP address (or all IP addresses) during a simulation. diskutility Exec. Displays or changes information in a disk file. displayscript Exec. Shows basic information about each event of a script. example.cc Pgm. A sample program to show how the simulator can be used to access information on the disk and send messages to an IP address. execution.log Produced by the simulator, contains a record of the program input and output of all user process threads. jeeves.log Produced by the simulator, contains a record of all transfer activity during a simulation. jeeves.o Link The object file containing the code for the simulator, the encrypt function, and the CRC function. jeeves.report Produced by the simulator, contains a summary of device actions, client actions, interrupts, privileged instructions, system process use and disk changes. minisave Cmd printer.log Command file for renaming simple simulator produced files. Produced by the simulator, contains all data actually printed on the printer, with ejection markers separating files. saveit Cmd Command file for renaming all simulator produced files. scripter Exec. Provides a way to create a script containing any combination of client actions. skeleton.cc Pgm. A sample operating system that does almost nothing. str.h Inc. Contains struct, union, and typedef definitions for all file system and disk structures. stringin.cc Pgm. A sample program to illustrate the use of istrstream for input from a c-string. Jeeves 24 June 2017 System Manual thedisk thedisk.final 102 The file containing the disk information - read by the simulator. A file containing the disk information after a simulation has terminated. trace.setup A data file read by the simulator to specify trace variable values. *.scr A collection of script files. A more detailed explanation of each script file is contained in another table. Files that are labeled "Exec." above are executable; and those labeled "Cmd" above are command files; both of these groups should be copied to your own ./bin directory. This directory is in your path by default so you can then execute these programs and command files by simply typing their names at the bash prompt. Files that are labeled "Inc." should be copied to the directory which you are using to work on this project. These files should then be included in your OS source code, preferably near the beginning. Files that are labeled "Pgm." are C++ programs - two of them (example.cc and skeleton.cc) are pseudo operating systems which can be compiled and linked with jeeves.o to make a complete program. Scripts Below is a brief description of the script files that are provided for your testing of your OS. Additional script files may be provided later. hello.scr One Telnet client login and logout only comm1.scr One Telnet client tries now, list, users, and show; one FTP client tries dir and get; the clients act consecutively. comm2.scr One Telnet client on the console followed by an invalid login and one FTP client; commands are similar to comm1.scr comm3.scr Two Telnet clients enter commands simultaneously; there are a few illegal commands; there are messages meant for other servers comm4.scr Several clients log in, three on different IP addresses simultaneously; Jeeves 24 June 2017 System Manual 103 one IP address is used consecutively by clients; there are messages meant for other servers; there are illegal commands; three clients access the one file at the same time; mixture of FTP and Telnet. accesses.scr Several access commands with list commands to verify them. copies.scr Several copy commands with list commands to verify them. deletes.scr Several delete commands with list commands to verify them. adds.scr Several add commands with users and list commands to verify them. removes.scr Several remove commands with users and list commands. done1.scr A selection of access, copy, and delete commands. done2.scr A selection of root operations: add, remove, root-only access. done3.scr A selection of mostly put and print commands, with printer status changes. done4.scr A selection of mostly run commands and tests of them. done5.scr Everything I can think of. now.scr Single now command list.scr Single list command dir.scr Single dir command users.scr Single users command get.scr Single get command show.scr Single show command access.scr Access command followed by a list to see the effect. copy.scr Copy command followed by a list to see the effect. delete.scr Delete command followed by list to see the effect. add.scr Add command followed by users and list to see the effect. remove.scr Remove followed by users and list to see the effect. put.scr print.scr run.scr Put command followed by dir to see the effect. Single print command Run command followed by list to see the effect. Jeeves 24 June 2017 System Manual 104 Programs Below are listings of several of the program files that are provided to you. They are included here so that you will have a convenient reference to their contents. basic.h Definitions for all registers, tracers, memory, and message components struct pmentry { unsigned char unsigned char unsigned short }; struct classBaddr { unsigned char unsigned char unsigned char }; union ipn { long classBaddr }; struct pregs { long long long classBaddr pmentry long long }; struct ioregs { long long long long long unsigned char // Page Map Entry Form resident; valid; pageframe; // Indicates if page is in memory // Indicates if page is part of program // Page Frame number // Class B IP Address Form netid[2]; subnet; host; // Network ID in two parts // Subnet number (mask is 255.255.255.0) // Host number // Union to allow dissection of an IP addr whole; ipv4; // Treat as a single value // Treat as a class B address for Version 4 // Process Control Registers userid; processid; thread; ipaddr; pagemap[16]; pgmioaddr; pgmiosize; // // // // // // // User Identification number Process ID number Thread number - unique IP responsible for process Page map for process Virtual address of program I/O Size of program I/O data // Input/Output Control Registers address; datasize; packetin; mousein; keyin; surface; // // // // // // Physical address of memory involved Number of bytes to transfer Physical address of where to put packet Physical address of where to put mouse info Physical address of where to put character Disk Surface number Jeeves 24 June 2017 System Manual unsigned char unsigned char char long 105 track; sector; action; // // // // bufferaddr; // Disk Track number Disk Sector number R to read, W to write, S to seek, B to send to buffer, P to print, E to eject Buffer address for printer }; struct registers { long long long long long long long long ioregs pregs }; // Registers for Jeeves clock; timer; icode; device; state; pc; genpur[8]; oserror; io; process; struct tracers { int icode; int instruction; int sysproc; int transfer; ipn ipaddr; int start; int finish; int diskdump; int memorydump; }; typedef char struct tcpheader { short short long char char char // // // // // // // // // // Clock - ticks each 10 microseconds Alarm clock - settable Interrupt/Trap code number Device number for interrupts & commands Device status Program counter General purpose registers OS Error code number I/O register group Process control register group // Tracer values // // // // // // // // // Interrupt/Trap(s) to trace Privileged Instruction(s) to trace System process to trace Data transfer category(ies) to trace IP to trace Clock time to start trace Clock time to end trace Dump part of disk indicator Dump part of memory indicator memory[128*1024]; // Jeeves' memory form // Simplified TCP message header srcport; destport; sequence; hlength; msgtype; appl[2]; // // // // // // // Source port number Destination port number Message sequence number, unique Header size (in bytes) (always 12) Message type: S (syn), P (psh), A (ack), F (fin) Application code: TN (telnet), FP (FTP) }; struct ipheader { char char short short char char // Simplified IP message header version; hlength; dlength; fragment; ftotal; protocol; // // // // // // Version number (always 4) Header size (in 32-bit units) (always 5) Data size - bytes in TCP header + data Fragment number - for large messages Total number of fragments, usually 0 Protocol (always T - for TCP) Jeeves 24 June 2017 System Manual 106 short unsigned short classBaddr classBaddr timetolive; crc16; source; dest; // // // // Time to live (always 64) 16-bit cyclic redundancy check value IP of message source IP of message destination }; struct message { ipheader tcpheader char }; str.h // Interface message form ip; tcp; data[512]; // IP header (20 bytes) // TCP header (12 bytes) // Data (content) of message Contains struct, union, and typedef definitions for all file system and disk structures typedef char typedef char fname[28]; id[9]; struct diskloc { unsigned char unsigned char unsigned char }; // Data type for a file name // Data type for a user name // Disk Location surface; track; sector; struct { char accesspair char wrtdel; rdexe; // Surface number (0-5) // Track number (0-127) // Sector number (0-31) // Access control spec // // // // R E W C (read, list, execute), (execute only), - (none) (update, append, create, delete) (create only), - (none) }; struct direntform // Directory entry form { fname filename; // File name long filesize; // Size in bytes long recordcount; // Size in records accesspair access[3]; // Access control specs for // System, Owner, and World, in order char kind; // Type of file (F, D, P or T) id owner; // Name of user who owns file char slack[4]; // First character is * diskloc diskref[24]; // Disk locations for clusters }; typedef char struct { char long long map[6][128]; bootform // Data type for bit map // Boot record form jump[12]; surfaces; tracks; // Fake instruction to boot // Number of surfaces on disk // Number of tracks / surface Jeeves 24 June 2017 System Manual 107 long long long diskloc diskloc diskloc diskloc sectors; sectorSize; clusterSize; accounting; rootdir; theOS; spooling[2]; diskloc swapping[2]; char bootstrap[1992]; // // // // // // // // // // // Number of sectors / track Number of bytes / sector Number of sectors / cluster Disk location of bit map Disk location of root directory Disk location of kernel Starting and ending disk locations of spooling area Starting and ending disk location of swapping area Fake bootstrap program }; struct diskuse { map bitmap; diskloc lastcluster; char slack[1277]; }; // Layout of cluster with bit map struct { long id char }; // Data type of a password file record // The bit map itself // Disk location of last used cluster // Junk - wasted space secret uid; username; encrypted[19]; struct instr { char unsigned char unsigned short }; // User Identification Number // User name // Encrypted password // User program instruction layout opcode; elapse; virtaddr; // Operation to perform // How long the operation takes // Virtual memory address that // the instruction references union clusterform // Multiple forms a cluster can take { bootform home; // Boot record form diskuse themap; // Bit map form direntform dentry[16]; // Directory form secret usafe[64]; // Password file form instr pgm[512]; // Program form char data[2048]; // Plain group of bytes }; typedef clusterform typedef atrack skeleton.cc atrack[8]; asurface[128]; // Data type for a disk track // Data type for a disk surface Minimal program that behaves enough like an operating system to run the simulator, without generating errors. Ignores all interrupts (except for clearing them) and terminates at Power_Down #include <iostream> Jeeves 24 June 2017 System Manual 108 #include <string> using namespace std; #include <queue> #include "basics.h" #include "str.h" // STL queue // Structs, types, union for regs and comm // Structs, unions, types for disk extern registers extern tracers extern memory R; T; M; void void void void void void void void Halt(); Wait(); Block(); RunSys(); RunUser(); GetStatus(); StartIO(); Clear(); // Jeeves' Registers // Trace variables // Jeeves Memory // Privileged instructions void BootStrap(); void encrypt (char [], char []); unsigned short CRC (ipheader &); void void void void void void DiskScheduler (); ProtocolHandler (); Login (); Shell (); Unspooler (); Transmitter (); // To start the simulator // To encrypt passwords // For cyclic redundancy checks // System processes // Put your Global structs and variables here or use an include int main () { BootStrap(); } void OpSys() { if (R.icode == 3) Clear(); else if (R.icode == 2) Halt(); Wait(); } // Only statement allowed in main // Entry to the Operating System // Clear input interrupts // Terminate on Power_Down // Wait for everything to happen void DiskScheduler (void) { } // stub void ProtocolHandler (void) { } // stub void Login (void) { } // stub Jeeves 24 June 2017 System Manual 109 void Shell (void) { } void Unspooler (void) { } // stub void Transmitter (void) { } // stub example.cc // stub A program to extract file information from any disk. The directory structure display that it produces is sent to IP address 12.34.56.78 Because communication with any IP address is expected to be initiated from that IP address; the simulator reports the following error when example is executed. The program is still allowed to continue. Note: This program assumes a simple directory (having fewer than 17 entries) for every directory. 2372 *** Error Code 25 *** Client skipped authentication: subnet 56 host 78 // This program is not an operating system. It's purpose it to extract // directory and file information from the disk. It displays this info // in each directory level by level, with labels. The program contains // its own interrupt handling and message generating functions; it interacts // with the simulator in ways similar to an operating system. The program // sends output to IP address 12.34.56.78; trace this IP address to see it #include <iostream> #include <iomanip> #include <strstream> using namespace std; #include <queue> #include "basics.h" #include "str.h" extern registers extern tracers extern memory void Halt(); // STL queue // Structs, types, union for regs and comm // Structs, unions, types for disk R; T; M; // Jeeves' Registers // Trace variables // Jeeves Memory // Privileged instructions Jeeves 24 June 2017 System Manual void void void void void void void 110 Wait(); Block(); RunSys(); RunUser(); GetStatus(); StartAct(); Clear(); void BootStrap(); void encrypt (char [], char []); unsigned short CRC (ipheader &); // To start the simulator // To encrypt passwords // For cyclic redundancy checks void void void void void void // System processes DiskScheduler (); ProtocolHandler (); Login (); Shell (); Unspooler (); Transmitter (); // Global structs and variables struct tcbform { pregs long long }; struct diskreq { unsigned char unsigned char unsigned char char long int char int }; struct packet { int start; int size; }; // Each thread has a tcbform regs; pc; genpur[8]; // Process registers for the thread // Program counter value when stopped // General purpose registers when stopped // Entry for disk queue surface; track; sector; action; addr; category; level[9]; count; // // // // // // // // surface number track number sector number action to take (R, W, S) memory address type of request directory name number of entries in directory // Output packet info // Where it begins in memory // how many bytes it is union combine // Union to assemble and dissemble a message { message detail; // Standard message form char text[544]; // Overlay with characters }; queue<diskreq> queue<tcbform> queue<packet> diskq; readyq; messageq; // Queue of disk requests // Queue of ready threads // Queue of outgoing packets Jeeves 24 June 2017 System Manual 111 int int int int outBuffer = 10240; bufferPtr = 0; interfaceState = 0; runningThread = 0; // // // // const const const const int int int int // Categories for disk actions tcbform tcbform BOOTREAD = 1; ROOTREAD = 2; DIRREAD = 3; USERREAD = 4; Base address for packets Offset into packet storage Interface state: 0 free, 1 busy Number of thread that is running // Templates for disk scheduler and transmitter threads dsched = {{999, 1, 100, {144,201,193,179}, {{1,1,91}, 0}, 0}, 0, {0}}; // DiskScheduler transmit = {{999, 6, 100, {144,201,193,179}, {{1,1,96}, 0}, 0}, 0, {0}}; // Transmitter void DiskDriver (void); void InterfaceOut (void); void BlockThread (void); int main () { BootStrap(); } // Responds to disk interrupts // Responds to comm output interrupts // Responds to block traps // Standard main program // All that is allowed in main // Place a request in the disk queue void DiskRequest (int surf, int trk, int sect, // surface, track, sector char act, // Action R read, W write, S seek int place, // Memory address to read/write int cat, // Category for DiskDriver action char level[], // Name on higher level directory int count) // # Entries in directory { diskreq starter; // A queue entry starter.surface = surf; starter.track = trk; // Fill queue entry and enqueue it starter.sector = sect; starter.action = act; starter.addr = place; starter.category = cat; strcpy(starter.level, level); starter.count = count; diskq.push(starter); } // Operating System entry point void OpSys() { tcbform chosen; // Used in CPU scheduling int j; // Loop index Jeeves 24 June 2017 System Manual 112 if (runningThread > 0) // If a thread was running, { // save the context elements readyq.front().pc = R.pc; for (j = 0; j < 8; j++) readyq.front().genpur[j] = R.genpur[j]; } runningThread = 0; // Indicate no thread is running switch (R.icode) // Respond to interrupt or trap { case 1: // Boot_Done DiskRequest (0,0,0,'R',4096,BOOTREAD," ",0); // Request boot record dsched.pc = transmit.pc = R.pc = 0; // Initialize contexts for (j = 0; j < 8; j++) // of DiskSched & Trans dsched.genpur[j] = transmit.genpur[j] = R.genpur[j] = 0; readyq.push(dsched); break; case 2: // Power_Down Halt(); break; case 3: // Device_In if (R.device == 20 || R.device == 9) // Ignore keyboard & comm in Clear(); else if (R.device == 19) // Respond only to disk DiskDriver(); break; case 4: // Device_Out if (R.device == 20) // Respond only to comm out InterfaceOut(); break; case 8: // Block_Self BlockThread(); // Block the thread break; } if (!readyq.empty()) // If threads ready, schedule one { chosen = readyq.front(); // Get first thread in queue R.process = chosen.regs; // Restore context R.pc = chosen.pc; for (j = 0; j < 8; j++) R.genpur[j] = chosen.genpur[j]; runningThread = R.process.thread; // Note which thread this is RunSys(); // Start it executing } else Wait(); // If nothing is ready, wait } // Save the contest of the thread at front of the queue // Then, remove it from the ready queue void BlockThread (void) { if (readyq.front().regs.processid == 1) dsched = readyq.front(); // Is it the DiskScheduler? Jeeves 24 June 2017 System Manual 113 else transmit = readyq.front(); readyq.pop(); // Remove thread from readyq } // Disk scheduler system process void DiskScheduler (void) { diskreq front; // Request at front of queue R.device = 19; // Set device and make sure it is ready do { GetStatus(); } while (R.state == 7); front = diskq.front(); // Get request info into registers R.io.surface = front.surface; R.io.track = front.track; R.io.sector = front.sector; R.io.action = front.action; R.io.address = front.addr; R.io.datasize = 2048; StartAct(); // Initiate disk operation Block(); // Ask to be blocked } // The other system processes must be defined, although they are // not needed in this program void ProtocolHandler (void) { } // stub void Login (void) { } // stub void Shell (void) { } // stub void Unspooler (void) { } // stub // Transmit packets system process void Transmitter (void) { packet front; // Output packet queue entry front = messageq.front(); // Get next output packet queue entry R.device = 20; // Make sure comm out is ready do { GetStatus(); } while (R.state == 7); R.io.address = front.start; // Set up registers Jeeves 24 June 2017 System Manual 114 R.io.datasize = front.size; StartAct(); interfaceState = 1; Block(); // Initiate output // Mark Comm Interface busy // Block transmitter } // Build a packet for output // Most elements of the message are fixed by the nature of the program // and are initialized when tosend is declared void MakeMessage (char text[]) // text is packet content { message tosend = { {4, 5, 0, 0, 0,'T', 64, 0, {144,201,193,179}, {12,34,56,78}}, {23, 23, 1, 12, 'A', 'T', 'N'}, 0}; // This initializes the message as follows: IP header // version=4, hlength=5, dlength=fragment=ftotal=0, protocol=T // timetolive=64, crc16=0, source=144.201.193.179, // dest=12.34.56.78, TCP header - srcport=destport=23, sequence=1, // hlength=12, msgtype=A, appl=TN int combine packet j; lump; msgref; // Loop index // Union for assembly of message // Outgoing packet for queue strcpy(tosend.data, text); tosend.ip.dlength = 13 + strlen(text); tosend.ip.crc16 = CRC (tosend.ip); lump.detail = tosend; for (j = 0; j < tosend.ip.dlength+20; j++) M[outBuffer+bufferPtr+j] = lump.text[j]; msgref.start = outBuffer + bufferPtr; msgref.size = tosend.ip.dlength + 20; bufferPtr += msgref.size; messageq.push(msgref); if (interfaceState == 0) readyq.push(transmit); // Put data in message // Compute length // Calculate CRC // Put msg in memory // Fill out msg queue entry // Adjust for next message // Enqueue the request // If Comm Interface is ready // awaken Transmitter } // Collect directory entry information into a message void FormLines (char text[], // Message being formed clusterform & chunk, // Just read cluster int count, // Number of directory entries char lead[]) // Padding to indent { char holding[500] = { 0 }; ostrstream internal(holding,500,ios::app); // Internal stream int j; for (j = 0; j < count; j++) // Append info from each dir ent { internal << lead << chunk.dentry[j].kind << setw(6) << chunk.dentry[j].recordcount << " " << chunk.dentry[j].filename << endl; Jeeves 24 June 2017 System Manual } internal << ends; strcat (text, holding); 115 // Attach a null // Add to message header } // Respond to disk interrupts void DiskDriver (void) { int j; diskreq front; clusterform chunk; int limit; int rootrecords; diskloc position; char text[512]; diskloc rootloc; front = diskq.front(); diskq.pop(); // // // // // // // // Loop index Copy of disk request Used for dissecting clusters Loop control for processing dir ents Number of entries in root directory First disk reference for each entry Area in which to form a message Disk reference for root directory // Get queue front // Discard queue entry switch (front.category) // Processing based on reason for request { case BOOTREAD: // Read of Boot record for (j = 0; j < 2048; j++) chunk.data[j] = M[front.addr+j]; rootloc = chunk.home.rootdir; // Get root dir location // Request read of root directory DiskRequest (rootloc.surface, rootloc.track, rootloc.sector, 'R',4096,ROOTREAD," ",0); break; case ROOTREAD: // Read of root directory for (j = 0; j < 2048; j++) chunk.data[j] = M[front.addr+j]; rootrecords = chunk.dentry[0].recordcount; // Get # root entries // from 1st cluster strcpy (text, "Entries in root\n"); // Start first msg for (j = 1; j < rootrecords; j++) { if (chunk.dentry[j].kind == 'F') // If entry is a folder { // read its 1st cluster position = chunk.dentry[j].diskref[0]; DiskRequest (position.surface, position.track, position.sector, 'R',4096, DIRREAD, chunk.dentry[j].filename, chunk.dentry[j].recordcount); } } FormLines (text, chunk, rootrecords, " "); // Add dir ents MakeMessage (text); // Put message in queue break; case DIRREAD: for (j = 0; j < 2048; j++) chunk.data[j] = M[front.addr+j]; // Read in a directory Jeeves 24 June 2017 System Manual 116 strcpy strcat strcat for (j { (text, " Entries in top-level directory "); // Start msg (text, front.level); (text, "\n"); = 0; j < front.count; j++) // If entry is a folder and the folder has some files, // request a read of first cluster if (chunk.dentry[j].kind == 'F' && chunk.dentry[j].recordcount > 0) { position = chunk.dentry[j].diskref[0]; // 1st cluster only DiskRequest (position.surface, position.track, position.sector, 'R',4096, USERREAD, chunk.dentry[j].filename, chunk.dentry[j].recordcount); } } FormLines (text, chunk, front.count, " MakeMessage (text); break; "); // Add dir ents // Put message in queue case USERREAD: for (j = 0; j < 2048; j++) // Read a user directory chunk.data[j] = M[front.addr+j]; strcpy (text, " Directory entries for "); // Start msg strcat (text, front.level); strcat (text, "\n"); FormLines (text, chunk, front.count," "); // Add dir ents MakeMessage (text); // Put message in queue break; }; if (!diskq.empty()) // If diskq is not empty, make readyq.push(dsched); // scheduler ready } // Respond to Communication Output interrupts void InterfaceOut (void) { interfaceState = 0; messageq.pop(); if (!messageq.empty()) readyq.push(transmit); else bufferPtr = 0; } // Make Comm output ready // Remove message from queue // If message queue not empty, // awaken Transmitter // Otherwise, reset pointer Using Linux To make use of kodiak somewhat easier, here are a few tips on ways to organize, compile, link, and test your files. There are also some ideas for ways to write your program Jeeves 24 June 2017 System Manual 117 and a mini-introduction to bash, in case you have not used Linux. Compiling, Linking, and Executing If you do not already have a bin subdirectory, you should create one. You can do this with a command such as mkdir bin entered at your top-level directory. By default, ~/bin is in your execution path. Therefore, when you enter a program name at the prompt and a file of that name is in ~/bin, it will execute. The ~ is shorthand for your home directory (for me that is /usr2/fac/jlwolfe ). You can find your home directory by giving the pwd command immediately after logging in. You may make a subdirectory for your source files and other files or just leave them in the top level directory. I put my files in a subdirectory called 432. Every time I log in and want to use this directory, I make it my default directory by entering cd 432 Then, I can proceed to compile, link. etc. as described below To compile a file such as example.cc, I should use the g++ (GNU C++) compiler and give a command like g++ -c -g example.cc This creates an object file named example.o in the default directory. The -g argument is to get the compiler to put vital debugging information into the object file. The -c argument specifies that I want to compile-only, i.e., not link. If I had left the -c out, g++ would have linked also, producing a file named a.out as an executable file in my default directory. Unless told otherwise, g++ always names the executable a.out. To create a more reasonable executable file name and put the executable in an appropriate place, I would use an argument to tell g++ what I want. Jeeves 24 June 2017 System Manual 118 g++ -g -o ~/bin/example example.cc This compiles example.cc (with debugging information and tries to link the object file produced by the compiler and build an executable file named example in the bin subdirectory. The designation of the executable is what follows the -o argument. The ~/bin/example is the path to where I want the executable file built. /example says make the executable file named example. Incidentally, this command does NOT work - example.o must be combined with jeeves.o (the simulator) to create a complete executable. So, giving the command as I am showing it above leads to many linker errors. If I had compiled-only as first illustrated above and then given the command g++ -o ~/bin/example example.o jeeves.o this would have worked. g++ would have looked the two files as object files in the default directory and combined them to form the executable in ~/bin. A more convenient way to compile and link is to take advantage of the make program. This program reads a "make file" specification of everything that goes into compiling and linking and takes care of all the details of determining what files need to be recompiled and linked. The make file contains two types of lines: dependencies which begin at the left margin and specify which files are needed to create a particular "final" file and commands which are indented and specify a compiler or linker action to perform if necessary to make the "final" file up-to-date. Below is a make file that can be used with example.cc to create a proper executable result. /usr2/fac/jlwolfe/bin/example: example.o jeeves.o g++ -o /usr2/fac/jlwolfe/bin/example example.o jeeves.o example.o: example.cc str.h basics.h g++ -c -g example.cc Jeeves 24 June 2017 System Manual 119 The first line says /usr2/fac/jlwolfe/bin/example is dependent on example.o and jeeves.o and that the command to perform if /usr2/fac/jlwolfe/bin/example is older than either of the object files is to link the two files (as specified on the second line). Note here that full path specifications are best in this situation; ~ seems to cause the GNU compiler a problem when used in a make file specification. The third line says example.o is dependent on example.cc, str.h, and basics.h and that the command to perform if example.o is older than any of these other files is to compile example.cc. The other files are included in example.cc If these lines are put in a file called example.mak, then the make program can perform all of the actions described above by processing the dependencies (bottom to top) and produce the finished executable. To use make, give the command make -f example.mak For more information about make, look at the man pages or use info. Programming Tips To avoid having any symbol conflicts, especially when debugging, I recommend that you do not name anything by using an underscore as the last character of the name. All global type names, class names, variable names and function names that the simulator uses end with an underscore character. (Obviously, there are exceptions for those definitions that your operating system and the simulator share: registers, memory, encrypt, etc.) If you avoid using underscores in this way in your operating system, there can never be a conflict over a name. The use of strstream is highly recommended for dealing with internal formatting needs in your program. To interpret client commands, it is convenient to be able to "read" them in Jeeves 24 June 2017 System Manual 120 the way cin would; however, commands arrive in a message packet as a whole string; and your OS must be able to dissect them - strstream can help. To construct outgoing message packets, the data portion needs to be formed in the same way one might use cout to "write"; however, the data portion must be combined with the headers and the whole thing must be sent out as a packet; your OS must build this data portion. strstream allows you to treat strings as a streams so that istream objects like cin can "read from a c-string" and ostream objects like cout can "write to a c-string." There is an example of how to use strstream for output in example.cc (in the FormLines function). The idea is simple. Declare a large character string area and initialize it to null. Then, declare an ostrstream object that can be used to output to the c-string area (the arguments in the declaration are: the char array, the size, and the mode - I used mode app to have each output element appended as the c-string was formed). Then, output using the ostrstream object just as you would any ostream object (including manipulators if you want). The output of ends at the end of the c-string ensures that it ends with null. The result can then be treated like any null-terminated c-string in C++. In FormLines, I concatenated this string with the header to form the complete message. Note: the c-string and ostrstream object are deliberately declared inside the function so that they are created new when the function is entered and destroyed when the function exits. There is no input using strstream in example.cc; but the idea is similar, with one little quirk. The object being declared is an istrstream; however, it takes one or two arguments. Here are two examples istrstream first (stash); stash must be a pre-existing null-terminated string. That is, at the point this declaration appears, stash must already have in it the complete contents that will serve as Jeeves 24 June 2017 System Manual 121 an input stream for first istrstream second (slow, 50); Here slow must be previously declared and capable of holding 50 characters; however, later actions may put the characters in slow, as long as they are in slow before second is used to extract them from the stream istrstream is very useful for parsing. It can be used to extract the components of a command which is held in a c-string. There is a sample program (named stringin.cc) that uses istrstream to parse a Telnet copy command; it is in the /usr2/fac/jlwolfe/jeeves directory. Notes: C-Strings used for istrstream cannot be reused after reading; there is no way to start over at the beginning and read the string again, unless a new istrstream object is created. CStrings used for ostrstream cannot be reused after writing; there is no way to rewrite such cstrings, unless a new ostrstream object is created. Take advantage of the way the STL implements linked lists and queues. Even though pointers are used, there is little chance that the methods for these functions will cause the dreaded "Segmentation Fault" error, if you take the precaution of checking before accessing a structure or using an iterator. I would recommend that when any problem is detected, you program should display an error message and use the "exit" function. This means that if you execute your OS under gdb control with a break point set on exit, when the function is reached, you can enter the backtrace command and locate the error almost immediately. If you do get a segmentation fault, it is always caused by using an array index that is outside the proper range for the array - unless you use some of your own pointers or use some more dangerous implementation of linked lists and queues. When a segmentation fault occurs, it is followed by a core dump - an image of the program at the time of the crash is written to a file, usually named core. This file can be analyzed after the crash by using gdb. You need Jeeves 24 June 2017 System Manual 122 to be aware that the core file will occupy 12.5 to 13 megabytes of disk space; so you probably won't want to keep it around for long. Two auxiliary functions are part of the simulator and are provided for your use. They are encrypt to encrypt passwords and CRC to calculate the 16-bit Cyclic Redundancy Check code. Use of both of the functions is quite easy. encrypt is a void function that takes two arguments; both are null terminated c-strings: the first argument is the clear-text password entered by a client, the second is the encrypted password that the function produces. CRC returns an unsigned short result (the CRC16 value) and takes one argument, a reference to an IP header in which the CRC16 field has been set to zero. There is a use of CRC in the MakeMessage function in example.cc. A Few bash Commands For those of you that have not used Linux or bash (the command language shell), here is a brief description of a few commands that you probably need for the course. In addition to the parameters shown for the commands, many of these commands have arguments that qualify the actions of the command. To see these arguments, use man on the command name. cd [directory] Changes the default directory (the directory whose files you can refer to without qualification). The directory specified may be specified absolutely as a path such as /usr2/student/course/spring2003 or specified relatively as in bin or ./bin or ../bin or it may be omitted to make the users home directory the default. cp sfile dfile Copies the source file (sfile) to the destination file (dfile). Jeeves 24 June 2017 System Manual ls [directory][file] 123 List the files in a directory or that match the file specification. If no directory is specified, the default is assumed. If no file is specified, all files are assumed. The file specification may contain wildcard characters and multiple specifications can be given in the same command, separated by spaces. A common argument to use with this command is -l to get the long (more detailed) listing. mkdir spec Creates a subdirectory in the default directory and names it spec mv sfile dfile Renames the sfile to be dfile pwd Displays what the default directory is at the moment. rm file Deletes (removes) the specified file. Multiple files may be specified, separated by spaces. rmdir directory Deletes the specified directory and all the files in it. chmod code file Sets the access protection of the specified file to the designated code. The code is a 3-digit octal number in which each digit represents a category level and each bit of a digit indicates an access capability. The bit positions are 4: read, 2: write, 1: execute. The categories are owner, group, world. The default protection is 755 (owner has all access, group and world have read and execute). umask code When placed in the .bash_profile file, causes all subsequently created files to have their access protection modified by the code. It is highly Jeeves 24 June 2017 System Manual 124 recommended that you put the command umask 066 in this file because the default access protection gives everyone read access to your files. The umask command will at least eliminate that. cat file Displays the contents of file on the screen. more file Displays the contents of file on the screen, one screen-full at a time. Character command input is required to move through the file. Space moves forward one screen; 'b' moves back one screen; 'q' quits. who Displays a listing of what users are currently logged in. ps Displays system process information. quota Displays how much disk space you have used with your files and how much you are allowed. man program Displays the "man" (manual) pages for the specified program. passwd logout Used to change your password. Terminate the session. Collecting the Stuff to Hand In For the Communications Phase and the Implementation Phase, you are required to hand in printouts and files. kodiak does not have a printer and there are a lot of files to hand in. What can you do? Jeeves 24 June 2017 System Manual 125 First, the printouts of your operating system must meet three requirements: 1. There must be no wrapping of lines. By now, you should have developed the habit of writing reasonable length lines in programs. Lines which wrap around the end are both confusing and ugly. 2. There must be no compiler or linker errors in your programs. I would suggest that you get into the habit of maintaining various versions of your program. emacs helps you with this; whenever you do a save of file xxxx with emacs, it renames the old version xxxx~ before writing the new xxxx file. But you probably need more than this. Build your operating system incrementally. When you get it working up to a point, save that source somewhere and then start adding more features to a copy. This will give you a program that at least compiles and links to fall back on in case you don't get the newer version working by the deadline. 3. The font should not use proportionate spacing and there should be no word processing features used. I recommend printing the file with NotePad or something equally simple. Do not try to put the file in a word processor that lets you manipulate the font or font style or pagination. Although kodiak has no printer, you can still print on any local or network printer that is attached to your computer. There is a script on kodiak called pcprint that is designed to be used in the form pcprint file When executed through Kermit, this command causes file to be printed on whatever printer is associated with LPT1. Unfortunately, the printouts produced by pcprint are in 12-point type and have no page numbers; nevertheless, these printouts could satisfy the three requirements. Jeeves 24 June 2017 System Manual 126 An alternative to pcprint is to use FTP to transfer your files from kodiak to your PC, then load each file into NotePad and print it. This has the advantage of allowing you to select 10-point if you want and to put the file name and page numbers on each page. Make sure you transfer the file in ASCII mode. WARNING: Although it is fine to transfer files from kodiak to the PC for printing, it is not such a good idea to try transfers in the other direction. emacs performs automatic indenting as you write a program; this makes alignment of statements within a loop or decision easy. Wordprocessors, even NotePad, on a PC do not format the source code in the same way. Consequently, if you try to write part of your program on a PC and then transfer it to kodiak for compilation, linking, debugging, many of the lines will be shifted when emacs or gdb is used - and you will almost have to use emacs to make a few small changes, unless you want to go totally crazy using FTP. FTP is also the answer for getting files like captured.ip, jeeves.log, etc. onto a disk for you to hand in. The problem is that the assignments ask you to provide multiple files for each of several scripts; and the scripts always produce files of the same name. Here is how to overcome this problem. Copy the files saveit and minisave from /usr2/fac/jlwolfe/jeeves to your bin directory and change their access to allow execution (chmod 700 saveit). Each of these files is a script that is meant to be run after executing the simulator. The saveit script renames all the files that the simulator outputs to so that you can run the simulator again without wiping out the results of the first execution. Suppose you just executed the simulator using script comm1.scr; then, run the saveit script by entering: saveit comm1 This causes jeeves.log to be renamed comm1.log and jeeves.report to be renamed comm1.report and so on. minisave is almost the same as saveit, except it does not rename Jeeves 24 June 2017 System Manual 127 the printer.log and execution.log files - it makes more sense to use minisave with comm1 because the comm1.scr script does not produce any printing or execution output. Below is a listing of saveit. # Rename the key files after simulator execution # Check if argument (prefix) is missing if [ -z "$1" ]; then echo "No prefix specified" echo "Usage: saveit prefix" else # Rename all simulator output files using the prefix if [ -f captured.ip ]; then mv captured.ip $1.capture fi mv jeeves.log $1.log mv jeeves.report $1.report mv printer.log $1.print mv execution.log $1.exec fi Comment lines start with # The first if tests the command line argument, $1, to be sure it is present. The second if tests to make sure captured.ip exists. This is a simple script but it still contains more complicated features of bash than you should need in the course. Once the output files have been named and the required scripts executed, you can use FTP to transfer the renamed files to a disk and hand it in. C++ Elements It is assumed that you know how to use lists and queues (and other data structures). Jeeves 24 June 2017 System Manual 128 To avoid having you create your own classes to make these objects, you may use the Standard Template Library template classes (in fact, you are encouraged to use them). You can see examples of using the queue template in the example.cc program. To use STL queues, put the line #include <queue> in your program and declare the queues you want, similar to those in example.cc. The principal member functions for STL queues are int size ( ) Returns the number of entries in the queue void pop ( ) Deletes the front entry of a queue void push (DataType &) Adds an entry of DataType to the rear of the queue DataType & front ( ) Returns a reference to the front entry of the queue bool empty ( ) Returns an indication as to whether the queue is empty To use STL lists, put the line #include <list> in your program and declare the lists you want. The list class comes with an embedded iterator class that you may use to access the list entries. The principal member functions for STL lists are int size ( ) Returns the number of entries in the list iterator begin ( ) Returns an iterator to the first entry in the list iterator end ( ) Returns an iterator to a place beyond the last entry of the list iterator insert (iterator & past, DataType &) Inserts a node just before the node pointed to by iterator past and puts in it the data specified. The return value refers to the new node. void erase (iterator) Deletes the node referred to by the iterator bool empty ( ) Returns an indication as to whether the list is empty The principal member functions for the STL list iterators are operator++ ( ) Advances the iterator to the next node Jeeves 24 June 2017 System Manual 129 operator-- ( ) Backs up the iterator to the previous node operator== ( ) To compare iterators for equality operator!= ( ) operator* ( ) To compare iterators for inequality To "dereference" the iterator, get a reference to the data element of a node operator-> ( ) To get a pointer to the data element of a node If you do not want to use the STL template classes, an alternate is provided in the file listque.h This file contains a queue template class, named Queue_, a list template class, named Linked_List_, and a separate list iterator class, named List_Itr_. The use of these classes is not the same as the STL templates; however, they do work; and you may use them if you wish. It is possible that you have not had much experience using c-strings (arrays of char that are null terminated). If you include <string.h> in your program, you will have access to many functions for manipulating c-strings. These are not member functions for a class; they are stand-alone functions that may be applied to any array of char. Below are a brief list of the principal functions; in each of them, the char * arguments are c-strings. int strlen (char *) Returns the length of the c-string (not counting null) char * strcpy (char *d, char * s) Copies the c-string s to the c-string d; returns a pointer to d char * strncpy (char *d, char * s, int n) Copies up to n characters of s to become the c-string at d; returns a pointer to d char * strcat (char *d, char *s) Concatenates the c-string s to the c-string d; returns a pointer to the new d char * strncat (char *d, char *s, int n) Jeeves 24 June 2017 System Manual 130 Concatenates up to n characters of s to d; returns a pointer to the new d int strcmp (char *d, char *s) Returns an integer indication of how d compares to s; if d < s, return is < 0; if d == s, return is 0; if d > s, return is > 0 int strncmp (char *d, char *s, int n) Returns an integer indication of how the first n characters of d compare to s; return value is the same as for strcmp char * strchr (char *s, char missing) Returns a pointer to the first occurrence of character missing in c-string s char * strrchr (char *s, char m) Returns a pointer to the last occurrence of character missing in c-string s char * strstr (char *d, char *s) Returns a pointer to the beginning of the first occurrence of c-string s in c-string d If you want to examine what other functions are available, look at /usr/include/string.h Editing With GNU Emacs Emacs is a very comprehensive editing program. Because it has been around so long and because it is an open source program, Emacs has grown to include all sorts of features, many of which can only be taken advantage of in specialty environments. This page is meant to describe how to deal with the basics of Emacs. Only enough commands are described to make it possible to edit simple programs and text. To get a notion of how extensive Emacs really is, try the the help command or use info. Emacs is an editor in which all actions (functions) are either command driven (entered at the minibuffer at the bottom of the screen) or keystroke driven (many, many keystroke combinations have been defined to invoke commands). Most of the discussion here is about Jeeves 24 June 2017 System Manual 131 the keystrokes. To understand them, three keys are important: Ctrl, Alt, and Esc. The Ctrl key is used in combination with some other key or keys; Emacs documentation always refers to the control key as C- (Capital C followed by a dash). So, Emacs would refer to Ctrl-h (typing h while holding the Ctrl key) as C-h. Emacs also uses the Meta key in combination with some other key or keys. The term Meta is derived from keyboards that (I don't think) exist any more. The idea is similar to the Ctrl key; to refer to the situation of holding down the Meta key while typing x, Emacs would show this as M-x. Although there is no Meta key, there are two keys on the keyboard that can be used in its place (Alt and Esc); however, they are used in different ways. To enter M-x, you can hold down Alt while typing x (because Alt is a key that is meant to be used simultaneously with other keys); or you can type Esc followed by x (a two-key sequence). These two methods may be used interchangeably. A few terms may also be helpful in understanding the following terminology. Buffer- a portion of memory that holds the contents of a file or what will become the contents of a file. Emacs can work with many buffers at the same time; generally the buffer name is the file name. The minibuffer is a special buffer that holds commands which are typed in. Region a portion of a buffer, from where a mark is set to where the cursor is at the moment. Regions are used for cutting and pasting and many other tasks. Register - a portion of memory (like the clipboard) that can hold a copy of a region. You may define many registers and have them hold copies of any text that you want. Window - a rectangular section of the screen. Generally, each window shows a portion of a buffer; typically, the screen shows two windows at a time, one holding a part of a buffer being worked on and one (at the very bottom of the screen) set aside for the minibuffer. Starting Emacs Enter either emacs or emacs file-specification When emacs starts, it looks for the file .emacs in your top-level directory. If it finds this file, Jeeves 24 June 2017 System Manual 132 emacs executes the commands that it contains. This give you a way of initializing emacs by defining any special features that you may want. Emacs is an extensible editor; you can define new key combinations, macros, new commands, etc. You should already have a basic .emacs file; later there is a brief discussion of adding to this file. Among the commands that you might want to use just after starting emacs (maybe for the first time) is C-h This command enters the Help system where you can find out a lot of information about emacs. Help provides a tutorial to illustrate how to use some of the basic keystroke actions. To run the tutorial, enter t after the C-h Help can also show you what function (command) a key runs (C-h c) or it can describe a function (C-h f), among other things. Another command that is useful just after starting emacs is the one to recover from a disconnection. Since you are using emacs through Kermit, there is a definite possibility that you will be disconnected. Emacs maintains a keystroke log of everything you do so it is possible to recover a file across a disconnection very easily. The most you could lose are the last few keystrokes that you entered. To make such a recovery, log in to kodiak after you have reestablished the connection and enter emacs (with on file specified). Then, enter M-x You can see M-x appear in the minibuffer and the cursor is moved to that buffer. Type the command recover-session and follow the directions on the screen to select from the saved logs the one you want to use for recovery. Then, answer the questions 'y' or 'yes' to actually do the recovery. Files If you do not specify a file when entering emacs, you can specify one later. There are a variety of actions that can be done with files. Here are a few; each is done with a combination of keystrokes. For example, the first is Ctrl-x followed by Ctrl-f Jeeves 24 June 2017 System Manual 133 Read a file into an emacs buffer C-x C-f Save the contents of a buffer back to the file on disk C-x C-s Insert the contents of another file into this buffer at the cursor C-x i Write the buffer to a specified file, may be different from the original file C-x C-w When a disk file is to be updated, the old version of the file is renamed by attaching ~ to the end of the name; then the new version is written. Thus, at any moment, you have access to the current version and the version before that. Cursor Motion Kermit provides some capability for moving the cursor. The arrow keys are mapped to move the cursor up, down, left, or right one character position. Page Up and Page Down also move the cursor (one screen up and one screen down, respectively). These keys are mapped to be emacs commands. Kermit also provides some mouse emulation - you should be able to move the cursor to any point on the screen by pointing and double left clicking with the mouse. Note: this is not very reliable because of the interaction of Kermit's calculation of cursor positions and the use of characters like Tab in the text. But, it should "sort of work." Emacs has many keys mapped to provide other cursor movement; here are some of them. Amount to move the cursor Backward (left or up) Forward (right or down) One Word M-b M-f One End of a Line C-a C-e Jeeves 24 June 2017 System Manual 134 One Screen Full M-v C-v One Page C-x [ C-x ] Whole Buffer M-< M-> Matches and Tabs Emacs is a mode dependent editor. That is, it adapts to the programming language being used; it does this based on the file type (.c for C programs, .cc for C++, .p for Pascal, .f for FORTRAN). There is a mode defined for each of these languages. In applying the mode, emacs tries to keep a program cleanly formatted, by providing automatic indentation, matching of symbol pairs (like parentheses), and placement of comments. Whenever you type the right member of a pair of something (parentheses, brackets, etc.), emacs shows you which left member it matches to. It also shows you mismatches; but you must correct the mismatches; it will not fix things for you. Normally, entering the Tab key is a way of getting a line properly positioned based on the indenting scheme that is built into the mode. However, there are times when you want to indent further than emacs would on its own. To get a true Tab into your file, you enter M-i Marking Marking is used to define a region, a section of the buffer contents. Once marked, a region may have a variety of operations performed on it. To mark a region, move the cursor to where the region is to begin and enter either C-@ or C-SPC where SPC is the space key. When you do this, the minibuffer shows a small message that says "Mark Set". Then, move the cursor to the end of the region. Wherever the cursor is when you give a region command determines what is in the region. Here are a few region commands that are widely used. Jeeves 24 June 2017 System Manual 135 Note: one command uses both Ctrl and Alt (C-M-\). Kill (delete) a region - these are saved so you can undo them C-w Yank (retrieve) the last thing killed - this may be a region or some other element C-y Indent the region - this is mode dependent C-M-\ Copy the region to a register C-x x Insert a register contents at the cursor C-x g Change everything in the region to uppercase C-x u Change everything in the region to lowercase C-x l When using the Copy or Insert commands, emacs prompts in the minibuffer with Copy to register: or Insert Register: You are expected to enter the name of the register at this point. Use names like, a or b or c, something short and easy to remember. Above, we noted that you can delete a region with C-w. You can also delete smaller elements of a buffer; obviously, the Backspace key and the Delete key can be used to delete the character to the left of the cursor. Use C-d to delete the character to the right of the cursor. In addition, you can delete a word (M-DEL for word to the left and M-d for word to the right); here M-DEL is Alt with Delete. And you can delete all or a portion of a line (from where the cursor is to the left end with M-O C-k or from the cursor to the right end with C-k). The newline character is deleted only if there is nothing but white space on the line. So, a simple way to get rid of a whole line is C-a C-k C-k to move the cursor to the left end, delete all characters on the line, and delete the newline that remains. Jeeves 24 June 2017 System Manual 136 Searching Emacs provides an unusual feature for searching; it is an incremental search. These are the kind of searches that you typically see in a windows help file when you search the index. As you specify what to look for, each character you enter leads you to the occurrence of the string you have entered so far. Emacs provides searching forward or backward through a buffer. To search forward, enter C-s Emacs displays the prompt I-search: and you should start typing the characters of what you want to search for. As you type, the contents of the window change as emacs moves forward through the buffer finding the sequence of characters you enter. When you get to the place you were searching for, enter any arrow key or the ESC (escape key) to terminate the search. You can also abort the search with C-g at any time. If the string you are searching for occurs multiple times and you want to find a later occurrence, when you get to an early occurrence, enter C-s and emacs will move forward to the next occurrence. Do this as often as necessary. To search backwards (in reverse), enter C-r instead of C-s. C-r works the same way as C-s In fact, if you are searching in one direction and get a message that says the search failed, you may want to immediately enter the other command key to change direction for the search. Emacs maintains the characters of the string you have entered even across changing directions. Generally, the incremental search is case insensitive. You can force it into case sensitivity by using uppercase or a combination of the two cases when specifying what to search for. Replacing Strings To search for a string and replace it with some other string, use the command key Jeeves 24 June 2017 System Manual 137 M-% Doing this enters a query replacement in which you are prompted first with Query replace: at which you are expected to enter the string that is to be replaced. When you press Enter, you are then prompted with Query replace xxx with: where xxx is what you specified. You then need to enter the replacement string. Then, emacs searches forward for each occurrence of the first string specified and waits for you to indicate whether the replacement should be done. The minibuffer shows the message Query replace xxx with yyy: (? for help) To apply the replacement, enter SPC (the space bar). Emacs will make the replacement and go on to the next occurrence of the string. To skip an occurrence (not do the replacement), enter DEL (the Delete key); to apply the replacement to all remaining occurrences of the string, enter ! (exclamation point) To abandon the replacement, enter ESC (the Escape key). Both replacing strings and searching for strings can use regular expressions in the string being searched for. This would make it possible to search for "wild card" strings and strings containing special characters like newline or backslash. This technique is not discussed here. Ending Emacs The only way to end emacs is to enter the command keys C-x C-c If you have buffers that have been changed and not saved when you enter this key combination, emacs asks you whether or not you want to save each of the changed buffers. You have to answer for each changed buffer separately. There is a simple way to suspend emacs which is very handy for writing programs. When you enter C-z emacs stops but does not terminate. The shell prompt appears and you can enter other bash commands. So, the common way to write a program with emacs is to Jeeves 24 June 2017 System Manual 138 edit the file, save it with C-x C-s, then enter C-z to suspend the editor and execute the compiler. Most compilers display any error messages on the screen and tell you about the line on which the error occurred (showing its line number). Armed with that information, you can resume emacs (use the bash command fg), move to the line with the error and correct it. Then, go through the whole cycle again. The next section shows you a quick way to get to the line with the error. Customizing Emacs You can add your own personal touches to how emacs operates by defining additional key combinations for your own use. In anticipation of this, emacs has provided a whole collection of key combinations that you can define. These all begin with C-c (Ctrl-c). One of the most common customizations is to define C-c g to be the goto-line command. When used, this command prompts you for a line number and jumps to that line in the buffer. To define this key combination, edit the .emacs file and put this command in it (global-set-key "\C-cg" 'goto-line) Be very careful when you type this. Then, the next time you execute emacs, you will have the goto-line capability. This will make locating compiler errors very easy. Miscellaneous Finally, a few miscellaneous notes. These are commands that you may find useful at some point, depending on how far you go with emacs. The first one to switch buffers is used frequently when making programs from multiple files; i.e., where you have a single .cc file with many .h files included in it. Switch between buffers (commonly used when editing two files at once) C-x b Delete all other windows but the one with the cursor in it (used to get C-x 1 Jeeves 24 June 2017 System Manual 139 back to normal after using Help or looking at a list of buffers) Undo the last change (you can use this repeatedly to undo long sequences of actions) C-x u Switch the cursor to another window (used when editing multiply buffers) C-x o GDB, the GNU Debugger (Most of this is taken directly from the man page for gdb and the gdb help command) The purpose of a debugger such as GDB is to allow you to see what is going on "inside'' another program while it executes or what another program was doing at the moment it crashed. GDB can do four main kinds of things (plus other things in support of these) to help you catch bugs in the act: Start your program, specifying anything that might affect its behavior. Make your program stop on specified conditions. These stopping places are referred to as break points. Examine what has happened, when your program has stopped. Change things in your program, so you can experiment with correcting the effects of one bug and go on to learn about another. To make full use of gdb, you must be sure to compile with the -g option for the g++ compiler. If you fail to put in this option, you will not be able to access the symbols properly during debugging; and you will not be able to see the source lines surrounding the places you halt execution. Jeeves 24 June 2017 System Manual 140 You can run gdb with no arguments or options; but the usual way to start gdb is with one argument or two, specifying an executable program as the argument: gdb program You can also start with both an executable program and a core file specified: gdb program core When gdb executes, it uses (gdb) as a prompt, although you can change this. To get gdb to perform an action, you ust enter a command. All commands may be abbreviated, as long as the abbreviation is unique. Commands Related to Execution continue Usage: continue [COUNT] Continue executing the program being debugged, after a breakpoint. A number COUNT may be used as an argument, which means to set the ignore count of that breakpoint to COUNT - 1 (so that the breakpoint won't break until the COUNTth time it is reached). kill Kill execution of program being debugged next Usage: next [N] Step program one line, proceeding through function calls. Like the "step" command as long as function calls do not happen; when they do, the call is treated as one instruction. Argument N means do this N times (or until the program stops for another reason). quit Exit from gdb - requires confirmation if a program is executing Jeeves 24 June 2017 System Manual run 141 Start the program being debugged; usually used with no argument. You may specify arguments that include "*", or "[...]"; they are expanded using "sh". Input and output redirection with ">", "<", or ">>" are also allowed. With no arguments, uses arguments last specified (with "run" or "set args"). step Usage: step [N] Step program until it reaches a different source line. Argument N means do this N times (or until the program stops for another reason). Steps into function calls. Commands Related to Making the Program Stop break Usage: break [LINE/ADDRESS/FUNCTION] Set breakpoint at specified line or function. Argument may be line number, function name, or "*" and an address. If line number is specified, break at start of code for that line. If function is specified, break at start of code for that function. If an address is specified, break at that exact address. With no argument, uses current execution address of selected stack frame. This is useful for breaking on return to a stack frame. Multiple breakpoints at one place are permitted, and useful if conditional. clear Usage: clear [LINE/ADDRESS/FUNCTION] Clear breakpoint at specified line or function. Argument may be line number, function name, or "*" and an address. If line number is specified, all breakpoints in that line are cleared. If function is specified, breakpoints at beginning of function are cleared. If an address is specified, breakpoints at that address are cleared. With no argument, clears all breakpoints in the line that the selected frame is executing in. commands Usage: commands [BREAKPOINT] Set commands to be executed when a breakpoint is hit. Give breakpoint number as argument after "commands". With no argument, the targeted breakpoint is the last Jeeves 24 June 2017 System Manual 142 one set. The commands themselves follow starting on the next line. Type a line containing "end" to indicate the end of them. Give "silent" as the first line to make the breakpoint silent; then no output is printed when it is hit, except what the commands print. condition Usage: condition BREAKPOINT COND Specify breakpoint number to break at only if COND is true. BREAKPOINT is an integer breakpoint number and COND is an expression to be evaluated whenever that breakpoint is reached. delete Usage: delete [BREAKPOINT . . .] Delete some breakpoints or auto-display expressions. Arguments are breakpoint numbers with spaces in between. To delete all breakpoints, give no argument. Also a prefix command for deletion of other gdb objects; example: delete display [EXPRESSION . . .] Cancel some expressions to be displayed when program stops. Arguments are the code numbers of the expressions to stop displaying; the expressions would have been previously specified with the display command. No argument means cancel all automatic-display expressions. disable Usage: disable [BREAKPOINT . . .] Disable some breakpoints. Arguments are breakpoint numbers with spaces in between. To disable all breakpoints, give no argument. A disabled breakpoint is not forgotten, but has no effect until reenabled. enable Usage: enable [BREAKPOINT . . .] Enable some breakpoints. arguments. Give breakpoint numbers (separated by spaces) as With no argument, all breakpoints are enabled until you command Jeeves 24 June 2017 System Manual 143 otherwise. This is used to cancel the effect of the "disable" command. ignore Usage: ignore BREAKPOINT COUNT Set ignore-count of breakpoint number specified by BREAKPOINT to COUNT, causing the breakpoint to be ignored COUNT - 1 times. watch Usage: watch EXPRESSION Set a watchpoint for an expression. A watchpoint stops execution of your program whenever the value of the expression changes. until Usage: until LINE/ADDRESS/FUNCTION Execute until the program reaches a source line greater than the current or a specified line or address or function (same args as break command). Execution will also stop upon exit from the current stack frame. xbreak Usage: xbreak [ADDRESS/FUNCTION] Set breakpoint at procedure exit. Argument may be function name, or "*" and an address. If function is specified, break at end of code for that function. If an address is specified, break at the end of the function that contains that exact address. With no arg, uses current execution address of selected stack frame. This is useful for breaking on return to a stack frame. Commands to Examine What Has Happened backtrace or bt Usage: bt [COUNT] Print backtrace of all stack frames, or innermost COUNT frames. With a negative argument, print outermost -COUNT frames. Use of the 'full' qualifier also prints the values of the local variables. Jeeves 24 June 2017 System Manual 144 The stack is made up of stack frames. Gdb assigns numbers to stack frames counting from zero for the innermost (currently executing) frame. At any time gdb identifies one frame as the "selected" frame. Variable look-ups are done with respect to the selected frame. When the program being debugged stops, gdb selects the innermost frame. The commands below can be used to select other frames by number or address. display Usage: display [/FMT] EXP Print value of expression EXP each time the program stops. FMT may be used before EXP as in the "print" command. The format letter may be "i" or "s"; a size letter is allowed, as in the "x" command. EXP is used to get the address to examine; and examining is done as in the "x" command. With no EXP, display all currently requested auto-display expressions. info Generic command for showing things about the program being debugged. Below is a listing of some of the more useful things that can be shown. info args Argument variables of current stack frame info breakpoints Status of user-settable breakpoints info display Expressions to display when program stops info frame NUM All about stack frame NUM info functions All function names info line Core addresses of the code for a source line info locals Local variables of current stack frame info program Execution status of the program info scope List the variables local to a scope Jeeves 24 June 2017 System Manual list 145 Usage: list [ARGUMENT] List specified function or line. With no argument, displays ten more lines after or around previous listing. "list -" displays the ten lines before a previous ten-line listing. One argument specifies a line, and ten lines are listed around that line. Two arguments with comma between specify starting and ending lines to list. Arguments can be specified in these ways: LINENUM to list around that line in current file, FILE:LINENUM to list around that line in that file, FUNCTION to list around beginning of that function, FILE:FUNCTION to distinguish among like-named static functions. *ADDRESS to list around the line containing that address. With two args if one is empty, it stands for ten lines away from the other arg. print Usage: print [/FMT] EXP Print value of expression EXP. Variables accessible are those of the lexical environment of the selected stack frame, plus all those whose scope is global or an entire file. EXP may be preceded with /FMT, where FMT is a format letter but no count or size letter (see "x" command). @ is a binary operator for treating consecutive data objects anywhere in memory as an array. FOO@NUM gives an array whose first element is FOO, whose second element is stored in the space following where FOO is stored, etc. for a total of NUM elements. FOO must be an expression whose value resides in memory. ptype Usage: ptype TYPE Print definition of type TYPE set Usage: set VAR = EXP Jeeves 24 June 2017 System Manual 146 Evaluate expression EXP and assign result to variable VAR. VAR may be a debugger "convenience" variable (names starting with $) or an actual variable in the program being debugged. EXP is any valid expression. Use "set variable" for variables with names identical to set sub commands. set also uses sub commands to modify parts of the gdb environment. A few selected set sub commands are shown below. set input-radix NUM Set default input radix for entering numbers to NUM set listsize NUM Set number of source lines gdb will list by default to NUM set output-radix NUM Set default output radix for printing of values to NUM set print pretty Make structs be displayed in an easy to read form set radix NUM Set default input and output number radices to NUM. Without an argument, sets both radices back to the default value of 10. set variable VAR = EXP whatis Evaluate EXP and assign result to variable VAR Usage: whatis EXP Print data type of expression EXP. x Usage: x [/FMT] ADDRESS Examine memory. ADDRESS is an expression for the memory address to examine. FMT is a repeat count followed by a format letter and a size letter. Format letters are o(octal), x(hex), d(decimal), u(unsigned decimal), t(binary), f(float), a(address), i(instruction), c(char) and s(string). Size letters are b(byte), h(halfword), w(word), g(giant, 8 bytes). The specified number of objects of the specified size are printed according to the format. Defaults for format and size letters are those previously used. Jeeves 24 June 2017 System Manual 147 Default repeat count is 1. Default address is following last thing printed with this command or "print". Jeeves 24 June 2017 System Manual 148 Communications Phase Write the user communications portion of an operating system for the Jeeves computer. It must perform as follows: 1. Respond to the Boot_Done interrupt by initializing your operating system's database. This includes reading from the disk information regarding the root and user directories and the password file. 2. Respond to clients who send SYN messages to start a Telnet or FTP session. Validate login attempts by the clients and send appropriate prompts to the client. 3. Allow validly logged in Telnet clients to issue any of the following commands AND send the appropriate output back to the clients in response to these commands: now 4. list users show Allow validly logged in FTP clients to issue any of the following commands AND send the appropriate output back to the clients in response to these commands: dir 5. get All other valid Telnet and FTP commands (access, copy, print, put, etc.) must be recognized as valid but no other actions are required for them yet. Respond to illegal commands by sending an appropriate error message. 6. Allow Telnet clients to use the logout command or to sent a FIN packet and FTP clients to use the quit command or to send a FIN packet. Respond with an appropriate message for logout and quit and end the session in any case. 7. Ignore packets that are intended for other servers. 8. Allow a Telnet client to log in at the console keyboard. Respond to all keyboard and screen interrupts using a device independent approach internally. Send command responses for the console to the screen. 9. Properly handle all Device_In and Device_Out interrupts associated with the console or communications interface. Jeeves 24 June 2017 System Manual 149 10. Implement CPU scheduling for the five system processes used during this phase. 11. Make the DiskScheduler, ProtocolHandler, Login, Shell, and Transmitter work as described in the Jeeves System Manual. 12. Do NOT implement a mouse driver; no script uses the mouse. To accomplish these tasks, your operating system database should have data structures to hold a variety of information, as examples: A linked list or array of information about each client or thread. Information about the status of each system device. Queues for the orderly processing of packets, disk requests, and scheduling of threads. Possibly other linked lists to keep track of threads that are not executable. Disk bitmap information in some form. Directory information for each directory in some form. Buffer areas set aside in memory to hold vital information. Some of Jeeves' memory must be permanently allocated to hold message packets and keystrokes. When a message arrives or a keystroke occurs, the hardware refers to registers to know where to put the incoming data - these registers must be set and the places the registers refer to must be ready to receive the input. Your OS must also meet the requirements of implementation that messages (both incoming and outgoing) must be stored in Jeeves' memory. It is acceptable to copy a message into an auxiliary storage area for assembly or disassembly; but messages must remain in Jeeve's memory when in queues for processing. A schedule is provided so that you can gauge the pace at which you should work to get the operating system completed. The bold dates are the deadlines for the graded parts. To meet these, especially the design phase deadline, you will have to at least begin working on one phase before you complete the previous phase. Don't let this panic you. Starting the design before finishing communications will actually have a beneficial effect. Jeeves 24 June 2017 System Manual 150 Activity Due on Set up the database January 30 Submit Printout of jeeves.log for the script hello.scr Implement now, dir, and February 13 Printout of jeeves.log for scripts comm1.scr and list comm2.scr Complete the Communi- February 25 Readable printout of all of the operating system cations phase you have written (no wrapped lines). A disk with your OS source, jeeves.log, jeeves.report, and captured.ip (for IP addr 0.0.0.0) from running on scripts comm1-4.scr Complete the Design March 25 phase Pseudo code, diagrams, UML or flow charts of the design Implement access, copy April 3 Printout of jeeves.log and captured.ip (for IP addr 0.0.0.0) from running on scripts accesses.scr and copies.scr Implement delete, add, April 17 Printout of jeeves.log and captured.ip (for IP remove addr 0.0.0.0) from running on deletes.scr, adds.scr, and removes.scr Complete mentation the Imple- April 28 phase, including print, put, and try run Jeeves 24 June 2017 System Manual 151 Comm Phase Evaluation Names _______________________ Sample Only Boot_Done Initialization _____ (3) users Command _____ (4) Setting up the database Boot Record _____ (2) Session Termination Bit Map _____ (2) logout _____ (1) Passwords _____ (2) quit _____ (1) Root Directory _____ (2) FIN message _____ (1) Login attempts SYN Error Handling _____ (2) Authentication _____ (4) Prompts _____ (2) now Command Message form _____ (2) Elements _____ (4) Parsing Telnet _____ (3) FTP _____ (2) Illegal commands _____ (3) Other valid _____ (3) list & dir Commands commands _____ (2) Messages for Other Message Form _____ (3) Elements _____ (3) Servers _____ (2) Prompts before show & get Commands Commands Disassembly _____ (4) Fragments _____ (3) Memory _____ (2) Jeeves 24 June 2017 System Manual 152 In-Message Buffers _____ (2) Out-Message Buffers _____ (2) Disk Access _____ (2) Keyboard _____ (2) Screen _____ (2) Device Independence _____ (4) System Process Structure DiskScheduler _____ (2) ProtocolHandler _____ (2) Login _____ (2) Shell _____ (2) Transmitter _____ (2) Documentation Miscellaneous _____ (10) _____ (4) Total __________ (100) Jeeves 24 June 2017 System Manual 153 Design Phase Design the remainder of an operating system for the Jeeves server that meets all of the following requirements. Other requirements are explicitly stated or implied by the Jeeves System Manual. 1. All Telnet and FTP commands must be recognized and acted upon correctly. Entered commands which use an improper verb or file name must be handled by displaying one of the specified messages. There will be NO errors due to causes other than those shown in the manual. 2. Output to the printer must be spooled and unspooled. Unspooling must accommodate Device_Disables and Device_Enables on the printer. Changes in printer status must be supported without choking the system or leaving tasks unfinished. If more print requests are made than can be handled immediately, the operating system must maintain a queue of them. 3. Multiprogramming must be supported. If more than one client wishes to run a program at the same time, the operating system must support the programs being ready to execute simultaneously and must do so fairly. The choice of a CPU scheduling algorithm is up to you. 4. Disk space management must be implemented. All used and unused space must be kept track of at all times. The disk bitmap, the root directory and all other directories, and the password file must be kept reasonably "current" on the disk, not just in the database. Jeeves 24 June 2017 System Manual 5. 154 Jeeves' memory must be managed to provide for running programs and buffers of all kinds. 6. root must be treated differently from all other clients. The OS must provide for getting around some access checking for the root. The OS must also make sure that only root can use the add and remove commands. Your design should begin with OpSys and should include a description of what each module is going to do (and generally how it is going to do it). You may wish to use a flowchart or pseudo-code to illustrate the design (this is encouraged). You may wish to show the form of tables or other data structures in the database that will be used by the operating system (this too is encouraged). You should also provide a written explanation of the crucial overall design decisions that you are making, for example: how memory is going to be managed (allocated and recovered) - maybe show a picture, how printing gets started and continues (after a lull in printing), how the disk request queue is handled, how CPU scheduling is going to be done, how interrupts can be handled while maintaining device activity and thread execution, how file and directory access checking and updating are to be handled, how file conflict is detected and dealt with. Your design should assume that you have a working communications phase. Thus, whenever there is a need to send an error message to a client, your design may simply show a function call and assume it will be handled (even though sending a message is an event with an associated disconnection). Thus, in command terms, your design need only address issues related to the client commands: access, add, copy, delete, remove, print, put, and run. Note that each of these requires at least two things: use of at least one page frame in memory and at least one transfer between memory and a disk. The complete design is due on March 25. It is highly recommended that your design Jeeves 24 June 2017 System Manual 155 be typed (not handwritten). Naturally, if part of your design is in flowchart form or consists of tables of values, these sections of the design need not be typed. Any handwritten parts must be legible and intelligible. As you know, this is a partnership project. This means that there must be cooperation and communication between the partners. I expect to see approximately equal contributions from each partner in each phase of the project. Of course, there may be variations during one phase of the project or another. However, I expect to see a genuine effort at working together. I expect that any complaints that one partner has about another partner will be brought to me as early as possible, before a problem develops that makes working together impossible. WARNING: DESIGNS ARE VERY IMPORTANT. Bad designs very often lead to bad implementations. Past experience shows that only 5% of bad designs lead to successful programs; 20% of bad designs lead to marginal programs; 75% of bad designs lead to truly horrible programs. Jeeves 24 June 2017 System Manual 156 Design Evaluation Names _____________________ Sample Only Commands access (4) _____ File Access Checking (3) _____ add (4) _____ Memory management (4) _____ remove (4) _____ Printing Disk usage (1) copy (6) _____ _____ Spooling (4) delete (6) _____ put (6) _____ print/run (4) _____ Queue (2) _____ Unspooling (6) _____ _____ Library/Common (2) _____ Device Enable/Disable (3) Error messages (3) File Conflict Checking (3) User Process Thread Support Input (3) _____ Output (3) _____ Time Out (2) _____ _____ _____ _____ Jeeves 24 June 2017 System Manual Termination (3) 157 _____ Context Switching (2) _____ CPU Scheduling (2) _____ Differentiating Disk Actions (6) _____ Connections (4) _____ Readability (10) _____ Total (100) _____ Jeeves 24 June 2017 System Manual 158 Implementing an Operating System (Due on or before 28 April) Based on the design that your partnership submitted (and suggestions that I have made or will make), write a C++ operating system for the Jeeves server. I suggest that you approach this task gradually by implementing some basic structures to support the simpler commands and work your way up to handling the most complicated commands (the Communications Phase description suggests a sequence to work on the commands). Probably, you will want to handle print, put and run last. A variety of scripts are available for you to test your operating system. Each of these scripts is kept in the /usr2/fac/jlwolfe/jeeves directory. The Jeeves System Manual briefly describes each of the scripts that are provided. Hand in a well-documented listing of your operating system. It is NOT acceptable to hand in a program that has compilation or linking errors. It is NOT acceptable to hand in a program printout in which the lines wrap. Your program MUST execute, whether it does the right thing or not. You must also hand in a disk with the source program and the jeeves.log, jeeves.report, captured.ip, printer.log, and execution.log files produced by executing on scripts done1.scr through done5.scr. If you construct any scripts of your own to demonstrate some feature of your operating system and want to show me that something works for your script (even if it doesn't work for mine), you may hand in these same files for those scripts. Be sure to name the files so I can differentiate them from the required ones. Notes: Jeeves 24 June 2017 System Manual 1. Look at the grading scheme. 159 You should see that the implementation of the run command (the hardest one to implement) has relatively few points associated with it. This is because I want you to concentrate on getting everything less to work first; then, try run if you have the time. 2. Hopefully, at this stage, your Communications Phase worked well enough and your Design was complete enough for you to begin implementing as soon as you hand in the Design. Do not wait for my evaluation of your design to start to work on the implementation. Jeeves 24 June 2017 System Manual 160 Implementation Evaluation Names _____________________ Sample Only Command Implementation (Breakdown: 8 - complete, 6 - marginal, 3 - some code, 0 - nothing) copy (8) _____ access (8) add (8) _____ put (8) remove (8) _____ delete (8) _____ _____ _____ print (6) run (4) _____ _____ Total _____ (58) Task Implementation (numbers shown are maximum possible) Interrupt handling Disk I/O handling Enable/Disable _____ (6) _____ (2) User Thread Trap Handling Input/Output Time Out _____ (6) _____ (2) Jeeves 24 June 2017 System Manual Terminate/Abort Space management (memory, disk) 161 _____ (2) _____ (5) Printing Queueing _____ (2) Unspooling _____ (5) Error reporting & messages Documentation _____ (2) _____ (10) Total _____ (42) OVERALL __________