Daemon does not write to file - c

I wrote a daemon that is supposed to log itself when it recieves a signal. If I do not daemonize the process, it works correctly and writes to the file and I can see all the signals it recieved. But when I daemonize it, and send a signal for ex kill -14 (pid) , the daemon never writes to the file that the signal is recieved. Code is below
#include <stdio.h>
#include <unistd.h>
#include "signalinfo.h"
#include <errno.h>
#include <string.h>
#include <limits.h>
#include <stdlib.h>
#include <fcntl.h>
#include <syslog.h>
#include <sys/resource.h>
#include <sys/stat.h>
char *newline = "\n ";
void
daemonize(const char *cmd)
{
int i, fd0, fd1, fd2;
pid_t pid;
struct rlimit rl;
struct sigaction sa;
umask(0);
if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
printf("Can't get file limit\n");
exit(EXIT_FAILURE);
}
if ((pid = fork()) < 0) {
printf("Can't Fork\n");
exit(EXIT_FAILURE);
}
else if (pid != 0) /* parent */
exit(0);
setsid();
sa.sa_handler = SIG_IGN;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
if (sigaction(SIGHUP, &sa, NULL) < 0){
printf("Can't ignore SIGHUP\n");
exit(EXIT_FAILURE);
}
if ((pid = fork()) < 0) {
printf("Can't Fork\n");
exit(EXIT_FAILURE);
}
else if (pid != 0) /* parent */
exit(0);
if (chdir("/") < 0) {
printf("Can't Change Directory to /\n");
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);
openlog(cmd, LOG_CONS, LOG_DAEMON);
if (fd0 != 0 || fd1 != 1 || fd2 != 2) {
syslog(LOG_ERR, "unexpected file descriptors %d %d %d",
fd0, fd1, fd2);
exit(1);
}
}
void
setsig(struct sigaction sa)
{
int i;
for(i=0; i<SIGNAL_LIST_LENGTH; i++) {
printf("%d Set\n", siglist[i].code);
if(sigaction(siglist[i].code, &sa, NULL) == -1) { //Will error on SIGSTOP & SIGKILL
}
}
}
void
handler(int sig)
{
char path[PATH_MAX];
int fd, flags, i;
flags = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IWOTH | S_IROTH;
getcwd(path, PATH_MAX);
strcat(path,"/signal.log");
fd = open(path, O_WRONLY | O_CREAT | O_APPEND | O_NONBLOCK , flags);
for(i=0; i<SIGNAL_LIST_LENGTH; i++) {
if(sig == siglist[i].code) {
write(fd, siglist[i].name, strlen(siglist[i].name));
write(fd, newline, strlen(newline));
}
}
close(fd);
}
int
main(int argc, char *argv[])
{
char *cmd;
struct sigaction sa;
sa.sa_handler = handler;
setsig(sa);
if((cmd = strchr(argv[0], '/')) == NULL)
cmd = argv[0];
else
cmd++;
daemonize(cmd);
while(1) {
sleep(1);
}
}
Any Idea as to why I can't write to the file that I created? It works correctly when I dont daemonize it but when I do, it doesn't work.

Related

Wanted to know why doesn't the print statement in child process is not printing

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <fcntl.h>
int main(int argc, char *argv[])
{
int rc = fork();
if (rc < 0)
{
printf("fork failed\n");
exit(1);
}
else if (rc == 0)
{
close(STDOUT_FILENO);
int ret = open("./out.log", O_CREAT | O_WRONLY | O_TRUNC, S_IRWXU);
if (ret == -1)
{
printf("Failed to open file for stdout redirection\n");
exit(1);
}
char *myargs[2];
myargs[0] = strdup("ls"); // execute ls command
myargs[1] = NULL;
int status = execvp(myargs[0], myargs);
if (status == -1)
{
printf("execvp: failed");
exit(1);
}
printf("Child: Finished\n");
}
else
{
wait(NULL);
printf("Parent: Finished\n");
}
return 0;
}

