Provided by: manpages-pl-dev_4.23.1-1_all bug

NAZWA

       execve - wykonuje program

BIBLIOTEKA

       Standardowa biblioteka C (libc, -lc)

SKŁADNIA

       #include <unistd.h>

       int execve(const char *pathname, char *const _Nullable argv[],
                  char *const _Nullable envp[]);

OPIS

       execve()  wykonuje  program  wskazywany  przez  pathname.  Program,  który  jest aktualnie
       wykonywany przez proces wywołujący jest zastępowany nowym programem, z nowo  zainicjowanym
       stosem, kopcem i (zainicjowanymi i niezainicjowanymi) segmentami danych.

       pathname  musi  być  albo wykonywalnym plikiem binarnym, albo skryptem zaczynającym się od
       wiersza w postaci:

           #!interpreter [opcjonalny-parametr]

       Szczegóły  tego  ostatniego  przypadku  można  znaleźć  poniżej   w   rozdziale   „Skrypty
       interpretowane”.

       argv  jest  tablicą  wskaźników do łańcuchów przekazywanych jako argumenty wiersza poleceń
       nowego programu. Zgodnie z konwencją, pierwszy z  nich  (tj.  argv[0])  powinien  zawierać
       nazwę  pliku  skojarzonego  z  wykonywanym  programem.  Tablica  argv  musi być zakończona
       wskaźnikiem null (dlatego w nowym programie, argv[argc] będzie wskaźnikiem null).

       envp jest tablicą wskaźników do łańcuchów, zgodnie  z  konwencją,  postaci  klucz=wartość,
       która  jest  przekazywana  jako  środowisko  do  nowego  programu.  Tablica  envp musi być
       zakończona wskaźnikiem pustym (NULL).

       Niniejszy podręcznik opisuje detale linuksowego wywołania systemowego; aby zapoznać się  z
       przeglądem  nomenklatury  oraz  wieloma,  często  preferowanymi,  standardowymi wariantami
       niniejszej funkcji udostępnianymi przez libc, w tym przeszukującymi  zmienną  środowiskową
       PATH, zob. exec(3).

       Argument  wektora  i  środowiska  może być dostępny z głównej funkcji nowego programu, gdy
       zostanie zdefiniowany jako:

           int main(int argc, char *argv[], char *envp[])

       Proszę jednak zauważyć, że użycie trzeciego argumentu głównej funkcji nie  jest  określone
       normą  POSIX.1;  zgodnie  z  POSIX.1,  dostęp  do środowiska powinien następować za pomocą
       zewnętrznej zmiennej environ(7).

       W  razie  powodzenia  execve()  nie  powraca,  a  sekcje  tekstu,  zainicjowanych  danych,
       niezainicjowanych  danych  (bss)  i  stos  wywołującego  procesu  są nadpisywane zgodnie z
       zawartością nowo ładowanego programu.

       Jeśli obecny program jest śledzony za pomocą ptrace, wysyła się mu  SIGTRAP  po  pomyślnym
       execve().

       Jeżeli  plik  programu,  do  którego odnosi się filename, ma ustawiony bit set-user-ID, to
       efektywny identyfikator użytkownika procesu wywołującego  jest  ustawiany  na  właściciela
       pliku  programu.  Podobnie,  jeżeli dla pliku programu ustawiony jest bit set-group-ID, to
       efektywnemu identyfikatorowi grupy procesu  wywołującego  jest  przypisywana  grupa  pliku
       programu.

       Wyżej  wymienione  przekształcenia  efektywnego identyfikatora nie są przeprowadzane (tzn.
       bity set-user-ID i set-group-ID są ignorowane) jeśli dowolny z  poniższych  warunków  jest
       prawdziwy:

       •  dla wywołującego wątku ustawiony jest atrybut no_new_privs (zob. prctl(2));

       •  przedmiotowy  system plików jest zamontowany z nosuid (znacznik MS_NOSUID dla mount(2))
          lub

       •  wywołujący proces jest śledzony za pomocą ptrace.

       Przywileje pliku programu (zob. capabilities(7)) są również ignorowane,  jeśli  dowolny  z
       powyższych warunków jest prawdziwy.

       Efektywny  identyfikator  użytkownika  jest  kopiowany do zapisanego set-user-ID; podobnie
       efektywny identyfikator grupy jest kopiowany do zapisanego set-group-ID. Kopiowanie odbywa
       się  po  zmianie  któregokolwiek  z  efektywnych  identyfikatorów związanej z bitami trybu
       set-user-ID i set-group-ID.

       Rzeczywisty  identyfikator  procesu  i  rzeczywisty  identyfikator  grupy,  podobnie   jak
       uzupełniające identyfikatory grupy, pozostają bez zmian przy wywołaniu do execve().

       Jeśli  program wykonywalny jest skonsolidowany dynamicznie w formacie a.out z bibliotekami
       dzielonymi, to na początku uruchamiania wywoływany jest konsolidator dynamiczny  ld.so(8),
       który ładuje wszystkie obiekty do pamięci i konsoliduje z nimi program wykonywalny.

       Jeżeli  program  jest  skonsolidowany  dynamicznie jako ELF, to do załadowania potrzebnych
       obiektów współdzielonych używany jest interpreter określony  w  segmencie  PT_INTERP.  Tym
       interpreterem  jest  zazwyczaj  /lib/ld-linux.so.2, w wypadku programów skonsolidowanych z
       glibc2 (zob. ld-linux.so(8)).

   Wpływ na atrybuty procesu
       Wszystkie atrybuty procesu są zachowywane podczas execve(), z wyjątkiem poniższych:

       •  Ustawienia obsługi sygnałów, które są przechwytywane, są zmieniane na wartości domyślne
          (signal(7)).

       •  Alternatywny stos sygnałów nie jest zachowywany (sigaltstack(2)).

       •  Mapowania pamięci nie są zachowywane (mmap(2))

       •  Dołączone segmenty pamięci dzielonej Systemu V są odłączane (shmat(2)).

       •  Regiony pamięci dzielonej POSIX są odmapowane (shm_open(3)).

       •  Otwarte kolejki komunikatów POSIX są zamykane (mq_overview(7)).

       •  Otwarte semafory nazwane POSIX są zamykane (mq_overview(7)).

       •  Timery POSIX nie są zachowywane (timer_create(2)).

       •  Otwarte strumienie katalogów są zamykane (opendir(3)).

       •  Blokady pamięci nie są zachowywane (mlock(2), mlockall(2)).

       •  Zarejestrowanie   funkcje  wykonywanych  po  zakończeniu  procesu  nie  są  zachowywane
          (atexit(3), on_exit(3)).

       •  Środowisko zmiennoprzecinkowe jest ustawiane na domyślne (patrz fenv(3)).

       Atrybuty procesu w liście przedstawionej  powyżej  są  określone  w  POSIX.1.  Następujące
       specyficzne dla Linuksa atrybuty procesu również nie są zachowywane podczas execve():

       •  Atrybut  „dumpable” („zrzucalny”) jest ustawiany na wartość 1, chyba że wykonywany jest
          program: z set-user-ID, z set-group-ID lub z przywilejami (ang. capabilities);  wówczas
          atrybut ten może być zresetowany na wartość z /proc/sys/fs/suid_dumpable, w przypadkach
          opisanych odnośnie PR_SET_DUMPABLE w podręczniku prctl(2). Proszę zauważyć,  że  zmiany
          atrybutu  „dumpable”  mogą  spowodować  zmianę  własności  plików  w  katalogu  procesu
          /proc/pid na root:root, zgodnie z opisem w podręczniku proc(5).

       •  Znacznik PR_SET_KEEPCAPS prctl(2) jest czyszczony.

       •  (Od Linuksa 2.4.36 / 2.6.23) Jeśli wykonywany program ma ustawiony bit set-user-ID  lub
          set-group-ID,  to  jest  czyszczony  znacznik PR_SET_PDEATHSIG  sygnału śmierci rodzica
          ustawiony przez  prctl(2).

       •  Nazwa procesu ustawiona przez PR_SET_NAME z prctl(2) (i wyświetlana przez  ps -o  comm)
          jest ustawiana na nazwę nowego pliku wykonywalnego.

       •  Znacznik SECBIT_KEEP_CAPS w securebits jest czyszczony. Patrz capabilities(7).

       •  Sygnał zakończenia jest ustawiany na SIGCHLD (patrz clone(2)).

       •  Tablica  deskryptora  plików  nie jest dzielona, co anuluje działanie flagi CLONE_FILES
          clone(2).

       Dalsze uwagi:

       •  Wszystkie wątki oprócz wątku wywołującego  są  niszczone  podczas  execve().  Zatrzaski
          (muteksy), zmienne warunkowe i inne obiekty pthreads nie są zachowywane.

       •  Odpowiednik setlocale(LC_ALL, "C") jest wykonywany po uruchomieniu programu.

       •  POSIX.1  określa,  że ustawienie procedur obsługi sygnału na ignorowanie lub na wartość
          domyślną jest pozostawiane bez zmian. POSIX.1 przewiduje jeden wyjątek od  tej  reguły:
          jeśli  SIGCHLD jest ignorowany, to implementacja może albo nie zmienić tego ustawienia,
          albo przestawić je na wartość domyślną; Linux robi to pierwsze.

       •  Wszystkie  asynchroniczne   operacje   wejścia/wyjście   są   anulowane   (aio_read(3),
          aio_write(3)).

       •  Sposób obsługi przywilejów procesu podczas execve() opisano w capabilities(7).

       •  Domyślnie   deskryptory  plików  pozostają  otwarte  po  execve().  Deskryptory  plików
          oznaczone jako „zamknij-przy-wykonaniu” są zamykane, patrz opis FD_CLOEXEC w  fcntl(2).
          (Jeśli  deskryptor  pliku  zostanie  zamknięty,  to zwolnione zostaną wszystkie blokady
          rekordów dotyczące pliku związanego z  tym  deskryptorem.  Szczegóły  można  znaleźć  w
          fcntl(2)).  POSIX.1  mówi, że jeżeli deskryptory plików 0, 1 i 2 zostałyby zamknięte po
          pomyślnym wykonaniu execve(), a proces uzyskałby przywileje  z  powodu  ustawionego  na
          wykonywanym  pliku  bitu  trybu  set-user-ID  lub set-group-ID, to system może otworzyć
          bliżej nieokreślony plik dla każdego z tych deskryptorów  plików.  Jako  zasadę  należy
          przyjąć,  że żaden przenośny program, uprzywilejowany czy nie, nie może zakładać, że te
          trzy deskryptory plików będą zamknięte po execve().

   Skrypty interpretowane
       Skrypt interpretowany jest plikiem  tekstowym  mającym  ustawione  prawo  do  wykonywania.
       Pierwszy wiersz tego pliku jest w postaci:

           #!interpreter [opcjonalny-parametr]

       interpreter mus być poprawną nazwą ścieżki do pliku wykonywalnego.

       Jeśli  argument  pathname  wywołania execve() określa interpreter, to zostanie uruchomiony
       interpreter z następującymi argumentami:

           interpreter [opcjonalny-arg] pathname arg...

       gdzie pathname jest ścieżką pliku podanego jako pierwszy argument execve(), a arg...  jest
       zestawem  słów,  na  które  wskazuje argument argv execve(), zaczynając od argv[1]. Proszę
       zauważyć, że nie da się pozyskać argv[0] przekazanego do wywołania execve().

       Dla zachowania przenośności na inne systemy, optional-arg albo w ogóle  nie  powinien  być
       podawany,  albo  powinien być podany jako pojedyncze słowo (nie powinien zawierać spacji);
       patrz UWAGI poniżej.

       Od Linuksa 2.6.28  jądro  pozwala,  aby  interpreterem  skryptu  również  był  skrypt.  To
       uprawnienie  jest  rekurencyjne,  aż po czterykroć, tak więc interpreter może być skryptem
       interpretowanym przez skrypt itd.

   Ograniczenia rozmiaru argumentów i środowiska
       Większość implementacji Uniksa narzuca ograniczenia na całkowity rozmiar argumentów  linii
       poleceń  (argv)  i  środowiska  (envp)  przekazywanych do nowego programu. POSIX.1 pozwala
       implementacji ogłosić te ograniczenia za  pomocą  stałej  ARG_MAX  (albo  zdefiniowanej  w
       <limits.h>,   albo   dostępnej   podczas   wykonywania   programu   za   pomocą  wywołania
       sysconf(_SC_ARG_MAX)).

       Przed Linuksem 2.6.23, pamięć używana do  przechowywania  łańcuchów  znaków  środowiska  i
       argumentów  była ograniczana do 32 stron (zdefiniowane przez stałą jądra MAX_ARG_PAGES). W
       architekturach mających strony o rozmiarze 4 kB  oznaczało  to  maksymalny  rozmiar  równy
       128 kB.

       W  Linuksie  2.6.23  i późniejszych, większość architektur obsługuje ograniczenie rozmiaru
       wywodzące się z miękkiego limitu zasobu RLIMIT_STACK (patrz getrlimit(2)),  obowiązującego
       podczas wywołania execve() (Wyjątek stanowią architektury nie mające jednostki zarządzania
       pamięcią: przechowują ograniczenie obowiązujące przed Linuksem 2.6.23). Zmiana ta  pozwala
       programom  na  posiadanie  znacznie  większej  listy  argumentów  lub  środowiska. Na tych
       architekturach całkowity rozmiar jest ograniczony do 1/4  dopuszczalnego  rozmiaru  stosu.
       (Limit 1/4 zapewnia, że zostanie jakaś przestrzeń na stos dla nowego programu). Dodatkowo,
       całkowity rozmiar jest ograniczony do 3/4 wartości  stałej  jądra  _STK_LIM  (8  MiB).  Od
       Linuksa  2.6.25  jądro  przyjmuje  również  wartość  minimalną  32  stron  dla tego limitu
       rozmiaru, tak żeby zagwarantować, że w przypadku gdy RLIMIT_STACK  ma  niewielką  wartość,
       aplikacje  dostaną  co  najmniej  taką  przestrzeń na argumenty i środowisko, jaką miały w
       Linuksie 2.6.22 i wcześniejszych. (Takiej gwarancji nie ma w Linuksach 2.6.23  i  2.6.24).
       Dodatkowo   ograniczeniem   na  pojedynczy  łańcuch  znaków  są  32  strony  (stała  jądra
       MAX_ARG_STRLEN), a maksymalna liczba takich łańcuchów wynosi 0x7FFFFFFF.

