Error in msgget: no such file or directory - c

I know a similar question like this has been asked, but I also believe my issue is slightly different. I'm learning about message queues for a class assignment and the professor suggested we use this tutorial: http://beej.us/guide/bgipc/html/multi/mq.html . It's incredibly helpful and has a sample sender and receiver code titled kirk and spock.
kirk.c:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
struct my_msgbuf {
long mtype;
char mtext[200];
};
int main(void)
{
struct my_msgbuf buf;
int msqid;
key_t key;
if ((key = ftok("kirk.c", 'B')) == -1) {
perror("ftok");
exit(1);
}
if ((msqid = msgget(key, 0644 | IPC_CREAT)) == -1) {
perror("msgget");
exit(1);
}
printf("Enter lines of text, ^D to quit:\n");
buf.mtype = 1; /* we don't really care in this case */
while(fgets(buf.mtext, sizeof buf.mtext, stdin) != NULL) {
int len = strlen(buf.mtext);
/* ditch newline at end, if it exists */
if (buf.mtext[len-1] == '\n') buf.mtext[len-1] = '\0';
if (msgsnd(msqid, &buf, len+1, 0) == -1) /* +1 for '\0' */
perror("msgsnd");
}
if (msgctl(msqid, IPC_RMID, NULL) == -1) {
perror("msgctl");
exit(1);
}
return 0;}
spock.c:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
struct my_msgbuf {
long mtype;
char mtext[200];
};
int main(void)
{
struct my_msgbuf buf;
int msqid;
key_t key;
if ((key = ftok("kirk.c", 'B')) == -1) { /* same key as kirk.c */
perror("ftok");
exit(1);
}
if ((msqid = msgget(key, 0644)) == -1) { /* connect to the queue */
perror("msgget");
exit(1);
}
printf("spock: ready to receive messages, captain.\n");
for(;;) { /* Spock never quits! */
if (msgrcv(msqid, &buf, sizeof buf.mtext, 0, 0) == -1) {
perror("msgrcv");
exit(1);
}
printf("spock: \"%s\"\n", buf.mtext);
}
return 0;
}
When I initially compiled this code I ran across the error: msgget: no such file or directory when executing spock.c. I understand this error is typically because of a permissions/file path issue. However, the working directory of both files is the same, as well as the permission is properly set for both. I later found the error is removed when I type ctrl+c (^c) into the terminal once I've completed my input. My issue is this project is based on using a file input of text and while it is simple to have this code take in a file, I need to place a getchar() in order to request for the user to type the ^C interrupt in order for the receiver to properly read the message queue. I was wondering if anyone has come across this issue, and if so any suggestions for fixing it so that I don't need the user to request the ^C interrupt? Apologies for not posting my altered code however, understandably, my professor does not want any possible copying/plagiarism from other students.
Here is more detail of what I am writing in to the terminal:
Successful Output with use of ^C:
user#user-ThinkPad-S1-Yoga:~/Documents/message_queue$ gcc -o kirk -g -Wall
kirk.c
user#user-ThinkPad-S1-Yoga:~/Documents/message_queue$ gcc -o spock -g -Wall
spock.c
user#user-ThinkPad-S1-Yoga:~/Documents/message_queue$ ./kirk
Enter lines of text, ^D to quit:
value1
value2
value3
^C
user#user-ThinkPad-S1-Yoga:~/Documents/message_queue$ ./spock
spock: ready to receive messages, captain.
spock: "value1"
spock: "value2"
spock: "value3"
^C
user#user-ThinkPad-S1-Yoga:~/Documents/message_queue$
Output with use of print instructions, meaning using ^D:
user#user-ThinkPad-S1-Yoga:~/Documents/message_queue$ gcc -o kirk -g -Wall
kirk.c
user#user-ThinkPad-S1-Yoga:~/Documents/message_queue$ gcc -o spock -g -Wall
spock.c
user#user-ThinkPad-S1-Yoga:~/Documents/message_queue$ ./kirk
Enter lines of text, ^D to quit:
value1
value2
value3
user#user-ThinkPad-S1-Yoga:~/Documents/message_queue$ ./spock
msgget: No such file or directory
user#user-ThinkPad-S1-Yoga:~/Documents/message_queue$
Now, even though a proper output occurs when ^C interrupt is typed by the user, I don't want to have to type that into the terminal and simply want the sender program to be executed, then followed by the receiver program execution with no need for a "quitting" action because a file will be loaded as the input for the sender program in place of the stdin.

Related

