Provided by: manpages-pl_4.23.1-1_all bug

NAZWA

       unix - gniazda lokalnej komunikacji międzyprocesowej

SKŁADNIA

       #include <sys/socket.h>
       #include <sys/un.h>

       unix_socket = socket(AF_UNIX, type, 0);
       error = socketpair(AF_UNIX, type, 0, int *sv);

OPIS

       Rodzina  gniazd AF_UNIX (znana również jako AF_LOCAL) służy do wydajnej komunikacji pomiędzy procesami na
       tej samej maszynie. Zgodnie z tradycją, gniazda domeny uniksowej mogą być albo anonimowe (tworzone  przez
       socketpair(2)),  albo  skojarzone  z  plikiem typu gniazda. Linux wspiera również abstrakcyjną przestrzeń
       nazw, niezależną od systemu plików.

       Poprawne typy gniazd w domenie Uniksa to: SOCK_STREAM dla gniazd strumieniowych, SOCK_DGRAM  dla   gniazd
       datagramowych,  które  zachowują granice komunikatów (w przypadku większości implementacji Uniksa gniazda
       uniksowe są zawsze niezawodne i nie zmieniają kolejności datagramów),  oraz  (od  wersji  Linuksa  2.6.4)
       SOCK_SEQPACKET  dla  gniazd  pakietów  sekwencyjnych zorientowanych połączeniowo, które zachowują granice
       komunikatu i dostarczają komunikaty w kolejności ich wysyłania.

       Za pośrednictwem pomocniczych danych można przez gniazda domeny uniksowej przekazywać do innych  procesów
       deskryptory plików i uwierzytelnienia procesów.

   Format adresu
       Adres gniazda domeny uniksowej jest reprezentowany przez następującą strukturę:

           struct sockaddr_un {
               sa_family_t sun_family;               /* AF_UNIX */
               char        sun_path[108];            /* Ścieżka */
           };

       Pole  sun_family  zawsze  zawiera  AF_UNIX.  W  Linuksie sun_path ma rozmiar 108 bajtów, zob. też USTERKI
       poniżej.

       Różne wywołania systemowe (np. bind(2), connect(2)  i  sendto(2))  przyjmują  argument  sockaddr_un  jako
       wejście.  Niektóre inne wywołania systemowe (np. getsockname(2), getpeername(2), recvfrom(2) i accept(2))
       zwracają argument tego typu.

       W strukturze sockaddr_un rozróżniane są trzy typy adresów:

       ścieżka
              gniazdo domeny uniksowej może zostać związane z zakończoną znakiem NULL nazwą  ścieżki  systemowej
              za   pomocą   bind(2).   Jeśli   adres   ścieżki   gniazda   jest  zwracany  (przez  jedno  z  ww.
              wywołań systemowych) to jego długością jest

                  offsetof(struct sockaddr_un, sun_path) + strlen(sun_path) + 1

              a sun_path zawiera zakończoną null ścieżkę. (W Linuksie powyższe wyrażenie offsetof()  jest  równe
              tej  samej  wartości  co sizeof(sa_family_t), lecz niektóre inne implementacje dołączają inne pola
              przed sun_path, więc bardziej przenośnie, wyrażenie offsetof() opisuje rozmiar struktury adresu).

              Więcej informacji o ścieżkach gniazd znajduje się poniżej.

       unnamed
              Gniazdo strumieniowe niezwiązane z nazwą ścieżki za pomocą bind(2) nie jest nazwane. Podobnie  dwa
              gniazda  utworzone  przez  socketpair(2)  nie  są  nazwane.  Jeśli adres nienazwanego gniazda jest
              zwracany, to jego długością  jest  sizeof(sa_family_t),  a  zawartość  sun_path  nie  powinna  być
              sprawdzana.

       abstract
              adres  gniazda  abstrakcyjnego  jest  rozróżniany  (od adresu ścieżki) po tym, że sun_path[0] jest
              bajtem NULL  ('\0'). Adres gniazda znajduje się w przestrzeni nazw podanej w dodatkowych bajtach w
              sun_path, które są pokryte przez długość struktury adresu (Bajty NULL w nazwie  nie  mają  żadnego
              specjalnego  znaczenia). Nazwa nie ma żadnego powiązania z nazwą pliku w systemie plików. Zwracany
              adres gniazda abstrakcyjnego ma w polu addrlen ustawioną długość większą  niż  sizeof(sa_family_t)
              (tj.  większą  niż  2),  a nazwa gniazda zawarta jest w pierwszych (addrlen - sizeof(sa_family_t))
              bajtach pola sun_path.

   Ścieżki gniazd
       Przy  przypisywaniu  gniazda  do  ścieżki  powinno  się  przestrzegać  kilku  zasad  w  celu  maksymalnej
       przenośności i łatwości programowania:

       •  Ścieżka w sun_path powinna być zakończona znakiem NULL.

       •  Długość ścieżki, w tym kończący bajt null nie powinna przekraczać rozmiaru sun_path.

       •  Argument addrlen opisujący obejmującą strukturę sockaddr_un powinien mieć wartość przynajmniej:

              offsetof(struct sockaddr_un, sun_path)+strlen(addr.sun_path)+1

          lub, prościej, addrlen powinien być podany jako sizeof(struct sockaddr_un).

       W  różnych  implementacjach  różnie  obsługiwane  są  adresy gniazd domen Uniksa, które nie przestrzegają
       powyższych zaleceń. Na przykład niektóre (lecz nie wszystkie) implementacje dodają  kończący  znak  null,
       jeśli nie jest on obecny w przekazanej sun_path.

       Przy  programowaniu przenośnych aplikacji proszę wziąć pod uwagę, że niektóre implementację mają sun_path
       o długości zaledwie 92 bajtów.

       Różne wywołania systemowe (accept(2), recvfrom(2),  getsockname(2),  getpeername(2))  zwracają  struktury
       adresów  gniazd.  Gdy  chodzi o gniazda domeny Uniksa, wartość-rezultat argumentu addrlen umieszczonego w
       wywołaniu powinna być zainicjowana jw. Gdy jest zwracany, argument ten jest  ustawiany  aby  przedstawiać
       aktualny rozmiar struktury adresu. Wywołujący powinien sprawdzić wartość zwracaną w tym argumencie, jeśli
       wartość  wyjściowa przekracza wartość wejściową, to nie ma gwarancji, że kończący znak null jest obecny w
       sun_path (zob PROBLEMY).

   Własność i uprawnienia ścieżki gniazd
       W implementacji  Linuksa,  ścieżki  gniazd  honorują  uprawnienia  katalogów,  w  których  się  znajdują.
       Utworzenie  nowego  gniazda  nie  powiedzie  się,  jeśli  proces  nie  ma uprawnień zapisu i wyszukiwania
       (wykonania) w katalogu, w którym tworzone jest gniazdo.

       W Linuksie, łączenie z gniazdem strumieniowym  wymaga  uprawnień  zapisu  w  stosunku  do  tego  gniazda;
       wysłanie  datagramu  do  gniazda datagramowego również wymaga uprawnień zapisu gniazda. POSIX nie zabiera
       głosu w sprawie efektu uprawnień pliku gniazda i w niektórych  systemach  (np.  starszych  wersjach  BSD)
       uprawnienia  gniazd  są  ignorowane.  Przenośne programy nie powinny opierać się na tym zachowaniu w celu
       zapewnienia bezpieczeństwa.

       Przy tworzeniu nowego gniazda, właściciel  i  grupa  pliku  gniazda  są  ustawiani  zgodnie  ze  zwykłymi
       zasadami. Plik gniazda ma włączone wszystkie uprawnienia, poza tym wyłączonymi przez proces umask(2).

       Właściciela, grupę i uprawnienia ścieżki gniazda można zmienić (za pomocą chown(2) i chmod(2)).

   Gniazda abstrakcyjne
       Uprawnienia  gniazd  nie  mają  znaczenia  dla  gniazd abstrakcyjnych: proces umask(2) nie ma wpływu przy
       kojarzeniu z gniazdem abstrakcyjnym, a zmiana własności  i  uprawnień  obiektu  (za  pomocą  fchown(2)  i
       fchmod(2)) nie wpływa na dostępność gniazda.

       Gniazda abstrakcyjne automatycznie znikają po zamknięciu wszystkich otwartych odniesień do takich gniazd.

       Przestrzeń nazw gniazd abstrakcyjnych jest nieprzenośnym rozszerzeniem systemu Linux.

   Opcje gniazda
       Ze  względów  historycznych  następujące opcje gniazd są podawane przy typie SOL_SOCKET, pomimo że są one
       specyficzne dla AF_UNIX. Można je ustawić za pomocą setsockopt(2), a odczytać  za  pomocą  getsockopt(2),
       podając SOL_SOCKET jako rodzinę gniazd.

       SO_PASSCRED
              Włączenie tej opcji gniazda powoduje przekazanie uwierzytelnień wysyłającego procesu w pomocniczej
              wiadomości  SCM_CREDENTIALS, w każdej kolejnej odebranej wiadomości. Zwracanymi uwierzytelnieniami
              są te określone przez nadawcę za pomocą SCM_CREDENTIALS lub, jeśli  nadawca  nie  określił  danych
              pomocniczych  SCM_CREDENTIALS,  wartość  domyślna  zawierająca: identyfikator procesu, rzeczywisty
              identyfikator użytkownika i rzeczywisty identyfikator grupy nadawcy.

              Przy  włączonej  tej  opcji  i  niepołączonym  jeszcze  gnieździe,  unikatowa  nazwa   gniazda   z
              abstrakcyjnej przestrzeni nazw jest generowana automatycznie.

              Podana  wartość  jest  argumentem do setsockopt(2), a zwracana jako wynik getsockopt(2) jest flaga
              logiczna będąca liczbą całkowitą.

       SO_PASSSEC
              Włącza odbiór etykiety bezpieczeństwa SELinux drugiego  gniazda  w  pomocniczym  komunikacie  typu
              SCM_SECURITY (zob. niżej).

              Podana  wartość  jest  argumentem do setsockopt(2), a zwracana jako wynik getsockopt(2) jest flaga
              logiczna będąca liczbą całkowitą.

              Opcja SO_PASSSEC jest obsługiwana w datagramowych gniazdach domeny uniksowej  od  Linuksa  2.6.18;
              obsługę w gniazdach strumieniowych domeny uniksowej dodano w jądrze Linux 4.2.

       SO_PEEK_OFF
              Patrz socket(7).

       SO_PEERCRED
              Jest   to  opcja  gniazda  tylko  do  odczytu,  która  zwraca  uwierzytelnienia  drugiego  procesu
              skojarzonego z tym gniazdem. Zwracanymi uwierzytelnieniami są te, które  obowiązywały  w  momencie
              wywołania connect(2), listen(2) lub socketpair(2).

              Argumentem  do  getsockopt(2)  jest  wskaźnik do struktury ucred; należy zdefiniować makro testowe
              _GNU_SOURCE aby pozyskać definicję tej struktury z <sys/socket.h>.

              Opcji tej można używać wyłącznie w połączonych  gniazdach  strumieniowych  AF_UNIX  oraz  w  parze
              gniazda strumieniowego i datagramowego AF_UNIX utworzonej za pomocą socketpair(2).

       SO_PEERSEC
              Ta  opcja  gniazda tylko do odczytu zwraca kontekst bezpieczeństwa drugiego gniazda skojarzonego z
              tym gniazdem. Domyślnie będzie to taka sama  wartość  jak  wartość  kontekstu  procesu  tworzącego
              drugie gniazdo, chyba że zostanie przesłoniona zasadami lub procesem z wymaganymi uprawnieniami.

              Argumentem do getsockopt(2) jest wskaźnik do bufora określonej długości w bajtach, którego łańcuch
              kontekstu  bezpieczeństwa  ma  zostać  skopiowany.  Jeśli długość bufora jest mniejsza niż długość
              łańcucha kontekstu bezpieczeństwa, to getsockopt(2) zwróci -1, ustawi errno  na  ERANGE  i  zwróci
              wymaganą długość za pomocą optlen. Wywołujący powinien początkowo przydzielić co najmniej NAME_MAX
              bajtów  dla  bufora,  choć  nie  ma  gwarancji,  że  będzie  to wielkość wystarczająca. Może zajść
              konieczność dostosowania wielkości bufora do zwróconej długości i wykonanie drugiego podejścia.

              Łańcuch kontekstu bezpieczeństwa może zawierać kończący znak null w zwracanej  długości,  ale  nie
              jest  to  gwarantowane. Kontekst bezpieczeństwa "foo" może być reprezentowany jako {'f','o','o'} o
              długości 3 lub {'f','o','o','\0'} o długości 4, oba te warianty są uważane za równorzędne. Łańcuch
              jest drukowalny, nie zawiera  znaków  null  innych  niż  kończące  łańcuch  oraz  ma  nieokreślone
              kodowanie (w szczególności, nie gwarantuje się kodowania ASCII lub UTF-8).

              Użycie  tej  opcji  do  gniazd  w  rodzinie  adresowej AF_UNIX jest obsługiwane od Linuksa 2.6.2 w
              przypadku  skojarzonych  gniazd  strumieniowych,  a  od  Linuksa  4.18  również  dla  par   gniazd
              strumieniowych i datagramowych utworzonych za pomocą socketpair(2).

   Automatyczne przypisywanie adresów
       Jeśli w wywołaniu bind(2) podane zostanie addrlen równe sizeof(sa_family_t) lub opcja SO_PASSCRED gniazda
       była  ustawiona  dla  gniazda nieprzypisanego do adresu, wtedy gniazdo jest automatycznie przypisywane do
       adresu abstrakcyjnego. Adres ten składa się z bajtu NULL, po którym następuje 5 bajtów ze  zbioru  znaków
       [0-9a-f].  W  związku  z  tym  liczba  automatycznie  przypisywanych adresów jest ograniczona do 2^20. (W
       Linuksie 2.1.15, w którym dodano możliwość automatycznego przypisywania adresów, i w  kolejnych  wersjach
       używane  było  8  bajtów,  a  limit  wynosił  2^32   adresów. Zostało to zmienione na 5 bajtów w Linuksie
       2.3.15).

   API gniazd
       W kolejnych paragrafach opisano pewne szczegóły implementacji API  gniazd  domeny  UNIX  specyficzne  dla
       Linuksa oraz cechy niewspierane.

       Gniazda  z  domeny  uniksowej  nie obsługują zawiadomienia o danych autonomicznych (flaga MSG_OOB funkcji
       send(2) i recv(2)).

       Flaga MSG_MORE funkcji send(2) nie jest obsługiwana dla gniazd domeny uniksowej.

       Przed Linuksem 3.4, użycie MSG_TRUNC w argumencie flags funkcji recv(2) nie było obsługiwane  dla  gniazd
       domeny uniksowej.

       Opcja  SO_SNDBUF  działa  w  przypadku  gniazd  domeny uniksowej, ale opcja SO_RCVBUF już nie. Dla gniazd
       datagramowych wartość SO_SNDBUF nakłada górny limit na rozmiar wychodzących datagramów.  Limit  ten  jest
       liczony  jako  podwojona  (patrz socket(7)) wartość opcji minus 32 bajty wymagane na informacje niebędące
       danymi.

   Komunikaty pomocnicze
       Dane pomocnicze są wysyłane i odbierane za pomocą sendmsg(2)  i  recvmsg(2).  Ze  względów  historycznych
       komunikaty  pomocnicze  poniższych  typów są podawane przy typie SOL_SOCKET, pomimo że są one specyficzne
       dla AF_UNIX. Aby je wysłać, należy ustawić pole  cmsg_level  struktury  cmsghdr  na  SOL_SOCKET,  a  pole
       cmsg_type na typ. Więcej informacji można znaleźć w cmsg(3).

       SCM_RIGHTS
              Odbieranie  od  innego procesu lub wysyłanie do niego zbioru otwartych deskryptorów plików. Porcja
              danych zawiera tablicę liczb całkowitych będących deskryptorami plików.

              Potocznie, operacja ta jest nazywana "przekazaniem deskryptora pliku" do  innego  procesu.  Jednak
              przyglądając  się  bliżej, można dostrzec że przekazywana jest referencja do otwartego deskryptora
              pliku (zob.  open(2)),  a  w  procesie  odbierającym  prawdopodobnie  użyty  zostanie  inny  numer
              deskryptora pliku. Operacja ta jest semantycznie równoważna duplikacji (dup(2)) deskryptora plików
              na tablicę deskryptora pliku innego procesu.

              Jeśli  bufor  używany  do odebrania danych pomocniczych zawierających deskryptory plików jest zbyt
              mały (lub jest nieobecny),  to  dane  pomocnicze  są  przycinane  (lub  odrzucane),  a  nadmiarowe
              deskryptory plików są automatycznie zamykane przez proces odbierający.

              Jeśli  liczba  deskryptorów plików otrzymana w danych pomocniczych spowodowałaby wykroczenie przez
              proces poza jego limit zasobów RLIMIT_NOFILE (zob. getrlimit(2)), to nadmiarowe deskryptory plików
              zostaną automatycznie zamknięte przez proces odbierający.

              Stała jądra SCM_MAX_FD określa limit liczby deskryptorów plików w tablicy. Próba wysłania  tablicy
              większej  od  limitu  spowoduje  błąd  EINVAL sendmsg(2). SCM_MAX_FD ma wartość 253 (lub 255 przed
              Linuksem 2.6.38).

       SCM_CREDENTIALS
              Odbieranie lub wysyłanie uwierzytelnień uniksowych. Może służyć do  autoryzacji.  Uwierzytelnienia
              są  przekazywane  jako  komunikat  pomocniczy  typu  struct ucred, zdefiniowanego w <sys/socket.h>
              następująco:

                  struct ucred {
                      pid_t pid;  /* identyfikator procesu wysyłającego */
                      uid_t uid;  /* ident. użytkownika procesu wysyłającego */
                      gid_t gid;  /* ident. grupy procesu wysyłającego */
                  };

              Począwszy od wersji 2.8 biblioteki glibc, aby uzyskać dostęp  do  definicji  powyższej  struktury,
              należy zdefiniować makro _GNU_SOURCE (przed dołączeniem jakichkolwiek plików nagłówkowych).

              Jądro  sprawdza  uwierzytelnienia  podane  przez  wysyłającego.  Proces uprzywilejowany może podać
              wartości, które różnią się od jego własnych. W pozostałych przypadkach wysyłający musi podać  swój
              własny identyfikator procesu (o ile nie ma ustawionego znacznika CAP_SYS_ADMIN, w przypadku którym
              można  podać identyfikator dowolnego istniejącego procesu), swój własny, rzeczywisty identyfikator
              użytkownika, efektywny identyfikator użytkownika lub ustawiony identyfikator  użytkownika  (o  ile
              nie  ma  ustawionego  znacznika  CAP_SETUID)  oraz  swój  własny  identyfikator  grupy,  efektywny
              identyfikator grupy lub  ustawiony  identyfikator  grupy  (o  ile  nie  ma  ustawionego  znacznika
              CAP_SETGID).

              Aby otrzymać komunikat typu struct ucred, dla gniazda musi być włączona opcja SO_PASSCRED.

       SCM_SECURITY
              Otrzymuje  kontekst bezpieczeństwa SELinux (etykietę bezpieczeństwa) drugiego gniazda. Otrzymywane
              dane pomocnicze są łańcuchem zakończonym znakiem null, zawierającym kontekst  bezpieczeństwa.  Dla
              tych  danych  odbiorca powinien przydzielić co najmniej NAME_MAX bajtów w porcji danych komunikatu
              pomocniczego.

              Do otrzymania kontekstu bezpieczeństwa konieczne jest włączenie w gnieździe opcji SO_PASSSEC (zob.
              wyżej).

       Przy wysyłaniu danych pomocniczych za pomocą sendmsg(2), w wysłanym  komunikacie  można  podać  tylko  po
       jednej pozycji dla każdego z powyższych typów.

       Przy  wysyłaniu  danych pomocniczych konieczne jest przesłanie choć jednego bajta rzeczywistych danych. W
       Linuksie jest to wymagane do poprawnego wysłania danych pomocniczych  za  pomocą  gniazda  strumieniowego
       domeny uniksowej. Przy wysyłaniu danych pomocniczych za pomocą gniazda datagramowego domeny uniksowej, na
       Linuksie  nie  ma  konieczności wysyłania jakichkolwiek rzeczywistych danych. Przenośne aplikacje powinny
       jednak również wysyłać choć jeden bajt rzeczywistych danych przy wysyłaniu danych pomocniczych za  pomocą
       gniazda datagramowego.

       Przy  odbieraniu  z  gniazda  strumieniowego,  dane  pomocnicze  stanowią  w  pewien  sposób  barierę dla
       odbieranych danych. Proszę przyjąć przykładowo, że nadawca transmituje:

              (1)  sendmsg(2) o wielkości czterech bajtów, bez danych pomocniczych.
              (2)  sendmsg(2) o wielkości jednego bajta, z danymi pomocniczymi.
              (3)  sendmsg(2) o wielkości czterech bajtów, bez danych pomocniczych.

       Przyjmijmy, że odbiorca wykonuje teraz wywołania recvmsg(2), każde  z  buforem  o  wielkości  20  bajtów.
       Pierwsze  wywołanie  otrzyma  pięć  bajtów  danych,  razem  z  danymi pomocniczymi wysłanymi przez drugie
       wywołanie sendmsg(2). Następne wywołanie otrzyma pozostałe cztery bajty danych.

       Jeśli przestrzeń przydzielona do otrzymywanych danych pomocniczych jest zbyt mała, to dane pomocnicze  są
       przycinane  do  liczby  nagłówków  mieszczących  się  w  udostępnionym  buforze  (lub,  w przypadku listy
       deskryptora  pliku  SCM_RIGHTS,  sama  lista  deskryptorów  pliku  może  zostać  przycięta).  Jeśli   dla
       przychodzących  danych  pomocniczych  nie  udostępniono  bufora  (np.  pole  msg_control struktury msghdr
       przekazanej do recvmsg(2) wynosi NULL),  to  przychodzące  dane  pomocnicze  są  odrzucane.  W  obu  tych
       przypadkach, flaga MSG_CTRUNC zostanie ustawiona na wartość msg.msg_flags zwróconą przez recvmsg(2).

   Kontrolki systemowe (ioctl)
       Następujące wywołania ioctl(2) zwracają informacje w parametrze value. Poprawna składnia to:

              int value;
              error = ioctl(unix_socket, ioctl_type, &value);

       ioctl_type może przyjmować wartość:

       SIOCINQ
              Dla  gniazd  SOCK_STREAM,  wywołanie to zwraca liczbę nieprzeczytanych jeszcze bajtów znajdujących
              się w buforze odbierającym. Gniazdo nie może się znajdować w stanie "LISTEN"; w przeciwnym wypadku
              zostanie zwrócony błąd (EINVAL). SIOCINQ  jest  zdefiniowany  w  <linux/sockios.h>.  Alternatywnie
              można  użyć  synonimu  FIONREAD  zdefiniowanego  w  <sys/ioctl.h>. Dla gniazd SOCK_DGRAM, zwracana
              wartość jest taka sama jak w przypadku datagramowych gniazd domeny Internet; zob. udp(7).

