The Open Group Base Specifications Issue 6
IEEE Std 1003.1, 2003 Edition
Copyright © 2001-2003 The IEEE and The Open Group

Definitions

The definitions in this section are stated so that they can be used as exact substitutes for the terms in text. They should not contain requirements or cross-references to sections within IEEE Std 1003.1-2001; that is accomplished by using an informative note. In addition, the term should not be included in its own definition. Where requirements or descriptions need to be addressed but cannot be included in the definitions, due to not meeting the above criteria, these occur in the General Concepts chapter.

In this revision, the definitions have been reworked extensively to meet style requirements and to include terms from the base documents (see the Scope).

Many of these definitions are necessarily circular, and some of the terms (such as "process") are variants of basic computing science terms that are inherently hard to define. Where some definitions are more conceptual and contain requirements, these appear in the General Concepts chapter. Those listed in this section appear in an alphabetical glossary format of terms.

Some definitions must allow extension to cover terms or facilities that are not explicitly mentioned in IEEE Std 1003.1-2001. For example, the definition of "Extended Security Controls" permits implementations beyond those defined in IEEE Std 1003.1-2001.

Some terms in the following list of notes do not appear in IEEE Std 1003.1-2001; these are marked suffixed with an asterisk (*). Many of them have been specifically excluded from IEEE Std 1003.1-2001 because they concern system administration, implementation, or other issues that are not specific to the programming interface. Those are marked with a reason, such as "implementation-defined".

Appropriate Privileges

One of the fundamental security problems with many historical UNIX systems has been that the privilege mechanism is monolithic-a user has either no privileges or all privileges. Thus, a successful "trojan horse" attack on a privileged process defeats all security provisions. Therefore, POSIX.1 allows more granular privilege mechanisms to be defined. For many historical implementations of the UNIX system, the presence of the term "appropriate privileges" in POSIX.1 may be understood as a synonym for "superuser" (UID 0). However, other systems have emerged where this is not the case and each discrete controllable action has appropriate privileges associated with it. Because this mechanism is implementation-defined, it must be described in the conformance document. Although that description affects several parts of POSIX.1 where the term "appropriate privilege" is used, because the term "implementation-defined" only appears here, the description of the entire mechanism and its effects on these other sections belongs in this equivalent section of the conformance document. This is especially convenient for implementations with a single mechanism that applies in all areas, since it only needs to be described once.

Byte

The restriction that a byte is now exactly eight bits was a conscious decision by the standard developers. It came about due to a combination of factors, primarily the use of the type int8_t within the networking functions and the alignment with the ISO/IEC 9899:1999 standard, where the intN_t types are now defined.

According to the ISO/IEC 9899:1999 standard:

The standard developers also felt that this was not an undue restriction for the current state-of-the-art for this version of IEEE Std 1003.1, but recognize that if industry trends continue, a wider character type may be required in the future.

Character

The term "character" is used to mean a sequence of one or more bytes representing a single graphic symbol. The deviation in the exact text of the ISO C standard definition for "byte" meets the intent of the rationale of the ISO C standard also clears up the ambiguity raised by the term "basic execution character set". The octet-minimum requirement is a reflection of the {CHAR_BIT} value.

Clock Tick

The ISO C standard defines a similar interval for use by the clock() function. There is no requirement that these intervals be the same. In historical implementations these intervals are different.

Command

The terms "command" and "utility" are related but have distinct meanings. Command is defined as "a directive to a shell to perform a specific task". The directive can be in the form of a single utility name (for example, ls), or the directive can take the form of a compound command (for example, "ls | grep name | pr" ). A utility is a program that can be called by name from a shell. Issuing only the name of the utility to a shell is the equivalent of a one-word command. A utility may be invoked as a separate program that executes in a different process than the command language interpreter, or it may be implemented as a part of the command language interpreter. For example, the echo command (the directive to perform a specific task) may be implemented such that the echo utility (the logic that performs the task of echoing) is in a separate program; therefore, it is executed in a process that is different from the command language interpreter. Conversely, the logic that performs the echo utility could be built into the command language interpreter; therefore, it could execute in the same process as the command language interpreter.

The terms "tool" and "application" can be thought of as being synonymous with "utility" from the perspective of the operating system kernel. Tools, applications, and utilities historically have run, typically, in processes above the kernel level. Tools and utilities historically have been a part of the operating system non-kernel code and have performed system-related functions, such as listing directory contents, checking file systems, repairing file systems, or extracting system status information. Applications have not generally been a part of the operating system, and they perform non-system-related functions, such as word processing, architectural design, mechanical design, workstation publishing, or financial analysis. Utilities have most frequently been provided by the operating system distributor, applications by third-party software distributors, or by the users themselves. Nevertheless, IEEE Std 1003.1-2001 does not differentiate between tools, utilities, and applications when it comes to receiving services from the system, a shell, or the standard utilities. (For example, the xargs utility invokes another utility; it would be of fairly limited usefulness if the users could not run their own applications in place of the standard utilities.) Utilities are not applications in the sense that they are not themselves subject to the restrictions of IEEE Std 1003.1-2001 or any other standard-there is no requirement for grep, stty, or any of the utilities defined here to be any of the classes of conforming applications.

Column Positions

In most 1-byte character sets, such as ASCII, the concept of column positions is identical to character positions and to bytes. Therefore, it has been historically acceptable for some implementations to describe line folding or tab stops or table column alignment in terms of bytes or character positions. Other character sets pose complications, as they can have internal representations longer than one octet and they can have display characters that have different widths on the terminal screen or printer.

In IEEE Std 1003.1-2001 the term "column positions" has been defined to mean character-not byte-positions in input files (such as "column position 7 of the FORTRAN input"). Output files describe the column position in terms of the display width of the narrowest printable character in the character set, adjusted to fit the characteristics of the output device. It is very possible that n column positions will not be able to hold n characters in some character sets, unless all of those characters are of the narrowest width. It is assumed that the implementation is aware of the width of the various characters, deriving this information from the value of LC_CTYPE , and thus can determine how many column positions to allot for each character in those utilities where it is important.