I have a race program in C that always has the same winner no matter what

The following program is controlled by named semaphores and is supposed to do this:
The main process creates N_PROC children and an id is assigned to each child (0 for the first child that has been created,1 for the second one and so on).
Each children waits for a signal from their father by using pause().
The main process sends his children a SIGUSR1 signal.
Each child repeats this until they die: they open a file (the same file for all children), write their id, close the file and then sleep during a random number of milliseconds between 1 and 100.
Each second, the main process opens the same file as his children, counts the number of times each id is present (printing them as he reads them) and, if a child has written its id 20 times, declares that child the winner, sends a SIGTERM to all his children, waits for them to finish and then deletes the semaphores.
My problem is that no matter how many times I recompile or rerun the program the parent always prints the same thing and thus child number 2 is always the winner.
Thank you in advance.
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <fcntl.h>
#include <time.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#define SEM1 "/example_sem1"
#define SEM2 "/example_sem2"
#define SEM3 "/example_sem3"
#define FFILE "ejercicio9.txt"
#define N_PROC 3
int valor_semaforo(sem_t *sem) {
int sval;
if (sem_getvalue(sem, &sval) == -1) {
perror("sem_getvalue");
sem_unlink(SEM1);
sem_unlink(SEM2);
sem_unlink(SEM3);
exit(EXIT_FAILURE);
}
return sval;
}
int main(void) {
sem_t *sem_write = NULL, *sem_read = NULL, *sem_count = NULL;
pid_t pid[N_PROC];
int i, numero, num[N_PROC], t;
struct sigaction act;
FILE *fp;
srand(time(NULL) + getpid());
if ((sem_write = sem_open(SEM1, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 1)) == SEM_FAILED) {
perror("sem_open");
exit(EXIT_FAILURE);
}
if ((sem_read = sem_open(SEM2, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 1)) == SEM_FAILED) {
perror("sem_open");
exit(EXIT_FAILURE);
}
if ((sem_count = sem_open(SEM3, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 0)) == SEM_FAILED) {
perror("sem_open");
exit(EXIT_FAILURE);
}
sigemptyset(&(act.sa_mask));
act.sa_flags = 0;
act.sa_handler = SIG_IGN;
if (sigaction(SIGUSR1, &act, NULL) < 0) {
perror("sigaction");
exit(EXIT_FAILURE);
}
for (i = 0; i < N_PROC; i++) {
num[i] = 0;
pid[i] = fork();
if (pid[i] < 0) {
perror("fork");
exit(EXIT_FAILURE);
}
if (pid[i] == 0) {
pause();
while (1) {
sem_wait(sem_write);
fp = fopen(FFILE, "a+");
fprintf(fp, "%d ", i);
fclose(fp);
sem_post(sem_write);
usleep(1 + (rand() % 100));
}
}
}
kill(0, SIGUSR1);
while (1) {
sleep(1);
sem_wait(sem_read);
sem_post(sem_count);
if (valor_semaforo(sem_count) == 1)
sem_wait(sem_write);
sem_post(sem_read);
fp = fopen(FFILE, "r");
while (fscanf(fp, "%d", &numero) > 0) {
printf("%d ", numero);
fflush(stdout);
for (i = 0; i < N_PROC; i++) {
if (numero == i)
(num[i])++;
if (num[i] == 20) {
printf("\nHa finalizado la carrera: el ganador es el proceso %d\n", i);
fflush(stdout);
act.sa_handler = SIG_IGN;
if (sigaction(SIGTERM, &act, NULL) < 0) {
perror("sigaction");
exit(EXIT_FAILURE);
}
kill(0, SIGTERM);
while (wait(NULL) > 0);
sem_close(sem_write);
sem_close(sem_read);
sem_close(sem_count);
sem_unlink(SEM1);
sem_unlink(SEM2);
sem_unlink(SEM3);
fclose(fp);
exit(EXIT_SUCCESS);
}
}
}
}
printf("\n");
fflush(stdout);
fp = fopen(FFILE, "w+");
fclose(fp);
sem_wait(sem_read);
sem_wait(sem_count);
if (valor_semaforo(sem_count) == 0)
sem_post(sem_write);
sem_post(sem_read);
}
You do not reset the num array before scanning the file. It happens that on your system the third child writes to the file first.
You should clear this array before parsing the file with:
memset(num, 0, sizeof num);
Or
for (i = 0; i < N_PROC; i++)
num[i] = 0;