BŁĘDY

       EADDRINUSE
              Podany adres lokalny jest zajęty lub obiekt gniazda w systemie plików już istnieje.

       EBADF  Błąd może zajść  dla  sendmsg(2),  przy  wysyłaniu  deskryptora  pliku  jako  dane  pomocnicze  za
              pośrednictwem  gniazda  domeny  uniksowej (zob. opis SCM_RIGHTS wyżej) i wskazuje że wysłany numer
              deskryptora pliku jest nieprawidłowy (np. nie jest to otwarty deskryptor pliku).

       ECONNREFUSED
              Adres zdalny podany w connect(2) nie odnosił  się  do  gniazda  nasłuchującego.  Błąd  może  także
              wystąpić jeśli docelowa ścieżka nie jest gniazdem.

       ECONNRESET
              Zdalne gniazdo zostało nieoczekiwanie zamknięte.

       EFAULT Nieprawidłowy adres pamięci użytkownika.

       EINVAL Podano nieprawidłowy argument. Najczęstszą przyczyną jest brak ustawionego AF_UNIX w polu sun_type
              przekazywanych gniazdu adresów lub nieprawidłowy dla danej operacji stan gniazda.

       EISCONN
              Wywołano connect(2) dla już połączonego gniazda lub podano adres docelowy dla połączonego gniazda.

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

       ENOENT Nie istnieje ścieżka dla zdalnego adresu przekazanego do connect(2).

       ENOMEM Brak pamięci.

       ENOTCONN
              Operacja na gnieździe wymaga adresu docelowego, a gniazdo nie jest połączone.

       EOPNOTSUPP
              Operacja  strumieniowa  wywołana  dla  gniazda  niestrumieniowego  lub  próba  użycia opcji danych
              autonomicznych.

       EPERM  Wysyłający podał nieprawidłowe uwierzytelnienia w struct ucred.

       EPIPE  Zdalne gniazdo strumieniowe zostało zamknięte. Gdy włączone,  wysyłany  jest  jednocześnie  sygnał
              SIGPIPE. Można tego uniknąć, przekazując znacznik MSG_NOSIGNAL do send(2) lub sendmsg(2).

       EPROTONOSUPPORT
              Podanym protokołem nie jest AF_UNIX.

       EPROTOTYPE
              Typ gniazda zdalnego różni się od typu gniazda lokalnego (SOCK_DGRAM wobec SOCK_STREAM).

       ESOCKTNOSUPPORT
              Nieznany typ gniazda.

       ESRCH  Przy   wysyłaniu   komunikatów   pomocniczych  zawierających  uwierzytelnienie  (SCM_CREDENTIALS),
              wywołujący podał identyfikator procesu, który nie dopasował żadnego istniejącego procesu.

       ETOOMANYREFS
              Błąd może zajść  dla  sendmsg(2),  przy  wysyłaniu  deskryptora  pliku  jako  dane  pomocnicze  za
              pośrednictwem  gniazda  domeny  uniksowej  (zob.  opis  SCM_RIGHTS wyżej). Występuje, jeśli liczba
              deskryptorów pliku "w locie" wykracza poza limit zasobów RLIMIT_NOFILE, a wywołujący  nie  posiada
              przywileju  CAP_SYS_RESOURCE.  Przez  deskryptor  pliku  w  locie  rozumiemy tu taki, który został
              wysłany za pomocą sendmsg(2), ale nie został jeszcze zaakceptowany przez proces docelowy za pomocą
              recvmsg(2).

              Błąd ten jest diagnozowany w głównej gałęzi jądra od Linuksa 4.5 (i  w  niektórych  wcześniejszych
              wersjach,  gdzie  zaaplikowano  odpowiednią  łatkę).  We wcześniejszych wersjach jądra, można było
              umieścić nieograniczoną liczbę deskryptorów plików w locie, poprzez wysłanie  każdego  z  nich  za
              pomocą  sendmsg(2),  a  następnie  zamknięcie  deskryptora  pliku, co nie liczyło się wobec limitu
              zasobów RLIMIT_NOFILE.

       Inne błędy mogą zostać wygenerowane przez podstawową warstwę  gniazd  lub  przez  system  plików  podczas
       tworzenia  obiektu  gniazda  w  systemie plików. Więcej informacji można znaleźć na odpowiednich stronach
       podręcznika.

