Why I'm getting trash on this pipe? - c

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.

Related

How to keep program unclosed after ctr+c in named pipe?

I have 2 programs.
One is server one is client. The Client sending string to the server, the server is swapping the string and return to the client.
the problems I have is when I pressing ctr+c the program(client) closed.(I'm using threads because I have been asking for.)
So how can I keep the program unclosed after ctr+c?
when clicking enter this is the right result and waiting for the server.
when entering ctl+c the program closed and cannot running server.c
The client.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <time.h>
#define MAX_BUF 1024
// client
int main()
{
int fd;
char *myfifo = "myfifo";
char str[MAX_BUF];
printf("Input string: ");
fgets(str, MAX_BUF, stdin);
str[strlen(str) - 1] = '\0';
if (mkfifo("myfifo", 0777) == -1)
{
if (errno != EEXIST)
{
printf("Could not create fifo file\n");
return 1;
}
}
/* create the FIFO (named pipe) */
fd = open(myfifo, O_WRONLY);
if (fd == -1)
return 2;
if (write(fd, str, MAX_BUF) == -1)
return 3;
close(fd);
fd = open(myfifo, O_RDONLY);
read(fd, str, MAX_BUF);
printf("%s\n", str);
/* remove the FIFO */
unlink(myfifo);
return 0;
}
The server
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <time.h>
#include <pthread.h>
#define MAX_BUF 1024
// server
// creatring struct for saving data
typedef struct thread_data
{
char str[MAX_BUF];
int result;
} thread_data;
// the
void *routine(void *arg)
{
int fd[2];
char *myfifo = "myfifo";
thread_data *tdata = (thread_data *)arg;
if (!(strcmp(tdata->str, "exit")))
tdata->result = 1; // is exit
else
tdata->result = 0; // not exit
if (tdata->result == 1)
{
fd[1] = open(myfifo, O_WRONLY);
write(fd[1], "Done", sizeof(MAX_BUF));
close(fd[1]);
}
else
{
char string[MAX_BUF] = {0};
char c = 0;
int length = 0, i = 0;
length = strlen(tdata->str);
printf("\nBefore Swap : %s\n", tdata->str);
for (i = 0; i < length / 2; i++)
{
c = tdata->str[i];
tdata->str[i] = tdata->str[length - 1 - i];
tdata->str[length - 1 - i] = c;
}
printf("\nAfter Swap String : %s\n", tdata->str);
fd[1] = open(myfifo, O_WRONLY);
write(fd[1], tdata->str, sizeof(MAX_BUF));
close(fd[1]);
}
pthread_exit(NULL);
}
int Calculation()
{
int fd[2];
// fd[0] read
// fd[1] write
char *myfifo = "myfifo";
char buf[MAX_BUF];
/* open, read, and display the message from the FIFO */
fd[0] = open(myfifo, O_RDONLY);
if(fd[0]==-1)
return 4;
if(read(fd[0], buf, MAX_BUF)==-1)
return 5;
close(fd[0]);
// res
int result;
thread_data tdata;
strcpy(tdata.str, buf);
pthread_t t1;
if (pthread_create(&t1, NULL, &routine, (void *)&tdata) != 0)
{
return 1;
}
if (pthread_join(t1, NULL) != 0)
{
return 2;
}
}
int main()
{
int res = Calculation();
return res;
}
To avoid closing a program you should capture and
manage the signal sent by CTRL + C, that is SIGINT, I have modified the code so that it captures the signal CTRL + C
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <time.h>
#define MAX_BUF 1024
// client
int main()
{
signal(SIGINT,SIG_IGN); // Register signal handler for ignoring the signal
int fd;
char *myfifo = "myfifo";
char str[MAX_BUF];
printf("Input string: ");
fgets(str, MAX_BUF, stdin);
str[strlen(str) - 1] = '\0';
if (mkfifo("myfifo", 0777) == -1)
{
if (errno != EEXIST)
{
printf("Could not create fifo file\n");
return 1;
}
}
/* create the FIFO (named pipe) */
fd = open(myfifo, O_WRONLY);
if (fd == -1)
return 2;
if (write(fd, str, MAX_BUF) == -1)
return 3;
close(fd);
fd = open(myfifo, O_RDONLY);
read(fd, str, MAX_BUF);
printf("%s\n", str);
/* remove the FIFO */
unlink(myfifo);
return 0;
}

How to write and read from a named pipe in C?

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

Getting a No such file or directory on fopen()

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;
}

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 is this named pipe not printing the sent line?

The following server creates a named pipe when it's run like this:
./serverprogram -p nameofthepipe -t 99
the optarg after t indicates a number of threads to be created (not done here).
Anyway, the pipe isn't working here:
/* Open the first named pipe for reading */
int rdfd = open(pipeName, O_RDONLY);
/* Read from the first pipe */
int numread = read(rdfd, command_and_pid, 280);
printf("what's being read is %s \n", command_and_pid); // not printing!!1!
Why?
Server program:
#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>
int main (int argc, char * argv[])
{
char pipeName[30];
int numThreads;
char command_and_pid[280];
int opcion;
if (argc < 2) {
printf ("ERROR: Missing arguments\n");//
exit(1);
}
opterr = 0;
while ((opcion = getopt (argc, argv, "p:t:w")) != -1)
{
switch (opcion) {
case 'p': // -p indica el nombre del pipe
printf("The name of the pipe is: %s\n",optarg);
strcpy(pipeName, optarg);
break;
case 't'://-t indica los hilos
printf("The number of threads is: %s\n",optarg);
numThreads= atoi(optarg);
break;
case '?':
fprintf(stderr,"no reconozco esa opcion\n");
break;
}
}
int ret_val = mkfifo(pipeName, 0666);
if ((ret_val == -1) && (errno != EEXIST)) {
perror("Error creating the named pipe");
exit (0);
}
/* Open the first named pipe for reading */
int rdfd = open(pipeName, O_RDONLY);
/* Read from the first pipe */
int numread = read(rdfd, command_and_pid, 280);
printf("what's being read is %s \n", command_and_pid); // not printing!!1!
close(rdfd);
return 0;
}
Client program:
#include <unistd.h>
#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
int main (int argc, char * argv[])
{
char pipeName[30];
printf("write the name of the pipe used to write to the server \n");
fgets(pipeName,30, stdin);
/* Open the first named pipe for writing */
int wrfd = open(pipeName, O_WRONLY);
printf("write the name of the command you want to execute \n");
char command_and_pid[280];
char command[250];
fgets(command,250, stdin);
puts(command); //quitar
strcpy(command_and_pid,command);
strcat(command_and_pid," ");
int pipeIntId;
char pidstring [30];
int pid= getpid();
sprintf(pidstring,"%d", pid);
strcat(command_and_pid,pidstring);
int written;
written=write(pipeIntId,command_and_pid,280);
//write to the pipe
// send the command and pid
close(pipeIntId); // close write pipe
return 0;
}
In the client, fgets keeps the newline at the end of the line, so you'll need to strip that before opening the file.
Also, in the code as given, you're opening wrfd but writing to pipeIntId, which is uninitialized (though perhaps you are extracting something from a function here).

Resources