Daemon Socket server in C - c

I have successfully created a C program which runs an infinite loop waiting for a connecting through sockets.
I would like to make it a daemon and be able to start and stop it. How can I do it? What changes should I do to my code to run in the background?

The classic tasks required to become a daemon are:
Change the working directory to the root, so that your daemon does not pin another mount;
Call fork() and have the parent exit, so that the process is not a process group leader;
Redirect standard input, standard output and standard error to /dev/null;
Call setsid() to make the process a session group leader of a new session with no controlling terminal.
Without error-checking:
chdir("/);
if (fork() > 0)
_exit();
close(0);
close(1);
close(2);
open("/dev/null", O_RDWR);
dup(0);
dup(0);
setsid();
On Linux, glibc provides a daemon() helper function to do these tasks.

To run a c program as daemon you need to do the following steps.
// Create child process
process_id = fork();
//unmask the file mode
umask(0);
//change the directory as your home directory
strcpy(home,"HOME");
home=getenv(home);
chdir(home) ;
//set new session
sid = setsid();
close(STDIN_FILENO); open("/dev/null", O_RDWR);
close(STDOUT_FILENO); open("/dev/null", O_RDWR);
close(STDERR_FILENO); open("/dev/null", O_RDWR);

Related

How to use stderr with execve [duplicate]

I'm writing a C program where I fork(), exec(), and wait(). I'd like to take the output of the program I exec'ed to write it to file or buffer.
For example, if I exec ls I want to write file1 file2 etc to buffer/file. I don't think there is a way to read stdout, so does that mean I have to use a pipe? Is there a general procedure here that I haven't been able to find?
For sending the output to another file (I'm leaving out error checking to focus on the important details):
if (fork() == 0)
{
// child
int fd = open(file, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
dup2(fd, 1); // make stdout go to file
dup2(fd, 2); // make stderr go to file - you may choose to not do this
// or perhaps send stderr to another file
close(fd); // fd no longer needed - the dup'ed handles are sufficient
exec(...);
}
For sending the output to a pipe so you can then read the output into a buffer:
int pipefd[2];
pipe(pipefd);
if (fork() == 0)
{
close(pipefd[0]); // close reading end in the child
dup2(pipefd[1], 1); // send stdout to the pipe
dup2(pipefd[1], 2); // send stderr to the pipe
close(pipefd[1]); // this descriptor is no longer needed
exec(...);
}
else
{
// parent
char buffer[1024];
close(pipefd[1]); // close the write end of the pipe in the parent
while (read(pipefd[0], buffer, sizeof(buffer)) != 0)
{
}
}
You need to decide exactly what you want to do - and preferably explain it a bit more clearly.
Option 1: File
If you know which file you want the output of the executed command to go to, then:
Ensure that the parent and child agree on the name (parent decides name before forking).
Parent forks - you have two processes.
Child reorganizes things so that file descriptor 1 (standard output) goes to the file.
Usually, you can leave standard error alone; you might redirect standard input from /dev/null.
Child then execs relevant command; said command runs and any standard output goes to the file (this is the basic shell I/O redirection).
Executed process then terminates.
Meanwhile, the parent process can adopt one of two main strategies:
Open the file for reading, and keep reading until it reaches an EOF. It then needs to double check whether the child died (so there won't be any more data to read), or hang around waiting for more input from the child.
Wait for the child to die and then open the file for reading.
The advantage of the first is that the parent can do some of its work while the child is also running; the advantage of the second is that you don't have to diddle with the I/O system (repeatedly reading past EOF).
Option 2: Pipe
If you want the parent to read the output from the child, arrange for the child to pipe its output back to the parent.
Use popen() to do this the easy way. It will run the process and send the output to your parent process. Note that the parent must be active while the child is generating the output since pipes have a small buffer size (often 4-5 KB) and if the child generates more data than that while the parent is not reading, the child will block until the parent reads. If the parent is waiting for the child to die, you have a deadlock.
Use pipe() etc to do this the hard way. Parent calls pipe(), then forks. The child sorts out the plumbing so that the write end of the pipe is its standard output, and ensures that all other file descriptors relating to the pipe are closed. This might well use the dup2() system call. It then executes the required process, which sends its standard output down the pipe.
Meanwhile, the parent also closes the unwanted ends of the pipe, and then starts reading. When it gets EOF on the pipe, it knows the child has finished and closed the pipe; it can close its end of the pipe too.
Since you look like you're going to be using this in a linux/cygwin environment, you want to use popen. It's like opening a file, only you'll get the executing programs stdout, so you can use your normal fscanf, fread etc.
After forking, use dup2(2) to duplicate the file's FD into stdout's FD, then exec.
You could also use the linux sh command and pass it a command that includes the redirection:
string cmd = "/bin/ls > " + filepath;
execl("/bin/sh", "sh", "-c", cmd.c_str(), 0);
For those such as myself who like a complete example with includes, here's this fantastic answer with a runnable example (still without error handling, left as an exercise):
#include <fcntl.h>
#include <sys/wait.h>
#include <unistd.h>
int main() {
if (fork() == 0) { // child
int fd = open("test.txt", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR);
dup2(fd, 1); // make stdout go to file
dup2(fd, 2); // make stderr go to file - you may choose to not do this
// or perhaps send stderr to another file
close(fd); // fd no longer needed - the dup'ed handles are sufficient
execlp("ls", "ls", NULL);
}
else {
while (wait(NULL) > 0) {} // wait for each child process
}
return 0;
}

How to avoid read() from hanging in the following situation?

I have some code that forks a third-party application and redirects its standard output to the parent process, roughly as follows (no error handling here for brevity):
char* args[] = {"/path/to/3rd/party/binary", "with", "args", NULL};
int fds[2];
pipe2(fds, O_CLOEXEC);
pid_t pid = fork();
if (pid == 0)
{
dup2(fds[1], STDOUT_FILENO);
execvp(args[0], args);
_exit(1);
}
else
{
close(fds[1]);
char buf[1024];
int bytes_read;
while ((bytes_read = read(fds[0], buf, sizeof buf - 1)) > 0)
{
buf[bytes_read] = '\0';
printf("%s", buf);
}
close(fds[0]);
waitpid(pid, NULL, 0);
}
I have no code for the third-party application, it is a proprietary binary. When running the third-party application in a terminal with the same arguments as used in the code above, it eventually finishes. However, when forking the third-party binary using the code above, it does not finish, but becomes a zombie process, and the code above hangs on the read() call.
The third-party binary that is forked itself forks two daemon processes (again, proprietary binaries I do not control), which I think is causing the problem here. The forked daemon processes will have a copy of the duplicated file descriptor, preventing the read() from finishing. Indeed, in case the dup2() call is replaced with:
dup3(fds[1], STDOUT_FILENO, O_CLOEXEC);
the child process finishes, but there is no output redirection to the parent process of course. Also, when the code above is modified to not do any output redirection to the parent over a pipe, the child process finishes correctly.
Is it possible to somehow prevent this hang on the read() call in this situation, or do I need to resort to some form of non-blocking I/O?
Update; using a simple popen() suffers from the same problem.
(Follow-up from: read() hangs on zombie process)
You need to specifically ignore SIGCHLD. It's your responsibility to reap the zombie, but you can't do it when blocked in read. If you call read after the SIGCHLD has been swallowed, you'll stay in read forever.

launch process with fork and exec while redirecting stdout to /dev/null

I have a very specific problem for which I am unable to find the answer after numerous searches. I have a linux program. It's job is to launch another secondary executable (via fork() and exec()) when it receives a specific message over the network. I do not have access to modify the secondary executable.
My program prints all its TTY to stdout, and I typically launch it via ./program > output.tty The problem I have is that this second executable is very verbose. It simultaneously prints to stdout while also putting the same TTY in a log file. So my output.tty file ends up containing both output streams.
How can I set things up such that the secondary executable's TTY gets redirected to /dev/null? I can't use system() because I can't afford to wait for the child process. I need to be able to fire and forget.
Thanks.
In child process use dup2() to redirect the output to a file.
int main(int argc, const char * argv[]) {
pid_t ch;
ch = fork();
int fd;
if(ch == 0)
{
//child process
fd = open("/dev/null",O_WRONLY | O_CREAT, 0666); // open the file /dev/null
dup2(fd, 1); // replace standard output with output file
execlp("ls", "ls",".",NULL); // Excecute the command
close(fd); // Close the output file
}
//parent process
return 0;
}
In the child process, before calling exec, you need to close the standard output stream.
pid_t pid =fork();
if (pid == 0) {
close(1);
// call exec
} else if (pid > 0) {
// parent
}

How to call UNIX sort command on data in pipe

I am creating a C program and with it I am setting up a pipe between separately forked process for interprocess communication.
The first process has written the data I need into the pipe.
However, with the second process reading from the pipe, I am trying to exec the process to become the UNIX sort command. I want to somehow call sort on the data in the pipe.
How can I call sort on a pipe? On the commandline, I can sort by supplying the filename to sort as a commandline argument e.g. "sort -r MyFileToSort". I know that pipes are essentially considered files, but they are only described by their file descriptor, and as far as I know, sort won't know what to do with a fd.
Thanks for any help/feedback
int p[2];
if (pipe(p) != 0) ...report error and do not continue...
pid_t pid = fork();
if (pid < 0) ...report error, close pipe descriptors, and do not continue...
if (pid == 0)
{
/* Child - becomes sort */
dup2(p[0], 0);
close(p[0]);
close(p[1]);
int fd = open("output-file", O_CREAT | O_EXCL | O_WRONLY, 0644);
if (fd < 0) ...report error and exit...
dup2(fd, 1);
close(fd);
execlp("sort", "sort", (char *)0);
...report error and exit...
}
else
{
/* Parent - writes data to sort */
close(fd[0]);
...write data to fd[1]...
close(fd[1]);
int status;
int corpse;
while ((corpse = wait(&status)) > 0 && corpse != pid)
...consider reporting which child died...
...consider reporting sort status...
...continue with the rest of the program...
}
You can decide whether to report errors related to dup2() failing, or close() failing. There isn't much you can do in either case except report the problem and exit. Unless someone has subjected your program to cruel and unusual punishment by not supplying it with standard input, standard output and standard error (or something elsewhere in the program has closed any of the standard channels), then the pipe and file descriptors can't be the standard I/O descriptors, so the closes are safe. If you're not sure how sick your users are, you might protect the closes:
if (p[0] > FILENO_STDERR)
close(p[0]);
That is normally unnecessarily paranoid (but it can be fun trying programs with missing standard I/O).
You don't need to pass sort any arguments to specify input source or output sink at all in this case. Instead, before execing it, you should make attach your pipeline's file descriptors to its stdin (FD 0, if receiving data from a pipe) or stdout (FD 1, if writing data to a pipe), as appropriate.
See the dup2() call, which lets you set the destination to which you're copying a FD, for this purpose. As #JonathanLeffler points out, you'll want to be sure to close the original FDs (after duplicating them to the numbers you want) before your exec call.
Since you've clarified, in comments, that your goal is to write to a file, you would attach FD 1 to that destination file before calling exec, with FD 0 attached to the output side of the pipeline containing input.

forkpty - socket

I'm trying to develop a simple "telnet/server" daemon which have to run a program on a new socket connection.
This part working fine.
But I have to associate my new process to a pty, because this process have some terminal capabilities (like a readline).
The code I've developped is (where socketfd is the new socket file descriptor for the new input connection) :
int masterfd, pid;
const char *prgName = "...";
char *arguments[10] = ....;
if ((pid = forkpty(&masterfd, NULL, NULL, NULL)) < 0)
perror("FORK");
else if (pid)
return pid;
else
{
close(STDOUT_FILENO);
dup2(socketfd, STDOUT_FILENO);
close(STDIN_FILENO);
dup2(socketfd, STDIN_FILENO);
close(STDERR_FILENO);
dup2(socketfd, STDERR_FILENO);
if (execvp(prgName, arguments) < 0)
{
perror("execvp");
exit(2);
}
}
With that code, the stdin / stdout / stderr file descriptor of my "prgName" are associated to the socket (when looking with ls -la /proc/PID/fd), and so, the terminal capabilities of this process doesn't work.
A test with a connection via ssh/sshd on the remote device, and executing "localy" (under the ssh connection) prgName, show that the stdin/stdout/stderr fd of this process "prgName" are associated to a pty (and so the terminal capabilities of this process are working fine).
What I am doing wrong?
How to associate my socketfd with the pty (created by forkpty) ?
Thank
Alex
You must write some code to transfer data from the socket to the master pty and vice versa. It's usually a parent process' job. Note that the data transfer must be bidirectional. There are many options: a select()-driven cycle to track both the masterfd and the socketfd
(just as hint, very bad code, not for production!!! Missing error and eof checks!!!)
for (;;) {
FD_ZERO(&set);
FD_SET(masterfd,&set);
FD_SET(socketfd,&set);
select(...,&set,...);
if (FD_ISSET(masterfd,&set)) {
read(masterfd,&c,1);
write(socketfd,&c,1);
}
if (FD_ISSET(sockerfd,&set)) {
read(sochetfd,&c,1);
write(masterfd,&c,1);
}
or a pair of threads, one for socketfd->masterfd and one for masterfd->sockefd transfers.
(just as hint, very bad code, not for production!!!)
/*thread 1 */
while (read(masterfd,&c,1) > 0)
write(socketfd,&c,1);
/*thread 2 */
while (read(socketfd,&c,1) > 0)
write(masterfdfd,&c,1);
Anyway you must add some code in the parent side of the branch.
Regards
---EDIT---
Of course, you must not redirect fd 0,1 and 2 to socketfd in the child process.

Resources