Making a Daemon using C and problems connecting it to a client - c

So, I've made a function in C that "daemonizes" a program, but when I do so, any code I want the daemon to execute, is not executed... even though the daemon is up and running in the background.
void makeDaemon(){
int i,fd0,fd1,fd2;
pid_t pid;
struct sigaction sa;
struct rlimit rl;
umask(0);
if(getrlimit(RLIMIT_NOFILE, &rl)<0) exit(EXIT_FAILURE);
if((pid=fork())<0) exit(EXIT_FAILURE);
if(pid>0) exit(EXIT_SUCCESS);
setsid();
sa.sa_handler=SIG_IGN;
sigemptyset(&sa.sa_mask);
sa.sa_flags=0;
if(sigaction(SIGHUP, &sa, NULL)<0) exit(EXIT_FAILURE);
if((pid=fork())<0) exit(EXIT_FAILURE);
if(pid>0) exit(EXIT_SUCCESS);
if(chdir("/")<0) exit(EXIT_FAILURE);
if(rl.rlim_max=RLIM_INFINITY) rl.rlim_max=1024;
for(i=0;i< rl.rlim_max; i++) close(i);
fd0=open("/dev/null",O_RDWR);
fd1=dup(0);
fd2=dup(0);
if(fd0!=0 || fd1!=1 || fd2!=2) exit(EXIT_FAILURE);
}
This is the "daemonizing" function, and this is an other program that I want to daemonize but it just doesnt do what it should...
int main(int argc, char ** argv){
makeDaemon();
char* path="./run/pipes/saturnd-request-pipe";
char* path2="./run/pipes/saturnd-reply-pipe";
//Creation d'un pipe au cas où il n'existe pas
//mkfireply_pipe(path,0666);
//Ouverture du pipe
int request_pipe;
request_pipe=open(path,O_RDONLY);
if(request_pipe==-1){
perror("Erreur d'ouverture du pipe");
return -1;
}
int reply_pipe;
reply_pipe=open(path2,O_WRONLY);
if(reply_pipe==-1){
perror("Erreur d'ouverture du pipe");
return -1;
}
char tmp1[2];
read(request_pipe,tmp1,2);
printf("%s",tmp1);
}
If someone has any advice on how to connect the two, I'd greatly appreciate it.

Related

Daemon not reactiing

I've already asked a similar question a few days ago. Basically I have to make a daemon-client communicate via named tubes. The client part is done and sends messages correctly, but the daemon part seems to not be receiving anything... Here's the code:
void makeDaemon(){
int i,fd0,fd1,fd2;
pid_t pid;
struct sigaction sa;
struct rlimit rl;
umask(0);
if(getrlimit(RLIMIT_NOFILE, &rl)<0) exit(EXIT_FAILURE);
if((pid=fork())<0) exit(EXIT_FAILURE);
if(pid>0) exit(EXIT_SUCCESS);
setsid();
sa.sa_handler=SIG_IGN;
sigemptyset(&sa.sa_mask);
sa.sa_flags=0;
if(sigaction(SIGHUP, &sa, NULL)<0) exit(EXIT_FAILURE);
if((pid=fork())<0) exit(EXIT_FAILURE);
if(pid>0) exit(EXIT_SUCCESS);
//if(chdir("/")<0) exit(EXIT_FAILURE);
if(rl.rlim_max=RLIM_INFINITY) rl.rlim_max=1024;
for(i=0;i< rl.rlim_max; i++) close(i);
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
//sigaction(SIGUSR1,&sac,NULL);
}
int main(){
makeDaemon();
char* path="./run/pipes/saturnd-request-pipe";
char* path2="./run/pipes/saturnd-reply-pipe";
//Creation d'un pipe au cas où il n'existe pas
//mkfireply_pipe(path,0666);
int timeout=5000;
struct pollfd pf[1];
int request_pipe;
while(1){
request_pipe=open(path,O_RDONLY);
if(request_pipe==-1){
perror("Erreur d'ouverture du pipe");
exit(EXIT_FAILURE);
}
pf[0].fd=request_pipe;
pf[0].events=POLLIN;
int p=poll(pf,1,timeout);
if(pf[0].revents & POLLIN){
char tmp1[2];
ssize_t s=read(request_pipe,tmp1,2);
if(s==-1) exit(EXIT_FAILURE);
printf("%s\n",tmp1);
int i=1;
}else{
printf("Timed out\n");
break;
}
return 0;
}
}
My question is, should I maybe make a handler containing this while loop so that the daemon can receive a signal? As of right now, it just times out and dies. We cannot use sockets, and everything is done via these two names pipes. Any suggestion would be appreciated. Thanks!