Named semaphores in C are not deleted after a signal handler call

So the following code is supposed to do the following:
The main process creates N_READ number of children processes and then proceeds to print some lines endlessly.
The children also print some lines endlessly.
When the main process receives a SIGINT signal (CTRL^C from the terminal in this case) he must send a SIGTERM to all his children, wait for them to finish and then delete all the semaphores used.
The use of named semaphores is justified by the fact that this is simulation of the readers-writers problem giving priority to the readers.
However when I end the program and start it again the semaphores have not been deleted, as I get an "semaphore already exists" error and they are in fact in /dev/shm.
P.D. This is college homework and they say global variables are not permitted.
Thank you in advance and here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#define SEM1 "/example_sem1"
#define SEM2 "/example_sem2"
#define SEM3 "/example_sem3"
#define N_READ 1
#define SECS 0
int valor_semaforo(sem_t *sem) {
int sval;
if (sem_getvalue(sem, &sval) == -1) {
perror("sem_getvalue");
sem_unlink(SEM1);
sem_unlink(SEM2);
sem_unlink(SEM3);
exit(EXIT_FAILURE);
}
return sval;
}
void manejador_SIGINT(int sig) {
kill(0,SIGTERM);
while(wait(NULL)>0);
/*xq no llega xq*/
sem_unlink(SEM1);
sem_unlink(SEM2);
sem_unlink(SEM3);
exit(EXIT_SUCCESS);
}
int main(void) {
sem_t *sem_write = NULL,*sem_read = NULL,*sem_count = NULL;
pid_t pid[N_READ];
int i;
struct sigaction act;
sigemptyset(&(act.sa_mask));
act.sa_flags = 0;
act.sa_handler = manejador_SIGINT;
if (sigaction(SIGINT, &act, NULL) < 0) {
perror("sigaction");
exit(EXIT_FAILURE);
}
if ((sem_write = sem_open(SEM1, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 1)) == SEM_FAILED) {
perror("sem_open");
exit(EXIT_FAILURE);
}
if ((sem_read = sem_open(SEM2, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 1)) == SEM_FAILED) {
perror("sem_open");
exit(EXIT_FAILURE);
}
if ((sem_count = sem_open(SEM3, O_CREAT | O_EXCL, S_IRUSR | S_IWUSR, 0)) == SEM_FAILED) {
perror("sem_open");
exit(EXIT_FAILURE);
}
for(i=0;i<N_READ;i++){
pid[i] = fork();
if (pid[i] < 0) {
perror("fork");
exit(EXIT_FAILURE);
}
if (pid[i] == 0) {
sigemptyset(&(act.sa_mask));
act.sa_flags = 0;
act.sa_handler = SIG_IGN;
if (sigaction(SIGINT, &act, NULL) < 0) {
perror("sigaction");
exit(EXIT_FAILURE);
}
while(1){
sem_wait(sem_read);
sem_post(sem_count);
if(valor_semaforo(sem_count)==1)
sem_wait(sem_write);
sem_post(sem_read);
printf("R-INI %d\n",getpid());
fflush(stdout);
sleep(SECS);
printf("R-FIN %d\n",getpid());
fflush(stdout);
sem_wait(sem_read);
sem_wait(sem_count);
if(valor_semaforo(sem_count)==0)
sem_post(sem_write);
sem_post(sem_read);
}
}
}
while(1){
sem_wait(sem_write);
printf("W-INI %d\n",getpid());
fflush(stdout);
sleep(SECS);
printf("W-FIN %d\n",getpid());
fflush(stdout);
sem_post(sem_write);
}
}
As #Jonathan said, the SIGTERM signal I use does terminate the process that should clean up the semaphores. By ignoring the signal in the parent process, everything works well.

