.Dd October 21, 2022 .Dt PIDCONN 2 .Os .Sh NAME .Nm pidconn .Nd PID-addressed communication .Sh LIBRARY .Lb libc .Sh SYNOPSIS .In unistd.h .Ft int .Fn pidconn "int op" "int iarg" "pid_t parg" .Sh DESCRIPTION .Nm supports communication, somewhat a la sockets, where the peer is identified by process ID. (Sockets are not suitable, mostly for internal code-structure reasons.) .Pp The .Ar op argument specifies what operation to perform; depending on the operation, .Ar iarg and .Ar parg potentially specify arguments to it. The operation can be: .Bl -tag -width indent .It Dv PIDCONN_LISTEN .Ar iarg and .Ar parg must each be zero. On success, the return value is a file descriptor which conceptually functions like a passive socket (see .Xr socket 2 ) , accepting incoming connections; on failure, the return value is -1. (Unlike sockets, there are no analogs to .Xr bind 2 or .Xr listen 2 ; they are unnecessary because the address is always the listening process's PID.) .It Dv PIDCONN_CONNECT Establishes a connection to a process which has a listening descriptor (see .Dv PIDCONN_LISTEN ) . This is the conceptual analog of .Xr connect 2 . The target process ID is given as .Ar parg ; .Ar iarg must be zero. The return value is the descriptor for the new connection, or -1 on error. I/O is not possible until the target process calls .Dv PIDCONN_ACCEPT to complete the connection; this can be detected by .Xr select 2 Ns No ing or .Xr poll 2 Ns No ing for write. (If the other end sends data first in the use case of interest, checking for read instead works too, but if you just want to wait for the accept, checking for read will not work, because a newly-connection will not show readable until the peer writes something to it (or disconnects).) .Pp If a process has multiple listening descriptors, the connection can be accepted on any of them; they are operationally equivalent. Thus, there is little-to-no reason to use multiple listening descriptors. .It Dv PIDCONN_ACCEPT Accepts an incoming connection. .Ar parg must be zero. .Ar iarg specifies a listening descriptor (see .Dv PIDCONN_LISTEN ) ; the accept operation is non-blocking exactly when listening descriptor is. (A non-blocking accept operation when no connections are pending returns showing error .Dv EWOULDBLOCK . ) .Pp The descriptor for the new connection is returned, or -1 on error. .It Dv PIDCONN_PEERPID , PIDCONN_PEERRUID , PIDCONN_PEEREUID .Ar parg must be zero. .Ar iarg must be a connected descriptor, such as is returned by .Dv PIDCONN_CONNECT or .Dv PIDCONN_ACCEPT . These return information about the process which issued the .Dv PIDCONN_ACCEPT or .Dv PIDCONN_CONNECT call which created the other end of the connection. .Dv PIDCONN_PEERPID returns the process ID, .Dv PIDCONN_PEERRUID returns the real user-ID, and .Dv PIDCONN_PEEREUID returns the effective user-ID. .Pp Note that the process that created the connection might not exist any longer at the time the .Dv PIDCONN_PEERxxx call is made, and if it does it may no longer have the same user-IDs it did at the time. The information returned by these calls comes from a snapshot taken at the moment the connection was created. .Pp Using these requests on a descriptor that isn't connected, that is, one that resulted from .Dv PIDCONN_CONNECT but for which the corresponding .Dv PIDCONN_ACCEPT call has not yet been made, or one from .Dv PIDCONN_LISTEN , will fail with error .Dv ENOTCONN . (Of course, passing an argument that isn't an open descriptor number, or a descriptor that didn't come from .Nm pidconn , will also produce an error.) They will work correctly for a connected descriptor whose other end has been closed; the information snapshot mentioned above is not discarded until both of the connection's endpoints have been closed. .It Dv PIDCONN_DEBUG Performs various debugging operations. This is a debugging facility and, as such, is not documented here; see the source. .El .Pp While endpoint addressing is bound to process IDs during the listen, connect, and accept phases, once a connection is established then the descriptors referring to that connection may be inherited through .Xr fork 2 , passed through .Dv SCM_RIGHTS messages over .Dv AF_LOCAL sockets, or the like, like any other descriptors. (Listening descriptors may be passed around similarly, but the resulting descriptor is equivalent to one created with .Dv PIDCONN_LISTEN by the target.) .Pp .Nm is not well suited to high-bandwidth bulk data transfer. Its intended use is low-volume non-urgent traffic such as interactive status inquiries. It will work for large amounts of data, but not well; to use an analogy, that is driving a nail with a crowbar: the tool will work for the purpose but it is not particularly well suited to it. .Sh RETURN VALUES .Nm Ap s return value depends on the request. For .Dv PIDCONN_LISTEN , .Dv PIDCONN_CONNECT , and .Dv PIDCONN_ACCEPT , it returns a new endpoint descriptor, or -1 on error. For .Dv PIDCONN_PEERPID , .Dv PIDCONN_PEERRUID , and .Dv PIDCONN_PEEREUID , the relevant ID is returned, or -1 for erroneous calls. Like everything else about .Dv PIDCONN_DEBUG beyond its bare existence, its return value is not documented here; see the source. .Sh ERRORS .Bl -tag -width Er .It Bq Er EINVAL For .Dv PIDCONN_LISTEN , either .Ar iarg or .Ar parg is nonzero. .Pp For .Dv PIDCONN_CONNECT , .Ar iarg is nonzero. .Pp For .Dv PIDCONN_ACCEPT , .Ar iarg isn't a listening descriptor. .Pp .Xr read 2 or .Xr write 2 was called on a listening descriptor, or on a descriptor resulting from .Dv PIDCONN_CONNECT but for which the target process has not yet done .Dv PIDCONN_ACCEPT . .Pp The first argument was not one of the defined .Dv PIDCONN_\&* values. .It Bq Er ESRCH For .Dv PIDCONN_CONNECT , the target process does not exist. .It Bq Er ECONNREFUSED For .Dv PIDCONN_CONNECT , the target process does not have any listening descriptors open. .It Bq Er EWOULDBLOCK For .Dv PIDCONN_ACCEPT , there are no connections pending for the calling process, and the listening descriptor is set nonblocking. .Pp .Xr read 2 was called on a connected descriptor which is set nonblocking but for which no data is queued. .Pp .Xr write 2 was called on a connected descriptor which is set nonblocking but for which the connection's buffers are full. .It Bq Er ECONNRESET I/O was attempted on a descriptor from .Dv PIDCONN_CONNECT but for which the target process closed all its listening descriptors before accepting the connection. .It Bq Er ENOLINK .Xr write 2 was called on a connected descriptor whose peer is closed. (This really should be .Dv EPIPE , but machinery elsewhere in the system insists on generating a .Dv SIGPIPE upon returning .Dv EPIPE . For the intended use cases, a different return code and no .Dv SIGPIPE is the more useful behaviour.) .El .Sh SEE ALSO .Xr socket 2 . .Sh STANDARDS .Nm is an extension, not specified in any standard. .Sh HISTORY .Nm first appeared in Mouse's post-5.2 NetBSD.