WARTOŚĆ ZWRACANA

       Po pomyślnym zakończeniu execve() nie wraca, w wypadku błędu zwracane jest -1 i  ustawiane
       errno wskazując błąd.

BŁĘDY

       E2BIG  Całkowita  liczba  bajtów  w środowisku (envp) i liście argumentów (argv) jest zbyt
              duża, argument łańcucha środowiska jest zbyt długi lub pełna ścieżka pathname pliku
              wykonywalnego  jest  zbyt  długa.  Końcowy  bajt  null  jest  wliczany  do długości
              łańcucha.

       EACCES Brak praw do przeszukiwania dla składnika ścieżki pathname lub ścieżki interpretera
              skryptu (patrz także path_resolution(7)).

       EACCES Plik lub interpreter skryptu nie jest zwykłym plikiem.

       EACCES Brak praw wykonywania dla pliku, skryptu lub intepretera ELF.

       EACCES System plików jest zamontowany jako noexec.

       EAGAIN (od Linuksa 3.1)
              Po  zmianie  swojego  rzeczywistego  UID  za  pomocą  jednego  z wywołań set*uid(),
              wywołujący był – i wciąż jest – powyżej swojego limitu zasobów  RLIMIT_NPROC  (zob.
              setrlimit(2)). Więcej informacji o tym błędzie znajduje się w rozdziale UWAGI.

       EFAULT pathname  lub  jeden ze wskaźników w wektorach argv lub envp wskazuje poza dostępną
              dla użytkownika przestrzeń adresową.

       EINVAL Plik wykonywalny w formacie ELF ma więcej niż  jeden  segment  PT_INTERP  (tzn.  ma
              więcej niż jeden interpreter).

       EIO    Wystąpił błąd wejścia/wyjścia.

       EISDIR Intepreter ELF jest katalogiem.

       ELIBBAD
              Nie został rozpoznany format interpretera ELF.

       ELOOP  Podczas  rozwiązywania  pathname, nazwy skryptu lub interpretera ELF napotkano zbyt
              wiele dowiązań symbolicznych.

       ELOOP  Osiągnięto maksymalny limit rekurencji podczas intepretacji rekurencyjnego  skryptu
              (zob. pow. "Skrypty interpretowane"). Przed Linuksem 3.8 w takim wypadku występował
              błąd ENOEXEC.

       EMFILE Zostało  osiągnięte  ograniczenie  na  liczbę  otwartych  deskryptorów  plików  dla
              procesu.

       ENAMETOOLONG
              Ścieżka pathname jest zbyt długa.

       ENFILE Zostało osiągnięte systemowe ograniczenie na całkowitą liczbę otwartych plików.

       ENOENT Plik pathname, skrypt lub interpreter ELF nie istnieje.

       ENOEXEC
              Nie  rozpoznano  formatu  pliku  binarnego,  plik  ten  jest skompilowany dla innej
              architektury albo wystąpił jakiś  inny  błąd  formatu  pliku,  który  powoduje,  że
              program nie może być uruchomiony.

       ENOMEM Brak pamięci jądra.

       ENOTDIR
              Składowa  ścieżki  pathname,  ścieżki skryptu lub ścieżki interpretera ELF nie jest
              katalogiem.

       EPERM  System plików jest zamontowany jako nosuid, użytkownik nie jest administratorem,  a
              plik ma ustawiony bit set-user-ID lub set-group-ID.

       EPERM  Proces  jest  śledzony  (trace),  użytkownik nie jest superużytkownikiem, a plik ma
              ustawiony bit set-user-ID lub set-group-ID.

       EPERM  Aplikacje ślepe na przywileje nie pozyskają pełnego zestawu dozwolonych przywilejów
              przyznanego przez plik wykonywalny. Zob. capabilities(7).

       ETXTBSY
              Podany plik wykonywalny był otwarty do zapisu przez jeden lub więcej procesów.

