struct passwd
is documented in POSIX, in pwd.h
. It is a structure used to store the /etc/passwd
entries for a given user. The three you mention are these:
uid_t pw_uid
Numerical user ID.char *pw_dir
Initial working directory. (Home directory.)char *pw_shell
Program to use as shell. (Default shell for the user.)
The function doauth
referenced in the code above probably either calls getpwent
or simulates that to fill in the appropriate values for the user on the remote system.
pv
is pair of file descriptors representing connected pipes, set up by pipe()
. pv[0]
is the "read side", pv[1]
the "write side". Anything written to pv[1]
can be read from pv[0]
.
In the code above, the parent process does:
close(pv[1]);
stderr_parent(sock, pv[0], pid);
which closes the write side, and, I'm guessing, wires the read side to (one of) the sockets used to communicate between the hosts.
The child process on the other hand does this:
close(pv[0]); // close the read side
dup2(pv[1], 2); // clone the write side to fd n° 2 (stderr)
close(pv[1]); // close the original write side (now only
// writable through fd n° 2
So basically, the child's stderr
stream is now connected to a network stream back to the client.
The rest of the code essentially sanitizes the environment (environment variables and working directory), checks permissions, sets the appropriate uid
/gid
and finally executes the command that the user wanted to run using execl()
via a shell. The actual command run on the remote system will be something like /bin/sh -c <user command string>
.
So with your example, assuming for example that your user's shell in /etc/passwd
is /bin/bash
, the execl
call will result in running this:
/bin/bash -c 'ulimit -n'
(Quotes since the user command is a single argument in the execl
call, it is not tokenized.)