WERSJE

       SCM_CREDENTIALS oraz abstrakcyjna przestrzeń nazw zostały wprowadzone w Linuksie 2.2  i  nie  należy  ich
       używać  w  przenośnych  programach. (Niektóre systemy wywodzące się z BSD również wspierają przekazywanie
       uwierzytelnień, ale implementacje różnią się szczegółami).

UWAGI

       W trakcie łączenia się z gniazdem mającym przypisaną nazwę pliku, tworzony jest plik specjalny gniazda  w
       systemie  plików, który musi zostać usunięty (za pomocą unlink(2)) przez wywołującego, gdy już nie będzie
       potrzebny. Stosuje się tu zwykła uniksowa składnia opóźnionego zamknięcia  (ang.  close-behind):  gniazdo
       można  skasować w dowolnym momencie, ale zostanie ono ostatecznie usunięte z systemu plików po zamknięciu
       ostatniego odwołania do niego.

       Aby przekazać deskryptory plików  lub  uwierzytelnienia  poprzez  SOCK_STREAM  trzeba  wysłać/odebrać  co
       najmniej jeden bajt niepomocniczych danych w tym samym wywołaniu sendmsg(2) lub recvmsg(2)

       Gniazda strumieniowe z domeny uniksowej nie obsługują zawiadomienia o danych autonomicznych.