STDIN input size restriction to 1k in C program

Probably a silly question, with read and other functions you can specify the number of bytes you want to read, however when reading from stdin I find that I can only type 1024 characters in the prompt, if I type the 1025 character, it's not written and if I want the line to be read (pressing ENTER key) I need to remove the 1024 character in order to leave space for '\n' I suppose. This occurs only in my c program not the shell so what's causing this restriction?
#include <unistd.h>
#include <stdio.h>
int main() {
char buf[2048];
int c;
c = read(fileno(stdin), &buf, sizeof(buf));
printf("%s\n", buf);
return 0;
}
Transferring select comments to form an answer.
General diagnosis
This is a property of the terminal driver on your system, rather than of the program or the C library. Modern shells such as Bash don't read a single line; they read characters as they become available using non-canonical input. See also Canonical vs non-canonical terminal input.
Barmar noted:
Note that read() doesn't add a null terminator to the input that it reads, but printf() expects a null-terminated string.
Instead of adding a null terminator, you could tell printf() how many characters to print:
printf("%.*s\n", c, buf);
That is, however, tangential to the question of how to get a long line of input.
If you use an open source o/s, you can modify the terminal driver source code and recompile your kernel to allow you to type more than 1 KiB on a single line, but anything much short of that isn't going to work. The terminal driver imposes a limit; you have to change the terminal driver to change that limit. If you're on Linux, you can poke around the /proc file system to see if there's a dynamic configuration parameter you can change (so you don't have to recompile the kernel, but you do have to alter the settings of the terminal driver); I've not heard of that being possible.
The limit can be a nuisance if you copy'n'paste more than 1 KiB of text with no newlines in it from a browser and want to paste it into a file on your system. Use a program such as Vim to manage it — it puts the terminal into a non-canonical mode and therefore doesn't run into the limit.
Using POSIX termios to slurp input from a terminal
If you want a program to read from a terminal without the line lengths (but also with line editing such as erase or kill processing), then you could consider this program — slurp:
/*
#(#)File: $RCSfile: slurp.c,v $
#(#)Version: $Revision: 1.3 $
#(#)Last changed: $Date: 2018/10/28 17:14:24 $
#(#)Purpose: Put terminal into non-canonical mode to slurp input
#(#)Author: J Leffler
*/
/*TABSTOP=4*/
#include "posixver.h"
#include "stderr.h"
#include <assert.h>
#include <fcntl.h>
#include <signal.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <termios.h>
#include <unistd.h>
static const char optstr[] = "a:ho:V";
static const char usestr[] = "[-hV][-a output | -o output]";
static const char hlpstr[] =
" -a output Append to named file (creating it if necessary)\n"
" -h Print this help message and exit\n"
" -o output Output to named file (truncating it if it exists)\n"
" -V Print version information and exit\n"
;
static struct termios saved = { 0 };
static bool sigint_enabled = false;
static bool sigquit_enabled = false;
static bool slurping = false;
static void reset_termios(void);
static void set_non_canonical(void);
static void sig_handler(int signum);
static void set_signal_handling(void);
static void slurp(int ofd, const char *filename);
#ifndef lint
/* Prevent over-aggressive optimizers from eliminating ID string */
extern const char jlss_id_slurp_c[];
const char jlss_id_slurp_c[] = "#(#)$Id: slurp.c,v 1.3 2018/10/28 17:14:24 jonathanleffler Exp $";
#endif /* lint */
int main(int argc, char **argv)
{
const char *filename = "standard output";
int ofd = STDOUT_FILENO;
int oflag = 0;
err_setarg0(argv[0]);
int opt;
while ((opt = getopt(argc, argv, optstr)) != -1)
{
switch (opt)
{
case 'h':
err_help(usestr, hlpstr);
/*NOTREACHED*/
case 'o':
case 'a':
if (ofd != STDOUT_FILENO)
{
err_remark("the -a and -o flags are mutually exclusive\n");
err_usage(usestr);
}
oflag = (opt == 'o') ? O_TRUNC : O_APPEND;
if ((ofd = open(optarg, O_WRONLY | O_CREAT | oflag, 0644)) < 0)
err_syserr("failed to open file %s for writing: ", optarg);
filename = optarg;
break;
case 'V':
err_version("PROG", &"#(#)$Revision: 1.3 $ ($Date: 2018/10/28 17:14:24 $)"[4]);
/*NOTREACHED*/
default:
err_usage(usestr);
/*NOTREACHED*/
}
}
if (optind != argc)
{
err_remark("unexpected file name options (first is '%s')\n", argv[optind]);
err_usage(usestr);
}
set_non_canonical();
if (slurping)
set_signal_handling();
slurp(ofd, filename);
return 0;
}
static void reset_termios(void)
{
tcsetattr(STDIN_FILENO, 0, &saved);
}
static void set_non_canonical(void)
{
if (tcgetattr(STDIN_FILENO, &saved) == 0)
{
struct termios modified = saved;
atexit(reset_termios);
/*
** On macOS 10.14 (at least), if you don't reset ISIG, the
** signal characters are not transferred to the program, so
** you can't detect those signals. With ICANON reset, they
** don't generate the signal either. The code does not try
** to handle the suspend (^Z) key specially, nor any other
** keys than EOF, INTR, QUIT.
*/
modified.c_lflag &= ~(ICANON | ISIG);
modified.c_cc[VMIN] = 1;
modified.c_cc[VTIME] = 0;
tcsetattr(STDIN_FILENO, TCSANOW, &modified);
slurping = true;
}
}
static void sig_handler(int signum)
{
reset_termios();
_exit(128 + signum);
}
/* Almost worth a data structure and a loop, but not quite */
static void set_signal_handling(void)
{
/* Simulate SIGINT and SIGQUIT */
if (signal(SIGINT, SIG_IGN) != SIG_IGN)
{
(void)signal(SIGINT, sig_handler);
sigint_enabled = true;
}
if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
{
(void)signal(SIGQUIT, sig_handler);
sigquit_enabled = true;
}
/* Have program terminate when sent normal signals */
if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
(void)signal(SIGHUP, sig_handler);
if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
(void)signal(SIGTERM, sig_handler);
if (signal(SIGPIPE, SIG_IGN) != SIG_IGN)
(void)signal(SIGPIPE, sig_handler);
}
static void slurp(int ofd, const char *filename)
{
char buffer[4096];
int nbytes;
while ((nbytes = read(STDIN_FILENO, buffer, sizeof(buffer))) > 0)
{
/* Simulate EOF and interrupt and quit signals */
if (nbytes == 1 && slurping)
{
if (buffer[0] == saved.c_cc[VEOF])
break;
if (sigint_enabled && buffer[0] == saved.c_cc[VINTR])
exit(128 + SIGINT);
if (sigquit_enabled && buffer[0] == saved.c_cc[VQUIT])
exit(128 + SIGQUIT);
}
if (write(ofd, buffer, nbytes) != nbytes)
err_syserr("failed to write %d bytes to %s: ", nbytes, filename);
}
}
The library code used is available in my SOQ (Stack Overflow Questions) repository on GitHub as files stderr.c, stderr.h and posixver.h in the libsoq sub-directory.
This deals with most of the traps for the unwary. It does its best to reset the terminal back to the initial ('known good') state when it exits. It does simulate EOF, interrupt and quit keyboard signals, but it does not simulate regular terminal processing such as erase or kill.
It doesn't make sense to use this when the standard input is not a terminal, but the code should handle that OK too (it simply does normal reads). You can send the output to standard output (default) or to a file (-o file to create or truncate a file, -a file to append or create a file).

undefined reference to main issue (using arduino, RaspberryPi, GCC)

I'm making a program(C language) on RaspberryPi
My program get a data from Arduino by Serial communication
Source Code here :
#ifdef RaspberryPi
//include system librarys
#include <stdio.h> //for printf
#include <stdint.h> //uint8_t definitions
#include <stdlib.h> //for exit(int);
#include <string.h> //for errno
#include <errno.h> //error output
//wiring Pi
#include <wiringPi.h>
#include <wiringSerial.h>
char device[]= "/dev/ttyACM0";
// filedescriptor
int fd;
unsigned long baud = 9600;
unsigned long time=0;
//prototypes
void loop(void);
void setup(void);
void setup(){
printf("%s \n", "Raspberry Startup!");
fflush(stdout);
//get filedescriptor
if ((fd = serialOpen (device, baud)) < 0){
fprintf (stderr, "Unable to open serial device: %s\n", strerror (errno)) ;
exit(1); //error
}
//setup GPIO in wiringPi mode
if (wiringPiSetup () == -1){
fprintf (stdout, "Unable to start wiringPi: %s\n", strerror (errno)) ;
exit(1); //error
}
}
void loop(){
// Pong every 3 seconds
if(millis()-time>=3000){
serialPuts (fd, "Received\n");
time=millis();
}
// read signal
if(serialDataAvail (fd)){
char newChar = serialGetchar (fd);
printf("%c", newChar);
if((int)newChar >= 1){
system("raspistill -o image.jpg");
system("convert image.jpg -threshold 20% imagebw.jpg");
system("tesseract imagebw.jpg imageocr");
system("cat imageocr.txt");
}
fflush(stdout);
}
}
int main(void){
setup();
while(1) loop();
return 0;
}
#endif //#ifdef RaspberryPi
Before I put
system("convert image.jpg -threshold 20% imagebw.jpg");
system("tesseract imagebw.jpg imageocr");
system("cat imageocr.txt");
this code, it worked well
But, It does not work even if I delete it.
I found following error on my compiler(GCC)
/usr/lib/gcc/arm-linux-gneabihf/4.9/../../../arm-linux-gnueabihf/ort1.o:In function '_start':/build/glibc-mqlSLF/glibc-2.19/csu/../ports/sysdeps/arm/start.S:119 : undefined reference to 'main'
collect2: error: ld returned 1 exit sutatus
And I used following two command
sudo gcc test.c -o hello -lwiringPi -DRaspberryPi <br>
sudo gcc test.c -o hello -lwiringPi -DRaspberryPi -nostartfiles
Can anybody help me with this issue?

