oracular (2) execve.2.gz

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⟩.