Problem with progamming an intern comands in a shell interpeter (made by myself)

I had a project of operating systems where I had to program a command interpreter in shell in C. I've done it most part of it, the code I've already implemented allows to execute simple commands like ls, or commands in background and/or with pipes.
But now I also have to program an intern command (a new one). Its name is going to be myTime and it should allow you to measure the time that takes to a process to execute its function. For example if you execute the command sleep 10 in the Linux shell, the process should sleep at least the time indicated. The goal of the intern command myTime is to measure that time.
IMPORTANT: In the code I've been giving some help from the teachers that allows me with a function called obtain_orden obtain the command introduced (ex: calling argvv[i][0] for the i command introduced), the arguments (argvv[i][1], the first argument), and if it is or not in background (bg =0/1)
Also, the function pid_t fork() creates a new process or a new child process and returns 0 if it's the child or pid if it's the parent.
I have additional code to compile etc, if you need it or its something nogt clear tell me. Thanks!
I´ve been searching in the sys/time.h library and the function gettimeofday. But i haven't been able to show the message I'm required to in my project: "Time spent: %f secs.\n"
As this intern command should measure the time that takes to a process to execute I've been told that I should execute a fork() and an exec(), and measure the time once the child process has done its function.
It should show like this:
msh> mytime sleep 5
Time spent: 5.001719 secs
msh>
extern int obtain_order(); /* See parser.y for description */
int main(void)
{
char ***argvv;
//int command_counter;
int num_commands;
//int args_counter;
char *filev[3];
int bg;
int ret;
setenv("Acc","0",1);
setbuf(stdout, NULL); /* Unbuffered */
setbuf(stdin, NULL);
while (1)
{
fprintf(stderr, "%s", "msh> "); /* Prompt */
ret = obtain_order(&argvv, filev, &bg);
if (ret == 0) break; /* EOF */
if (ret == -1) continue; /* Syntax error */
num_commands = ret - 1; /* Line */
if (num_commands == 0) continue; /* Empty line */
if(num_commands==1){
//Implementación propia para salir del mini-shell
if(strcmp(argvv[0][0], "exit") == 0){
exit(0);
}
if(strcmp(argvv[0][0],"myTime")==0){
//HERE IS WHERE I HAVE TO IMPLEMENT THE INTERN COMMAND MYTIME
}else{ //For all other commands ls, etc... (with pipes (max 3)and background)
int pid;
int estado;
pid = fork();
switch(pid) {
case -1: /* error */
fprintf(stderr, "%s","Error en el fork del mandato simple\n");
return (-1);
case 0: /* hijo */
if (filev[0] != NULL) {
close(STDIN_FILENO);
open(filev[0],O_RDONLY);
}
if (filev[1] != NULL) {
close(STDOUT_FILENO);
open(filev[1],O_CREAT|O_WRONLY,0666);
}
if (filev[2] != NULL) {
close(STDERR_FILENO);
open(filev[2],O_CREAT|O_WRONLY,0666);
}
execvp(argvv[0][0], argvv[0]);
fprintf(stderr, "%s","Error en el execvp del mandato simple\n");
return(-1);
default: /* padre */
if(!bg){
while (wait(&estado) != pid);
}else printf("%d\n",pid);
} //fin switch (1 mandato)
} //fin if (si es comando interno o no)
}else if(num_commands==2){
int pid;
int estado;
int fd[2];
pipe(fd);
pid = fork();
switch(pid) {
case -1: /* error */
fprintf(stderr, "%s","Error en el fork del primer mandato\n");
return (-1);
case 0: /* hijo1 */
close(STDOUT_FILENO);
dup(fd[1]);
close(fd[0]);
close(fd[1]);
if (filev[0] != NULL) {
close(STDIN_FILENO);
open(filev[0],O_RDONLY);
}
if (filev[2] != NULL) {
close(STDERR_FILENO);
open(filev[2],O_CREAT|O_WRONLY,0666);
}
execvp(argvv[0][0], argvv[0]);
fprintf(stderr, "%s","Error en el execvp del primer mandato\n");
return(-1);
default: /* padre */
pid = fork();
switch(pid) {
case -1: /* error */
fprintf(stderr, "%s","Error en el fork del segundo mandato\n");
return (-1);
case 0: /* hijo 2*/
close(STDIN_FILENO);
dup(fd[0]);
close(fd[0]);
close(fd[1]);
if (filev[1] != NULL) {
close(STDOUT_FILENO);
open(filev[1],O_CREAT|O_WRONLY,0666);
}
if (filev[2] != NULL) {
close(STDERR_FILENO);
open(filev[2],O_CREAT|O_WRONLY,0666);
}
execvp(argvv[1][0], argvv[1]);
fprintf(stderr, "%s","Error en el execvp del segundo mandato\n");
return(-1);
default: /* padre */
close(fd[0]);
close(fd[1]);
if(!bg){
while (wait(&estado) != pid);
}else printf("%d\n",pid);
} //fin switch2 (2 mandatos)
} //fin switch1 (2 mandatso)
}else if(num_commands==3){
int pid;
int estado;
int fd[2], fd2[2];
pipe(fd);
pid = fork();
switch(pid) {
case -1: /* error */
fprintf(stderr, "%s","Error en el fork del primer mandato\n");
return (-1);
case 0: /* hijo1 */
close(STDOUT_FILENO);
dup(fd[1]);
close(fd[0]);
close(fd[1]);
if (filev[0] != NULL) {
close(STDIN_FILENO);
open(filev[0],O_RDONLY);
}
if (filev[2] != NULL) {
close(STDERR_FILENO);
open(filev[2],O_CREAT|O_WRONLY,0666);
}
execvp(argvv[0][0], argvv[0]);
fprintf(stderr, "%s","Error en el execvp del primer mandato\n");
return(-1);
default: /* padre */
pipe(fd2);
pid = fork();
switch(pid) {
case -1: /* error */
fprintf(stderr, "%s","Error en el fork del segundo mandato\n");
return (-1);
case 0: /* hijo 2*/
close(STDIN_FILENO);
dup(fd[0]);
close(STDOUT_FILENO);
dup(fd2[1]);
close(fd[0]);
close(fd[1]);
close(fd2[0]);
close(fd2[1]);
if (filev[2] != NULL) {
close(STDERR_FILENO);
open(filev[2],O_CREAT|O_WRONLY,0666);
}
execvp(argvv[1][0], argvv[1]);
fprintf(stderr, "%s","Error en el execvp del segundo mandato\n");
return(-1);
default: /* padre */
close(fd[0]);
close(fd[1]);
pid = fork();
switch(pid) {
case -1: /* error */
fprintf(stderr, "%s","Error en el fork del tercer mandato\n");
return (-1);
case 0: /* hijo 3*/
close(STDIN_FILENO);
dup(fd2[0]);
close(fd2[0]);
close(fd2[1]);
if (filev[1] != NULL) {
close(STDOUT_FILENO);
open(filev[1],O_CREAT|O_WRONLY,0666);
}
if (filev[2] != NULL) {
close(STDERR_FILENO);
open(filev[2],O_CREAT|O_WRONLY,0666);
}
execvp(argvv[2][0], argvv[2]);
fprintf(stderr, "%s","Error en el execvp del tercer mandato\n");
return(-1);
default: /* padre */
close(fd2[0]);
close(fd2[1]);
if(!bg){
while (wait(&estado) != pid);
}else printf("%d\n",pid);
} //fin switch 3 (3 mandatos)
} //fin switch2 (3 mandatos)
} //fin switch1 (tres mandatos)
} //fin if (número de mandatos)
} //fin while
return 0;
} //fin main