USTERKI

       Przy  wiązaniu  gniazda  z  adresem, Linux jest jedną z implementacji dodających kończące null, jeśli nie
       poda się go w sun_path. Zwykle jest to bezproblemowe, gdy adres gniazda  jest  pozyskiwany  będzie  on  o
       jeden  bajt  dłuższy  niż  podawany  początkowo.  Jest  jednak  jeden  przypadek mogący spowodować mylące
       zachowanie: jeśli podany zostanie adres 108 bajtowy, bez znaku null, to dodanie znaku null  spowodowałoby
       przekroczenie  długości  ścieżki  poza sizeof(sun_path). W konsekwencji, przy pozyskiwaniu adresu gniazda
       (np. poprzez accept(2)), jeśli wejściowy argument addrlen dla pozyskiwanego wywołania  jest  podany  jako
       sizeof(struct sockaddr_un), to zwrócona struktura adresu nie będzie miała kończącego null w sun_path.

       Dodatkowo,  niektóre  implementacje  nie wymagają kończącego null przy wiązaniu gniazda (argument addrlen
       jest używany do określenia długości sun_path), a  gdy  w  tych  implementacjach  jest  pozyskiwany  adres
       gniazda, to nie ma kończącego null w sun_path.

       Aplikacje  pozyskujące  adresy  gniazd mogą posiadać (przenośny) kod do obsługi możliwości, że w sun_path
       nie ma kończącego null zauważając fakt, że liczba prawidłowych bajtów w ścieżce to:

           strnlen(addr.sun_path, addrlen - offsetof(sockaddr_un, sun_path))

       Alternatywnie, aplikacja może pozyskać adres gniazda przez przydzielenie buforu o rozmiarze sizeof(struct
       sockaddr_un)+1 który jest wyzerowany przed pozyskaniem. Pobierające wywołanie może określić addrlen  jako
       sizeof(struct  sockaddr_un),  a  dodatkowy  bajt zero zapewnia, że w łańcuchu zwróconym w sun_path będzie
       kończące null:

           void *addrp;

           addrlen = sizeof(struct sockaddr_un);
           addrp = malloc(addrlen + 1);
           if (addrp == NULL)
               /* Obsługa błędu */ ;
           memset(addrp, 0, addrlen + 1);

           if (getsockname(sfd, (struct sockaddr *) addrp, &addrlen)) == -1)
               /* obsługa błędu */ ;

           printf("sun_path = %s\n", ((struct sockaddr_un *) addrp)->sun_path);

       Tego bałaganu można uniknąć, jeśli jest pewność, że aplikacja tworząca ścieżki gniazd  przestrzega  reguł
       opisanych powyżej rozdziale Ścieżki gniazd.

