LinuxQuestions.org
Review your favorite Linux distribution.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices



Reply
 
Search this Thread
Old 06-26-2010, 01:23 PM   #1
doru
Member
 
Registered: Sep 2008
Distribution: Ubuntu 8.04 LTS Server
Posts: 89

Rep: Reputation: 16
fifo special characters


I use fifos to communicate between two simple programs, a client and a server. The client runs, sends three characters to the server on a fifo, reads three characters from the server on another fifo, and ends. When I use write and read with size (3'rd parameter) 3 or 4 I get strange characters when I read the fifos both in client and server. When I use write and read with size 64, everything looks right. As a beginner it took me a while to figure this out, and I would like to know what happens. I know that the client sends an EOF when it exits, but this does not seem to be a problem with size 64. Please throw to me some suggestions, as of what could cause this behaviour.

Here are the programs, in case you need them:

Code:
//client 
#include <stdio.h>
#include <string.h>
#include <fcntl.h>

#define CP "c6"
#define BUFSIZE 3

int main(void){

  int a, fdi, fdo;
  char *fifo1="fifo1", *fifo2="fifo2", s[BUFSIZE]="123", t[BUFSIZE];

  fdo = open(fifo1, O_WRONLY);
  printf("%s - fdo: %i\n", CP, fdo);

  fdi = open(fifo2, O_RDONLY);
  printf("%s - fdi: %i\n", CP, fdi);

  a = write(fdo, s, BUFSIZE);
  printf("%s - write: %i\n", CP, a);

  a = read(fdi, t, BUFSIZE);
  printf("%s - read: %i\n", CP, a);

  printf("%s - read: %s\n", CP, t);

}

//server
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
//#include <stdlib.h>

#define CP "s6"
#define BUFSIZE 3

int main(void){

  int a, fdo, fdi;
  char *fifo1="fifo1", *fifo2="fifo2", s[BUFSIZE]="321", t[BUFSIZE];

  fdi = open(fifo1, O_RDWR);
  printf("%s - fdi: %i\n", CP, fdi);

  fdo = open(fifo2, O_RDWR);
  printf("%s - fdo: %i\n", CP, fdo);

  for(;;){

    a = read(fdi, t, BUFSIZE);
    printf("%s - read: %i\n", CP, a);

    printf("%s - read: %s\n", CP, t);

    a = write(fdo, s, BUFSIZE);
    printf("%s - write: %i\n", CP, a);

//    read(0, t, BUFSIZE);

  }

}
 
Old 06-27-2010, 07:19 AM   #2
harry edwards
Member
 
Registered: Nov 2007
Location: Lincolnshire, UK
Distribution: CentOS, Fedora, and Suse
Posts: 365

Rep: Reputation: 48
BUFSIZE should be four as each char array should allow room to be NUL terminated, thus, a char's size is always one more than you want. The reason is due to how the C programming language handles strings. The length of a C char is found by searching for the (first) NUL byte. Samples of C string handling code can be seen in strlen and strcpy. If there is no NUL character you'll see erroneous output.
 
1 members found this post helpful.
Old 06-27-2010, 10:08 AM   #3
doru
Member
 
Registered: Sep 2008
Distribution: Ubuntu 8.04 LTS Server
Posts: 89

Original Poster
Rep: Reputation: 16
Thank you for your help.
You are right, it works with four.
 
Old 06-28-2010, 04:09 AM   #4
doru
Member
 
Registered: Sep 2008
Distribution: Ubuntu 8.04 LTS Server
Posts: 89

Original Poster
Rep: Reputation: 16
now from console

When I read from console a short string like "12 34":
Code:
char t[11];
read(0, t, 10);
I get t = "12 34\n". read does not add '\0'. One solution is to add it myself:
Code:
t[5]='\0';
Is there a better solution which I overlook? Or this is how it should work? Of course I could replace the first '\n' in t with '\0' with some code.
 
Old 06-28-2010, 05:08 PM   #5
harry edwards
Member
 
Registered: Nov 2007
Location: Lincolnshire, UK
Distribution: CentOS, Fedora, and Suse
Posts: 365

Rep: Reputation: 48
The preferred method I would recommend is to NUL terminate based on the length of data read from the console. The read function returns the length of the data read, thus, you can use this value to terminate e.g.

Code:
#include <stdio.h>
#include <string.h>
#include <fcntl.h>

int main(void)
{
char t[11];
int len = 0;
len = read(0, t, 10);

  t[len-1]=0;
  printf("[%s]", t);
}
Of course, you should also check the value of len, as it could be zero.
 
1 members found this post helpful.
Old 06-29-2010, 03:51 AM   #6
doru
Member
 
Registered: Sep 2008
Distribution: Ubuntu 8.04 LTS Server
Posts: 89

Original Poster
Rep: Reputation: 16
Thank you again. Now it makes sense.
 
Old 07-08-2010, 05:08 AM   #7
doru
Member
 
Registered: Sep 2008
Distribution: Ubuntu 8.04 LTS Server
Posts: 89

Original Poster
Rep: Reputation: 16
I am sorry that I have to return.

I used this short program to test how can I write to a fifo from bash.
Code:
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>

#define BFOUT 12

int main(void){
  int fdo, fdi, a;
  char *fifo1="fifo1", *fifo2="fifo2", *s, t[BFOUT];

  if((fdi = open(fifo2, O_RDONLY)) == -1) err_sys("client fifo2 open error");

  if(read(fdi, t, BFOUT) == -1) err_sys("client fifo2 read error");

  write(1, t, strlen(t)); // javascript arrays do not use "\0", so no need for + 1
  }

int err_sys(const char *s){
  printf("%s\n", s);
  exit(1);}
I do:
Code:
mkfifo fifo2;
./rdfifo&
echo abc$'\0' > fifo2
and again I get the special characters after abc. Can you please point me in the right direction as of why does this happen?

in man bash, search \\n and you will find that $'\0' is supposed to write a character with ASCII code 0 - the null character.

Still:
Code:
cat fifo2&
echo abc$'\0' > fifo2
works well.

Writing to fifo from C and reading from bash goes well, too.

I also wonder what happens to stdin and stdout of a process which was run in the background from bash, and then the bash was stopped. Such a process becomes a child of init, and I believe that its stdin and stdout are no more connected to any terminal.
 
Old 07-08-2010, 06:08 AM   #8
Wim Sturkenboom
Senior Member
 
Registered: Jan 2005
Location: Roodepoort, South Africa
Distribution: Slackware 10.1/10.2/12, Ubuntu 12.04, Crunchbang Statler
Posts: 3,786

Rep: Reputation: 282Reputation: 282Reputation: 282
My guess: strlen(t) will return 3, not 4, as it does not count the string terminator

Furher: when running something in the background from bash and killing bash will also kill the background application (as far as I know).
 
Old 07-09-2010, 05:56 AM   #9
doru
Member
 
Registered: Sep 2008
Distribution: Ubuntu 8.04 LTS Server
Posts: 89

Original Poster
Rep: Reputation: 16
Quote:
Originally Posted by Wim Sturkenboom View Post
My guess: strlen(t) will return 3, not 4, as it does not count the string terminator
This is irrelevant, as write will only print 3 characters to the terminal, without any garbage.

Quote:
Originally Posted by Wim Sturkenboom View Post
Furher: when running something in the background from bash and killing bash will also kill the background application (as far as I know).
My textbook says that any child process of a process that ends automatically becomes a child of init, and:
Code:
pstree | grep process
before and after you close the current terminal (in my case, putty) clearly show that this is the case.
 
Old 07-09-2010, 12:49 PM   #10
Wim Sturkenboom
Senior Member
 
Registered: Jan 2005
Location: Roodepoort, South Africa
Distribution: Slackware 10.1/10.2/12, Ubuntu 12.04, Crunchbang Statler
Posts: 3,786

Rep: Reputation: 282Reputation: 282Reputation: 282
You were right on both counts.
 
Old 07-10-2010, 06:18 AM   #11
doru
Member
 
Registered: Sep 2008
Distribution: Ubuntu 8.04 LTS Server
Posts: 89

Original Poster
Rep: Reputation: 16
Quote:
Originally Posted by Wim Sturkenboom View Post
You were right on both counts.
Please give me any idea of why
Code:
echo abc$'\0' > fifo2
does not print the right '\0'.
 
Old 07-20-2010, 05:39 AM   #12
doru
Member
 
Registered: Sep 2008
Distribution: Ubuntu 8.04 LTS Server
Posts: 89

Original Poster
Rep: Reputation: 16
Quote:
Originally Posted by doru View Post
Please give me any idea of why
Code:
echo abc$'\0' > fifo2
does not print the right '\0'.
I discovered that echo abc$'\0' > fifo does not really send $'\0' to the pipe. Probably bash thinks that this is silly, and it just does not send it. $'\0' is probably expanded in '\0', as it should, but then I don't see it in the pipe.

The solution is to use:
Code:
printf "abc\0" > fifo
printf is also a builtin and it works like a charm. I can see the '\0' character in the fifo.

Last edited by doru; 07-20-2010 at 05:42 AM.
 
  


Reply

Tags
characters, fifo


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Special Characters SimeonV Suse/Novell 14 07-07-2006 02:29 PM
Special characters in filenames gmartin Linux - General 2 01-05-2006 09:22 PM
special characters greenbox Linux - Software 9 12-23-2005 08:33 PM
Special characters consty Programming 3 08-07-2005 06:53 AM
using special characters one_ro Mandriva 5 11-04-2004 09:52 AM


All times are GMT -5. The time now is 07:14 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration