Getting a No such file or directory on fopen() - c

I have a program I'm writing with a globally defined File variable that I'm trying to access by the parent after it forks a child. However, the child is the one that is writing to the file so when I try to read it as the parent I get a Error: No such file or directory. Only it's not thrown as an error, it's stored in the tmpFP file. I'm not sure how to get around this.
I've omitted some code for legibility, the references to sockets are from a custom library, assume that works. The relevant comments should be in all caps, they point to where I believe the problem arises.
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#include <ctype.h>
#include <stdbool.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <unistd.h>
#include <stdarg.h>
#include "Socket.h"
#include "ToUpper.h" /* definitions shared by client and server */
#define LINE_SIZE 50
#define MAX_WORDS 10
#define MAX_LINE 1024
#define MAX_TMP 100
#define MAX_ARGS 4 /* allows program name + 3 positional parameters */
#define MIN_ARGS 2 /* must have at least 1 positional parameter */
#define NUM_PARMS 4 /* allows program name + 2 parameters + NULL */
#define ERR_RETURN -1
/* variables to hold socket descriptors */
ServerSocket welcome_socket;
Socket connect_socket;
char new_line[MAX_LINE];
char tmp_name[MAX_TMP]; //DECLARING FILENAME
char id_str[MAX_TMP];
char arr[LINE_SIZE]={0};
int id;
FILE *fp; //FILE USED IN CHILD PROCESS
void toupper_service(void);
int main(int argc, char* argv[])
{
FILE *tmpFP; //FILE USED IN PARENT PROCESS
pid_t spid; /* pid_t is typedef for Linux process ID */
int c=0,index=0;
id = (int) getpid();
sprintf(id_str, "%d", id);
strcpy(tmp_name,"tmp");
strcat(tmp_name, id_str);
if (argc < 2)
{
printf("No port specified\n");
return (-1);
}
welcome_socket = ServerSocket_new(atoi(argv[1]));
connect_socket = ServerSocket_accept(welcome_socket);
Socket_close(welcome_socket);
while (c!=EOF)
{
while((c=Socket_getc(connect_socket))!='\n')
{
arr[index]=c;
index++;
}
arr[index]='\0';
/* accept an incoming client connection; blocks the
* process until a connection attempt by a client.
* creates a new data transfer socket.
*/
spid = fork(); /* create child == service process */
if (spid == -1)
{
perror("fork");
exit (-1);
}
if (spid == 0)
{/* code for the service process */
toupper_service();
Socket_close(connect_socket);
exit (0);
} /* end service process */
else /* daemon process closes its connect socket */
{
waitpid(spid,NULL,0);
//PASSES THIS TEST SOMEHOW
if((tmpFP = fopen (tmp_name, "r")) == NULL)
{
fprintf(stderr, "%s\n",tmp_name);
fprintf (stderr, "error opening tmp file\n");
exit (-1);
}
while((c=fgetc(tmpFP))!=EOF)
{
//PRINTS OUT ERROR HERE A LETTER AT A TIME
fprintf(stderr, "c: %d %c\n", c, (char)c);
Socket_putc(c, connect_socket);
}
remove(tmp_name);
Socket_putc('\0', connect_socket);
Socket_close(connect_socket);
/* reap a zombie every time through the loop, avoid blocking*/
}
}/* end of infinite loop for daemon process */
fprintf(stderr, "C: %d\n",c);
}
void toupper_service(void)
{
int i=0, c, pointer,num_words=0,index=0;
int too_many_words=0;
char *word[MAX_WORDS]={NULL};
//THIS IS THE OTHER PLACE TMP_NAME IS USED
fp = freopen(tmp_name, "w", stdout);
while ((c=arr[index])!='\0')
{
if(c==' '||c=='\t'||c=='\n') //word encountered
{
if(num_words>=MAX_WORDS-1)
{
printf("Too many commands passed\n");
too_many_words=1;
exit(0);
break;
}
arr[index]='\0';
word[num_words]=&arr[pointer];
pointer=i+1;
num_words++;
}
index++;
}
word[num_words]=NULL;
if(too_many_words==0)
{
c=0;
int error=execvp(word[0],word);
}
return;
}

Related

Named pipe (FIFO) halts execution when read and write are called

Trying to create a process ring using named pipes for an assignment, and whenever I call read/write to those files it pauses the execution at that point. I've tried everything I could find for hours now, and have no idea why this is happening.
More context: Process ring with named pipes, passing a token between n processes, from a process i to i+1 in each loop.
Any help would be very much appreciated, and thank you for taking the time!
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
#include <math.h>
#include <errno.h>
#define MAX 50
int main(int argc, char** argv) {
// File descriptors for pipes i and i+1 and token
int fd1, fd2, token = 0;
pid_t pid;
// Pipes path array
char* fifos[2][MAX] = { "pipe1to2" , "pipe2to1" }
...
// Create pipes
for(int i =0 ; i < 2 ; i++){
char* fileToCreate = fifos[i];
if ((mkfifo(fileToCreate,S_IRWXU)) != 0) {
if(errno == 17){ // If a file with the same name exists, this overwrites it
unlink(fileToCreate);
mkfifo(fileToCreate,S_IRWXU);
}else{
printf("Unable to create a fifo; errno=%d\n",errno);
exit(1);
}
}
}
while(true){
char* file = fifos[itr];
fd1 = open(file,O_WRONLY);
if(fd1 == -1){
printf("Open error\n");
return 1;
}
if(write(fd1,token,sizeof(int)) == -1){
printf("Write error");
return 2;
}
close(fd1);
...
}
}

C linux daemon does not write into file after opening FIFO

I have following program in C, which should run as a deamon and whenever is something written into FIFO, it should write it into a file.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <string.h>
#include <signal.h>
#include <syslog.h>
#define BUF_LENGTH 255
volatile int signal_flag = 1;
void signal_handler(int sig)
{
signal_flag = 1;
}
char *getTimeString()
{
time_t rawtime;
struct tm * timeinfo;
time ( &rawtime );
timeinfo = localtime ( &rawtime );
char *timeStr = asctime (timeinfo);
timeStr[strlen(timeStr) - 1] = 0;
return timeStr;
}
void printUsage()
{
printf("Usage: syslog_daemon PATH INTERVAL\n");
}
int main(int argc, char *argv[])
{
/* print usage */
if(argc != 3)
{
printUsage();
exit(EXIT_SUCCESS);
}
/* process arguments */
char *logFilePath = argv[1];
int interval = atoi(argv[2]);
/* establish the signal handler */
struct sigaction action;
sigemptyset(&action.sa_mask);
action.sa_flags = 0;
action.sa_handler = signal_handler;
sigaction(SIGALRM, &action, NULL);
/* initialize variables */
int fd;
/*char buf[BUF_LENGTH];
int length;*/
int msgs = 0;
/* Create FIFO if not created */
if (mkfifo("/tmp/pb173_syslog", 0766) == -1 && errno != EEXIST)
{
fprintf(stderr, "Making FIFO failed with error %d\n", errno);
exit(EXIT_FAILURE);
}
/* Run */
daemon(1, 1);
while(1)
{
/* Open FIFO */
fd = open("/tmp/pb173_syslog", O_RDONLY);
close(fd);
/* Open and write into file */
FILE *f = fopen(logFilePath, "a");
fprintf(f, "Daemon write: %d\n", msgs);
fclose(f);
/* Process SIGALRM and write syslog */
if(signal_flag)
{
openlog("syslog_daemon v2", LOG_CONS, LOG_DAEMON);
syslog(LOG_INFO, "Messages written: %d\n", msgs);
closelog();
msgs++;
signal_flag = 0;
alarm(interval);
}
}
return 0;
}
But this program does not write anything into the file. It seems, that when the FIFO is open, it cannot write anywhere. But if I don't open the FIFO, the program writes into the file without any problems. Does anyone know what is the problem? Thanks for any help.
It hangs on open trying to open a FIFO which does not have the second endpoint (the writer) connected.
You may want to use O_NONBLOCK.
Here is a quote from strace output that shows where it hangs:
$ strace -p 23114
Process 23114 attached - interrupt to quit
open("/tmp/pb173_syslog", O_RDONLY
If you write something to the FIFO (e.g. echo test > /tmp/pb173_syslog) it unblocks and starts working.

Usage of message queue fork + execlp + ftok

The main purpose here is to create a message queue by executing thise command : ./create_msg_queue fileForQueue
We want to create the file fileForQueue if it doesn't exist.
Regarding my code, if the file doesn't exist, I get this error
ftok: No such file or directory
So how can I have this file create BEFORE ftok() is called with the file name ?
Provided code :
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
// IPC and KEYS -------------
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/wait.h>
//---------------------------
#define _XOPEN_SOURCE
// message structure
typedef struct {
// id message
long type;
// Size : 12 bytes
double mesure;
pid_t pidClient;
} message_t;
int main (int argc, char * argv []) {
key_t key;
message_t message;
int file;
int pid;
// Check arg number
if (argc != 2) {
fprintf(stderr, "Syntaxe : %s fichier_clé\n",argv[0]);
exit(EXIT_FAILURE);
}
// Create the empty file given in parameter
if ((pid = vfork()) == -1)
{
perror("fork");
exit(1);
}
if (pid)
{
// code replacement to create the FILE
execlp("touch", "touch", argv[1], NULL);
perror("execlp");
exit(1);
}else
{
// Trying to wait for the forked() process to finish its file creation
wait (NULL);
// I GET ERROR HERE IF THE FILE DON'T EXIST BEFORE I LAUNCH THE PROGRAM
// Create key with the file given in parameter and then created
if ((key = ftok(argv[1], 0)) == -1) {
// errNo value
perror("ftok");
exit(EXIT_FAILURE);
}
// Create message queue
if ((file = msgget(key, IPC_CREAT | 0666)) == -1) {
perror("msgget");
exit(EXIT_FAILURE);
}
// Registering message content
message.type = 1;
message.mesure = -1;
message.pidClient = getpid();
// Sending message
if (msgsnd(file, (void *) & message, 12, 0) <0) {
perror("msgsnd");
exit(EXIT_FAILURE);
}
}
return EXIT_SUCCESS;
}
Thanks in advance for help. I struggle :)
key_t ftok(const char *path, int id);
ftok(argv[1], 0))
Only the low-order 8-bits of id are significant. The behavior of
ftok() is unspecified if these bits are 0.
Also note that you have to
#define _XOPEN_SOURCE
at the very begin

working with pipes

I am trying to make this work but no luck, basically i need to write to the pipe and then make the pipe return back with the text i sent. I have a server.c and client.c , so i make the server.c run..., open a new terminal and then run the client.. the problem is that the client doesnt do anything when i run it.. I am sure i am missing something.. like closing the pipe. i am not sure.. I would really appreciate some guidance
server.c
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#define PIPE1 "PIPE1"
#define PIPE5 "PIPE5"
#define MAX_BUF_SIZE 255
int main(int argc, char *argv[])
{
int rdfd1,rdfd2,rdfd3,rdfd4, wrfd1,wrfd2,wrfd3,wrfd4,ret_val, count, numread1,numread2,numread3,numread4;
char buf1[MAX_BUF_SIZE];
char buf2[MAX_BUF_SIZE];
char buf3[MAX_BUF_SIZE];
char buf4[MAX_BUF_SIZE];
/* Create the first named - pipe */
ret_val = mkfifo(PIPE1, 0666);
if ((ret_val == -1) && (errno != EEXIST)) {
perror("Error creating the named pipe");
return 1;
}
ret_val = mkfifo(PIPE5, 0666);
if ((ret_val == -1) && (errno != EEXIST)) {
perror("Error creating the named pipe");
return 1;
}
/* Open the first named pipe for reading */
rdfd1 = open(PIPE1, O_RDONLY);
/* Open the first named pipe for writing */
wrfd1 = open(PIPE5, O_WRONLY);
/* Read from the pipes */
numread1 = read(rdfd1, buf1, MAX_BUF_SIZE);
buf1[numread1] = '0';
printf("Server : Read From the pipe : %sn", buf1);
/*
* Write the converted content to
* pipe
*/
write(wrfd1, buf1, strlen(buf1));
}
client.c
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define PIPE1 "PIPE1"
#define PIPE5 "PIPE5"
#define MAX_BUF_SIZE 255
int main(int argc, char *argv[ ]) {
pid_t childpid;
int error;
int i;
int nprocs;
/* check command line for a valid number of processes to generate */
int wrfd1, rdfd1, numread;
char rdbuf[MAX_BUF_SIZE];
if ( (argc != 2) || ((nprocs = atoi (argv[1])) <= 0) ) {
fprintf (stderr, "Usage: %s nprocs\n", argv[0]);
return 1;
}
for (i = 1; i < nprocs; i++) {
/* create the remaining processes */
if ((childpid = fork()) == -1) {
fprintf(stderr, "[%ld]:failed to create child %d: %s\n", (long)getpid(), i, strerror(errno));
return 1;
}
/* Open the first named pipe for writing */
wrfd1 = open(PIPE5, O_WRONLY);
/* Open the second named pipe for reading */
rdfd1 = open(PIPE1, O_RDONLY);
if (childpid)
break;
char string1[100];
if(sprintf(string1, "This is process %d with ID %ld and parent id %ld\n", i, (long)getpid(), (long)getppid())) {
write(wrfd1,string1, strlen(string1));
}
/* Read from the pipe */
numread = read(rdfd1, rdbuf, MAX_BUF_SIZE);
rdbuf[numread] = '0';
printf("Full Duplex Client : Read From the Pipe : %sn", rdbuf);
}
return 0;
}
It seems like both server and client read from PIPE1 and write to PIPE5. Shouldn't one of them write to PIPE1 so that the other can read it from the other end?
Also, if you're testing with ./client 1, your for (i = 1; i < nprocs; i++) loop will never execute.
One last thing, see this question. I'm not entirely sure it applies to your code, but it's worth keeping in mind.
Shouldn't this line be '\0' ?
buf1[numread1] = '0';

Why I'm getting trash on this pipe?

I'm running a full-duplex server/client code I found on Oracle's website:
When writing ./fd_client hahaha I get something like:
HAHAHA0�$0
The upper case is OK (it's what the server it's supposed to return) but, how the hell do I avoid that trailing trash?
fd_client.c
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include "fullduplex.h" /* For name of the named-pipe */
int main(int argc, char *argv[])
{
int wrfd, rdfd, numread;
char rdbuf[MAX_BUF_SIZE];
/* Check if an argument was specified. */
if (argc != 2) {
printf("Usage : %s \n", argv[0]);
exit (0);
}
/* Open the first named pipe for writing */
wrfd = open(NP1, O_WRONLY);
/* Open the second named pipe for reading */
rdfd = open(NP2, O_RDONLY);
/* Write to the pipe */
write(wrfd, argv[1], strlen(argv[1]));
/* Read from the pipe */
numread = read(rdfd, rdbuf, MAX_BUF_SIZE);
rdbuf[numread] = '0';
printf("Full Duplex Client : Read From the Pipe : %s\n", rdbuf);
return 0;
}
fd_server.c
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include "fullduplex.h" /* For name of the named-pipe */
int main(int argc, char *argv[])
{
int rdfd, wrfd, ret_val, count, numread;
char buf[MAX_BUF_SIZE];
/* Create the first named - pipe */
ret_val = mkfifo(NP1, 0666);
if ((ret_val == -1) && (errno != EEXIST)) {
perror("Error creating the named pipe");
exit (0);
}
ret_val = mkfifo(NP2, 0666);
if ((ret_val == -1) && (errno != EEXIST)) {
perror("Error creating the named pipe");
exit (0);
}
/* Open the first named pipe for reading */
rdfd = open(NP1, O_RDONLY);
/* Open the second named pipe for writing */
wrfd = open(NP2, O_WRONLY);
/* Read from the first pipe */
numread = read(rdfd, buf, MAX_BUF_SIZE);
buf[numread] = '0';
printf("Full Duplex Server : Read From the pipe : %s \n", buf);
/* Convert to the string to upper case */
count = 0;
while (count < numread) {
buf[count] = toupper(buf[count]);
count++;
}
/*
* Write the converted string back to the second
* pipe
*/
write(wrfd, buf, strlen(buf));
}
fullduplex.h
#define NP1 "/tmp/np1"
#define NP2 "/tmp/np2"
#define MAX_BUF_SIZE 255
Did you mean:
rdbuf[numread] = '\0';
buf in fd_server.c has the same problem.
This:
buf[numread] = '0';
is wrong. You want:
buf[numread] = '\0';
(Same with rdbuf[numread] = '0';.)
These lines produce bad output:
buf[numread] = '0';
printf("Full Duplex Server : Read From the pipe : %s \n", buf);
First, buf[numread] = '0'; Overwrites your null-terminator.
With this overwritten, printf(%s) doesn't know where to stop printing.
The null-terminator tells C where the string ends.
After you overwrote it, C no longer knows where the end of the string is, and prints your string "HAHAHA", but keeps printing garbage after that.

Resources