WERSJE

       POSIX  nie  opisuje  zachowania  #!,  lecz  istnieje  ono  (z pewnymi odmianami) na innych
       systemach Uniksowych.

       Pod Linuksem argv i envp może być podany jako NULL. W  obu  przypadkach,  ma  to  ten  sam
       skutek  co  podanie  danego  argumentu  jako  wskaźnika  do  listy zawierającej pojedynczy
       wskaźnik  null.  Prosimy   nie   wykorzystywać   tej   niestandardowej   i   nieprzenośnej
       pseudofunkcji!  Na  większości  innych systemów Uniksowych podanie jako argv wartości NULL
       spowoduje wystąpienie błędu (EFAULT). Część innych systemów Uniksowych traktuje  przypadek
       envp==NULL tak samo jak Linux.

       POSIX.1 określa, że wartości zwracane przez sysconf(3) nie powinny się zmieniać przez cały
       czas życia procesu. Jednakże od wersji 2.6.23 Linuksa zmiana limitu  zasobów  RLIMIT_STACK
       powoduje również zmianę wartości zwracanej przez _SC_ARG_MAX, żeby odzwierciedlić fakt, że
       zmieniły się ograniczenia przestrzeni służącej do przechowywania argumentów linii  poleceń
       i zmiennych środowiska.

   Skrypty interpretowane
       Jądro narzuca maksymalną długość tekstu następującego po znakach „#!” na początku skryptu;
       znaki wykraczające poza limit są ignorowane. Przed Linuksem 5.1, limit wynosi 127  znaków.
       Od Linuksa 5.1, limit wynosi 255 znaków.

       Semantyka  argumentu optional-arg skryptu interpretera różni się pomiędzy implementacjami.
       Pod Linuksem cały łańcuch znaków występujący po nazwie interpretera jest przekazywany jako
       pojedynczy  argument.  Jednakże  inne  systemy  zachowują  się  inaczej.  Niektóre systemy
       traktują  pierwszy  znaku  białej  spacji  jako  znak  kończący  optional-arg.  Na  innych
       systemach  skrypt interpretera może przyjmować wiele argumentów i białe znaki optional-arg
       służą do ich rozdzielania.

       Linux (podobnie jest większość innych współczesnych  systemów  uniksowych)  ignoruje  bity
       set-user-ID i set-group-ID dla skryptów.