The term "column position" was used instead of the more natural "column" because the latter is frequently used in the different contexts of columns of figures, columns of table values, and so on. Wherever confusion might result, these latter types of columns are referred to as "text columns".

Controlling Terminal

The question of which of possibly several special files referring to the terminal is meant is not addressed in POSIX.1. The filename /dev/tty is a synonym for the controlling terminal associated with a process.

Device Number*

The concept is handled in stat() as ID of device.

Direct I/O

Historically, direct I/O refers to the system bypassing intermediate buffering, but may be extended to cover implementation-defined optimizations.

Directory

The format of the directory file is implementation-defined and differs radically between System V and 4.3 BSD. However, routines (derived from 4.3 BSD) for accessing directories and certain constraints on the format of the information returned by those routines are described in the <dirent.h> header.

Directory Entry

Throughout IEEE Std 1003.1-2001, the term "link" is used (about the link() function, for example) in describing the objects that point to files from directories.

Display

The Shell and Utilities volume of IEEE Std 1003.1-2001 assigns precise requirements for the terms "display" and "write". Some historical systems have chosen to implement certain utilities without using the traditional file descriptor model. For example, the vi editor might employ direct screen memory updates on a personal computer, rather than a write() system call. An instance of user prompting might appear in a dialog box, rather than with standard error. When the Shell and Utilities volume of IEEE Std 1003.1-2001 uses the term "display", the method of outputting to the terminal is unspecified; many historical implementations use termcap or terminfo, but this is not a requirement. The term "write" is used when the Shell and Utilities volume of IEEE Std 1003.1-2001 mandates that a file descriptor be used and that the output can be redirected. However, it is assumed that when the writing is directly to the terminal (it has not been redirected elsewhere), there is no practical way for a user or test suite to determine whether a file descriptor is being used. Therefore, the use of a file descriptor is mandated only for the redirection case and the implementation is free to use any method when the output is not redirected. The verb write is used almost exclusively, with the very few exceptions of those utilities where output redirection need not be supported: tabs, talk, tput, and vi.

Dot

The symbolic name dot is carefully used in POSIX.1 to distinguish the working directory filename from a period or a decimal point.

Dot-Dot

Historical implementations permit the use of these filenames without their special meanings. Such use precludes any meaningful use of these filenames by a Conforming POSIX.1 Application. Therefore, such use is considered an extension, the use of which makes an implementation non-conforming; see also Pathname Resolution .

Epoch

Historically, the origin of UNIX system time was referred to as "00:00:00 GMT, January 1, 1970". Greenwich Mean Time is actually not a term acknowledged by the international standards community; therefore, this term, "Epoch", is used to abbreviate the reference to the actual standard, Coordinated Universal Time.

FIFO Special File

See Pipe .

File

It is permissible for an implementation-defined file type to be non-readable or non-writable.

File Classes

These classes correspond to the historical sets of permission bits. The classes are general to allow implementations flexibility in expanding the access mechanism for more stringent security environments. Note that a process is in one and only one class, so there is no ambiguity.

Filename

At the present time, the primary responsibility for truncating filenames containing multi-byte characters must reside with the application. Some industry groups involved in internationalization believe that in the future the responsibility must reside with the kernel. For the moment, a clearer understanding of the implications of making the kernel responsible for truncation of multi-byte filenames is needed.

Character-level truncation was not adopted because there is no support in POSIX.1 that advises how the kernel distinguishes between single and multi-byte characters. Until that time, it must be incumbent upon application writers to determine where multi-byte characters must be truncated.

File System