Why can't I simulate auto-completion with '\t' in busybox

I want to use "yp\t\n\0" to run “ypdomainname” command by exploiting auto-completion in busybox, but it failed. my code and result are below:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <fcntl.h>
#define DEFAULT_BUSYBOX_PATH "/bin/busybox"
#define MAX_BUF 1000
int main()
{
int fd[2];
pid_t pid;
FILE *file;
int status;
if(pipe(fd) < 0){
fprintf(stderr, "pipe error!\n");
return -1;
}
if((pid = fork()) < 0){
fprintf(stderr, "pipe error!\n");
}else if(pid == 0){ //child
close(fd[1]);
int fd_output;
fd_output = open("result", O_CREAT | O_RDWR, 777);
if(fd_output != STDOUT_FILENO){
if(dup2(fd_output, STDOUT_FILENO) != STDOUT_FILENO)
fprintf(stderr, "dup2 error to stdout\n");
}
if(fd[0] != STDIN_FILENO){
if(dup2(fd[0], STDIN_FILENO) != STDIN_FILENO)
fprintf(stderr, "dup2 error to stdin\n");
}
execl(DEFAULT_BUSYBOX_PATH, DEFAULT_BUSYBOX_PATH, "ash", NULL);
close(fd[0]);
close(fd_output);
return 0;
}else{ //parent
close(fd[0]);
char buf[MAX_BUF] = "yp";
buf[2] = '\t';
buf[3] = '\n';
buf[4] = '\0';
write(fd[1], buf, strlen(buf));
close(fd[1]);
return 0;
}
}
Result of my code
What makes me confused is that the character is not changed in function lineedit_read_key() in file lineedit.c and it will run the function input_tab() when the character is '\t'.
input_tab will be executed when character is '\t'
Recently, i took some time to learn about terminal to simulate auto-completion, but i still failed. My code is below:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <signal.h>
#include <pty.h>
#define DEFAULT_BUSYBOX_PATH "/bin/busybox"
#define MAX_BUF 1000
#define BUFFSIZE 512
typedef void Sigfunc(int);
static void sig_term(int);
static volatile sig_atomic_t sigcaught;
ssize_t writen(int fd, const void *ptr, size_t n){
size_t nleft;
ssize_t nwritten;
nleft = n;
while(nleft > 0){
if((nwritten = write(fd, ptr, nleft)) < 0){
if(nleft == n){
return(-1);
}else{
break;
}
}else if(nwritten == 0) {
break;
}
nleft -= nwritten;
ptr += nwritten;
}
return(n - nleft);
}
Sigfunc *signal_intr(int signo, Sigfunc *func){
struct sigaction act;
struct sigaction oact;
act.sa_handler = func;
sigemptyset(&act.sa_mask);
act.sa_flags = 0;
#ifdef SA_INTERRUPT
act.sa_flags |= SA_INTERRUPT;
#endif
if (sigaction(signo, &act, &oact) < 0)
return(SIG_ERR);
return(oact.sa_handler);
}
int ptym_open(char *pts_name, int pts_namesz)
{
char ptr[50];
int fdm;
int err;
if((fdm = posix_openpt(O_RDWR)) < 0){
return(-1);
}
if(grantpt(fdm) < 0){
goto errout;
}
if(unlockpt(fdm) < 0){
goto errout;
}
if(ptsname_r(fdm, ptr, 50) != 0){
goto errout;
}
strncpy(pts_name, ptr, pts_namesz);
pts_name[pts_namesz - 1] = '\0';
return(fdm); /* return fd of master */
errout:
err = errno;
close(fdm);
errno = err;
return(-1);
}
int ptys_open(char *pts_name){
int fds;
if((fds = open(pts_name, O_RDWR)) < 0)
return(-1);
return(fds);
}
pid_t pty_fork(int *ptrfdm, char *slave_name, int slave_namesz, const struct termios *slave_termios, const struct winsize *slave_winsize){
int fdm, fds;
pid_t pid;
char pts_name[20];
if((fdm = ptym_open(pts_name, sizeof(pts_name))) < 0){
fprintf(stderr, "can't open master pty: %s, error %d", pts_name, fdm);
}
if(slave_name != NULL) {
strncpy(slave_name, pts_name, slave_namesz);
slave_name[slave_namesz - 1] = '\0';
}
if((pid = fork()) < 0) {
return(-1);
}else if (pid == 0) { /* child */
if(setsid() < 0){
fprintf(stderr, "setsid error");
}
if((fds = ptys_open(pts_name)) < 0){
fprintf(stderr, "can't open slave pty");
}
close(fdm);
if(slave_termios != NULL) {
if (tcsetattr(fds, TCSANOW, slave_termios) < 0)
fprintf(stderr, "tcsetattr error on slave pty");
}
if(slave_winsize != NULL) {
if (ioctl(fds, TIOCSWINSZ, slave_winsize) < 0)
fprintf(stderr, "TIOCSWINSZ error on slave pty");
}
if(dup2(fds, STDIN_FILENO) != STDIN_FILENO){
fprintf(stderr, "dup2 error to stdin");
}
if(dup2(fds, STDOUT_FILENO) != STDOUT_FILENO){
fprintf(stderr, "dup2 error to stdout");
}
if(dup2(fds, STDERR_FILENO) != STDERR_FILENO){
fprintf(stderr, "dup2 error to stderr");
}
if(fds != STDIN_FILENO && fds != STDOUT_FILENO && fds != STDERR_FILENO){
close(fds);
}
return(0);
} else { /* parent */
*ptrfdm = fdm;
return(pid);
}
}
void loop(int ptym, int ignoreeof)
{
pid_t child;
int nread;
char buf[BUFFSIZE];
if((child = fork()) < 0) {
fprintf(stderr, "fork error");
}else if(child == 0) {
/*for ( ; ; ){
if((nread = read(STDIN_FILENO, buf, BUFFSIZE)) < 0){
fprintf(stderr, "read error from stdin");
}else if(nread == 0){
break;
}
if(writen(ptym, buf, nread) != nread)
fprintf(stderr, "writen error to master pty");
}*/
char *temp_buf = "yp\t\n";
if(writen(ptym, temp_buf, strlen(temp_buf)) != strlen(temp_buf)){
fprintf(stderr, "writen error to master pty");
}
if(ignoreeof == 0){
kill(getppid(), SIGTERM);
}
exit(0);
}
if (signal_intr(SIGTERM, sig_term) == SIG_ERR)
fprintf(stderr, "signal_intr error for SIGTERM");
for( ; ; ){
if ((nread = read(ptym, buf, BUFFSIZE)) <= 0){
}
//printf("nread = %d\n", nread);
if (writen(STDOUT_FILENO, buf, nread) != nread){
fprintf(stderr, "writen error to stdout");
}
}
if (sigcaught == 0){
printf("sigcaught == 0 and kill child\n");
kill(child, SIGTERM);
}
}
static void sig_term(int signo)
{
sigcaught = 1;
}
int main(int argc, char *argv[]){
int fd[2];
pid_t pid;
FILE *file;
int status;
int fdm;
int ignoreeof;
char slave_name[40];
struct termios orig_termios;
struct winsize size;
pid = pty_fork(&fdm, slave_name, sizeof(slave_name), &orig_termios, &size);
if(pid < 0){
fprintf(stderr, "fork error!\n");
}else if(pid == 0){ //child
if(execl(DEFAULT_BUSYBOX_PATH, DEFAULT_BUSYBOX_PATH, "ash", NULL) < 0){
fprintf(stderr, "can't execute: %s", DEFAULT_BUSYBOX_PATH);
}
/*if(execvp(argv[1], &argv[1]) < 0){
fprintf(stderr, "can't execute: %s", argv[1]);
}*/
}
loop(fdm, ignoreeof);
}
like the result of my first try, the result is: ash: yp: not found.
Your code fails because a pipe is not a terminal. Many programs will use isatty(3) and alike to detect if the standard input is connected to a terminal and adjust their behaviour depending on the result.
What you can do is to open a pseudo terminal pair using openpty(3) and run the command with the slave duplicated to its standard input, output and error descriptors, and using the master to communicate with it. Unfortunately I have no time right now writing a full solution as it is rather intricate; I've done it ever in Python and it was tricky even there.