Connection between group of daemons and main process - mkfifo

I was trying to connect daemons (group of daemons without a leader) with main process as in title, the problem is that i have to send statement from each daemon(which are supporting SIGUSR1 signal) to main process, but i don' t even know how to do that, in my code i used mkfifo, but it's not working at all..
here is the main process source:
int main(int argc, char* argv[])
{
pid_t pid;
int i;
int n = atoi(argv[1]);
char c, message[255];
if(argc!=2){
printf("please insert one parametr\n");
return -1;
}
int fd = open("pipe", O_RDONLY);
if (fd == -1) {
perror("Failed open fifo to read");
return EXIT_FAILURE;
}
for( i = 0; i < n; i++) {
pid=fork();
if (pid==0){
printf("daemon created..\n");
}
else{
execl("daemons", "daemons", argv[1], NULL);
while(1){
sleep(2);
read(fd, message, c);
printf("P received: %s\n", message);
close(fd);
//read(fd[0], message, sizeof(message));
}
}
}
return 0;
}
and here is some source code in which i create daemons:
int fd = open("pipe", O_WRONLY);
if (fd < 0){
perror("cannot open fifo: ");
return EXIT_FAILURE;
}
if ( getppid() == 1 )
return 0;
/* Creating daemon */
pid[n] = fork();
if (pid[n] < 0)
exit(EXIT_FAILURE);
if (pid[n] > 0)
exit(EXIT_SUCCESS);
/* Setting leader of session */
sid = setsid();
if (sid < 0){
exit(EXIT_FAILURE);
}
/* fork one more time to make children
to have an opportunity to destroy
session leader */
for ( i = 0; i < n; i++){
pid[i] = fork();
if(pid[i] < 0){
printf("filed to fork...\n");
exit(EXIT_FAILURE);
}
if(pid[i]==0){
while(1){
sleep(2);
printf("Demon[%d]: My ID in pipe.%d\n", i+1, getpid());
signal(SIGUSR1, sigHandler);
write(fd, "Hi\n", strlen("Hi\n"));
close(fd);
}
}
chdir(".");
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
file = fopen("log_file.txt", "w+");
fclose(file);
umask(027);
}
at least i' m not sure about that i am creating daemons in good way..
And where i should put signal, which can be later executed?
Do you have any suggestions?

