Путеводитель по Руководству Linux

  User  |  Syst  |  Libr  |  Device  |  Files  |  Other  |  Admin  |  Head  |



   execv.3p    ( 3 )

выполнить файл (execute a file)

Обоснование (Rationale)

Early proposals required that the value of argc passed to main() be ``one or greater''. This was driven by the same requirement in drafts of the ISO C standard. In fact, historical implementations have passed a value of zero when no arguments are supplied to the caller of the exec functions. This requirement was removed from the ISO C standard and subsequently removed from this volume of POSIX.1‐2017 as well. The wording, in particular the use of the word should, requires a Strictly Conforming POSIX Application to pass at least one argument to the exec function, thus guaranteeing that argc be one or greater when invoked by such an application. In fact, this is good practice, since many existing applications reference argv[0] without first checking the value of argc.

The requirement on a Strictly Conforming POSIX Application also states that the value passed as the first argument be a filename string associated with the process being started. Although some existing applications pass a pathname rather than a filename string in some circumstances, a filename string is more generally useful, since the common usage of argv[0] is in printing diagnostics. In some cases the filename passed is not the actual filename of the file; for example, many implementations of the login utility use a convention of prefixing a <hyphen-minus> ('‐') to the actual filename, which indicates to the command interpreter being invoked that it is a ``login shell''.