How to run my stdin through the cut command using the execl() function?

My objective is to make an IPC between a child and parent through a FIFO. The child should run
execl ("/bin/cat", "cat", "/etc/passwd", (char *)0);
redirect its output to the parents input and the parent should run this command:
cut -l : -f 1
and output this to command line.
Right now, I've successfully linked my FIFO and redirected the output of my child process to the input of the parent. I've done multiple tests and that connection is working properly. The problem is with the execl for the cut, which should look something like this:
execlp("/bin/cut", "cut", "-l:", "-f", "1", NULL);
but I'm pretty sure it isn't.
int cut(){
//
int myfifo;
char buf[MAX_BUF];
printf("\nCut opening FIFO");
if((myfifo = open("/tmp/myfifo", O_RDONLY | O_TRUNC))<0){
perror("open FIFO at cut");
quit(EXIT_FAILURE);}
else{printf("\nCut has FIFO opened and is reading\n");}
//read(myfifo, buf, MAX_BUF); outputting buf goes as supposed to
if( dup2(myfifo, 0) < 0 ){
perror("dup2 at cut");
quit(EXIT_FAILURE);}
//read(STDIN_FILENO, buf, MAX_BUF);
close(myfifo);
execlp("/bin/cut", "cut", "-l:", "-f", "1", NULL);
//this is for testing buf, but i guess the program shouldn't even get here
printf("\nCut has received: %s\nAnd is closing FIFO", buf);
return -1;
}
int cat(){
int myfifo;
//OPEN FIFO
printf("\nCat opening FIFO");
if( (myfifo = open("/tmp/myfifo", O_WRONLY | O_TRUNC) )<0){
perror("open FIFO at cat");
quit(EXIT_FAILURE);
}
else{
printf("\nCat has opened FIFO");
//WRITE OUTPUT OF "cat \etc\passwd" TO FIFO
dup2(myfifo, 1);
execl ("/bin/cat", "cat", "/etc/passwd", (char *)0);
}
close(myfifo);
return 0;
}
The main currently only creates the fifo (mkfifo), forks() and calls the function.
My problem could with the stdin of the parent (running cut), but I don't think so, or maybe I'm assuming execl() reads directly from the stdin and It doesn't.
I think it's really bcause I'm not writing the "cut" through execl() properly.
Any corrections to the code, or even the way I expressed some ideas can indicate that I don't understand something properly, would be very appreciated.
Thank you for helping
As noted in a comment, the cut command under GNU and BSD (and POSIX) does not support a -l option; the option you need is -d for delimiter.
This code works for me. On my machine, /bin/cat is correct, but /usr/bin/cut is correct (not /bin/cut), so I had to compile with:
$ rmk cutcat UFLAGS=-DCUT_CMD=/usr/bin/cut && ./cutcat
gcc -O3 -g -std=c11 -Wall -Wextra -Werror -DCUT_CMD=/usr/bin/cut cutcat.c -o cutcat
$
That uses a custom variant of make (called rmk) and a custom makefile, but the location of the cut command is specified on the command line via the UFLAGS (user flags) macro. The STRING and EXPAND macros in the C code are a nuisance, but not as much of a nuisance as trying to get double quotes past the shell that invokes make (or rmk) and then the shell that make invokes to run the compiler.
The code:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <sys/stat.h>
#ifndef CUT_CMD
#define CUT_CMD /bin/cut
#endif
#ifndef CAT_CMD
#define CAT_CMD /bin/cat
#endif
#define EXPAND(x) #x
#define STRING(x) EXPAND(x)
static const char cut_cmd[] = STRING(CUT_CMD);
static const char cat_cmd[] = STRING(CAT_CMD);
static inline void quit(int status) { exit(status); }
enum { MAX_BUF = 4096 };
static void cut(void)
{
int myfifo;
printf("\nCut opening FIFO");
if ((myfifo = open("/tmp/myfifo", O_RDONLY | O_TRUNC)) < 0)
{
perror("open FIFO at cut");
quit(EXIT_FAILURE);
}
printf("\nCut has FIFO opened and is reading\n");
if (dup2(myfifo, 0) < 0)
{
perror("dup2 at cut");
quit(EXIT_FAILURE);
}
close(myfifo);
execlp(cut_cmd, "cut", "-d:", "-f", "1", NULL);
fprintf(stderr, "Failed to execute %s\n", cut_cmd);
exit(1);
}
static
void cat(void)
{
int myfifo;
printf("\nCat opening FIFO");
if ( (myfifo = open("/tmp/myfifo", O_WRONLY | O_TRUNC) ) < 0)
{
perror("open FIFO at cat");
quit(EXIT_FAILURE);
}
printf("\nCat has opened FIFO");
dup2(myfifo, 1);
close(myfifo);
execl(cat_cmd, "cat", "/etc/passwd", (char *)0);
fprintf(stderr, "Failed to execute %s\n", cat_cmd);
exit(1);
}
int main(void)
{
mkfifo("/tmp/myfifo", 0600);
if (fork() == 0)
cat();
else
cut();
/*NOTREACHED*/
fprintf(stderr, "You should not see this message\n");
return 0;
}
Sample output:
Much truncated
…
nobody
root
daemon
_uucp
_taskgated
_networkd
…
The code is really not very different from what you had. I removed some clutter. I did ensure that close(myfifo) was executed by cat(); it wasn't in the original. It might be significant.

