I am having problem debugging why n_bytes in read_from_fifo function in client.c doesn't correspond to the value written to the fifo. It should only write 25 bytes but it tries to read a lot more (1836020505 bytes (!) to be exact). Any idea why this is happening?
server.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <signal.h>
#include <pthread.h>
#include <sys/stat.h>
typedef enum { false, true } bool;
//first read the int with the number of bytes the data will have
//then read that number of bytes
bool read_from_fifo(int fd, char* var)
{
int n_bytes;
if (read(fd, &n_bytes, sizeof(int)))
{
printf("going to read %d bytes\n", n_bytes);
if (read(fd, var, n_bytes))
printf("read var\n");
else {
printf("error in read var. errno: %d\n", errno);
exit(-1);
}
}
return true;
}
int main()
{
mkfifo("/tmp/foo", 0660);
int fd = open("/tmp/foo", O_RDONLY);
char var[100];
read_from_fifo(fd, var);
printf("var: %s\n", var);
return 0;
}
client.c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
typedef enum { false, true } bool;
//first write to fd a int with the number of bytes that will be written afterwards
bool write_to_fifo(int fd, char* data)
{
int n_bytes = (strlen(data)) * sizeof(char);
printf("going to write %d bytes\n", n_bytes);
if (write(fd, &n_bytes, sizeof(int) != -1))
if (write(fd, data, n_bytes) != -1)
return true;
return false;
}
int main()
{
int fd = open("/tmp/foo", O_WRONLY);
char data[] = "some random string abcdef";
write_to_fifo(fd, data);
return 0;
}
Help is greatly appreciated. Thanks in advance.
The return value for an error from read(2) is -1, not 0. So your if statement for the first 4-byte read, at least, is wrong.
Did you verify if nbytes printed by read_from_fifo() function displayed the correct value ?
Just notice that on write(fd, data, n_bytes) you did not write the end of string char '\0', and whenever you read it by read(fd, var, n_bytes), you did not added a '\0' to the end of string just read, so the printf("var: %s\n", var); could display a not \0 ended string resulting unpredicted results.
I have found the solution myself.
The problem is a ')' believe it or not. The n_bytes variable is correct, the problem is that I am not writing that to the fifo.
this (write(fd, &n_bytes, sizeof(int) != -1))
should be this (write(fd, &n_bytes, sizeof(int)) != -1)
Thanks anyway for your answers.
Related
Here is my code I tried also to do casting in mmap but it didn't work.
I need that after I use in memcpy *src include array of the shared from integer type and that printf print array of integer(the pid in code). with %d in printf the code not compile and when I use 5p its print me hexadecimal address
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/stat.h>
int main(int argc, char const *argv[])
{
int shared[3];
void* src = mmap(0,num, PROT_READ|PROT_WRITE,MAP_ANONYMOUS|MAP_SHARED, fd, 0);
if (src == MAP_FAILED)
{
fprintf(stderr, "mmap() failed\n");
exit(EXIT_FAILURE);
}
//placement of shared array and print
for(int i = 0; i < num; i++)
{
if ((pid = fork()) < 0)
{
perror("fork error\n");
}
else
{
//Placement of pid to shared array
shared[i]=getpid();
}
//need to change the permission in map, create a virtual memory
}
memcpy(src,shared, num+1);
printf("%d\n",src);
close(fd);
return 0;
}
I was trying out some exercises with the C language, specifically open() and read(). However, I've reached an impasse when I try printing to STDOUT the contents of a a text file (text.txt) that I have in the same directory as the c file. The size in bytes get printed, but the contents of the file do not.
I allocated space according to the size of the file, and added "1" for the null terminator. The manual page for read() states that it reads the contents of the file into the second parameter (void* buff). What am I missing/doing wrong?
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main(int argc, char* argv[]){
int fd = open("text.txt", O_RDONLY);
if (fd == -1){
printf("%s\n", strerror(errno));
return -1;
}
else {
int func = lseek(fd, 0, SEEK_END);
printf("%d bytes in size\n", func);
char* ptr = (char*)malloc(sizeof(char)*func + 1);
read(fd, ptr, func);
printf("%s", ptr);
free(ptr);
}
close(fd);
return 0;
}```
You need to move back to the beginning of the file before the read.
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main(int argc, char* argv[]){
int fd = open("text.txt", O_RDONLY);
if (fd == -1){
printf("%s\n", strerror(errno));
return -1;
}
else {
int size = lseek(fd, 0, SEEK_END);
printf("%d bytes in size\n", size);
char* ptr = (char *) malloc(sizeof(char) * size + 1);
lseek(fd, 0, SEEK_SET); // move back to the beginning
read(fd, ptr, size);
printf("%.*s", size, ptr);
free(ptr);
}
close(fd);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main(int argc, char* argv[]){
int fd = open("text.txt", O_RDONLY);
if (fd == -1){
printf("%s\n", strerror(errno));
return -1;
}
else {
int size = lseek(fd, 0, SEEK_END);
printf("%d bytes in size\n", size);
char* ptr = (char *) malloc(sizeof(char) * size + 1);
lseek(fd, 0, SEEK_SET); // move back to the beginning
read(fd, ptr, size);
printf("%.*s", size, ptr);
free(ptr);
}
close(fd);
return 0;
}
(venv) [ttucker#zim stackoverflow]$ cat text.txt
asdf
qwer
sdfg
(venv) [ttucker#zim stackoverflow]$ gcc -o print print.c
(venv) [ttucker#zim stackoverflow]$ ./print
15 bytes in size
asdf
qwer
sdfg
I have 2 programs (write.c and read.c). I want to continuously write to the named pipe from standard input, and read from it on the other end (and write to standard output). I've made something work, but it isn't working right. The program on the other end reads in the wrong order or reads special characters (so it reads more then it needs?). I also want to be able to compare the named pipe output to a certain string.
Anyways, here's the code from both files:
write.c:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define BUFFSIZE 512
#define err(mess) { fprintf(stderr,"Error: %s.", mess); exit(1); }
void main()
{
int fd, n;
char buf[BUFFSIZE];
mkfifo("fifo_x", 0666);
if ( (fd = open("fifo_x", O_WRONLY)) < 0)
err("open")
while( (n = read(STDIN_FILENO, buf, BUFFSIZE) ) > 0) {
if ( write(fd, buf, strlen(buf)) != strlen(buf)) {
err("write");
}
}
close(fd);
}
read.c:
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFSIZE 512
#define err(mess) { fprintf(stderr,"Error: %s.", mess); exit(1); }
void main()
{
int fd, n;
char buf[BUFFSIZE];
if ( (fd = open("fifo_x", O_RDONLY)) < 0)
err("open")
while( (n = read(fd, buf, BUFFSIZE) ) > 0) {
if ( write(STDOUT_FILENO, buf, n) != n) {
exit(1);
}
}
close(fd);
}
Example of input:
hello how are you
123
test
Example of incorrect output:
hello how are you
b123
o how are you
btest
how are you
b
Another example of input:
test
hi
And output:
test
hi
t
The buffer modify by read is not a valid c string so
write(fd, buf, strlen(buf)) != strlen(buf) // write.c
is undefined behaviour. You should do
write(fd, buf, n) != n
because you read n octet with read().
It's funny because you do it for read.c but not for write.c
The type of n must but ssize_t and not int, man read.
main() must return a int Declare main prototype
I'm trying to write and read from a named fifo with some methods... Apparently when I run it gets stuck on write_fifo(0) for no reason... So my question is am I using named fifo in the right way? Or does the unlink method mess with my program? When and where can I unlink a named fifo.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#define FILE_MODE (S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH)
void write_fifo(int s)
{
printf("write_fifo");
int writing, n;
writing = open("myFIFO",O_WRONLY);
n = write(writing, &s, sizeof(s));
printf("write: %i byte.\n", n);
close(writing);
unlink("myFIFO");
}
int read_fifo()
{
printf("read_fifo");
int reading, n, s;
reading = open("myFIFO", O_RDONLY);
n = read(reading , &s, sizeof(s));
printf("read: %i byte: %d\n", n, s);
close(reading);
unlink("myFIFO");
return s;
}
int main()
{
printf("beginning");
printf("removing myFIFO");
if (mkfifo("myFIFO", FILE_MODE) == -1)
{
perror("myFIFO");
exit(1);
}
write_fifo(0);
printf("\n\n\n\n\n\n\nReading %d",read_fifo());
return 0;
}
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.