making shell for homework

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <string.h>
#include <sys/stat.h>
#include <fcntl.h>
void exec(char **args){
pid_t pid;
int status;
if ((pid = fork()) < 0) {
printf("*** ERROR: forking child process failed\n");
exit(1);
}
else if (pid == 0) {
if(execvp(args[0],args)<0)//{
//printf("argv[0]=%s argv[1]=%s",args[0],args[1]);
printf("**error in exec\n");
}
else {
while (wait(&status) != pid);
}
}
void exec2(char **args, char *file){
printf("file =%s\n",file);
int fd;
pid_t pid;
int status;
if ((pid = fork()) < 0) {
printf("*** ERROR: forking child process failed\n");
exit(1);
}
else if (pid == 0) {
fd = open(file, O_RDWR | O_CREAT, (mode_t)0600);
close(1);
dup2(fd, 1);
if(execvp(args[0],args)<0){
printf("**error in exec");
}
else {
printf("\nhere\n");
close(fd);
while (wait(&status) != pid){
fflush(stdout) ;
}
}
}
close (fd);
}
void main(){
char *command;
char inp[512];
char *filepath;
size_t size=0;
char *substr;
char *args[512];
command = (char *) malloc(sizeof(char *) * 512);
int flag=0;
int redirect=0;
int i=0;
while (1){
printf("$ ");
command = fgets(inp, 512/*sizeof(char *)*/, stdin);
command[strlen(command)-1]='\0';
if (strchr(command,'>')){
redirect=1;
strtok_r(command,">",&filepath);
}
size_t siz=4;
//printf("command=%s\n",command);
int i=0;
while(1){
//printf("i=%d\n",i);
char *tok = strtok_r(command," ",&substr);
if (tok==NULL){
break;
}
args[i++] = tok;
/* printf("tok=%s\n",tok);
printf("len tok = %d\n",(int)strlen(tok));
printf("command=%s\n",command);
printf("substr=%s\n",substr);
*/ command = substr;
}
//printf("args[0]=%s",args[0]);
if (!strncasecmp(args[0],"exit",siz) || !strncasecmp(args[0],"quit",siz))
{
printf("\nBye\n");
exit(0);
}
else if(strcmp(args[0],"cd")==0){
chdir(args[1]);
//printf("chdir") ;
//system("pwd");
}
else if (redirect==1){
exec2(args,filepath);
}
else exec(args);
}
}
Okay this is my code for my shell. When i run it, i put ls and it gives correct output. Then i put ls -l and then ls again and it gives
ls: cannot access : No such file or directory
Also when i use cd, ls doesnt give output and pwd says "ignoring unused arguments"
ALso cat doesnt work.
Though mkdir, ps and ls -l works.
Don't close stdout!
Do it like this, after the fork and before the exec:
if (child) {
int fd = open(file, O_RDWR | O_CREAT, (mode_t)0600);
close(1);
dup2(fd, 1);
if(execvp(args[0],args)<0){
printf("**error in exec");
}
}

Resources