Also, note that the test and [ utilities require specific strings for the argv[0] argument to have deterministic behavior across all implementations.

Historically, there have been two ways that implementations can exec shell scripts.

One common historical implementation is that the execl(), execv(), execle(), and execve() functions return an [ENOEXEC] error for any file not recognizable as executable, including a shell script. When the execlp() and execvp() functions encounter such a file, they assume the file to be a shell script and invoke a known command interpreter to interpret such files. This is now required by POSIX.1‐2008. These implementations of execvp() and execlp() only give the [ENOEXEC] error in the rare case of a problem with the command interpreter's executable file. Because of these implementations, the [ENOEXEC] error is not mentioned for execlp() or execvp(), although implementations can still give it.

Another way that some historical implementations handle shell scripts is by recognizing the first two bytes of the file as the character string "#!" and using the remainder of the first line of the file as the name of the command interpreter to execute.

One potential source of confusion noted by the standard developers is over how the contents of a process image file affect the behavior of the exec family of functions. The following is a description of the actions taken:

1. If the process image file is a valid executable (in a format that is executable and valid and having appropriate privileges) for this system, then the system executes the file.

2. If the process image file has appropriate privileges and is in a format that is executable but not valid for this system (such as a recognized binary for another architecture), then this is an error and errno is set to [EINVAL] (see later RATIONALE on [EINVAL]).

3. If the process image file has appropriate privileges but is not otherwise recognized:

a. If this is a call to execlp() or execvp(), then they invoke a command interpreter assuming that the process image file is a shell script.

b. If this is not a call to execlp() or execvp(), then an error occurs and errno is set to [ENOEXEC].

Applications that do not require to access their arguments may use the form:

main(void)

as specified in the ISO C standard. However, the implementation will always provide the two arguments argc and argv, even if they are not used.

Some implementations provide a third argument to main() called envp. This is defined as a pointer to the environment. The ISO C standard specifies invoking main() with two arguments, so implementations must support applications written this way. Since this volume of POSIX.1‐2017 defines the global variable environ, which is also provided by historical implementations and can be used anywhere that envp could be used, there is no functional need for the envp argument. Applications should use the getenv() function rather than accessing the environment directly via either envp or environ. Implementations are required to support the two-argument calling sequence, but this does not prohibit an implementation from supporting envp as an optional third argument.

This volume of POSIX.1‐2017 specifies that signals set to SIG_IGN remain set to SIG_IGN, and that the new process image inherits the signal mask of the thread that called exec in the old process image. This is consistent with historical implementations, and it permits some useful functionality, such as the nohup command. However, it should be noted that many existing applications wrongly assume that they start with certain signals set to the default action and/or unblocked. In particular, applications written with a simpler signal model that does not include blocking of signals, such as the one in the ISO C standard, may not behave properly if invoked with some signals blocked. Therefore, it is best not to block or ignore signals across execs without explicit reason to do so, and especially not to block signals across execs of arbitrary (not closely cooperating) programs.

The exec functions always save the value of the effective user ID and effective group ID of the process at the completion of the exec, whether or not the set-user-ID or the set-group-ID bit of the process image file is set.

The statement about argv[] and envp[] being constants is included to make explicit to future writers of language bindings that these objects are completely constant. Due to a limitation of the ISO C standard, it is not possible to state that idea in standard C. Specifying two levels of const-qualification for the argv[] and envp[] parameters for the exec functions may seem to be the natural choice, given that these functions do not modify either the array of pointers or the characters to which the function points, but this would disallow existing correct code. Instead, only the array of pointers is noted as constant. The table of assignment compatibility for dst=src derived from the ISO C standard summarizes the compatibility:

┌────────────────────┬──────────┬────────────────┬───────────────┬─────────────────────┐ │ dst: │ char *[] const char *[] char *const[] const char *const[] │ ├────────────────────┼──────────┼────────────────┼───────────────┼─────────────────────┤ │src: │ │ │ │ │ │char *[] │ VALID │ — │ VALID │ — │ │const char *[] │ — │ VALID │ — │ VALID │ │char * const [] │ — │ — │ VALID │ — │ │const char *const[] │ — │ — │ — │ VALID │ └────────────────────┴──────────┴────────────────┴───────────────┴─────────────────────┘ Since all existing code has a source type matching the first row, the column that gives the most valid combinations is the third column. The only other possibility is the fourth column, but using it would require a cast on the argv or envp arguments. It is unfortunate that the fourth column cannot be used, because the declaration a non-expert would naturally use would be that in the second row.

The ISO C standard and this volume of POSIX.1‐2017 do not conflict on the use of environ, but some historical implementations of environ may cause a conflict. As long as environ is treated in the same way as an entry point (for example, fork()), it conforms to both standards. A library can contain fork(), but if there is a user-provided fork(), that fork() is given precedence and no problem ensues. The situation is similar for environ: the definition in this volume of POSIX.1‐2017 is to be used if there is no user-provided environ to take precedence. At least three implementations are known to exist that solve this problem.

E2BIG The limit {ARG_MAX} applies not just to the size of the argument list, but to the sum of that and the size of the environment list.

EFAULT Some historical systems return [EFAULT] rather than [ENOEXEC] when the new process image file is corrupted. They are non-conforming.

EINVAL This error condition was added to POSIX.1‐2008 to allow an implementation to detect executable files generated for different architectures, and indicate this situation to the application. Historical implementations of shells, execvp(), and execlp() that encounter an [ENOEXEC] error will execute a shell on the assumption that the file is a shell script. This will not produce the desired effect when the file is a valid executable for a different architecture. An implementation may now choose to avoid this problem by returning [EINVAL] when a valid executable for a different architecture is encountered. Some historical implementations return [EINVAL] to indicate that the path argument contains a character with the high order bit set. The standard developers chose to deviate from historical practice for the following reasons:

1. The new utilization of [EINVAL] will provide some measure of utility to the user community.

2. Historical use of [EINVAL] is not acceptable in an internationalized operating environment.

ENAMETOOLONG Since the file pathname may be constructed by taking elements in the PATH variable and putting them together with the filename, the [ENAMETOOLONG] error condition could also be reached this way.

ETXTBSY System V returns this error when the executable file is currently open for writing by some process. This volume of POSIX.1‐2017 neither requires nor prohibits this behavior.

Other systems (such as System V) may return [EINTR] from exec. This is not addressed by this volume of POSIX.1‐2017, but implementations may have a window between the call to exec and the time that a signal could cause one of the exec calls to return with [EINTR].

An explicit statement regarding the floating-point environment (as defined in the <fenv.h> header) was added to make it clear that the floating-point environment is set to its default when a call to one of the exec functions succeeds. The requirements for inheritance or setting to the default for other process and thread start-up functions is covered by more generic statements in their descriptions and can be summarized as follows:

posix_spawn (3p) 14 Set to default.

fork (3p) 14 Inherit.

pthread_create (3p) 14 Inherit.

The purpose of the fexecve() function is to enable executing a file which has been verified to be the intended file. It is possible to actively check the file by reading from the file descriptor and be sure that the file is not exchanged for another between the reading and the execution. Alternatively, a function like openat() can be used to open a file which has been found by reading the content of a directory using readdir().