Is there any other way to build pipe in C?

I want to know that is this possible to code this program with using write(), read() functions. It takes 2 initial arguments with argv[] then fork() and after that child process' stdout passes to parents stdin and result will be showed on screen.
when I execute the program like this ---> ./program date wc
It must show a result as same as date | wc does in shell programming.
I coded this program with dup(). it works fine but I want to other way around. Thank you and sorry for my english.
int main(int argc, char* argv[]){
char* argument1[]={argv[1], NULL};
char* argument2[]={argv[2], NULL};
int fd[2];
int d;
pid_t pid;
char buffer[30];
if(argc < 3){
printf("No parameter");
return 1;
}
if(pipe(fd)==-1){
perror("pipe failed");
exit(1);
}
else{
pid=fork();
if(pid==0){
/*child process*/
close(1);
dup(fd[1]);
close(fd[0]);
//close(fd[1]);
execvp(argument1[0], argument1);
}
else if(pid>0){
/*Parent process*/
close(0);
dup(fd[0]);
close(fd[1]);
//close(fd[0]);
execvp(argument2[0], argument2);
}
}
return 0;
}
Same code with dup2: (I let you make your m_exec function)
int m_pipe(char *cmd1, char *cmd2)
{
int fd[2];
if (pipe(fd) == -1)
{
perror("Pipe failed ");
return (-1);
}
if (fork() == 0)
{
/*Child process*/
dup2(fd[0], 0);
close(fd[1]);
m_exec(cmd2);
}
else
{
/*Parent process*/
dup2(fd[1], 1);
close(fd[0]);
m_exec(cmd1);
}
return (0);
}
int main(int argc, char* argv[])
{
if(argc != 3)
{
write(2, "Usage ./a.out cmd1 cmd2\n", strlen("Usage ./a.out cmd1 cmd2\n"));
return EXIT_FAILURE;
}
if (m_pipe(argv[1], argv[2]) == -1)
return EXIT_FAILURE;
return EXIT_SUCCESS;
}

