I have two processes running by two different users. Both users are in the same group. I want to write to a stdin from one process by writing to /proc/<pid>/fd/0, but the permissions are only set for the other user so I get a permission denied. Can I somehow change the permissions somehow so the other process can write to it?

$ ls -lsa /proc/<pid>/fd/
0 lrwx------ 1 foo group1 64 Feb 14 23:15 0 -> /dev/pts/3
  • Can you explain what you are trying to do? To begin with, stdin is, well, for input, you should not be writing to it (it might work though, if stdin and stdout point to the same descriptor.). If you explain what the goal is, there might be a better way to interact with the other program. – Eduardo Trápani Feb 14 at 23:38
0 lrwx------ 1 foo group1 64 Feb 14 23:15 0 -> /dev/pts/3

Can I somehow change the permissions somehow so the other process can write to it?

Yes, but writing will probably not do what you want.

/dev/pts/3 is a pseudo-terminal slave device. The process you're after takes its input from a pseudo-terminal. You can change the permissions of such device with chmod. The node named 0 will not reflect the change but /dev/pts/3 will. To use the changed permissions you need to write to /dev/pts/3, not to 0.

The result will most likely not meet your expectations though. To explain it run a shell in a terminal emulator (konsole, xterm) or in a terminal multiplexer (tmux, screen) and invoke ls -l /proc/$$/fd/. You will find the shell reads and writes to the same pts. When it reads, it reads what you type. When it writes, it makes characters appear in the terminal.

The same will happen if you write to /dev/pts/3: characters will appear in the terminal which provides input for the process in question. Your action will not inject input as if you typed in the terminal, i.e. it will not provide input for the process.

To inject input as if you typed, you would need to write to the corresponding master device. This is not trivial. In short:

On Linux, using devpts, there is no master device file. The process on the master end uses a file descriptor, which it gets by opening ptmx, but there’s no corresponding device node.

"The process on the master end" is the terminal emulator, terminal multiplexer, sshd (if the client requested a pseudo-terminal), expect, …

However this other answer states:

There's a special ioctl (TIOCSTI) which allows you to insert a byte into the input queue of a tty, as if it were received from the other end. TIOCSTI will only work as root when not used on the controlling tty of the process calling it.

See the whole answer for details. I guess it may not be very useful for you because of the root access requirement.

The simplest way to (unidirectionally) connect two processes is to connect them with a pipe:

foo | bar

In case of processes that are about to be started by two different users, use a named pipe instead of unnamed pipe:

# any user
mkfifo pipeA
chmod …     # allow access for the other user

# user1
foo >pipeA

# user2
<pipeA bar

Named pipes behave like you expected while pseudo-terminal slave devices don't.

Note foo and bar are started with respective stdout and stdin already redirected. A running process can redirect its own stdin (e.g. shells can on demand) but there is no easy/elegant way to force it to.

E.g. if the process in question was an interactive bash, you could make it redirect its stdin from pipeA by invoking exec 0<pipeA. Then from another console you could do like echo date >pipeA and the shell would execute date as if you typed it (and it would probably exit because all descriptors writing to the pipe are now closed; to avoid this open the named pipe in the shell also for writing in the first place: exec 0<>pipeA).

|improve this answer|||||
  • Thanks so much for the detailed explanation! The example with the named pipe was exactly what I was looking for! Thanks again – Daniel Stephens Feb 15 at 5:17

In general, you cannot write to standard input. Standard input is, as its name suggests, for input, not output, and even when it's a regular file, you can't assume that it's been opened with anything other than read-only access.

What it sounds like you're trying to do is produce the output of one program on the input of another, which is generally only going to work if they're connected by a pipe. If you opened that file descriptor file (if you were permitted), instead of creating a pipe to the existing standard input of that process, you'd just be writing to that process's TTY instead. The user of that TTY would be quite unhappy with you for that, which is why it's typically not allowed.

It is possible to spawn a process of a different user with a pipe attached, but it generally requires root privileges or the aid of a program which has them (like sudo).

If you need to communicate between two processes and can't or don't want to use a pipe, then you probably want to use a Unix socket. One process should open the socket and listen on it, and other processes can then open the socket and connect to it, creating a bidirectional channel between two processes. Because the socket lives in the file system, you can grant it permissions such that members of the same group can both use it.

|improve this answer|||||
  • Thanks so much for the explanation! – Daniel Stephens Feb 15 at 5:14
  • Btw, I think a named pipe does what I was looking for, but I just found an example for a Unix socket you mentioned and I think I can use that for actually another problem I have :-) :-) Thanks! – Daniel Stephens Feb 15 at 5:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.