STANDARDY

       POSIX.1-2008.

HISTORIA

       POSIX.1-2001, SVr4, 4.3BSD.

       W  Uniksie V6  lista  argumentów  wywołania  exec()  była  kończona  0,  podczas gdy lista
       argumentów funkcji main była kończona -1. Dlatego lista argumentów przekazana do main  nie
       mogła być bezpośrednio użyta w wywołaniu exec(). Od Uniksa V7 obie te wartości są NULL.

UWAGI

       Można czasami przeczytać, że execve() (i powiązane funkcje opisane w exec(3)) są opisywane
       jako „wykonujące nowy proces” (lub podobnie). Jest  to  stwierdzenie  bardzo  mylące:  nie
       występuje tu nowy proces; wiele atrybutów procesu wywołującego pozostaje niezmienionych (w
       szczególności jego identyfikator procesu). Wszystko, co robi  execve(),  to  zaaranżowanie
       wykonania nowego programu przez istniejący proces (proces wywołujący).

       Procesy  z  ustawionymi znacznikami set-user-ID oraz set-group-ID nie mogą być śledzone za
       pomocą ptrace(2).

       Efekt zamontowania systemu plików nosuid  jest  różny  dla  różnych  wersji  jądra  Linux:
       niektóre  odmówią  uruchomienia programów set-user-ID i set-group-ID, gdy spowodowałoby to
       udostępnienie użytkownikowi możliwości, którymi w danym momencie nie dysponuje  (i  zwrócą
       EPERM),  inne  po  prostu  zignorują  bity set-user-ID i set-group-ID i pomyślnie wykonają
       exec().

       W większości sytuacji gdy execve() zawiedzie,  kontrola  powraca  do  oryginalnego  obrazu
       wykonywalnego,  a  wywołujący  execve()  może następnie obsłużyć błąd. Jednak są (rzadkie)
       przypadki (zwykle przy braku zasobów), gdy błąd może  wystąpić  w  momencie  bez  powrotu:
       oryginalny  obraz  wykonywalne  został  podzielony, a nie można całkowicie zbudować nowego
       obrazu. W takich sytuacjach jądro zabija  proces  sygnałem  SIGSEGV  (SIGKILL  do  Linuksa
       3.17).

   execve() i EAGAIN
       Poniżej  znajduje  się  bardziej  szczegółowy  opis  błędu EAGAIN, który może wystąpić (od
       Linuksa 3.1) przy wywoływaniu execve().

       Błąd  EAGAIN  może  wystąpić,  gdy  wywołanie  poprzedzające  setuid(2),  setreuid(2)  lub
       setresuid(2)  spowodowało,  że  rzeczywisty ID użytkownika procesu zmienił się i ta zmiana
       doprowadziła do  wyczerpania  jego  limitu  zasobów  RLIMIT_NPROC  (tzn.  liczba  procesów
       należących  do  nowego  rzeczywistego  UID  przekroczy limit zasobów). Od Linuksa 2.6.0 do
       Linuksa 3.0 powodowało to niepowodzenie wywołania  set*uid().  Przed  Linuksem  2.6  limit
       zasobów   nie   był  nakładany  w  przypadku  procesów  zmieniających  swój  identyfikator
       użytkownika.

       Od Linuksa 3.1, opisana sytuacja  nie  powoduje  już  niepowodzenia  wywołania  set*uid(),
       ponieważ  zbyt  często  prowadziło  to do dziur bezpieczeństwa, gdy nieprawidłowo napisane
       programy nie sprawdzały statusu zakończenia  i  przyjmowały,  że  –  jeśli  wywołujący  ma
       uprawnienia  roota – wywołanie zawsze powiedzie się. Obecnie wywołania set*uid() poprawnie
       zmieniają  rzeczywisty  UID,  lecz  jądro  ustawia  wewnętrzną  flagę   PF_NPROC_EXCEEDED,
       wskazując  że  przekroczono limit zasobów RLIMIT_NPROC. Jeśli flaga PF_NPROC_EXCEEDED jest
       ustawiona, a limit zasobów jest wciąż przekroczony w trakcie kolejnego wywołania execve(),
       to  wywołanie to zakończy się z błędem EAGAIN.  Ta logika jądra zapewnia, że limit zasobów
       RLIMIT_NPROC jest wciąż wymuszony dla zwykłej pracy demonów uprzywilejowanych – przykładem
       jest fork(2)  + set*uid()  + execve().

       Jeśli jednak limit zasobów nie był już przekroczony w trakcie wywołania execve() (ponieważ
       zakończyły się inne procesy  należące  do  tego  rzeczywistego  UID  pomiędzy  wywołaniami
       set*uid()  i  execve()), to wywołanie execve() powiedzie się, a jądro usunie flagę procesu
       PF_NPROC_EXCEEDED. Flaga jest usuwana również wówczas, gdy kolejne  wywołanie  do  fork(2)
       przez ten proces powiedzie się.