WHy are my processes behaving like this?

it's some implementation of linux shell in c. Since i have added background process support i have some output that i fail to understand. Here is the code:
#include <stdlib.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <signal.h>
#include <wait.h>
#define DEFAULT_PROMPT "\nLog710H2014%>"
#define EXIT_CMD "exit"
#define CD_CMD "cd"
#define HOME_ENV_VAR "HOME"
#define NEW_LINE "\n**************************************************\n"
#define BCG_CMD_FLAG "&"
void cd_handler(int argc, char *argv[]);
int lire(char *chaine, int longueur);
char** init_command(int* size,char *str);
int execProg(int *argc, char **argv);
int execProgBg(int *argc, char **argv);
void sigchldHandler(int sig_num);
struct beanProcess {
pid_t pid;
int job_num;
char *command;
};
struct beanProcess *beans;
int jobCount = 1;
int main() {
printf(NEW_LINE);
printf("Bienvenue sur le shell de l'equipe 1");
printf(NEW_LINE);
while(1){
char str[200];
printf(DEFAULT_PROMPT);
lire(str, 200);
int commArgsC = 0, bg = 0;
char** comms = init_command(&commArgsC, str);
if(commArgsC == 0){
printf("Saisie vide, veuillez entrez une commande.");
continue;
}
if(strcmp(comms[commArgsC-1], BCG_CMD_FLAG) == 0){
bg = 1;
comms[commArgsC-1] = 0;
}
if(strcmp(comms[0], CD_CMD) == 0){
cd_handler(commArgsC, comms);
commArgsC = commArgsC -1;
}
else if (strcmp(comms[0], EXIT_CMD) == 0){
exit(0);
}
else {
if(bg){
execProgBg(&commArgsC, comms);
}
else{
execProg(&commArgsC, comms);
}
}
}
exit;
}
void cd_handler(int argc, char *argv[]){
char buff[512];
char * directory;
if(argc < 2){
directory = getenv(HOME_ENV_VAR);
}else if (argc == 2){
directory = argv[1];
}else{
exit(1);
}
if (chdir(directory) == -1) {
printf ("Erreur de changement de repertoire actif", strerror (errno));
}else{
if (getcwd(buff, sizeof(buff)) == NULL)
perror("Impossible d'afficher le repertoire courant");
else
printf("le repertoire courant est: %s\n", buff);
}
}
//Cette fonction est adaptée a partir du code de refp sur http://stackoverflow.com/questions/11198604/c-split-string-into-an-array-of-strings
char** init_command(int* size, char* str){
char ** res = NULL;
char * p = strtok (str, " ");
int n_spaces = 0;
while (p) {
res = realloc (res, sizeof (char*) * ++n_spaces);
if (res == NULL){
exit (-1);
}
res[n_spaces-1] = p;
p = strtok (NULL, " ");
}
res = realloc (res, sizeof (char*) * (n_spaces+1));
res[n_spaces] = 0;
*size = n_spaces;
return res;
}
//cette fonction est tirée d'un exemple de http://fr.openclassrooms.com/informatique/cours/apprenez-a-programmer-en-c/recuperer-une-chaine-de-caracteres
int lire(char *chaine, int longueur)
{
char *positionEntree = NULL;
if (fgets(chaine, longueur, stdin) != NULL)
{
positionEntree = strchr(chaine, '\n');
if (positionEntree != NULL)
{
*positionEntree = '\0';
}
return 1;
}
else
{
return 0;
}
}
int execProg(int *argc, char **argv){
char path[] = "/bin/";
strcat(path,argv[0]);
printf("\nThis is the %d process executing the code in non bg mode\n", getpid());
printf("Voici le resultat de l'execution de votre commande\n");
pid_t pid;
pid = fork();
if (pid < 0) {
perror("Creation de processus avec fork echouee");
exit(-1);
}
else if (pid == 0) {
if(execvp(argv[0], argv) == -1){
printf("\nthis is the child process %d executing the command in non bg mode\n", getpid());
perror("execv");
return EXIT_FAILURE;
}
}
else {
printf("\nthis is the parent process %d showing the stats in non bg mode\n", getpid());
struct rusage rusg;
long temp, tempCpu;
wait (NULL);
getrusage(RUSAGE_CHILDREN, &rusg);
printf("\nStatistique de la commande %s:\n", argv[0]);
temp = (rusg.ru_utime.tv_sec * 1000) + (rusg.ru_utime.tv_usec / 1000);
tempCpu = (rusg.ru_stime.tv_sec * 1000) + (rusg.ru_stime.tv_usec / 1000);
printf("\nLe temps wall-clock (ms): %ld", temp);
printf("\nLe temps CPU (ms) %ld", tempCpu);
printf("\nNB interruptions volontaires: %ld", rusg.ru_nvcsw);
printf("\nNB interruptions involontaires: %ld", rusg.ru_nivcsw);
printf("\nNB defaults de pages: %ld", rusg.ru_majflt);
printf("\nNB defaults de pages satifaits du noyau : %ld", rusg.ru_minflt);
}
return EXIT_SUCCESS;
}
int execProgBg(int *argc, char **argv){
signal(SIGCHLD, sigchldHandler);
printf("\nThis is the %d process executing the code in bg mode\n", getpid());
pid_t pid;
pid = fork();
if (pid < 0) {
perror("Creation de processus avec fork echouee");
return EXIT_FAILURE;
}
else if (pid == 0) {
//printf("This is the pid %d", getpid());
printf("\nthis is the child process %d executing the command in bg mode\n", getpid());
if(execvp(argv[0], argv) == -1){
perror("execvp");
return EXIT_FAILURE;
}
}
else {
printf("\nthis is the parent process %d showing the queue in bg mode\n", getpid());
printf("[%d] %d", jobCount, pid);
jobCount++;
//cleanJobList(childPid);
//ajoutProcess();
}
return EXIT_SUCCESS;
}
void sigchldHandler(int sig_num)
{
int status;
int childPid;
childPid = waitpid(-1, &status, 1);
printf("Hello the process %d has died\n", childPid);
//cleanJobList(childPid);
}
When i execute a bg command like "ls &", here's the output:
**************************************************
Bienvenue sur le shell de l'equipe 1
**************************************************
Log710H2014%>ls &
This is the 23464 process executing the code in bg mode
this is the parent process 23464 showing the queue in bg mode
[1] 23472
Log710H2014%>
this is the child process 23472 executing the command in bg mode
Debug PARTIE3.c
Hello the process 23472 has died
This is the 23464 process executing the code in non bg mode
Voici le resultat de l'execution de votre commande
this is the parent process 23464 showing the stats in non bg mode
Debug PARTIE3.c
Statistique de la commande ls:
Le temps wall-clock (ms): 0
Le temps CPU (ms) 2
NB interruptions volontaires: 2
NB interruptions involontaires: 9
NB defaults de pages: 0
NB defaults de pages satifaits du noyau : 644
Log710H2014%>
Why is that the parent process overlapping the lire() function and going directly to execProg function after the first execution ?
You are in a while loop. When your execProgBg function returns, no matter what it returns, the loop keeps going. If you want to stop you need to break or call exit from execProgBg.
Why is that the parent process overlapping the lire() function and
going directly to execProg function after the first execution
I don't know how you are executing your program but it looks like the second time around fgets fails, which you don't notice since you don't check the return code of the lire function. SO you go on and reuse the buffer from the previous call. It seems likely that you pass EOF to the program - perhaps by hitting ctrl-d.
I decided to run the code and obtained the same result as the OP does by hitting CTRL-D after the first ls &.
It is besides the point but warrants some explanation:
exit;
This evaluates the function exit converting it to a function pointer and throws away the result. It does not call the function. More importantly, calling exit as the last statement of main is pointless, since main is exiting anyway. You should just return some_code to indicate success of failure.

Resources