SIGXFSZ is sent by kernel unless something is printed to stdout?

I am learning "Advanced Programming in Unix Environment", and have a problem with exercise no.11 in chapter 10.
In my program, I set RLIMIT_FSIZE to 1024.
So the kernel should send SIGXFSZ to my program when write trying to exceed that limit.
But I found that SIGXFSZ is not send unless something is printed to stdout.
Here is my code:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <signal.h>
#define BUFFSIZE 100
void xfsz_handler(int signo)
{
fprintf(stderr, "%d, %s\n", signo, strsignal(signo));
}
int main(int argc, char* argv[])
{
int n;
char buf[BUFFSIZE];
struct rlimit fsizeLimit;
fsizeLimit.rlim_cur=1024;
fsizeLimit.rlim_max=1024;
if(setrlimit(RLIMIT_FSIZE, &fsizeLimit) < 0)
{
perror("setrlimit error");
exit(-1);
}
if(signal(SIGXFSZ, xfsz_handler)==SIG_ERR)
{
fprintf(stderr, "set signal handler error for %d\n", SIGXFSZ);
exit(-1);
}
printf("what ever\n"); /* we need this to get SIGXFSZ sent */
while ( (n=read(STDIN_FILENO, buf, BUFFSIZE)) > 0)
{
int byteWrite = 0;
if ( (byteWrite = write(STDOUT_FILENO, buf, n)) < 0)
{
perror("write error");
exit(-1);
}
if(byteWrite!=n)
{
fprintf(stderr, "byteWrite=%d, n=%d\n", byteWrite, n);
exit(-1);
}
}
if (n<0)
{
perror("read error");
exit(-1);
}
return 0;
}
if I comment out the following line in the code, kernel will not transmit SIGXFSZ.
printf("What ever . . . \n");
Why this happens? Thanks in advance.
[root#luaDevelopment ex11]# ./myCopy < /root/workspace/AdvanceProgrammingInTheUnixEnvironment.20140627.tar.bz2 >aa.tar.bz2
byteWrite=24, n=100
[root#luaDevelopment ex11]# make
gcc -o myCopy myCopy.c -std=gnu99 -I../../lib/ -L../../lib/ -lch10
[root#luaDevelopment ex11]# ./myCopy < /root/workspace/AdvanceProgrammingInTheUnixEnvironment.20140627.tar.bz2 >aa.tar.bz2
byteWrite=24, n=100
25, File size limit exceeded
[root#luaDevelopment ex11]#
user3693690 found the answer in Appendix C of the book:
10.11 Under Linux 3.2.0, Mac OS X 10.6.8, and Solaris 10, the signal handler for SIGXFSZ is never called because the loop exits the program on a short write, but write returns a count of 24 as soon as the file’s size reaches 1,024 bytes. When the file’s size has reached 1,000 bytes under FreeBSD 8.0, the signal handler is called on the next attempt to write 100 bytes, and the write call returns −1 with errno set to EFBIG("File too big"). On all four platforms, if we attempt an additional write at the current file offset (the end of the file), we will receive SIGXFSZ and write will fail, returning −1 with errno set to EFBIG.

Why is stat() returning EFAULT?

I'm writing a program that when run from two separate bash sessions as two separate processes, opens a named pipe between the two to allow strings to be sent from one to the other.
When the process is first executed from one terminal, it checks stat(fname, buf) == -1 to see if a file at path fname exists and if not, creates it. The process then assumes that since it was the one to make the FIFO, it is the one that will be sending messages through it and continues accordingly.
After that occurs, the program can then be run from another terminal that should determine that it will be the receiver of messages through the pipe by checking stat(fname, buf) == -1. The condition should return false now, and stat(fname, buf) itself should return 0 because there exists a file at fname now.
But for reasons I am unable to discern, when the second process is run, stat(fname, buf) still returns -1. The variable errno is set to EFAULT. The man page for stat() only decribes EFAULT as "Bad address." Any help determining why the error occurs or what is meant by "Bad address." would be greaty appreciated.
I've verified that the file is indeed created by the first process as intended. The first process waits at the line pipe = open(fname, O_WRONLY); because it can't continue until the other end of pipe is opened.
Edit: The following is a self-contained implementation of my code. I have confirmed that it compiles and experiences the problem I described here.
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#define MAX_LINE 80
#define oops(m,x) { perror(m); exit(x); }
int main(int argc, char const *argv[]) {
char line[MAX_LINE];
int pipe, pitcher, catcher, initPitcher, quit;
struct stat* buf;
char* fname = "/tmp/absFIFOO";
initPitcher = catcher = pitcher = quit = 0;
while (!quit) {
if (((!pitcher && !catcher && stat(fname, buf) == -1) || pitcher) && !quit) {
// Then file does not exist
if (errno == ENOENT) {
// printf("We're in the file does not exist part\n");
if (!pitcher && !catcher) {
// Then this must be the first time we're running the program. This process will take care of the unlink().
initPitcher = 1;
int stat;
if (stat = mkfifo(fname, 0600) < 0)
oops("Cannot make FIFO", stat);
}
pitcher = 1;
// open a named pipe
pipe = open(fname, O_WRONLY);
printf("Enter line: ");
fgets(line, MAX_LINE, stdin);
if (!strcmp(line, "quit\n")) {
quit = 1;
}
// actually write out the data and close the pipe
write(pipe, line, strlen(line));
close(pipe);
}
} else if (((!pitcher && !catcher) || catcher) && !quit) {
// The first condition is just a check to see if this is the first time we've run the program. We could check if stat(...) == 0, but that would be unnecessary
catcher = 1;
pipe = open("/tmp/absFIFO", O_RDONLY);
// set the mode to blocking (note '~')
int flags;
flags &= ~O_NONBLOCK;
fcntl(pipe, F_SETFL, flags); //what does this do?
// read the data from the pipe
read(pipe, line, MAX_LINE);
if (!strcmp(line, "quit\n")) {
quit = 1;
}
printf("Received line: %s\n", line);
// close the pipe
close(pipe);
}
}
if (initPitcher)
unlink(fname);
return 0;
}
You have this piece of code:
struct stat* buf;
...
if (((!pitcher && !catcher && stat(fname, buf) == -1)
When you call stat(), buf isn't initalized and there's no telling what it points to.
You must allocate some storage for it, so stat() has a valid place to store the result.
The easiest thing is to just allocate it on the stack:
struct stat buf;
...
if (((!pitcher && !catcher && stat(fname, &buf) == -1)
You have not shown your code, but EFAULT means 'bad address'. This indicates that you have not properly allocated (or passed) your buffer for stat or the filename (fname).
buf isn't initialised anywhere. What exactly do you expect to happen?

Resources