PRZYKŁADY

       Poniższy  kod  demonstruje użycie gniazd pakietów sekwencyjnych do lokalnej komunikacji międzyprocesowej.
       Składa się z dwóch programów. Serwer czeka na połączenie z programu klienckiego. Klient wysyła  każdy  ze
       swoich  argumentów  wiersza  poleceń w oddzielnych wiadomościach. Serwer traktuje przychodzące wiadomości
       jako liczby całkowite i dodaje je.  Klient  wysyła  łańcuch  polecenia  "END".  Serwer  odsyła  komunikat
       zawierający  sumę  klienckich  liczb  całkowitych.  Klient  wypisuje  sumę  i  wychodzi.  Serwer czeka na
       połączenie od kolejnego klienta. Aby zatrzymać  serwer,  klient  jest  wywoływany  z  argumentem  wiersza
       poleceń "DOWN".

       Podczas  działania  serwera  w  tle  i  kolejnych  uruchomień klienta zarejestrowano następujące wyjście.
       Wykonywanie programu serwera kończy się, gdy otrzymuje on polecenie "DOWN".

   Przykładowe wyjście
           $ ./server &
           [1] 25887
           $ ./client 3 4
           Wynik = 7
           $ ./client 11 -5
           Wynik = 6
           $ ./client DOWN
           Wynik = 0
           [1]+  Done                    ./server
           $

   Kod źródłowy programu

       /*
        * Plik connection.h
        */
       #ifndef CONNECTION_H
       #define CONNECTION_H

       #define SOCKET_NAME "/tmp/9Lq7BNBnBycd6nxy.socket"
       #define BUFFER_SIZE 12

       #endif  // include guard (ochr. przed wielokr. przetw.)

       /*
        * Plik server.c
        */

       #include <stdio.h>
       #include <stdlib.h>
       #include <string.h>
       #include <sys/socket.h>
       #include <sys/types.h>
       #include <sys/un.h>
       #include <unistd.h>

       #include "connection.h"

       int
       main(void)
       {
           int                 down_flag = 0;
           int                 ret;
           int                 connection_socket;
           int                 data_socket;
           int                 result;
           ssize_t             r, w;
           struct sockaddr_un  name;
           char                buffer[BUFFER_SIZE];

           /* Tworzenie gniazda lokalnego. */

           connection_socket = socket(AF_UNIX, SOCK_SEQPACKET, 0);
           if (connection_socket == -1) {
               perror("socket");
               exit(EXIT_FAILURE);
           }

           /*
            * Ze względu na przenośność konieczne jest wyczyszczenie całej
            * struktury, ponieważ niektóre implementacje zawierają dodatkowe
            * (nieprzenośne) pola w strukturze.
            */

           memset(&name, 0, sizeof(name));

           /* Skojarzenie gniazda z nazwą gniazda. */

           name.sun_family = AF_UNIX;
           strncpy(name.sun_path, SOCKET_NAME, sizeof(name.sun_path) - 1);

           ret = bind(connection_socket, (const struct sockaddr *) &name,
                      sizeof(name));
           if (ret == -1) {
               perror("bind");
               exit(EXIT_FAILURE);
           }

           /*
            * Przygotowanie do przyjmowania połączeń. Rozmiar dziennika zaległości
            * ustawiony na 20. W trakcie przetwarzania jednego żądania, inne mogą
            * zatem oczekiwać.
            */

           ret = listen(connection_socket, 20);
           if (ret == -1) {
               perror("listen");
               exit(EXIT_FAILURE);
           }

           /* To jest główna pętla do obsługi połączeń. */

           for (;;) {

               /* Oczekiwanie na połączenie przychodzące. */

               data_socket = accept(connection_socket, NULL, NULL);
               if (data_socket == -1) {
                   perror("accept");
                   exit(EXIT_FAILURE);
               }

               result = 0;
               for (;;) {

                   /* Oczekiwanie na następny pakiet danych. */

                   r = read(data_socket, buffer, sizeof(buffer));
                   if (r == -1) {
                       perror("read");
                       exit(EXIT_FAILURE);
                   }

                   /* Upewnienie się, że bufor jest zakończony 0. */

                   buffer[sizeof(buffer) - 1] = 0;

                   /* Obsługa poleceń. */

                   if (!strncmp(buffer, "DOWN", sizeof(buffer))) {
                       down_flag = 1;
                       continue;
                   }

                   if (!strncmp(buffer, "END", sizeof(buffer))) {
                       break;
                   }

                   if (down_flag) {
                       continue;
                   }

                   /* Dodanie otrzymanego składnika. */

                   result += atoi(buffer);
               }

               /* Wysłanie wyniku. */

               sprintf(buffer, "%d", result);
               w = write(data_socket, buffer, sizeof(buffer));
               if (w == -1) {
                   perror("write");
                   exit(EXIT_FAILURE);
               }

               /* Zamknięcie gniazda. */

               close(data_socket);

               /* Wyjście na polecenie DOWN. */

               if (down_flag) {
                   break;
               }
           }

           close(connection_socket);

           /* Odlinkowanie gniazda. */

           unlink(SOCKET_NAME);

           exit(EXIT_SUCCESS);
       }

       /*
        * Plik client.c
        */

       #include <stdio.h>
       #include <stdlib.h>
       #include <string.h>
       #include <sys/socket.h>
       #include <sys/types.h>
       #include <sys/un.h>
       #include <unistd.h>

       #include "connection.h"

       int
       main(int argc, char *argv[])
       {
           int                 ret;
           int                 data_socket;
           ssize_t             r, w;
           struct sockaddr_un  addr;
           char                buffer[BUFFER_SIZE];

           /* Tworzenie gniazda lokalnego. */

           data_socket = socket(AF_UNIX, SOCK_SEQPACKET, 0);
           if (data_socket == -1) {
               perror("socket");
               exit(EXIT_FAILURE);
           }

           /*
            * Ze względu na przenośność konieczne jest wyczyszczenie całej
            * struktury, ponieważ niektóre implementacje zawierają dodatkowe
            * (nieprzenośne) pola w strukturze.
            */

           memset(&addr, 0, sizeof(addr));

           /* Łączenie gniazda z adresem gniazda. */

           addr.sun_family = AF_UNIX;
           strncpy(addr.sun_path, SOCKET_NAME, sizeof(addr.sun_path) - 1);

           ret = connect(data_socket, (const struct sockaddr *) &addr,
                          sizeof(addr));
           if (ret == -1) {
               fprintf(stderr, "Serwer jest wyłączony.\n");
               exit(EXIT_FAILURE);
           }

           /* Wysyłanie argumentów. */

           for (int i = 1; i < argc; ++i) {
               w = write(data_socket, argv[i], strlen(argv[i]) + 1);
               if (w == -1) {
                   perror("write");
                   break;
               }
           }

           /* Żądanie wyniku. */

           strcpy(buffer, "END");
           w = write(data_socket, buffer, strlen(buffer) + 1);
           if (w == -1) {
               perror("write");
               exit(EXIT_FAILURE);
           }

           /* Otrzymanie wyniku. */

           r = read(data_socket, buffer, sizeof(buffer));
           if (r == -1) {
               perror("read");
               exit(EXIT_FAILURE);
           }

           /* Upewnienie się, że bufor kończy się 0. */

           buffer[sizeof(buffer) - 1] = 0;

           printf("Wynik = %s\n", buffer);

           /* Zamknięcie gniazda. */

           close(data_socket);

           exit(EXIT_SUCCESS);
       }

       Przykłady użycia SCM_RIGHTS można znaleźć w podręcznikach cmsg(3) i seccomp_unotify(2).

ZOBACZ TAKŻE

       recvmsg(2), sendmsg(2), socket(2), socketpair(2), cmsg(3),  capabilities(7),  credentials(7),  socket(7),
       udp(7)

TŁUMACZENIE

       Autorami    polskiego    tłumaczenia   niniejszej   strony   podręcznika   są:   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   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.

Linux man-pages 6.8                              2 maja 2024 r.                                          UNIX(7)