PRZYKŁADY

       Następujący  program  jest  zaprojektowany  do wykonania przez drugi program przedstawiony
       poniżej. Wyświetla swoje argumenty uruchomienia po jednym w wierszu.

           /* myecho.c */

           #include <stdio.h>
           #include <stdlib.h>

           int
           main(int argc, char *argv[])
           {
               for (size_t j = 0; j < argc; j++)
                   printf("argv[%zu]: %s\n", j, argv[j]);

               exit(EXIT_SUCCESS);
           }

       Tego programu można użyć do uruchomienia programu podanego w argumencie wiersza poleceń:

           /* execve.c */

           #include <stdio.h>
           #include <stdlib.h>
           #include <unistd.h>

           int
           main(int argc, char *argv[])
           {
               static char *newargv[] = { NULL, "witaj", "świecie", NULL };
               static char *newenviron[] = { NULL };

               if (argc != 2) {
                   fprintf(stderr, "Użycie: %s <plik-do-wykon>\n", argv[0]);
                   exit(EXIT_FAILURE);
               }

               newargv[0] = argv[1];

               execve(argv[1], newargv, newenviron);
               perror("execve");   /* execve() powraca tylko przy błędzie */
               exit(EXIT_FAILURE);
           }

       Możemy użyć drugiego programu do uruchomienia pierwszego:

           $ cc myecho.c -o myecho
           $ cc execve.c -o execve
           $ ./execve ./myecho
           argv[0]: ./myecho
           argv[1]: witaj
           argv[2]: świecie

       Możemy także użyć tych programów  do  pokazania  używania  interpretera  skryptu.  Aby  to
       zrobić, tworzymy skrypt, którego „interpreterem” jest nasz program myecho:

           $ cat > script
           #!./myecho script-arg
           ^D
           $ chmod +x script

       Następnie używamy naszego programu do wykonania skryptu:

           $ ./execve ./script
           argv[0]: ./myecho
           argv[1]: script-arg
           argv[2]: ./script
           argv[3]: witaj
           argv[4]: świecie