Historically, the meaning of this term has been overloaded with two meanings: that of the complete file hierarchy, and that of a mountable subset of that hierarchy; that is, a mounted file system. POSIX.1 uses the term "file system" in the second sense, except that it is limited to the scope of a process (and a process' root directory). This usage also clarifies the domain in which a file serial number is unique.

Graphic Character

This definition is made available for those definitions (in particular, TZ ) which must exclude control characters.

Group Database

See User Database .

Group File*

Implementation-defined; see User Database .

Historical Implementations*

This refers to previously existing implementations of programming interfaces and operating systems that are related to the interface specified by POSIX.1.

Hosted Implementation*

This refers to a POSIX.1 implementation that is accomplished through interfaces from the POSIX.1 services to some alternate form of operating system kernel services. Note that the line between a hosted implementation and a native implementation is blurred, since most implementations will provide some services directly from the kernel and others through some indirect path. (For example, fopen() might use open(); or mkfifo() might use mknod().) There is no necessary relationship between the type of implementation and its correctness, performance, and/or reliability.

Implementation*

This term is generally used instead of its synonym, "system", to emphasize the consequences of decisions to be made by system implementors. Perhaps if no options or extensions to POSIX.1 were allowed, this usage would not have occurred.

The term "specific implementation" is sometimes used as a synonym for "implementation". This should not be interpreted too narrowly; both terms can represent a relatively broad group of systems. For example, a hardware vendor could market a very wide selection of systems that all used the same instruction set, with some systems desktop models and others large multi-user minicomputers. This wide range would probably share a common POSIX.1 operating system, allowing an application compiled for one to be used on any of the others; this is a [ specific] implementation. However, such a wide range of machines probably has some differences between the models. Some may have different clock rates, different file systems, different resource limits, different network connections, and so on, depending on their sizes or intended usages. Even on two identical machines, the system administrators may configure them differently. Each of these different systems is known by the term "a specific instance of a specific implementation". This term is only used in the portions of POSIX.1 dealing with runtime queries: sysconf() and pathconf().

Incomplete Pathname*

Absolute pathname has been adequately defined.

Job Control

In order to understand the job control facilities in POSIX.1 it is useful to understand how they are used by a job control-cognizant shell to create the user interface effect of job control.

While the job control facilities supplied by POSIX.1 can, in theory, support different types of interactive job control interfaces supplied by different types of shells, there was historically one particular interface that was most common when the standard was originally developed (provided by BSD C Shell). This discussion describes that interface as a means of illustrating how the POSIX.1 job control facilities can be used.

Job control allows users to selectively stop (suspend) the execution of processes and continue (resume) their execution at a later point. The user typically employs this facility via the interactive interface jointly supplied by the terminal I/O driver and a command interpreter (shell).

The user can launch jobs (command pipelines) in either the foreground or background. When launched in the foreground, the shell waits for the job to complete before prompting for additional commands. When launched in the background, the shell does not wait, but immediately prompts for new commands.

If the user launches a job in the foreground and subsequently regrets this, the user can type the suspend character (typically set to <control>-Z), which causes the foreground job to stop and the shell to begin prompting for new commands. The stopped job can be continued by the user (via special shell commands) either as a foreground job or as a background job. Background jobs can also be moved into the foreground via shell commands.

If a background job attempts to access the login terminal (controlling terminal), it is stopped by the terminal driver and the shell is notified, which, in turn, notifies the user. (Terminal access includes read() and certain terminal control functions, and conditionally includes write().) The user can continue the stopped job in the foreground, thus allowing the terminal access to succeed in an orderly fashion. After the terminal access succeeds, the user can optionally move the job into the background via the suspend character and shell commands.

Implementing Job Control Shells

The interactive interface described previously can be accomplished using the POSIX.1 job control facilities in the following way.

The key feature necessary to provide job control is a way to group processes into jobs. This grouping is necessary in order to direct signals to a single job and also to identify which job is in the foreground. (There is at most one job that is in the foreground on any controlling terminal at a time.)

The concept of process groups is used to provide this grouping. The shell places each job in a separate process group via the setpgid() function. To do this, the setpgid() function is invoked by the shell for each process in the job. It is actually useful to invoke setpgid() twice for each process: once in the child process, after calling fork() to create the process, but before calling one of the exec family of functions to begin execution of the program, and once in the parent shell process, after calling fork() to create the child. The redundant invocation avoids a race condition by ensuring that the child process is placed into the new process group before either the parent or the child relies on this being the case. The process group ID for the job is selected by the shell to be equal to the process ID of one of the processes in the job. Some shells choose to make one process in the job be the parent of the other processes in the job (if any). Other shells (for example, the C Shell) choose to make themselves the parent of all processes in the pipeline (job). In order to support this latter case, the setpgid() function accepts a process group ID parameter since the correct process group ID cannot be inherited from the shell. The shell itself is considered to be a job and is the sole process in its own process group.

The shell also controls which job is currently in the foreground. A foreground and background job differ in two ways: the shell waits for a foreground command to complete (or stop) before continuing to read new commands, and the terminal I/O driver inhibits terminal access by background jobs (causing the processes to stop). Thus, the shell must work cooperatively with the terminal I/O driver and have a common understanding of which job is currently in the foreground. It is the user who decides which command should be currently in the foreground, and the user informs the shell via shell commands. The shell, in turn, informs the terminal I/O driver via the tcsetpgrp() function. This indicates to the terminal I/O driver the process group ID of the foreground process group (job). When the current foreground job either stops or terminates, the shell places itself in the foreground via tcsetpgrp() before prompting for additional commands. Note that when a job is created the new process group begins as a background process group. It requires an explicit act of the shell via tcsetpgrp() to move a process group (job) into the foreground.

When a process in a job stops or terminates, its parent (for example, the shell) receives synchronous notification by calling the waitpid() function with the WUNTRACED flag set. Asynchronous notification is also provided when the parent establishes a signal handler for SIGCHLD and does not specify the SA_NOCLDSTOP flag. Usually all processes in a job stop as a unit since the terminal I/O driver always sends job control stop signals to all processes in the process group.

To continue a stopped job, the shell sends the SIGCONT signal to the process group of the job. In addition, if the job is being continued in the foreground, the shell invokes tcsetpgrp() to place the job in the foreground before sending SIGCONT. Otherwise, the shell leaves itself in the foreground and reads additional commands.

There is additional flexibility in the POSIX.1 job control facilities that allows deviations from the typical interface. Clearing the TOSTOP terminal flag allows background jobs to perform write() functions without stopping. The same effect can be achieved on a per-process basis by having a process set the signal action for SIGTTOU to SIG_IGN.

Note that the terms "job" and "process group" can be used interchangeably. A login session that is not using the job control facilities can be thought of as a large collection of processes that are all in the same job (process group). Such a login session may have a partial distinction between foreground and background processes; that is, the shell may choose to wait for some processes before continuing to read new commands and may not wait for other processes. However, the terminal I/O driver will consider all these processes to be in the foreground since they are all members of the same process group.

In addition to the basic job control operations already mentioned, a job control-cognizant shell needs to perform the following actions.

When a foreground (not background) job stops, the shell must sample and remember the current terminal settings so that it can restore them later when it continues the stopped job in the foreground (via the tcgetattr() and tcsetattr() functions).

Because a shell itself can be spawned from a shell, it must take special action to ensure that subshells interact well with their parent shells.

A subshell can be spawned to perform an interactive function (prompting the terminal for commands) or a non-interactive function (reading commands from a file). When operating non-interactively, the job control shell will refrain from performing the job control-specific actions described above. It will behave as a shell that does not support job control. For example, all jobs will be left in the same process group as the shell, which itself remains in the process group established for it by its parent. This allows the shell and its children to be treated as a single job by a parent shell, and they can be affected as a unit by terminal keyboard signals.

An interactive subshell can be spawned from another job control-cognizant shell in either the foreground or background. (For example, from the C Shell, the user can execute the command, CONVERSION ERROR (.Cm) csh  & .) Before the subshell activates job control by calling setpgid() to place itself in its own process group and tcsetpgrp() to place its new process group in the foreground, it needs to ensure that it has already been placed in the foreground by its parent. (Otherwise, there could be multiple job control shells that simultaneously attempt to control mediation of the terminal.) To determine this, the shell retrieves its own process group via getpgrp() and the process group of the current foreground job via tcgetpgrp(). If these are not equal, the shell sends SIGTTIN to its own process group, causing itself to stop. When continued later by its parent, the shell repeats the process group check. When the process groups finally match, the shell is in the foreground and it can proceed to take control. After this point, the shell ignores all the job control stop signals so that it does not inadvertently stop itself.

Implementing Job Control Applications

Most applications do not need to be aware of job control signals and operations; the intuitively correct behavior happens by default. However, sometimes an application can inadvertently interfere with normal job control processing, or an application may choose to overtly effect job control in cooperation with normal shell procedures.

An application can inadvertently subvert job control processing by "blindly" altering the handling of signals. A common application error is to learn how many signals the system supports and to ignore or catch them all. Such an application makes the assumption that it does not know what this signal is, but knows the right handling action for it. The system may initialize the handling of job control stop signals so that they are being ignored. This allows shells that do not support job control to inherit and propagate these settings and hence to be immune to stop signals. A job control shell will set the handling to the default action and propagate this, allowing processes to stop. In doing so, the job control shell is taking responsibility for restarting the stopped applications. If an application wishes to catch the stop signals itself, it should first determine their inherited handling states. If a stop signal is being ignored, the application should continue to ignore it. This is directly analogous to the recommended handling of SIGINT described in the referenced UNIX Programmer's Manual.

If an application is reading the terminal and has disabled the interpretation of special characters (by clearing the ISIG flag), the terminal I/O driver will not send SIGTSTP when the suspend character is typed. Such an application can simulate the effect of the suspend character by recognizing it and sending SIGTSTP to its process group as the terminal driver would have done. Note that the signal is sent to the process group, not just to the application itself; this ensures that other processes in the job also stop. (Note also that other processes in the job could be children, siblings, or even ancestors.) Applications should not assume that the suspend character is <control>-Z (or any particular value); they should retrieve the current setting at startup.

Implementing Job Control Systems

The intent in adding 4.2 BSD-style job control functionality was to adopt the necessary 4.2 BSD programmatic interface with only minimal changes to resolve syntactic or semantic conflicts with System V or to close recognized security holes. The goal was to maximize the ease of providing both conforming implementations and Conforming POSIX.1 Applications.

It is only useful for a process to be affected by job control signals if it is the descendant of a job control shell. Otherwise, there will be nothing that continues the stopped process.

POSIX.1 does not specify how controlling terminal access is affected by a user logging out (that is, by a controlling process terminating). 4.2 BSD uses the vhangup() function to prevent any access to the controlling terminal through file descriptors opened prior to logout. System V does not prevent controlling terminal access through file descriptors opened prior to logout (except for the case of the special file, /dev/tty). Some implementations choose to make processes immune from job control after logout (that is, such processes are always treated as if in the foreground); other implementations continue to enforce foreground/background checks after logout. Therefore, a Conforming POSIX.1 Application should not attempt to access the controlling terminal after logout since such access is unreliable. If an implementation chooses to deny access to a controlling terminal after its controlling process exits, POSIX.1 requires a certain type of behavior (see Controlling Terminal ).

Kernel*

See System Call* .

Library Routine*

See System Call* .

Logical Device*

Implementation-defined.

Map

The definition of map is included to clarify the usage of mapped pages in the description of the behavior of process memory locking.

Memory-Resident

The term "memory-resident" is historically understood to mean that the so-called resident pages are actually present in the physical memory of the computer system and are immune from swapping, paging, copy-on-write faults, and so on. This is the actual intent of IEEE Std 1003.1-2001 in the process memory locking section for implementations where this is logical. But for some implementations-primarily mainframes-actually locking pages into primary storage is not advantageous to other system objectives, such as maximizing throughput. For such implementations, memory locking is a "hint" to the implementation that the application wishes to avoid situations that would cause long latencies in accessing memory. Furthermore, there are other implementation-defined issues with minimizing memory access latencies that "memory residency" does not address-such as MMU reload faults. The definition attempts to accommodate various implementations while allowing conforming applications to specify to the implementation that they want or need the best memory access times that the implementation can provide.

Memory Object*

The term "memory object" usually implies shared memory. If the object is the same as a filename in the file system name space of the implementation, it is expected that the data written into the memory object be preserved on disk. A memory object may also apply to a physical device on an implementation. In this case, writes to the memory object are sent to the controller for the device and reads result in control registers being returned.

Mount Point*

The directory on which a "mounted file system" is mounted. This term, like mount() and umount(), was not included because it was implementation-defined.

Mounted File System*

See File System .

Name

There are no explicit limits in IEEE Std 1003.1-2001 on the sizes of names, words (see the definition of word in the Base Definitions volume of IEEE Std 1003.1-2001), lines, or other objects. However, other implicit limits do apply: shell script lines produced by many of the standard utilities cannot exceed {LINE_MAX} and the sum of exported variables comes under the {ARG_MAX} limit. Historical shells dynamically allocate memory for names and words and parse incoming lines a character at a time. Lines cannot have an arbitrary {LINE_MAX} limit because of historical practice, such as makefiles, where make removes the <newline>s associated with the commands for a target and presents the shell with one very long line. The text on INPUT FILES in the Shell and Utilities volume of IEEE Std 1003.1-2001, Section 1.11, Utility Description Defaults does allow a shell to run out of memory, but it cannot have arbitrary programming limits.

Native Implementation*

This refers to an implementation of POSIX.1 that interfaces directly to an operating system kernel; see also hosted implementation. A similar concept is a native UNIX system, which would be a kernel derived from one of the original UNIX system products.

Nice Value

This definition is not intended to suggest that all processes in a system have priorities that are comparable. Scheduling policy extensions, such as adding realtime priorities, make the notion of a single underlying priority for all scheduling policies problematic. Some implementations may implement the features related to nice to affect all processes on the system, others to affect just the general time-sharing activities implied by IEEE Std 1003.1-2001, and others may have no effect at all. Because of the use of "implementation-defined" in nice and renice, a wide range of implementation strategies is possible.

Open File Description

An "open file description", as it is currently named, describes how a file is being accessed. What is currently called a "file descriptor" is actually just an identifier or "handle''; it does not actually describe anything.

The following alternate names were discussed:

Orphaned Process Group

Historical implementations have a concept of an orphaned process, which is a process whose parent process has exited. When job control is in use, it is necessary to prevent processes from being stopped in response to interactions with the terminal after they no longer are controlled by a job control-cognizant program. Because signals generated by the terminal are sent to a process group and not to individual processes, and because a signal may be provoked by a process that is not orphaned, but sent to another process that is orphaned, it is necessary to define an orphaned process group. The definition assumes that a process group will be manipulated as a group and that the job control-cognizant process controlling the group is outside of the group and is the parent of at least one process in the group (so that state changes may be reported via waitpid()). Therefore, a group is considered to be controlled as long as at least one process in the group has a parent that is outside of the process group, but within the session.

This definition of orphaned process groups ensures that a session leader's process group is always considered to be orphaned, and thus it is prevented from stopping in response to terminal signals.

Page

The term "page" is defined to support the description of the behavior of memory mapping for shared memory and memory mapped files, and the description of the behavior of process memory locking. It is not intended to imply that shared memory/file mapping and memory locking are applicable only to "paged" architectures. For the purposes of IEEE Std 1003.1-2001, whatever the granularity on which an architecture supports mapping or locking, this is considered to be a "page" . If an architecture cannot support the memory mapping or locking functions specified by IEEE Std 1003.1-2001 on any granularity, then these options will not be implemented on the architecture.

Passwd File*

Implementation-defined; see User Database .

Parent Directory

There may be more than one directory entry pointing to a given directory in some implementations. The wording here identifies that exactly one of those is the parent directory. In pathname resolution, dot-dot is identified as the way that the unique directory is identified. (That is, the parent directory is the one to which dot-dot points.) In the case of a remote file system, if the same file system is mounted several times, it would appear as if they were distinct file systems (with interesting synchronization properties).

Pipe

It proved convenient to define a pipe as a special case of a FIFO, even though historically the latter was not introduced until System III and does not exist at all in 4.3 BSD.

Portable Filename Character Set

The encoding of this character set is not specified-specifically, ASCII is not required. But the implementation must provide a unique character code for each of the printable graphics specified by POSIX.1; see also Filenames .

Situations where characters beyond the portable filename character set (or historically ASCII or the ISO/IEC 646:1991 standard) would be used (in a context where the portable filename character set or the ISO/IEC 646:1991 standard is required by POSIX.1) are expected to be common. Although such a situation renders the use technically non-compliant, mutual agreement among the users of an extended character set will make such use portable between those users. Such a mutual agreement could be formalized as an optional extension to POSIX.1. (Making it required would eliminate too many possible systems, as even those systems using the ISO/IEC 646:1991 standard as a base character set extend their character sets for Western Europe and the rest of the world in different ways.)

Nothing in POSIX.1 is intended to preclude the use of extended characters where interchange is not required or where mutual agreement is obtained. It has been suggested that in several places "should" be used instead of "shall". Because (in the worst case) use of any character beyond the portable filename character set would render the program or data not portable to all possible systems, no extensions are permitted in this context.

Regular File

POSIX.1 does not intend to preclude the addition of structuring data (for example, record lengths) in the file, as long as such data is not visible to an application that uses the features described in POSIX.1.

Root Directory

This definition permits the operation of chroot(), even though that function is not in POSIX.1; see also File Hierarchy .

Root File System*

Implementation-defined.

Root of a File System*

Implementation-defined; see Mount Point* .

Signal

The definition implies a double meaning for the term. Although a signal is an event, common usage implies that a signal is an identifier of the class of event.

Superuser*

This concept, with great historical significance to UNIX system users, has been replaced with the notion of appropriate privileges.

Supplementary Group ID

The POSIX.1-1990 standard is inconsistent in its treatment of supplementary groups. The definition of supplementary group ID explicitly permits the effective group ID to be included in the set, but wording in the description of the setuid() and setgid() functions states: "Any supplementary group IDs of the calling process remain unchanged by these function calls". In the case of setgid() this contradicts that definition. In addition, some felt that the unspecified behavior in the definition of supplementary group IDs adds unnecessary portability problems. The standard developers considered several solutions to this problem:

  1. Reword the description of setgid() to permit it to change the supplementary group IDs to reflect the new effective group ID. A problem with this is that it adds more "may''s to the wording and does not address the portability problems of this optional behavior.

  2. Mandate the inclusion of the effective group ID in the supplementary set (giving {NGROUPS_MAX} a minimum value of 1). This is the behavior of 4.4 BSD. In that system, the effective group ID is the first element of the array of supplementary group IDs (there is no separate copy stored, and changes to the effective group ID are made only in the supplementary group set). By convention, the initial value of the effective group ID is duplicated elsewhere in the array so that the initial value is not lost when executing a set-group-ID program.

  3. Change the definition of supplementary group ID to exclude the effective group ID and specify that the effective group ID does not change the set of supplementary group IDs. This is the behavior of 4.2 BSD, 4.3 BSD, and System V Release 4.

  4. Change the definition of supplementary group ID to exclude the effective group ID, and require that getgroups() return the union of the effective group ID and the supplementary group IDs.

  5. Change the definition of {NGROUPS_MAX} to be one more than the number of supplementary group IDs, so it continues to be the number of values returned by getgroups() and existing applications continue to work. This alternative is effectively the same as the second (and might actually have the same implementation).

The standard developers decided to permit either 2 or 3. The effective group ID is orthogonal to the set of supplementary group IDs, and it is implementation-defined whether getgroups() returns this. If the effective group ID is returned with the set of supplementary group IDs, then all changes to the effective group ID affect the supplementary group set returned by getgroups(). It is permissible to eliminate duplicates from the list returned by getgroups(). However, if a group ID is contained in the set of supplementary group IDs, setting the group ID to that value and then to a different value should not remove that value from the supplementary group IDs.

The definition of supplementary group IDs has been changed to not include the effective group ID. This simplifies permanent rationale and makes the relevant functions easier to understand. The getgroups() function has been modified so that it can, on an implementation-defined basis, return the effective group ID. By making this change, functions that modify the effective group ID do not need to discuss adding to the supplementary group list; the only view into the supplementary group list that the application writer has is through the getgroups() function.

Symbolic Link

Many implementations associate no attributes, including ownership with symbolic links. Security experts encouraged consideration for defining these attributes as optional. Consideration was given to changing utime() to allow modification of the times for a symbolic link, or as an alternative adding an lutime() interface. Modifications to chown() were also considered: allow changing symbolic link ownership or alternatively adding lchown(). As a result of alignment with the Single UNIX Specification, the lchown() function is included as part of the XSI extension and XSI-conformant systems may support an owner and a group associated with a symbolic link. There was no consensus to define further attributes for symbolic links, and for systems not supporting the XSI extension only the file type bits in the st_mode member and the st_size member of the stat structure are required to be applicable to symbolic links.

Historical implementations were followed when determining which interfaces should apply to symbolic links. Interfaces that historically followed symbolic links include chmod(), link(), and utime(). Interfaces that historically do not follow symbolic links include chown(), lstat(), readlink(), rename(), remove(), rmdir(), and unlink(). IEEE Std 1003.1-2001 deviates from historical practice only in the case of chown(). Because there is no requirement for systems not supporting the XSI extension that there is an association of ownership with symbolic links, there was no interface in the base standard to change ownership. In addition, other implementations of symbolic links have modified chown() to follow symbolic links.

In the case of symbolic links, IEEE Std 1003.1-2001 states that a trailing slash is considered to be the final component of a pathname rather than the pathname component that preceded it. This is the behavior of historical implementations. For example, for /a/b and /a/b/, if /a/b is a symbolic link to a directory, then /a/b refers to the symbolic link, and /a/b/ is the same as /a/b/., which is the directory to which the symbolic link points.

For multi-level security purposes, it is possible to have the link read mode govern permission for the readlink() function. It is also possible that the read permissions of the directory containing the link be used for this purpose. Implementations may choose to use either of these methods; however, this is not current practice and neither method is specified.

Several reasons were advanced for requiring that when a symbolic link is used as the source argument to the link() function, the resulting link will apply to the file named by the contents of the symbolic link rather than to the symbolic link itself. This is the case in historical implementations. This action was preferred, as it supported the traditional idea of persistence with respect to the target of a hard link. This decision is appropriate in light of a previous decision not to require association of attributes with symbolic links, thereby allowing implementations which do not use inodes. Opposition centered on the lack of symmetry on the part of the link() and unlink() function pair with respect to symbolic links.

Because a symbolic link and its referenced object coexist in the file system name space, confusion can arise in distinguishing between the link itself and the referenced object. Historically, utilities and system calls have adopted their own link following conventions in a somewhat ad hoc fashion. Rules for a uniform approach are outlined here, although historical practice has been adhered to as much as was possible. To promote consistent system use, user-written utilities are encouraged to follow these same rules.

Symbolic links are handled either by operating on the link itself, or by operating on the object referenced by the link. In the latter case, an application or system call is said to "follow" the link. Symbolic links may reference other symbolic links, in which case links are dereferenced until an object that is not a symbolic link is found, a symbolic link that references a file that does not exist is found, or a loop is detected. (Current implementations do not detect loops, but have a limit on the number of symbolic links that they will dereference before declaring it an error.)

There are four domains for which default symbolic link policy is established in a system. In almost all cases, there are utility options that override this default behavior. The four domains are as follows:

  1. Symbolic links specified to system calls that take filename arguments

  2. Symbolic links specified as command line filename arguments to utilities that are not performing a traversal of a file hierarchy

  3. Symbolic links referencing files not of type directory, specified to utilities that are performing a traversal of a file hierarchy

  4. Symbolic links referencing files of type directory, specified to utilities that are performing a traversal of a file hierarchy


First Domain

The first domain is considered in earlier rationale.

Second Domain

The reason this category is restricted to utilities that are not traversing the file hierarchy is that some standard utilities take an option that specifies a hierarchical traversal, but by default operate on the arguments themselves. Generally, users specifying the option for a file hierarchy traversal wish to operate on a single, physical hierarchy, and therefore symbolic links, which may reference files outside of the hierarchy, are ignored. For example, chown owner file is a different operation from the same command with the -R option specified. In this example, the behavior of the command chown owner file is described here, while the behavior of the command chown -R owner file is described in the third and fourth domains.

The general rule is that the utilities in this category follow symbolic links named as arguments.

Exceptions in the second domain are:

All other standard utilities, when not traversing a file hierarchy, always follow symbolic links named as arguments.

Historical practice is that the -h option is specified if standard utilities are to act upon symbolic links instead of upon their targets. Examples of commands that have historically had a -h option for this purpose are the chgrp, chown, file, and test utilities.

Third Domain

The third domain is symbolic links, referencing files not of type directory, specified to utilities that are performing a traversal of a file hierarchy. (This includes symbolic links specified as command line filename arguments or encountered during the traversal.)

The intention of the Shell and Utilities volume of IEEE Std 1003.1-2001 is that the operation that the utility is performing is applied to the symbolic link itself, if that operation is applicable to symbolic links. The reason that the operation is not required is that symbolic links in some implementations do not have such attributes as a file owner, and therefore the chown operation would be meaningless. If symbolic links on the system have an owner, it is the intention that the utility chown cause the owner of the symbolic link to change. If symbolic links do not have an owner, the symbolic link should be ignored. Specifically, by default, no change should be made to the file referenced by the symbolic link.

Fourth Domain

The fourth domain is symbolic links referencing files of type directory, specified to utilities that are performing a traversal of a file hierarchy. (This includes symbolic links specified as command line filename arguments or encountered during the traversal.)

Most standard utilities do not, by default, indirect into the file hierarchy referenced by the symbolic link. (The Shell and Utilities volume of IEEE Std 1003.1-2001 uses the informal term "physical walk" to describe this case. The case where the utility does indirect through the symbolic link is termed a "logical walk".)

There are three reasons for the default to be a physical walk:

  1. With very few exceptions, a physical walk has been the historical default on UNIX systems supporting symbolic links. Because some utilities (that is, rm) must default to a physical walk, regardless, changing historical practice in this regard would be confusing to users and needlessly incompatible.

  2. For systems where symbolic links have the historical file attributes (that is, owner, group, mode), defaulting to a logical traversal would require the addition of a new option to the commands to modify the attributes of the link itself. This is painful and more complex than the alternatives.

  3. There is a security issue with defaulting to a logical walk. Historically, the command chown -R user file has been safe for the superuser because setuid and setgid bits were lost when the ownership of the file was changed. If the walk were logical, changing ownership would no longer be safe because a user might have inserted a symbolic link pointing to any file in the tree. Again, this would necessitate the addition of an option to the commands doing hierarchy traversal to not indirect through the symbolic links, and historical scripts doing recursive walks would instantly become security problems. While this is mostly an issue for system administrators, it is preferable to not have different defaults for different classes of users.

However, the standard developers agreed to leave it unspecified to achieve consensus.

As consistently as possible, users may cause standard utilities performing a file hierarchy traversal to follow any symbolic links named on the command line, regardless of the type of file they reference, by specifying the -H (for half logical) option. This option is intended to make the command line name space look like the logical name space.

As consistently as possible, users may cause standard utilities performing a file hierarchy traversal to follow any symbolic links named on the command line as well as any symbolic links encountered during the traversal, regardless of the type of file they reference, by specifying the -L (for logical) option. This option is intended to make the entire name space look like the logical name space.

For consistency, implementors are encouraged to use the -P (for "physical") flag to specify the physical walk in utilities that do logical walks by default for whatever reason. The only standard utilities that require the -P option are cd and pwd; see the note below.

When one or more of the -H, -L, and -P flags can be specified, the last one specified determines the behavior of the utility. This permits users to alias commands so that the default behavior is a logical walk and then override that behavior on the command line.

Exceptions in the Third and Fourth Domains

The ls and rm utilities are exceptions to these rules. The rm utility never follows symbolic links and does not support the -H, -L, or -P options. Some historical versions of ls always followed symbolic links given on the command line whether the -L option was specified or not. Historical versions of ls did not support the -H option. In IEEE Std 1003.1-2001, unless one of the -H or -L options is specified, the ls utility only follows symbolic links to directories that are given as operands. The ls utility does not support the -P option.

The Shell and Utilities volume of IEEE Std 1003.1-2001 requires that the standard utilities ls, find, and pax detect infinite loops when doing logical walks; that is, a directory, or more commonly a symbolic link, that refers to an ancestor in the current file hierarchy. If the file system itself is corrupted, causing the infinite loop, it may be impossible to recover. Because find and ls are often used in system administration and security applications, they should attempt to recover and continue as best as they can. The pax utility should terminate because the archive it was creating is by definition corrupted. Other, less vital, utilities should probably simply terminate as well. Implementations are strongly encouraged to detect infinite loops in all utilities.

Historical practice is shown in Historical Practice for Symbolic Links . The heading SVID3 stands for the Third Edition of the System V Interface Definition.

Historically, several shells have had built-in versions of the pwd utility. In some of these shells, pwd reported the physical path, and in others, the logical path. Implementations of the shell corresponding to IEEE Std 1003.1-2001 must report the logical path by default. Earlier versions of IEEE Std 1003.1-2001 did not require the pwd utility to be a built-in utility. Now that pwd is required to set an environment variable in the current shell execution environment, it must be a built-in utility.

The cd command is required, by default, to treat the filename dot-dot logically. Implementors are required to support the -P flag in cd so that users can have their current environment handled physically. In 4.3 BSD, chgrp during tree traversal changed the group of the symbolic link, not the target. Symbolic links in 4.4 BSD do not have owner, group, mode, or other standard UNIX system file attributes.

Table: Historical Practice for Symbolic Links

Utility

SVID3

4.3 BSD

4.4 BSD

POSIX

Comments

cd

 

 

 

-L

Treat ".." logically.

cd

 

 

 

-P

Treat ".." physically.

chgrp

 

 

-H

-H

Follow command line symlinks.

chgrp

 

 

-h

-L

Follow symlinks.

chgrp

-h

 

 

-h

Affect the symlink.

chmod

 

 

 

 

Affect the symlink.

chmod

 

 

-H

 

Follow command line symlinks.

chmod

 

 

-h

 

Follow symlinks.

chown

 

 

-H

-H

Follow command line symlinks.

chown

 

 

-h

-L

Follow symlinks.

chown

-h

 

 

-h

Affect the symlink.

cp

 

 

-H

-H

Follow command line symlinks.

cp

 

 

-h

-L

Follow symlinks.

cpio

-L

 

-L

 

Follow symlinks.

du

 

 

-H

-H

Follow command line symlinks.

du

 

 

-h

-L

Follow symlinks.

file

-h

 

 

-h

Affect the symlink.

find

 

 

-H

-H

Follow command line symlinks.

find

 

 

-h

-L

Follow symlinks.

find

-follow

 

-follow

 

Follow symlinks.

ln

-s

-s

-s

-s

Create a symbolic link.

ls

-L

-L

-L

-L

Follow symlinks.

ls

 

 

 

-H

Follow command line symlinks.

mv

 

 

 

 

Operates on the symlink.

pax

 

 

-H

-H

Follow command line symlinks.

pax

 

 

-h

-L

Follow symlinks.

pwd

 

 

 

-L

Printed path may contain symlinks.

pwd

 

 

 

-P

Printed path will not contain symlinks.

rm

 

 

 

 

Operates on the symlink.

tar

 

 

-H

 

Follow command line symlinks.

tar

 

-h

-h

 

Follow symlinks.

test

-h

 

-h

-h

Affect the symlink.

Synchronously-Generated Signal

Those signals that may be generated synchronously include SIGABRT, SIGBUS, SIGILL, SIGFPE, SIGPIPE, and SIGSEGV.

Any signal sent via the raise() function or a kill() function targeting the current process is also considered synchronous.

System Call*

The distinction between a "system call" and a "library routine" is an implementation detail that may differ between implementations and has thus been excluded from POSIX.1.

See "Interface, Not Implementation" in .

System Reboot

A "system reboot" is an event initiated by an unspecified circumstance that causes all processes (other than special system processes) to be terminated in an implementation-defined manner, after which any changes to the state and contents of files created or written to by a Conforming POSIX.1 Application prior to the event are implementation-defined.

Synchronized I/O Data (and File) Integrity Completion

These terms specify that for synchronized read operations, pending writes must be successfully completed before the read operation can complete. This is motivated by two circumstances. Firstly, when synchronizing processes can access the same file, but not share common buffers (such as for a remote file system), this requirement permits the reading process to guarantee that it can read data written remotely. Secondly, having data written synchronously is insufficient to guarantee the order with respect to a subsequent write by a reading process, and thus this extra read semantic is necessary.

Text File

The term "text file" does not prevent the inclusion of control or other non-printable characters (other than NUL). Therefore, standard utilities that list text files as inputs or outputs are either able to process the special characters or they explicitly describe their limitations within their individual descriptions. The definition of "text file" has caused controversy. The only difference between text and binary files is that text files have lines of less than {LINE_MAX} bytes, with no NUL characters, each terminated by a <newline>. The definition allows a file with a single <newline>, but not a totally empty file, to be called a text file. If a file ends with an incomplete line it is not strictly a text file by this definition. The <newline> referred to in IEEE Std 1003.1-2001 is not some generic line separator, but a single character; files created on systems where they use multiple characters for ends of lines are not portable to all conforming systems without some translation process unspecified by IEEE Std 1003.1-2001.

Thread

IEEE Std 1003.1-2001 defines a thread to be a flow of control within a process. Each thread has a minimal amount of private state; most of the state associated with a process is shared among all of the threads in the process. While most multi-thread extensions to POSIX have taken this approach, others have made different decisions.

Note:
The choice to put threads within a process does not constrain implementations to implement threads in that manner. However, all functions have to behave as though threads share the indicated state information with the process from which they were created.

Threads need to share resources in order to cooperate. Memory has to be widely shared between threads in order for the threads to cooperate at a fine level of granularity. Threads keep data structures and the locks protecting those data structures in shared memory. For a data structure to be usefully shared between threads, such structures should not refer to any data that can only be interpreted meaningfully by a single thread. Thus, any system resources that might be referred to in data structures need to be shared between all threads. File descriptors, pathnames, and pointers to stack variables are all things that programmers want to share between their threads. Thus, the file descriptor table, the root directory, the current working directory, and the address space have to be shared.

Library implementations are possible as long as the effective behavior is as if system services invoked by one thread do not suspend other threads. This may be difficult for some library implementations on systems that do not provide asynchronous facilities.

See Threads for additional rationale.

Thread ID

See Thread IDs for additional rationale.

Thread-Safe Function

All functions required by IEEE Std 1003.1-2001 need to be thread-safe; see Thread-Safety and Thread-Safety for additional rationale.

User Database

There are no references in IEEE Std 1003.1-2001 to a "passwd file" or a "group file", and there is no requirement that the group or passwd databases be kept in files containing editable text. Many large timesharing systems use passwd databases that are hashed for speed. Certain security classifications prohibit certain information in the passwd database from being publicly readable.

The term "encoded" is used instead of "encrypted" in order to avoid the implementation connotations (such as reversibility or use of a particular algorithm) of the latter term.

The getgrent(), setgrent(), endgrent(), getpwent(), setpwent(), and endpwent() functions are not included as part of the base standard because they provide a linear database search capability that is not generally useful (the getpwuid(), getpwnam(), getgrgid(), and getgrnam() functions are provided for keyed lookup) and because in certain distributed systems, especially those with different authentication domains, it may not be possible or desirable to provide an application with the ability to browse the system databases indiscriminately. They are provided on XSI-conformant systems due to their historical usage by many existing applications.

A change from historical implementations is that the structures used by these functions have fields of the types gid_t and uid_t, which are required to be defined in the <sys/types.h> header. IEEE Std 1003.1-2001 requires implementations to ensure that these types are defined by inclusion of <grp.h> and <pwd.h>, respectively, without imposing any name space pollution or errors from redefinition of types.

IEEE Std 1003.1-2001 is silent about the content of the strings containing user or group names. These could be digit strings. IEEE Std 1003.1-2001 is also silent as to whether such digit strings bear any relationship to the corresponding (numeric) user or group ID.

Database Access

The thread-safe versions of the user and group database access functions return values in user-supplied buffers instead of possibly using static data areas that may be overwritten by each call.

Virtual Processor*

The term "virtual processor" was chosen as a neutral term describing all kernel-level schedulable entities, such as processes, Mach tasks, or lightweight processes. Implementing threads using multiple processes as virtual processors, or implementing multiplexed threads above a virtual processor layer, should be possible, provided some mechanism has also been implemented for sharing state between processes or virtual processors. Many systems may also wish to provide implementations of threads on systems providing "shared processes" or "variable-weight processes". It was felt that exposing such implementation details would severely limit the type of systems upon which the threads interface could be supported and prevent certain types of valid implementations. It was also determined that a virtual processor interface was out of the scope of the Rationale (Informative) volume of IEEE Std 1003.1-2001.

XSI

This is introduced to allow IEEE Std 1003.1-2001 to be adopted as an IEEE standard and an Open Group Technical Standard, serving both the POSIX and the Single UNIX Specification in a core set of volumes.

The term "XSI" has been used for 10 years in connection with the XPG series and the first and second versions of the base volumes of the Single UNIX Specification. The XSI margin code was introduced to denote the extended or more restrictive semantics beyond POSIX that are applicable to UNIX systems.


UNIX ® is a registered Trademark of The Open Group.
POSIX ® is a registered Trademark of The IEEE.
[ Main Index | XBD | XCU | XSH | XRAT ]