s1.ms.compin 04/19/84 0958.7r w 02/20/84 1350.0 6048 .ifi init_mpm "AN69" .srv section 1 .ifi l0h "Introduction" The message segment facility enables the user to create and delete repositories for messages. It can perform a set of operations on the repository and control access to it in a unique way called extended access. .spb 2 The message segment facility is layered. It consists of a primitive facility on which software for specific applications can be built. The subsystem programmer can define a class of repository and a subset of the available operations. .spb 2 The message repository used by the facility is an inner ring segment that will be referred to as a message segment. .brp .fin .inl 0  s2.ms.compin 04/19/84 0958.8r w 02/20/84 1350.0 53316 .ifi init_mpm "AN69" .srv section 2 .ifi l0h "Design Goals" The message segment facility is designed to: .spb .inl 10 .unl 5 1. Provide for the protected and ordered exchange of messages between processes and within processes. .spb .unl 5 2. Provide a partitioned facility to allow various higher level applications. .spb .unl 5 3. Be able to restore is message data to a consistent form so that it contains functioning if a message is damaged. .spb .unl 5 4. Make the time during which any primitive operation puts the message data in an inconsistent state as small as possible, so as to minimize the chance that it will be left in this state be crash or malfunction. .spb .unl 5 5. Allow the size of the message data storage unit to be changed easily so that the most efficient unit size can be determined and used. .spb .unl 5 6. Be executable in the user ring for debugging purposes. .inl 0 .ifi l1h "Requirements" The requirements of the message segment facility are threefold. It must have one higher level subsystem to provide queue facility for the I/O and Absentee Daemons. This queue facility must perform the operations listed below: .spb .inl 10 .unl 5 1. Enter a request so that its order is retained in queue. .spb .unl 5 2. Obtain a request in some ordered fashion from the queue. .spb .unl 5 3. Delete a request from the queue. .spb .unl 5 4. Rewrite the request within the queue. .spb .unl 5 5. Obtain certain status concerning the queue. .spb .inl 0 This higher level queue facility must also provide appropriate access control that allows users of the facility to enter, obtain, and cancel their own requests without being able to tamper with requests of other users. .spb 2 There must be a second higher level subsystem to support the mail and send_message facilities. Within this subsystem the user must be able to: .spb .inl 10 .unl 5 1. Add, read, and delete mail and messages in an ordered fashion. .spb .unl 5 2. Send, obtain, and delete mail and messages without affecting mail and messages sent by other users. .spb .unl 5 3. Allow and defer messages. .inl 0 .spb 2 The message segment facility must also provide the user with the ability to specify other types of message segments and to design high level subsystems to implement these types of message segments. .ifi l1h "Design" Use of extended access requires that the message repository and the procedures that access it are in an inner ring restricted to system use. Ring 1 has been reserved for this purpose. All message segments are bracketed 1,1,1. .spb 2 The internal consistency of a message segment is protected as follows: .spb .inl 10 .unl 5 1. The sequence of operations that leave the message segment in an inconsistent state is short to minimize the probability of being interrupted by system failure. .spb .unl 5 2. Quits are inhibited during this sequence so that the user cannot interrupt it. .spb .unl 5 3. A switch is turned on while the sequence is executing. In the rare case when system failure or an unrecoverable error has left the message segment inconsistent, this switch will be on. .spb .unl 5 4. There is a salvager, called by any message operation when the switch is found to be on, that is capable of restoring the message segment to a usable state. This salvager cannot be responsible for the text portion of a message because the text does not follow any particular rules. .spb 2 .inl 0 The choice of what message operations should be available is influenced by the need to make each one brief. The read operations in particular are affected by this consideration. If a message segment contains messages in threaded form and a user wishes to perform a read operation that involves chasing the threads (i.e., read the fifth message, or read all messages with a given property), then one call can take considerable time. To avoid this problem, only the following read operations exist: .spb .inl 5 1. Read the first message .spb 2. Read the last message. .spb 3. Read the next message. .spb 4. Read the previous message. .spb .inl 0 The caller thus has the ability, by combining calls, to find any desired message. The chasing of message threads is done in the user ring. .spb 2 The implementation of these read operations presents a problem with respect to access control. Assume a user wishes to read a message from the message segment but has access to read only his own messages and no access to obtain status information such as the number of messages in the message segment. If a read operation returned nothing when it encountered a message that the user does not have access to read, the user could find out how many messages there are and which ones are his. To avoid this, the read first operation should, for example, return the first message that the user has access to. .spb 2 .brp A set of own read operations are provided for this purpose. These operations are implemented a level above the actual read operations in the administrative ring. They invoke the appropriate read operations repetitively until they read a message sent by the caller and then return that message. Although they are in the administrative ring, they do not access the repository directly and therefore can be interrupted. .spb 2 To facilitate adding new types of message segments to the system, the primitives are partitioned. All code specific to one type of message segment is placed in a separate module. Each module performs the appropriate checks for an individual type of message facility. The relationship can be diagrammed as follows. Solid arrows represent the flow of control between modules. Notice that control can pass form module I downward to either the own or nonown entries in the primitive facility. .brp .spd +30 .ifi fig "Sample Message Segment Facility Configuration" .brp .fin .inl 0  s3.ms.compin 04/19/84 0958.8r w 02/20/84 1350.0 38268 .ifi init_mpm "AN69" .srv section 3 .ifi l0h "Properties and Structure" .ifi l1h "Properties" A message segment is accessible only in the administrative ring. It has a suffix name defined for some type of message segment. A subset of the extended access bits in the ACL entries is defined for that type of message segment. These bits are set by the administrative ring software and used by that software to determine access to the message segment. A message segment may not be a multisegment file. .ifi l1h "Structure" .ifi l2h "Message Segment Structure" The first block of words in the message segment is the message segment header. It contains: .spb .inl 10 .unl 5 1. A lock (a word set by the standard Multics locking and unlocking operations). .spb .unl 5 2. An identification bit pattern checked by the message segment primitive to help ensure the identity of the message segment. .spb .unl 5 3. An offset to the beginning of the first message in the message segment. .spb .unl 5 4. An offset to the beginning of the last message in the message segment. .spb .unl 5 5. A count of the number of messages in the message segment. .spb .unl 5 6. A version number. .spb .unl 5 7. A block of words for a special header message. .spb .unl 5 8. A count of the number of bits in this header message if the header message is present. .spb .unl 5 9. Switches: .spb .inl 15 .unl 5 a. A switch that is on whenever the message segment is being manipulated by the primitives and is in an inconsistent state. .spb .unl 5 b. A switch that is on whenever the message segment has been restored by the message segment salvager. .spb .unl 5 c. A switch that is on whenever a special message is present in the message segment header. .inl 0 .spb 2 To maintain the ability to vary the size of the block in which messages are stored, the following data is also kept: .spb .inl 10 .unl 5 1. An allocation bit string where each bit represents a block of words in the message segment. A particular bit is turned on when the block corresponding to it is in use. .spb .unl 5 2. A number indicating the length of the allocation bit string. .spb .unl 5 3. A number indicating the size of a message block. .spb .unl 5 4. A count of the number of unused blocks in the message segment. .inl 0 .spb 2 The remainder of the message segment consists of messages. Each message is threaded to the next and previous message with a forward and backward thread. A message consists of one or more message blocks. Each block of a message is threaded to the next block of the message with a forward and backward thread. Each block of a message is threaded to the next block of that message with a forward thread. .inl 0 .ifi l2h "Message Block Structure" The first portion of every message block contains the following header information: .spb .inl 10 .unl 5 1. An offset to the next block in the message. If the current block in the message is the last block, this value is zero. .spb .unl 5 2. A first block switch that is on if the current block is the first block in the message. .spb .unl 5 3. A count of the number of message bits used in the block. .inl 0 .spb 2 Following the header is all or part of a message. Present only in the first block of each message is a message block trailer, consisting of: .spb .inl 10 .unl 5 1. A unique bit pattern used to identify the beginning of the trailer when dumping message segments. .spb .unl 5 2. An offset to the first block of the next message in the message segment. If the current message is the first message in the segment, this value is zero. .spb .unl 5 3. An offset to the first block of the previous message in the message segment. If the current message is the first message in the segment, this value is zero. .spb .unl 5 4. The size, in bits, of the current message. .spb .unl 5 5. The time the message was sent. .spb .unl 5 6. The validation level of the sender of the message. .spb .unl 5 7. The Person_id.Project_is identification of the sender of the message. .inl 0 .spb 2 The include files that describe the message segment header, the message header, and the message trailer are located in in Appendix A. .brp .fin .inl 0  s4.ms.compin 04/19/84 0958.8r w 02/20/84 1350.0 208368 .ifi init_mpm "AN69" .srv section "4" .ifi l0h "The Primitive Message Segment Facility" The primitive message segment facility consists of the following modules: .spb .inl 10 .unl 5 1. A module to create and delete message segments. .spb .unl 5 2. A module to open and close message segments. These operations are analogous to initiating and terminating a segment. When the message segment is opened, an index is returned. This index is used to refer to the message segment in subsequent operations. .spb .unl 5 3. A module to manipulate the extended access of a message segment. This module contains entries analogous to the current ACL primitive entries. .spb .unl 5 4. A module to lock and unlock a message segment. .spb .unl 5 5. A module to manipulate messages. .spb .unl 5 6. A module to manipulate own messages. .spb .unl 5 7. A module to salvage a message segment. .spb .unl 5 8. A data base containing constants relevant to the operation of the message segment primitives. .spb .unl 5 9. A module to convert a message segment from a previous format. .spb .unl 5 10. A metering data base. .spb 2 .inl 0 Following is a description of each module. None of these modules can be called from the user ring. Each is called by the administrative ring module that defines a particular type of message segment. References to ring number are implemented in such a way that if the user has appropriate access to certain system procedures, he can execute the primitives in any ring. .inl 0 .ifi l1exact "C_R_E_A_T_I_N_G_ A_N_D_ D_E_L_E_T_I_N_G_ M_E_S_S_A_G_E_ S_E_G_M_E_N_T_S_ (msu_)" .ifi l1toc "Creating and Deleting Message Segments" .spb 2 .inl 0 This particular sequence is followed to ensure that no window to access the segment occurs during creation. The segment is created first with null access and then access is added. .spb 2 .inl 10 .unl 5 Deleting a message segment consists of: .spb .unl 5 1. Setting the validation level to the called ring. .spb .unl 5 2. Verifying that the segment is a message segment. This is done by checking the name of the segment and its ring brackets when it is initiated. .spb .unl 5 3. Checking that the caller has appropriate extended access to delete the message segment, currently delete extended access (d, the second extended access bit, must be on). This access check serves also as a further identity check. .spb .unl 5 4. Setting up a cleanup handler to turn off guaranteed eligibility. This step is needed because the locking procedure called next turns on guaranteed eligibility. If a crawlout occurs in the locking procedure, a return to the user ring with guarantee eligibility on must be prevented. .spb .unl 5 5. Locking the message segment. .spb .unl 5 6. Deleting the message segment. .spb .unl 5 7. Turning off guaranteed eligibility. .spb .unl 5 8. Resetting the validation level to the called ring. .inl 0 .ifi l1exact "O_P_E_N_I_N_G_ A_N_D_ C_L_O_S_I_N_G_ M_E_S_S_A_G_E_ S_E_G_M_E_N_T_S_ (mseg_index)" .ifi l1toc "Opening and Closing Message Segments" It is a violation of access control conventions to initiate a message segment in an inner ring and pass a pointer to it across rings. Therefore a message segment is opened and closed rather than initiated and terminated. This procedure opens and closes message segments and maintains the correspondence between inner ring pointers to message segments and the indices used in outer ring references to message segments. .spb 2 The procedure mseg_index_ contains an entry to open a message segment, an entry to close a message segment, and an entry to return a pointer to a message segment given its index. The last is used by the other primitive functions and is not available in the user ring. .ifi l1exact "M_A_N_I_P_U_L_A_T_E_D_ E_X_T_E_N_D_E_D_ A_C_C_E_S_S_ (mseg_access_)" .ifi l1toc "Manipulating Extended Access" This procedure is used to manipulate and to read extended access. It contains entries corresponding to the hardcore ACL primitive entries. Calls are mapped and passed to the hardcore entries. .spb 2 This procedure mseg_access_ also ensures that at least two entries are maintained on the Access Control List (ACL) of the message segment. A call to delete all the entries form the ACL of a message segment is mapped by this procedure into a call to replace the ACL with two entries, one for *.*.* and one for *.SysDaemon.*, with rew real access and null extended access. These ACL entries must be maintained so that the primitives themselves will never be denied real access to the message segments and backup will always be able to dump and reload message segments. .ifi l1exact "L_O_C_K_I_N_G_ A_N_D_ U_N_L_O_C_K_I_N_G_ M_E_S_S_A_G_E_ S_E_G_M_E_N_T_S_ (mesg_)" This procedure locks and unlocks message segments to prevent simultaneous access by more than one process. It makes use of the standard file system locking mechanism. .spb 2 This procedure must be able to validate an existing lock. If a process terminates while it has a message segment locked, the Multics salvager does not unlock the message segment. Therefore, when this locking procedure encounters a locked message segment, it makes a call to a hardcore procedure, which checks the process ID in the lock. If the process ID does not correspond to an existing process, the hardcore procedure relocks the message segment with the process ID of the caller. .spb 2 ring_1_lock_ makes a specified number of attempts at locking a message segment. After each unsuccessful attempt, it goes blocked for a short while before trying again. .spb 2 Unlocking is accomplished with the standard unlocking instruction. .spb 2 ring_1_lock_ turns on guaranteed eligibility when it locks a message segment and turns off guaranteed eligibility when it unlocks a message segment. Cleanup handlers exist to ensure that guaranteed eligibility is always off on an abnormal return. .ifi l1h "Manipulating Messages" The module that actually manipulates messages is composed of three procedures: a procedure that checks access and dispatches calls; a procedure that reads and deletes messages; and a procedure that adds messages. .ifi l2exact "C__h_e_c_k_i_n_g A__c_c_e_s_s _a_n_d D__i_s_p_a_t_c_h_i_n_g C__a_l_l_s (mseg_)" .ifi l2toc "Checking Access and Dispatching Calls" This procedure is the heart of the message segment facility. It is the lowest level primitive through which all calls to access the message segment are routed. It does the following: .spb .inl 10 .unl 5 1. Gets a pointer to the message segment. .spb .unl 5 2. Checks the identity for the segment being referenced. .spb .unl 5 3. Checks the user's access to the message segment and rejects the call if access is insufficient. .spb .unl 5 4. Locks the message segment. .spb .unl 5 5. Converts the message if it is not in the current format. .spb .unl 5 6. Establishes a cleanup handler to invoke the message segment salvager, return appropriate arguments to the caller, and turn off guaranteed eligibility. .spb .unl 5 7. If the call is one that reads or sets data in the header, performs the required action. .spb .unl 5 8. If the call is to read or delete a message, dispatches it to the appropriate procedure. .spb .unl 5 9. If the call is to add a message, fills in the header of the message segment if empty and dispatches the call. .spb .unl 5 10. If the operation leaves no information in the message segment, truncates the message segment to zero length. .spb 2 .inl 0 All the variables for the creation of the message segment header are computed from the block size on the message facility data base. The algorithm for this computation is: .spb .inl 10 .unl 5 1. Get the maximum size of the message segment. .spb .unl 5 2. Get the block size from the message facility data base. .spb .unl 5 3. The number of possible blocks in the message segment is equal to 1_ divided by 2_. Since the allocation bit string contains one bit for each block, the computed value is the bit length of that string. .spb .unl 5 4. Compute the number of blocks needed for the header of the message segment. This is done by taking the length of the header, adding the length of the allocation bit string, and dividing by the block size. .spb .unl 5 5. Compute the number of blocks remaining for messages. This is 3_ - 4_. .spb .inl 0 The purpose of this computation is to eliminate dependence on a particular block size. .spb 2 Whenever mseg_ discovers an inconsistency or possible inconsistency in the message segment, it invokes the message segment salvager and returns. .inl 0 .ifi l2exact "H__e_a_d_i_n_g _a_n_d D__e_l_e_t_i_n_g M__e_s_s_a_g_e_s (mseg_util_)" .ifi l2toc "Heading and Deleting Messages" This procedure is one of several called by mseg_. Its function is to return and/or delete messages. .spb 2 All operations begin by gathering the data necessary to locate a message. This data is taken from the header of the message segment and the message facility data base. Data taken from the data base consists of : .spb .inl 10 .unl 5 1. The length in words of a message header. .spb .unl 5 2. The length in words of a message trailer. .inl 0 .spb If the length of either structure is changed, that value must be updated in the data base. .spb 2 The next step common to all operations is to locate the desired message. This can be the first message, the last message, or an incremental massage. If the message desired is the first or last message, its offset is stored in the message segment header. Two arguments supplied by the caller are used to locate an incremental message: the location and time of the message from which to read incrementally and the direction in which to increment. (The caller obtains the location and time form the previous read operation.) The format of the message is then checked. Information regarding the message is extracted from the trailer. .spb 2 A final access check is made. An entryname determines whether the call is being made from an own entry or from a nonown entry. If the call is own and the user did not send the message (Person_id.Project_id in the message trailer does not match Person_id.Project_id in the group ID), then only the data extracted from the trailer is returned. This sequence of operations allows the own module (see Figure 2-1) to call mseg_ repeatedly and get back only the information needed for another incremental read until mseg_ reads a message sent by the caller. .spb 2 The message thread is now chased. If the message is being returned, it is copied out to a user area. If it is being deleted, the aip bit is turned on, the appropriate blocks are zeroed out, the header information is updated, and the aip bit is turned off. .inl 0 .ifi l2exact "A__d_d_i_n_g M__e_s_s_a_g_e_s (mseg_add_)" .ifi l2toc "Adding Messages" .inl 10 .unl 5 To add a message, this procedure: .spb .unl 5 1. Computes the number of blocks for the message. .spb .unl 5 2. Finds that number of unused blocks in the segment. .spb .unl 5 3. Threads these blocks together. .spb .unl 5 4. Fills the message and block header and trailer data into the blocks. .spb .inl 0 If processing is interrupted during one of the above steps the message segment is left in a consistent state. The blocks containing the new message are not yet threaded into the segment itself or recorded in the header as in use. .spb .inl 10 .unl 5 5. Turns on the aip in the header of the message segment. .spb .unl 5 6. Threads the message into the segment. .spb .unl 5 7. Updates the header. .spb .unl 5 8. Turns off the aip bit. .spb .inl 0 This procedure contains an entry to add a message using a sender ID specified by the caller. The entry is used by the conversion module described under the heading "Converting Message Segments" and is not available in the user ring. .inl 0 .ifi l1exact "M_A_N_I_P_U_L_A_T_I_N_G_ O_N_L_Y_ C_A_L_L_E_R_ M_E_S_S_A_G_E_S_ (mseg_own_)" This procedure provides controlled access to a message segment by returning to the caller the appropriate entry in mseg_ to read a message. If a nonzero length message is returned, mseg_own_ returns this message to the caller. Otherwise it calls to read another message. .spb 2 Since mseg_own_ does not access the message segment directly, it does not turn on guaranteed eligibility. .ifi l1h "Salvaging Message Segments" The module that salvages message segments is invoked to restore the message segment to a consistent state. The basic approach to salvaging is to save only those messages that are in a consistent state and not to attempt to repair messages. The reason for this approach is twofold: .spb .inl 10 .unl 5 1. The salvager cannot ensure the correctness of the text the message. Even if it could restore damaged threads, header, and trailer data, the message itself might be garbled. Furthermore, messages that are contained in damaged blocked are more likely to be garbled than those in undamaged blocks. .spb .unl 5 2. The salvager is much simplified by this implementation .spb .inl 0 The salvager is divided into two procedures, ms_salvager_ and ms_salv_util_. The procedure ms_salvager_ does the following: .spb .inl 10 .unl 5 1. Establishes a cleanup handler to truncate the message segment. This step prevents repeated crawlouts from the administrative ring. .spb .unl 5 2. Computes the variables needed in salvaging. These are the same variables used by mseg_ (see the description of mseg_). .spb .unl 5 3. Calls ms_salv_util_ to attempt a backward salvage. .spb .unl 5 4. If all messages were saved, skips the next step. .spb .unl 5 5. Call ms_salv_util_ to attempt a backward salvage. .spb .unl 5 6. If anything was saved, updates the inconsistent information in the message segment. .spb .inl 0 No changes are made to the message segment until it is determined that some data has been saved. This sequence is necessary because the salvager is used in the conversion module to check the format of a message segment before it is converted. If the message segment salvager wrote into a message segment of an incorrect format, it would render the segment useless. .inl 0 .ifi l1h "Converting Message Segments" This module is responsible for converting message segments from one format to another. It consists of the following procedures: .ifi l2exact "_m_s_e_g_" .ifi l2toc "mesg_" This is the dispatching procedure through which all calls to manipulate message segments are routed. After checking access to the message segment, mseg_ takes the following steps: .spb .inl 10 .unl 5 1. Checks the version number of the message segment. A version 1 message segment lacks a unique identifier in the second word of the message segment header. All other message segments contain the version number in a fixed location in the header. .spb .unl 5 2. If a format error is detected, salvages the message segment and returns. .spb .unl 5 3. If the version number in the message segment header is not equal to the version number stored in the message segment data base, attempts to convert the message segment. The conversion is accomplished by calling a procedure with a standard calling sequence. This code should not have to be changed if another version of message segments is created. .spb .unl 5 4. If the conversion is successful, continues the operation. .spb .unl 5 5. If the conversion is unsuccessful because a needed procedure was missing (error_table_$improper_data_format returned from mseg_convert_), returns this code to the user, unlocks the message segment, and returns. .spb .unl 5 6. If the conversion was unsuccessful for any other reason, assumes a format error in the current version and attempts to salvage. .inl 0 .ifi l2exact "_m_s_e_g__a_d_d_" .ifi l2toc "mseg_add_" This procedure is used to add a message to a message segment. It normally obtains the user ID of the message from get_group_id_. An entry named mseg_add_$convert is provided for conversion purposes to add a message with a user ID specified by the caller. .inl 0 .ifi l2exact "_m_s_e_g__c_o_n_v_e_r_t_" .ifi l2toc "mseg_convert_" This procedure is called by the mseg_ routine and is responsible for performing the conversion. It accepts as arguments the version number of the message segment to be converted and the version number to which to convert it. The procedure mseg_convert_ executes the following steps: .spb .inl 10 .unl 5 1. Checks for the existence of procedures needed to convert the message segment to the version just previous to the current version. If these procedures are not present, returns the code error_table_$improper_data_format. .spb .unl 5 2. If the old version is less than the current version - 1, calls itself recursively, decrementing the current version by 1. .spb .unl 5 3. If the old version is equal to the current version - 1, then: .spb .inl 15 .unl 5 a. Invokes the salvager corresponding to the old version. This step is executed to ensure consistency of the message segment. .spb .unl 5 b. Invokes the conversion procedure to convert form old version to old version + 1. .inl 0 .ifi l2exact "_m_s__s_a_l_v_a_g_e_r__v_n_" .ifi l2toc " ms_salvager_vn_" This procedure is made from the previous version salvager when a new version of message segments is created. _n is the now previous version number. Steps are: .spb .inl 10 .unl 5 1. Remove code to truncate bad message segments. .spb .unl 5 2. Change proc; add end statements and rename. .inl 0 .ifi l2exact "_m_s__s_a_l_v__u_t_i_l__v_n_" .ifi l2toc "ms_salv_util_vn_" This procedure is created from the previous version procedure by changing the proc: and end statements and renaming. .ifi l2exact "_m_s_e_g__u_t_i_l__v_n_" .ifi l2toc "mseg_util_vn_" This procedure is created from the previous version procedure by changing the proc: and end statements and renaming. .inl 0 .ifi l1exact "T__h_e M__e_s_s_a_g_e S__e_g_m_e_n_t D__a_t_a B__a_s_e (mseg_data_)" .ifi l1toc "The Message Segment Data Base" This data base contains all the constants needed by the message segment facility. A copy is included in Appendix A. .ifi l1h "Execution in the user Ring" A set of procedures that allow the facility to be executed in the user ring for debugging purposes. These procedures enable the caller to set breaks using debug and to run the facility without endangering installed message segments. To use this debugging environment: .spb .inl 10 .unl 5 1. The user must have access to phcs_. .spb .unl 5 2. The installed primitives must not have been installed by the user's process. If uncertain, it is wise to do a new_proc at this point. .spb .unl 5 3. To set up the environment, the user executes the following commands: .spb .inl 15 .unl 5 a. set_exmode_level _n; .spb .unl 5 b. in dummy_admin_gate_admin_gate .brf in dummy_message_segment_ message_segment_ .brf in dummy_mailbox_ mailbox_ .brf (These commands initiate private versions of the gates used by the message segment facility.) .spb .unl 5 c. Various procedures that manipulate message segments have entries to set the pathname of the directory containing the message segment. These entries should be called with the pathname of the user's test directory. .spb .unl 5 d. Message segments can now be created in the test directory and message segment commands executed on them. For a description of these commands see the queue message segment facility and the mailbox message segment facility. .inl 0 .ifi l1h "The Message Segment Command Utility" The message segment command utility (ms_create) has separate entries for queue message segment and mailbox commands and can be modified to add entries for new types of message segments. Data particular to each type of message segment is kept in an include file called extended_access_data. The commands check that the segments they work on have certain properties described in extended_access_data. Among these are the name suffix and the number of extended access bits defined. .spb 2 The commands are described under "Commands Interface" sections for each application. They dispatch appropriate message segment subroutine calls by: .spb .inl 10 .unl 5 1. Concatenating gate and entrynames for the type of message segment, obtained from extended_access_data. .spb .unl 5 2. Calling hcs_$make_ptr to get a pointer to the gate entry. .spb .unl 5 3. Calling cu_$ptr_call to call through the pointer with a uniform set of arguments. .spb 2 .inl 0 The module has its own name duplication handler to remove names from and to delete message segments. These operations require calls to message segment primitives. .spb 2 the ACL commands (ms_list_acl, mbx_delete_acl, etc.) call find_common_acl_names_ to return all the ACL entries that match a given set of access control name arguments. find_common_acl_names_ and its caller share data in the following structure: .spb .inl 5 .fif 1 data aligned based (datap), 2 aclp pointer, 2 bsp pointer, 2 acl_count fixed bin(17), 2 extended_access_bit_length fixed bin(17), 2 real_access_bit_length fixed bin(17); .fin .inl 0 .spb 2 Each ACL command with its list of access control name arguments does the following: .spb .inl 10 .unl 5 1. Calls find_common_acl_names_$init to list the ACL of the message segment, setting aclp. .spb .unl 5 2. Allocates and initializes to zero a string of bits corresponding to the ACL entries. Sets bsp to point to this bit string. Allocates an array big enough to hold all the access names. .spb .unl 5 3. Calls find_common_acl_names for each access control name argument. Gets back an updated bit string and an array of all matching names that were not returned by previous calls. Add these names to an ACL array that it is building. The ACL array contains no duplicated entries. .spb .unl 5 4. After all arguments have been processed, calls the appropriate ACL primitive with the new ACL array. .spb .unl 5 5. Frees the bit string, the ACL arrays, and the array of names. .spb .unl 5 Access control names are of the form: .spb .. .spb .inl 0 The matching strategy used by find_common_acl_names_ can be summarized in three rules: .spb .inl 10 .unl 5 1. A literal component name, including *, matches only a component of the same name. .spb .unl 5 2. A missing component name not delimited by a period (eg. *.Multics, in which the third component is missing) is treated the same as a literal *. Missing components on the left must be delimited by periods. .spb .unl 5 3. A missing component delimited by a period matches a component. .brp .inl 0  s5.ms.compin 04/19/84 0958.8r w 02/20/84 1350.0 338445 .ifi init_mpm "AN69" .srv section 5 .ifi l0h "Message Segment Applications" This section describes two specific applications of the message segment facility. These applications are queues and mailboxes. .ifi l1h "Extended Access" The extended access attributes for both kinds of message segment are: .spb .inl 10 .unl 5 a allows a user to add a message .spb .unl 5 d allows a user to delete any message .spb .unl 5 r allows a user to read any message .spb .unl 5 o allows a user to read and/or delete messages sent by him .spb .unl 5 s allows a user to find out the number of messages in the message segment and whether or not the message segment has been salvaged .inl 0 .ifi l1h "The Queue Message Segment Facility" The queue message segment facility is used to implement the I/O Daemon and Absentee Daemon queues. .spb 2 Topics discussed below include the subroutine calls and commands that work on queues. .ifi l2h "The Queue Message Segment Module" The queue message segment module is that portion of the message segment facility that defines queue message segments. It is composed of: .spb .inl 10 .unl 5 1. A gate (message_segment_) from the user ring into the administrative ring. It contains all the entries to queue message segment primitives. .spb .unl 5 2. A defining procedure (queue_mseg_) called through the gate. Before passing the call on to the appropriate primitive, this procedure checks that the name of the segment being referenced ends in the suffix ms. It also checks for any call involving the ACL of a message segment that only the first five bits of extended access (adros) are on. .inl 0 .ifi l2h "The Queue Message Segment Subroutine Interface" The following is a list of standard error codes returned by queue message segment facility subroutines. .spb .inl 37 .unl 37 C__o_d_e M__e_a_n_i_n_g .spb .unl 37 error_table_$bad_segment an inconsistency was detected in the message segment causing it to be salvaged. The call should be made again. .spb .unl 37 error_table_$moderr extended access is insufficient to perform the operation. .spb .unl 37 error_table_$no_message the requested message was not found. .spb .unl 37 error_table_$improper_data_format a message segment of different version number was encountered and the software necessary to perform the conversion cannot be found. .spb 2 .inl 0 The following is an alphabetized list of arguments used in the described calls. .inl 37 .spb .unl 37 acl_count (fixed bin) is the number of entries in the structure pointed to be aclp. .spb .unl 37 aclp (pointer) is a pointer to the following structure: .spb .inl 0 .fif declare 1 acl_entries (acl_count) aligned based (aclp), 2 access_name char(32) aligned, 2 modes bit(36) aligned, 2 extended_access bit(36) aligned, 2 reterr fixed bin(35); .fin .spb 2 .inl 0 where: .spb .inl 37 .unl 32 access_name is the access name (in the form Person_id.Project_id.tag) that identifies a class of users. .spb .unl 32 modes is the real access for this access name. .spb .unl 32 extended_access is the extended access for this access name. .spb .unl 32 reterr is a standard Multics system status code. .spb .unl 32 areap (pointer) is a pointer to a user defined area. .spb .unl 32 argp (pointer) is a pointer to the following structure: .spb .inl 0 .fif declare 1 mseg_return_args_ aligned based (argp), 2 ms_ptr ptr, 2 ms_len fixed bin(18), 2 sender_id char(32) aligned, 2 level fixed bin, 2 ms_id bit(72) aligned, 2 sender_authorization bit(72), 2 access_class bit(72); .fin .spb 2 .inl 0 where: .spb .inl 37 .unl 32 ms_ptr is a pointer to the returned message. .spb .unl 32 ms_len is the bit length of the returned message. .spb .unl 32 sender_id is the ID of the sender of the message in the form Person_id.Project_id.tag. .spb .unl 32 level is the validation level of the sender of the message. .spb .unl 32 ms_id is the ID of the returned message. .spb .unl 32 sender_authorization is the access authorization of the sender. .spb .unl 32 access_class is the access class of the message. .spb .unl 32 code (fixed bin(35)) is a standard file system error code. .spb .unl 32 dir_name (char (*)) is the pathname of the directory containing the message segment to be referenced. .spb .unl 32 direction (bit(2) aligned) is a switch indicating the direction of an incremental read. "00"b" => current message; "10"b => previous message; "01"b" => next message. .spb .unl 32 ent_name (char(*)) is a the entryname of the message segment to be referenced. .spb .unl 32 index (fixed bin) is an index to the message segment to be referenced. .spb .unl 32 message_count (fixed bin) is the number of messages in the message segment. .spb .unl 32 message_id (bit(72) aligned) is a unique identifier corresponding to a message in the message segment. .spb .unl 32 message_length (fixed bin(24)) is the length, in bits, of a message. .spb .unl 32 message_wanted (bit(1) aligned) is a switch indicating which message is wanted. "0"b => first message; "1"b => last message. .spb .unl 32 messagep (pointer) is a pointer to the message. .spb .unl 32 new_name (char(*)) is the name to which to rename a message segment. .spb .unl 32 old_name (char(*)) is the name of the message segment to be renamed. .spb .unl 32 salvaged_bit(bit(1) aligned) is a switch indicating whether or not the message segment has been salvaged. "0"b => no; "1"b => yes. .spb .unl 32 turn_off (bit(1) aligned) is a switch indicating whether or not to turn off salvaged bit. "0"b => no; "1"b => yes. .spb 2 .inl 0 The following is a list of subroutine calls to the queue message segment facility. They are grouped by class. .ifi l1h "Creating and Deleting Queue Message Segments" .ifi l2h "E__n_t_r_y: message_segment_$create" This entry point is used to create a queue message segment. .ifi l2h "Usage" .inl 10 .unl 5 declare message_segment_$create entry .brf (char(*), char(*), fixed bin(35)); .spb .unl 5 call message_segment_$create .brf (dir_name, ent_name, code); .spb .unl 5 1. dir_name Input .spb .unl 5 2. ent_name Input .spb .unl 5 3. code Output .inl 0 .ifi l2h "E__n_t_r_y: message_segment_$delete" This entry is used to delete a queue message segment. .ifi l2h "Usage" .inl 10 .unl 5 declare message_segment_$delete .brf (char (*), char(*), fixed bin(35)); .spb call message_segment_$delete .brf (dir_name, ent_name, code); .spb .unl 5 1. dir_name Input .spb .unl 5 2. ent_name Input .spb .unl 5 3. code Output .inl 0 .ifi l1h "Manipulating Queue Message Segment Extended Access" .ifi l2h "E__n_t_r_y: message_segment_$ms_acl_add" This entry point is used to add one or more entries to the access control list of a queue message segment. .ifi l2h "Usage" .inl 10 .unl 5 declare message_segment_$ms_acl_add .brf entry (char(*), char(*), ptr, fixed bin, fixed!bin(35)); .spb .unl 5 call message_segment_$ms_acl_add .brf (dir_name, ent_name, aclp, acl_count, code); .spb .unl 5 1. dir_name Input .spb .unl 5 2. ent_name Input .spb .unl 5 3. aclp Input .spb .unl 5 4. acl_count Input .spb .unl 5 5. code Output .inl 0 .ifi l2h "E__n_t_r_y: message_segment_$ms_acl_delete" This entry point is used to delete one or more entries from the access control list of a queue message segment. .ifi l2h "Usage" .inl 10 .unl 5 declare message_segment_$ms_acl_delete .brf entry (char(*), char(*), ptr, fixed!bin, ptr, fixed!Bin 35)); .spb .unl 5 call message_segment_$ms_acl_delete .brf (dir_name, ent_name, aclp, acl_count, areap, code); .spb .unl 5 1. dir_name Input .spb .unl 5 2. ent_name Input .spb .unl 5 3. aclp see Note .spb .unl 5 4. acl_count see Note .spb .unl 5 5. areap see Note .spb .unl 5 6. code Output .inl 0 .ifi l2h "Note" If acl_count is equal to -1, areap is assumed to point to a user area. In this case the entire ACL is replaced with two entries, one for *.*.* and one for *.SysDaemon.*, both with null extended access. Information about these entries is returned in this area pointed to be areap. aclp is set to point to the allocated data and acl_count is set to the number of entries. If acl_count is not -1, then aclp is assumed to point to a structure containing the ACL entries enumerated by acl_count. The entries for *.*.* and *.SysDaemon.* cannot be deleted. .inl 0 .ifi l2h "E__n_t_r_y: message_segment_$ms_acl_list" This entry point is used to list one or more items from the access control list of a queue message segment. .ifi l2h "Usage" .inl 10 .unl 5 declare message_segment_$ms_acl_list_entry .brf (char(*), char(*), ptr, fixed!bin, ptr, fixed bin!35)); .spb .unl 5 call message_segment_$ms_acl_list (dir_name, ent_name, aclp, acl_count, areap, code); .spb .unl 5 1. dir_name Input .spb .unl 5 2. ent_name Input .spb .unl 5 3. aclp See Note .spb .unl 5 4. acl_count see Note .spb .unl 5 5. areap see Note .spb .unl 5 6. code Output .inl 0 .ifi l2h "Note" If acl_count is -1, areap is assumed to point to a user defined area. A list of the entire ACL is returned in space allocated in this area and aclp is set to point to the list. if acl_count is not -1, areap may be null and aclp is assumed to point to an ACL data structure in which data is returned. .inl 0 .ifi l2h "E__n_t_r_y: message_segment_$ms_acl_replace" This entry point is used to replace the access control list of a queue message segment. .ifi l2h "Usage" .inl 10 .unl 5 declare message_segment_$ms_acl_replace_entry" .brf (dir_name, ent_name, aclp, acl_count, code); .spb .unl 5 1. dir_anme Input .spb .unl 5 2. ent_name Input .spb .unl 5 3. aclp Input .spb .unl 5 4. acl_count Input .spb .unl 5 5. code Output .inl 0 .ifi l2h "Note" The list of entries replacing the current access control list must contain entries for *.*.* and *.SysDaemon.*. .ifi l2h "E__n_t_r_y: message_segment_$chname_file" .ifi l1h "Manipulating Queue Message Segments" This entry point is used to rename a queue message segment. .ifi l2h "Usage" .inl 10 .unl 5 declare message_segment_$chname_file entry .brf (char(*), char(*), char(*), char(*), fixed bin!35Z)); .spb .unl 5 call message_segment_$chname_file .brf (dir_name, ent_name, old_name, new_name, code); .spb .unl 5 1. dir_name Input .spb .unl 5 2. ent_name Input .spb .unl 5 3. old_name Input .spb .unl 5 4. new_name Input .spb .unl 5 5. code Output .inl 0 .spb 2 The remaining primitives in this section can be called either of two ways: .spb .inl 10 .unl 5 1. The message segment can be opened using message_segment_$open and calls made with the index thus obtained. .spb .unl 5 2. The primitive can be called directly using dir_name and ent_name to reference the segment. .spb 2 .inl 0 The former method is more efficient for repeated calls as it avoids repeated initiations and terminations of the message segment in the administrative ring. .spb 2 The entries are documented in pairs corresponding to the two modes of use. .ifi l1h "Opening and Closing a Queue Message Segment" This entry point is called to open and get an index to a queue message segment. .ifi l2h "Usage" .inl 10 .unl 5 declare message_segment_$open_entry .brf (char(*), char(*), fixed bin, fixed bin(35); .spb .unl 5 call message_segment_$open .brf (dir_name, ent_name, index, code); .spb .unl 5 1. dir_name Input .spb .unl 5 2. ent_name Input .spb .unl 5 3. index Output .spb .unl 5 4. code Output .inl 0 .ifi l2h "E__n_t_r_y: message_segment_$close" This entry point is used to close a queue message segment after it has been opened. .ifi l2h "Usage" .inl 10 .unl 5 declare message_segment_$close entry .brf (fixed bin fixed bin(35)); .spb .unl 5 call message_segment_$close .brf (index, code); .spb .unl 5 1. index Input .spb .unl 5 2. code Output .inl 0 .ifi l1h "Obtaining Queue Message Segment Header Status" .spb 2 E__n_t_r_y: message_segment_$check_salv_bit_index" .brf message_segment_$check_salv_bit_file .ifi l2toc "check_salv_bit" This entry point is used to check whether or not a queue message segment has been salvaged. .ifi l2h "Usage" .inl 10 .unl 5 declare message_segment_$check_salv_bit_index .brf entry (fixed bin, bit(1) aligned, bit(1) aligned, fixed bin(35)); .spb .unl 5 call message_segment_$check_salv_bit_index .brf (index, turn_off, salvaged_bit, code) .spb .unl 10 or: .spb .unl 5 declare message_message_$check_salv_bit_file entry .brf (char(*), char(*), bit(1) aligned, bit(1) aligned, fixed bin(35)); .spb .unl 5 call message_segment_$check_salv_bit_file .brf (dir_name, ent_name, turn_off, salvaged_bit, code); .spb .unl 5 1. index Input .spb .unl 5 2. turn_off Input .spb .unl 5 3. salvaged_bit Input .spb .unl 5 4. code Output .spb .unl 5 5. dir_name Input .spb .unl 5 6. ent_name Input .inl 0 .ifi l2h "Note" The caller must have s extended access to the message segment. If the turn_off bit is on, indicating that the caller wishes to turn off the salvaged bit, the caller must have delete extended access to the message segment. .spb 2 E__n_t_r_y: message_segment_$get_message_count_index .brf message_segment_$get_message_count_file .inl 0 This entry point is used to obtain the number of messages in a message segment. .ifi l2h "Usage" .inl 10 .unl 5 declare message_segment_$get_message_count_index .brf entry (fixed bin, fixed bin(24), fixed bin(35)); .spb .unl 5 call message_segment_$get_message_count_index .brf (index, message_count, code); .spb .unl 10 or: .spb .unl 5 declare message_segment_$get_message_count_file .brf entry (char(*), char(*), fixed bin, fixed bin(35)); .spb .unl 5 call message_segment_$get_message_count_file .brf (dir_name, ent_name, message_count, code); .spb .unl 5 1. index Input .spb .unl 5 2. message_count Output .spb .unl 5 3. code output .spb .unl 5 4. dir_name Input .spb .unl 5 5. ent_name Output .inl 0 .ifi l2h "Note" The caller must have status extended access to the message segment. .ifi l1h "Obtaining Effective Access to a Message Segment" E__n_t_r_y: message_segment_$get_mode_index .brf message_segment_$get_mode_file .ifi l2toc "get_mode" .spb 2 .inl 0 This entry point is used to find out the user's effective extended access to a message segment. .ifi l2h "Usage" .inl 10 .unl 5 declare message_segment_$get_mode_index entry .brf (fixed bin, fixed bin(5), fixed bin(35)); .spb .unl 5 call message_segment_$get_mode_index .brf (index, mode, code); .spb .unl 10 or: .spb .unl 5 declare message_segment_$get_mode_file entry .brf (char(*), char(*), fixed bin(5), fixed bin(35)); .spb .unl 5 call message_segment_$get_mode_file .brf (dir_name, ent_name, mode, code); .spb .unl 5 1. index Input .spb .unl 5 2. mode Output .spb .unl 5 3. code Output .spb .unl 5 4. dir_name Input .spb .unl 5 5. ent_name Input .inl 0 .ifi l1h "Adding Messages to a Queue Message Segment" E__n_t_r_y: message_segment_$add_index .brf message_segment_$add_file .ifi l2toc "add" This entry point is used to add a message to a message segment. .ifi l2h "usage" .inl 10 .unl 5 declare message_segment_$add_index entry .brf (fixed bin, ptr, fixed bin(24), bit(72) aligned, fixed bin(35)); .spb .unl 5 call message_segment_$add_index .brf (index, messagep, message_length, message_id, code); .spb .unl 10 or: .spb .unl 5 declare message_segment_$add_file entry .brf (char(*), char(*), ptr, fixed bin(24), bit(72) aligned, fixed bin(35)); .spb .unl 5 call message_segment_$add_file .brf (dir_name, ent_name, messagep, message_length, message_id, code); .spb .unl 5 1. index Input .spb .unl 5 2. messagep Input .spb .unl 5 3. message_length Input .spb .unl 5 4. message_id Input .spb .unl 5 5. code Output .spb .unl 5 6. dir_name Input .spb .unl 5 7. ent_name Input .inl 0 .ifi l2h "Note" The caller must have append extended access to the message segment. .ifi l1h "Deleting Messages From a Queue Message Segment" E__n_t_r_y: message_segment_$delete_index .brf message_segment_$delete_file .ifi l2toc "delete" This entry point is used to delete a message from a message segment. .ifi l2h "Usage" .inl 10 .unl 5 declare message_segment_$delete_index entry .brf (fixed bin, bin(72) aligned, fixed bin(35)); .spb .unl 5 call message_segment_$delete_index .brf (index, message_id, code); .spb .unl 10 or: .spb .unl 5 declare message_segment_$delete_file entry .brf (char(*), char(*), bit(72) aligned, fixed bin(35)); .spb .unl 5 call message_segment_$delete_file .brf (dir_name, ent_name, message_id, code); .spb .unl 5 1. index Input .spb .unl 5 2. message_id Input .spb .unl 5 3. code Output .spb .unl 5 4. dir_name Input .spb .unl 5 5. ent_name Input .inl 0 .ifi l2h "Note" To delete a message sent by the caller, owner and/or delete extended access to the message segment is required. To delete a message sent by someone other than the caller, delete extended access to the message segment is required. .inl 0 .ifi l1h "Reading Messages From a Queue Message Segment" E__n_t_r_y: message_segment_$read_index .brf message_segment_$read_file .ifi l2toc "read" This entry point is used to read the first or last message from a message segment. .ifi l2h "Usage" .inl 10 .unl 5 declare message_segment_$read_index entry .brf (fixed bin, ptr, bit(1) aligned, ptr, fixed bin(35)); .spb .unl 5 call message_sgment_$read_index .brf (index, areap, message_wanted, argp, code); .spb .unl 10 or: .spb .unl 5 declare message_segment_$read_file entry .brf (char(*), char(*), ptr, bit(1) aligned, ptr, fixed!bin(35)); .spb .unl 5 call message_segment_$read_file .brf (dir_name, ent_name, areap, message_wanted, argp, code); .spb .unl 5 1. index Input .spb .unl 5 2. areap Input .spb .unl 5 3. message_wanted Input .spb .unl 5 4. argp Input .spb .unl 5 5. code Output .spb .unl 5 6. dir_name Input .spb .unl 5 7. ent_name Input .inl 0 .ifi l2h "Note" The caller must have read extended access to the message segment. E__n_t_r_y: message_segment_$incremental_read_index"" message_segment_$incremental_read_file .ifi l2toc "incremental read" This entry point is used to read a message incremental to another message. The message_id of the message from which the incremental read is to take place must be supplied as an argument, therefore the read entry must be called prior to calling this entry. .ifi l2h "Usage" .inl 10 .unl 5 declare message_segment_$incremental_read_index .brf entry(fixed bin, ptr, bit(2) aligned, bit(72) aligned, ptr, fixed bin(35)); .spb .unl 5 call message_segment_$incremental_read_index .brf (index, areap, direction, message_id, argp, code); .spb .unl 10 or: .spb .unl 5 declare message_segment_$incremental_read_file .brf entry (char(*), char(*), ptr, bit(2) aligned, bit(72) aligned, ptr, fixed bin(35)); .spb .unl 5 call message_segment_$incremental_read_file .brf (dir_name, ent_name, areap, direction, message_id, argp, code); .spb .unl 5 1. index Input .spb .unl 5 2. areap Input .spb .unl 5 3. direction Input .spb .unl 5 4. message_id Input .spb .unl 5 5. argp Input .spb .unl 5 6. code output .spb .unl 5 7. dir_name Input .spb .unl 5 8. ent_name Input .inl 0 .ifi l2h "Note" The caller must have read extended access to the segment. .ifi l1h "Combined Read and Delete From a Queue Message Segment" E__n_t_r_y: message_segment_$read_delete_index .brf message_segment_$read_delete_file .ifi l2toc "read_delete" This entry point is used to read and delete the first or last message from a queue message segment. .ifi l2h "Usage" .inl 10 .unl 5 declare message_segment_$read_delete_index .brf entry (fixed bin, ptr, bit(1) aligned, ptr, fixed bin(35)); .spb .unl 5 call message_segment_$read_delete_index .brf (index, areap, message_wanted, argp, code); .spb .unl 5 1. index Input .spb .unl 5 2. areap Input .spb .unl 5 3. message_wanted Input .spb .unl 5 4. argp Input .spb .unl 5 5. code Output .spb .unl 5 6. dir_name Input .spb .unl 5 7. ent_name Input .inl 0 .ifi l2h "Note" The caller must have read and delete extended access to the message segment. .ifi l1h "Rewriting Messages in a Queue Message Segment" E__n_t_r_y: message_segment_$update_message_index .brf message_segmetn_$update_message_file .ifi l2toc "updating_message" .spb 2 This entry point is used to rewrite the first n bits of an existing message in a queue message segment. .ifi l2h "Usage" .inl 10 .unl 5 declare message_segment_$update_message_index .brf entry (fixed bin, fixed bin(24), bit(72) aligned, ptr, fixed bin(35)); .spb .unl 5 call message_segment_$update_message_index .brf (index, message_length, message_id, messagep, code); .spb .unl 10 or: .spb .unl 5 declare message_segment_$update_message_file .brf entry (char(*), char(*), fixed bin(18), bit(72) aligned, ptr, fixed bin(35)); .spb .unl 5 call message_segment_$update_message_file .brf (dir_name, ent_name, message_length, message_id, messagep, code); .spb .unl 5 1. index Input .spb .unl 5 2. message_length Input .brf is the number of bits of the message to be rewrtten. .spb .unl 5 3. message_id Input .spb .unl 5 4. messsagep Input .spb .unl 5 5. code Output .spb .unl 5 6. dir_name Input .spb .unl 5 7. ent_name Input .inl 0 .ifi l2h "Note" The caller must have delete extended access to the message segment. .spb 2 The lengths of the old and new messages must be the same. .ifi l1h "Reading Caller Messages From a Queue Message Segment" These entries return a message that was sent by the caller. In contrast to the read extended access, these entries require read and/or owner extended access. .spb 2 E__n_t_r_y: message_segment_$own_read_index .brf message_segment_$own_read_file .ifi l2toc "own_read" These entries return a message that was sent by the caller. In contrast to the read and incremental_read entries, which require read extended access, these entries require read and/or owner extended access. .spb 2 E__n_t_r_y: message_segment_$own_read_index .brf message_segment_$own_read_file .spb 2 This entry point is used to read the first or last message placed by the caller in a queue message segment. .ifi l2h "Usage" .inl 10 .unl 5 declare message_segment_$own_read_index .brf entry (fixed bin, ptr, bit(1) aligned, ptr, fixed b in(35)); .spb .unl 5 call message_segment_$own_read_index .brf (index, areap, message_wanted, arg_ptr, code); .spb .unl 10 or: .spb .unl 5 declare message_segment_$own_read_file .brf entry (char(*), char(*), ptr, bit(1) aligned, ptr, fixed bin(35)); .spb .unl 5 call message_segment_$own_read_file .brf (dir_name, ent_name, areap, message_wanted, arg_ptr, code); .spb .unl 5 1. index Input .spb .unl 5 2. areap Input .spb .unl 5 3. message_wanted Input .spb .unl 5 4. arg_ptr Input .spb .unl 5 5. code Output .spb .unl 5 6. dir_name Input .spb .unl 5 7. ent_name Input .spb 2 E__n_t_r_y: message_segment_$own_incremental_read_index .brf message_segment_$own_incremental_read_file .ifi l2toc "own_incremental_read" This entry point is used to read a message placed by the caller in q queue message segment incremental to another message placed by the caller in that message segment. The message_id of the message from which the incremental read is to take place must be supplied, therefore the own_read entry must be called prior to calling this entry. .ifi l2h "Usage" .inl 10 .unl 5 declare message_segment_$own_incremental_read_index .brf entry (fixed bin, ptr, bit(2) aligned, bit(72) aligned, ptr, fixed bin(35)); .spb .unl 5 call message_segment_$own_incremental_read_index .brf (index, areap, direction, message_id, argp, code); .spb .unl 10 or: .spb .unl 5 declare message_segment_$own_incremental_read_file .brf entry (char(*), char(*), ptr, bit(2) aligned, bit(72) aligned, ptr, fixed bin(35)); .spb .unl 5 call message_segment_$own_incremental_read_file .brf (dir_name, ent_name, areap, direction, message_id, argp, code); .spb .unl 5 1. index Input .spb .unl 5 2. areap Input .spb .unl 5 3. direction Input .spb .unl 5 4. message_id Input .spb .unl 5 5. argp Input .spb .unl 5 6. code Output .spb .unl 5 7. dir_name Input .spb .unl 5 8. ent_name Input .inl 0 .ifi l2h "The Queue Message Segment Command Interface" The following is an alphabetized list of the commands that manipulate queue message segments. .ifi l3h "N__a_m_e: ms_add_name, msan" The ms_add_name command adds alternate names to the exisitng name(s) of a message segment. .ifi l2h "Usage" ms_add_name path entries .spb 2 where: .spb .inl 10 .unl 10 1. path .brf is the pathname of a message segment. The star convention is allowed. .spb .unl 10 2. entries .brf are names to be added. The equal convention is allowed. .inl 0 .ifi l2h "Note" If the suffix ms does not appear at the end of path, it is assumed. .spb Entry must be unique in the directory. If there is a name duplication and the old segment has only one name, the user is interrogated as to whether the old segment is to be deleted. If the old segment has other names, the conflicting name is removed and a message is printed to that effect. .spb 2 E__x_a_m_p_l_e .spb msan >ddd>idd>io_daemon_3 io_queue_3 .spb in the directory >ddd>idd. .ifi l3h "N__a_m_e: ms_create, mscr" The ms_create command create a message segment of a given name in a given directory. .ifi l2h "Usage" ms_create paths .spb where paths are the pathnames of message segments to be created. .inl 0 .ifi l2h "Notes" If the suffix ms does not appear at the end of path, it is assumed. .spb 2 The user must have append (a) access to the containing directory. .spb 2 Name duplication is handled similarly to ms_add_name. .spb 2 The user is given adros extended access to he message segment created. Null extended access is given to *.*.*. .spb 2 E__x_a_m_p_l_e .spb mscr io_daemon_3.ms >ddd>idd>io_daemon_2 .spb causes the message segment io_daemon_3.ms to be created in the working directory and the message segment io_daemon_2.ms to be created in the directory >ddd>idd. .ifi l3h "N__a_m_e: ms_delete, msdl" The ms_delete command deletes message segments. .ifi l2h "Usage" ms_delete paths .spb where paths are the pathnames of message segments to be deleted. The star convention is allowed. .ifi l2h "Notes" If the suffix ms does not appear at the end of path, it is assumed. .spb 2 The user must have modify (m) access to the containing directory and delete (d) extended access is lacking, the user is interrogated as to whether the message segment is to be deleted. .spb 2 E__x_a_m_p_l_e_s .spb msdl ** .spb deletes all message segments in the working directory. .spb msdl a.ms >udd>m>Doe>b .spb deletes a.ms in the working directory and b.ms in >udd>m>Doe. .ifi l3h "N__a_m_e: ms_delete_acl, msda" This control deletes some or all of the items on the Access Control List (ACL) of a message segment. .ifi l2h "Usage" ms_delete_acl path -acnames- .spb 2 where: .spb .inl 10 .unl 10 1. path .brf is the pathname of a message segment. The star convention is allowed. .spb .unl 10 2. acnames .brf are access control names. If there is no acname specified, the user's process group ID is assumed if it is -all (-a), the entry ACL is deleted. Person_id.Project_id.tag. Every ACL entry whose name matches the access control name is deleted. See "Noted" below for a description of the matching strategy. .inl 0 .ifi l2h "Notes" If the suffix ms does not appear at the end of path, it is assumed. .spb 2 An asterisk (*), in the access control name means the literal star character. Therefore, *.*.* matches only the ACL entry *.*.*. If a missing component; is not delimited by a period, it is assumed to be a literal star. *.Multics matches only the ACL entry *.Multics.*. If a missing component is delimited by a period, however, it matches any component. .spb .inl 12 .unl 12 Multics .brf Matches the ACL Multics.*.*. The absence of a leading period makes Multics the first component. .spb .unl 12 .bbl 1 .Multics. .brf matches any entry with middle component Multics .spb .unl 12 .bbl 1 .. .brf matches any ACL entry .spb .bbl 1 .unl 12 . matches any entry whose last component is * .spb .unl 12 null string .brf matches any entry ending in .*.* .inl 0 .spb 2 E__x_a_m_p_l_e .spb msda foo .Multics ..a .spb deletes from the ACL of foo.ms all entries ending in .Multics* and all entries with instance tag a. .spb msda foo.ms *.Multics.* Fred.. .spb deletes the entry *.Multics.* or prints an error message and deletes all entries with first component Fred. .inl 0 .ifi l3h "N__a_m_e: ms_delte_name, msdn" This command delete names form message segment having multiple names. .ifi l2h "Usage" ms_delete_name paths .spb where paths are the pathnames of message segments. The entryname portion is the name to be deleted. The star convention is allowed. .inl 0 .ifi l2h "Notes" If the suffix ms is missing from path, it is assumed. .spb 2 If deleting a name would leave no names on the message segment, the user is interrogated as to whether the message segment is to be deleted. .spb 2 E__x_a_m_p_l_e .spb msdn alpha >udd>Multics>Doe>beta .spb deletes the name aplha.ms form the list of names for the appropriate message segment in the current working directory and deletes the name beta.ms form the list of names for the appropriate message segment in the directory >udd>Multic>Doe. .inl 0 .ifi l3h "N__a_m_e: sms_list_acl, msla" This command lists some or all of the items on the Access Control List (ACL) of a message segment. .ifi l2h "Usage" ms_list_acl path -acnames- .spb .inl 0 where .inl 10 .unl 10 1. path .brf is the pathname of a messsage segment. The star convention is allowed. .spb .unl 10 2. acnames .brf are access control names. If there is no acname specified or if it is -all (-a), the entire ACL of the message segment is listed. Otherwise, acname must be of the form Person_id.Project_id.tag. All ACL entries with names matching the access control names are listed. The strategy for matching is described under "Notes" for ms_delete_acl. .inl 0 .ifi l2h "Note" If the suffix ms does not appear at the end of path, it is assumed. .spb 2 E__x_a_m_p_l_e_s .spb msla foo .Multics ..a .spb lists from the ACl of foo.ms all entries ending in .Multics.* and all entries with instance tag a. .inl 0 .ifi l3h "N__a_m_e: ms_rename, msrn" The ms_rename command replaces a specified name on a message segment, without affecting any other names the message segment has. .ifi l2h "Usage" ms_rename path1_ name1_...pathn_ namen_ .spb 2 where: .spb .inl 10 .unl 10 1. specifies the old name. The star convention is allowed. .spb .unl 10 2. namei_ .brf specifies the new name (i.e., replaces the entryname portion of pathi_). The equal convention is allowed. .inl 0 .ifi l2h "Notes" If the suffix ms does not appear at the end of pathi_ or namei_, it is assumed. .spb 2 Name duplication is handled similarly to ms_add_name. .spb 2 E__x_a_m_p_l_e .spb msrn alpha beta >udd>Multics>Doe>gamma.ms delta.ms .spb causes alpha.ms in the current working directory to be renamed beta.ms, and gamma.ms in the directory >udd>Multics>Doe to be renamed delta.ms. .inl 0 .ifi l3h "N__a_m_e: ms_set_acl, mssa" This command adds items to the Access Control List (ACL) of a message segment. .ifi l2h "Usage" .spb 2 where: .spb .inl 10 .unl 10 1. path .brf is the pathname of a message segment. The star convention is allowed. .spb .unl 10 2. adi_ .brf is the access to be given. It can consist of any or all of the letters adros or it can be null, n, or "" to denote null access. .spb .unl 10 3. acnamei_ .brf is an access control name. It must be of the form Person_id.Project_id.tag. If all three components are present, the ACL is searched for an entry by that name. If one is found, the access is changed. Otherwise, a new ACL entry is added. If one or more components are missing from the access control name, the access is changed on all entries that match the access control name. The strategy for matching is described under "Notes" for ms__delete_acl. .inl 0 .ifi l2h "Note" If the suffix ms does not appear at the end of path, it is assumed. .spb 2 E__x_a_m_p_l_e_s .spb mssa n ad Joe.proj .spb add to the ACL of the message segment n.ms an entry for Joe.Proj.* with add and delete access. .spb mssa ** adros * .spb gives *.*.* "adros" access to every message segment in the working directory. .ifi l2h "The Mailbox Message Segment Facility" The mailbox message segment facility implements user mailboxes for interprocess mail and messages. It resembles the queue message segment facility, with the following differences: .inl 10 .unl 5 1. The suffix on a mailbox is mbx instead of ms. .spb .unl 5 2. Two additional extended access bits determine what kinds of wakeups can accompany mailbox messages. These bits are: .inl 15 .spb .unl 5 w allows a user to send a normal wakeup when adding a message. .spb .unl 5 u allows a user to send an urgent wakwup when adding a message. .inl 0 .ifi l2h "The Mailbox Message Segment Module" The gate mailbox_ is similar to the gate message_segment_ in the queue message segment module. It has fewer entries. These are listed under "Subroutine Interface". .spb 2 The defining procedure mbx_mseg_ is similar to queue_mseg_ in the queue message segment module and makes similar checks before passing on its calls. Unlike queue_mseg_, it reserves the front part of each message for data peculiar to mailbox applications. The include file mail_format.incl.pl1 contains a structure describing this data: .spb .fif .inl 5 dcl 1 mail_format aligned 2 version fixed bin(17) 2 sent_from char(32) aligned, 2 lines fixed bin(17) 2 text_len fixed bin(17) 2 switches aligned, 3 wakeup bit(1) unaligned, 3 urgent bit(1) unaligned, 3 has_been_read bit(1) unaligned, 3 acknowledge bit(1) unaligned, 3 others bit(32) unaligned, 2 text aligned char (text_length refer(mail_format.text_len)); .fin .spb 2 .inl 0 where: .spb .inl 12 .unl 12 version .brf is a version number for the mailbox. .spb .unl 12 sent_from .brf is a terminal ID or other ID. .spb .unl 12 lines .brf is the number of lines in text. .spb .unl 12 wakeup .brf is one for a wakeup message .spb .unl 12 urgent .brf is on for an urgent wakeup message. .spb .unl 12 has_been_read .brf is on for an old message .spb .unl 12 acknowledge .brf is on if acknowledgement is desired. .spb .unl 12 text .brf is the actual text of the message. .spb .unl 12 text_length .brf is the actual number of characters in text. .inl 0 .ifi l2h "The Mailbox Message Segment Subroutine Interface" mailbox_$entry calls are similar to message_segment_$entry calls and take the same arguments. The following entries are available: .fif .inl 5 create delete chname open close .spb add_index delete_index read_index read_delete_index incremental_read_index own_read_index own_incremental_read_index .spb get_message_count_index get_mode_index check_salv_bit_index .spb 2 .inl 0 .fin mailbox_ ACL calls are similar to the corresponding message_segment_ calls, though they recognize seven extended access bits instead of five. The ACL calls are: .spb .inl 5 .fif mbx_acl_add mbx_axl_delete mbx_acl_list mbx_acl_replace .fin .inl 0 .ifi l2h "The Mailbox Message Segment Command Interface" The commands mbx_ (mbcc) perform the same functions or mailboxes that ms_ (mscc commands perform on queue message segments. They have the same user interface. Commands that work on ACLs recognize normal wakwup and urgent wakeup extended access. If the pathname of a mailbox does not end is mbx, that suffix is assumed. .brp .fin .inl 0  appa.ms.compin 04/19/84 0958.8r w 02/20/84 1401.2 34083 .ifi init_mpm "AN69" .srv section "A" .ifi l0exact "extended access data" .ifi l0toc "extended_access_data" dcl typp_count fixed bin(17) aligned int static init (2), .spb .fif 1 segdata (2) aligned int static, 2 gate_name char(32) aligned init ("message_segment_", "mailbox_"), 2 acl_prefix char(8) varying aligned init ("ms_", "mbx_"), 2 segment suffix length fixed bin (17) aligned init (3, 4), 2 segment_sufix char(8) aligned init (".ms", ".mbx"), 2 full_extended_access bit(36) aligned init ("111110000000000000000000000000000000"b, "111110000000000000000000000000000000"b) 2 first_extended_access_bit fixed bin(17) aligned init (1, 1), 2 mode_letter_count fixed bin(17) aligned init (5, 7), 2 mode_letters (36) char(1) aligned init ("a", "d", "r", "o", "s", (31)"", "a", "d", "r", "o", "s", "s", "u",(29)""); .brp .alc ms_block_hdr .alb .spb 5 dcl block_ptr pointer, /* pointer to message block */ .spb 1 ms_blocck_hdr aligned based (block_ptr), /* message block header structure */ 2 f_offset bit(18) unaligned, /* offset to next block of message */ 2 first_block bit(1) unaligned, /* ON if block is first in message */ 2 block_count bit(17) unaligned; /* number of message bits in block */ .fin .brp .alc ms_block trailer .alb .fif dcl tr_ptr pointer, /* pointer to message block trailer */ .spb 1 ms_block_trailer aligned based (tr_ptr), /* message block trailer structure */ 2 tr_pattern bit(36) aligned, /* to identify beginning of trailer */ 2 f_offset bit(18) unaligned, /* offset to next logical message */ 2 b_offset bit(18) unaligned, /* offset to previous logical message */ 2 ms_size bit (18) unaligned, /* bit count of the message */ 2 time bit(54) unaligned, /* time the message was sent */ 2 ring_no bit(18) unaligned, /* validation level */ 2 pad bit(18) unaligned, .spb 2 sender_id char(32) aligned; /* id of message sender */ .fin .brp .alc mseg_data_ .alb .spb 5 .fif segdef max_message_size segdef block_size segdef version_number segdef block_hdr_data segdef block_trailer_number segdef mseg_b36 segdef mseg_tr36 .spb max_message_size: dec 2048 block_size: dec 32 version_number: dec 2 block_hdr_data: dec 1 block_trailer_data dec 13 mseg_b36 oct 252525252525 mseg_tr36 oct 777777777777 .fin .brp .alc mseg_hdr .alb .spb 5 .fif dcl mptr pointer /* pointer to message segment */ .spb 1 mseg_hdr aligned based (mptr), /* message segment header */ 2 lock bit(36) aligned, /*standard file system lock */ 2 mseg_pattern bit(36) aligned, /* to identity a message system */ 2 pad (6) fixed bin(17) aligned, 2 first_ms_offset bit(18) aligned, /* offset to first message */ 2 last_ms_offset bit818) aligned, /* offset to last message */ 2 alloc_len fixed bin, /* length of allocation bit string */ 2 space_left fixed bin, /* number of empty blocks */ 2 number_of_messages fixed bin, /* message count */ 2 block_size fixed bin, /* message block size */ 2 switches unaligned, 3 aip bit(1), /* ON if allocation is in progress */ 3 os bit(1), /* ON if message segment was salvaged */ 3 ms_in_hdr bit(1), /* ON if there is a header message */ 3 pad2 bit(33), 2 version_number fixed bin, /* version of message seg */ 2 hdr_ms_len fixed bin, /* length of header message */ 2 hdr_ms char(hdr_ms_len), /* space for header message */ 2 alloc_bits bit(alloc_len) aligned; /* allocation bit string */ .fin .brp .inl 0 ----------------------------------------------------------- Historical Background This edition of the Multics software materials and documentation is provided and donated to Massachusetts Institute of Technology by Group BULL including BULL HN Information Systems Inc. as a contribution to computer science knowledge. This donation is made also to give evidence of the common contributions of Massachusetts Institute of Technology, Bell Laboratories, General Electric, Honeywell Information Systems Inc., Honeywell BULL Inc., Groupe BULL and BULL HN Information Systems Inc. to the development of this operating system. Multics development was initiated by Massachusetts Institute of Technology Project MAC (1963-1970), renamed the MIT Laboratory for Computer Science and Artificial Intelligence in the mid 1970s, under the leadership of Professor Fernando Jose Corbato. Users consider that Multics provided the best software architecture for managing computer hardware properly and for executing programs. Many subsequent operating systems incorporated Multics principles. Multics was distributed in 1975 to 2000 by Group Bull in Europe , and in the U.S. by Bull HN Information Systems Inc., as successor in interest by change in name only to Honeywell Bull Inc. and Honeywell Information Systems Inc. . ----------------------------------------------------------- Permission to use, copy, modify, and distribute these programs and their documentation for any purpose and without fee is hereby granted,provided that the below copyright notice and historical background appear in all copies and that both the copyright notice and historical background and this permission notice appear in supporting documentation, and that the names of MIT, HIS, BULL or BULL HN not be used in advertising or publicity pertaining to distribution of the programs without specific prior written permission. Copyright 1972 by Massachusetts Institute of Technology and Honeywell Information Systems Inc. Copyright 2006 by BULL HN Information Systems Inc. Copyright 2006 by Bull SAS All Rights Reserved