ZOBACZ TAKŻE

       chmod(2),   execveat(2),  fork(2),  get_robust_list(2),  ptrace(2),  exec(3),  fexecve(3),
       getauxval(3),   getopt(3),   system(3),   capabilities(7),   credentials(7),   environ(7),
       path_resolution(7), ld.so(8)

TŁUMACZENIE

       Autorami   polskiego   tłumaczenia   niniejszej   strony  podręcznika  są:  Przemek  Borys
       <pborys@dione.ids.pl>, Andrzej Krzysztofowicz <ankry@green.mf.pg.gda.pl>,  Robert  Luberda
       <robert@debian.org> i Michał Kułach <michal.kulach@gmail.com>

       Niniejsze  tłumaczenie  jest  wolną  dokumentacją. Bliższe informacje o warunkach licencji
       można   uzyskać   zapoznając   się   z   GNU   General   Public   License   w   wersji   3
       ⟨https://www.gnu.org/licenses/gpl-3.0.html⟩   lub   nowszej.   Nie  przyjmuje  się  ŻADNEJ
       ODPOWIEDZIALNOŚCI.

       Błędy w tłumaczeniu  strony  podręcznika  prosimy  zgłaszać  na  adres  listy  dyskusyjnej
       ⟨manpages-pl-list@lists.sourceforge.net⟩.