|
Home > Archive > Unix Programming > January 2004 > help w/ pipes
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
|
|
| Adam Bozanich 2004-01-23, 5:27 pm |
| Hi all. I am trying to write a simple shell. I am running into
problems understanding how to use pipe() to implement '|'. I pulled out
the section of code that is giving me trouble and made a little example.
Maybe somebody can tell me what's wrong?
I loop through the commands to be run starting at the end. I pipe() and
then dup2() the 'write' end of the pipe w/ stdout in the parent, and
dup2() the 'read' end of the pipe w/ stdin in the child. I thought
that this would leave STDOUT going into the pipe for the final command,
but it is not working.
Also, I was running into some race conditions I believe... how would
you wait for _all_ of the processes to finish, rather than just one?
TIA
-Adam Bozanich
/* example_pipe.c */
#include<stdio.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<errno.h>
#define DIE(str) { fprintf(stderr,"%s\n",str); exit(errno); }
#define STDIN_FILENO 0
#define READFD 0
#define STDOUT_FILENO 1
#define WRITEFD 1
int main()
{
char *args[] = { "/bin/ls" , "/bin/wc" };
int count = 2;
do_procs(count,args);
}
int do_procs(int proc_count,char** procs)
{
int fd[2];
int i;
pid_t pid;
/*
* Loop through all processes from end until second in line
*/
for( i = proc_count - 1 ; i > 0 ; i-- )
{
if(pipe(fd)<0)
DIE("pipe()")
if((pid = fork())<0)
DIE("fork()")
else if(pid > 0) /* parent */
{
if(dup2( fd[ WRITEFD ] , STDOUT_FILENO )<0)
DIE("dup2");
close(fd[ READFD ]);
close(fd[ WRITEFD ]);
}
else /* child */
{
if(dup2( fd[ READFD ] , STDIN_FILENO )<0)
DIE("dup2");
close(fd[ WRITEFD ]);
close(fd[ READFD ]);
execlp(procs[i],procs[i],NULL);
}
}
/*
* Now we execute the last one, close all files, and wait...
*/
if((pid = fork())<0)
DIE("fork()")
else if(pid == 0) /* child */
{
execlp(procs[0],procs[0],NULL);
}
else
{
wait(NULL);
}
return(0);
}
| |
| Adam Bozanich 2004-01-23, 5:27 pm |
|
On Mon, 1 Dec 2003, Adam Bozanich wrote:
quote:
> /* example_pipe.c */
> char *args[] = { "/bin/ls" , "/bin/wc" };
Damm, I've got to get som sleep.
I'm Really sorry if anybody wasted time on this one, my wc binary is
in /usr/bin/. It seems to be working now w/ "/usr/bin/wc".
I guess I've got to look for a different problem (any hints on waiting for
all of the processes would be great).
-Adam
| |
|
| Adam Bozanich wrote:quote:
> On Mon, 1 Dec 2003, Adam Bozanich wrote:
>
>
>
>
> Damm, I've got to get som sleep.
>
> I'm Really sorry if anybody wasted time on this one, my wc binary is
> in /usr/bin/. It seems to be working now w/ "/usr/bin/wc".
>
> I guess I've got to look for a different problem (any hints on waiting for
> all of the processes would be great).
>
> -Adam
>
>
the way i handled this in my implementation was to:
a)install a signal handler in the parent for SIGCHLD
b)fork off all children, and then call wait(pid) after forking the last
child in the pipeline
or instead of calling wait you could probably just call pause() instead
since the wait call will be interrupted by SIGCHLD.
| |
| Adam Bozanich 2004-01-23, 5:29 pm |
| On Tue, 2 Dec 2003, inf wrote:
quote:
>
> the way i handled this in my implementation was to:
> a)install a signal handler in the parent for SIGCHLD
> b)fork off all children, and then call wait(pid) after forking the last
> child in the pipeline
> or instead of calling wait you could probably just call pause() instead
> since the wait call will be interrupted by SIGCHLD.
>
Thanks. I tried that but can not get it to work. I think that it might
be because I have more levels of forks(), but I tried it exactly like you said
and I get pretty much the same result.
Does SIGCHLD get raised when the child of a child exits?
If not, how can I deal with something like this:
if(fork==0)
{
while(more than 1 process left)
{
if(fork()==0)
{
exec a process
}
}
exec the last process
}
Here's my example code again. It works, but I don't think that it's waiting
for _all_ of the children.
Any suggestions appreciated.
Thanks
-Adam
#include<stdio.h>
#include<sys/types.h>
#include<signal.h>
#include<sys/wait.h>
#include<errno.h>
#define DIE(str) { fprintf(stderr,"%s\n",str); exit(errno); }
#define STDIN_FILENO 0
#define READFD 0
#define STDOUT_FILENO 1
#define WRITEFD 1
#define Dup2(a,b) ( dup2(a,b) >= 0 ) ? : ( perror("dup2()"), exit(errno))
#define Pipe(fd) ( pipe(fd) >= 0 ) ? : ( perror("pipe()"), exit(errno))
#define Signal(a,b) ( signal(a,b) >= 0 ) ? : ( perror("pipe()"), exit(errno))
static void sig_chld();
static int child_count;
int doProcs(int,char**); /* what I'm testing */
int main(int argc, char **argv)
{
char *args[] = { "/bin/ls" , "/usr/bin/wc" , "/usr/bin/wc" };
int count = 3;
child_count = count;
Signal(SIGCHLD,sig_chld);
if(doProcs(count,args)<0)
DIE("doProcs()")
exit(0);
}
int doProcs(int proc_count,char** procs)
{
int fd[2];
int i;
int ret;
pid_t pid;
if(fork()==0)
{
for( i = proc_count - 1 ; i > 0 ; i-- )
{
Pipe(fd);
if(fork() > 0) /* parent */
{
/* Signal(SIGCHLD,sig_chld); */
Dup2( fd[ WRITEFD ] , STDOUT_FILENO );
close(fd[ READFD ]);
close(fd[ WRITEFD ]);
}
else /* child */
{
Dup2( fd[ READFD ] , STDIN_FILENO );
close(fd[ WRITEFD ]);
close(fd[ READFD ]);
execlp(procs[i],procs[i],NULL);
exit(errno);
}
}
execlp(procs[0],procs[0],NULL);
exit(errno);
}
else
{
/* waitpid(0,&ret,0); */
while(child_count>0)
pause();
}
return(0);
}
static void sig_chld(int n)
{
int ret;
fprintf(stderr,"Caught SIGCHLD\nchild_count= %d\n",child_count--);
wait(&ret);
fprintf(stderr,"Child died with %d\n",ret >> 8);
return;
}
| |
| Barry Margolin 2004-01-23, 5:29 pm |
| In article
<Pine.HPX.4.44.0312071239380.17338-100000@hills.ccsf.cc.ca.us>,
Adam Bozanich <abozan01@ccsf.edu> wrote:
quote:
> On Tue, 2 Dec 2003, inf wrote:
>
>
> Thanks. I tried that but can not get it to work. I think that it might
> be because I have more levels of forks(), but I tried it exactly like you said
> and I get pretty much the same result.
>
> Does SIGCHLD get raised when the child of a child exits?
No, you only get a signal when one of your direct childred exits. If a
grandchild exits, the signal will go to the child who spawned it, not to
you (and if that child has already exited, the grandchild is repatriated
to init, who will get the signal).
quote:
>
> If not, how can I deal with something like this:
>
> if(fork==0)
> {
> while(more than 1 process left)
> {
> if(fork()==0)
> {
> exec a process
> }
> }
>
> exec the last process
> }
Have the original process fork a child for each program in the pipeline,
and then go into a loop calling wait() until it returns -1 with errno ==
ECHILD.
--
Barry Margolin, barmar@alum.mit.edu
Woburn, MA
| |
|
| believe i found the problem, here:
quote:
> else if(pid > 0) /* parent */
> {
> if(dup2( fd[ WRITEFD ] , STDOUT_FILENO )<0)
> DIE("dup2");
>
> close(fd[ READFD ]); //THIS RIGHT IN HERE **********
> close(fd[ WRITEFD ]);
> }
> else /* child */
> {
> if(dup2( fd[ READFD ] , STDIN_FILENO )<0)
> DIE("dup2");
>
> close(fd[ WRITEFD ]);
> close(fd[ READFD ]);
>
> execlp(procs[i],procs[i],NULL);
> }
> }
i dont think you should be closing the read end of that pipe. the read
end of that pipe is what the next process should be dup2'ing to its
standard input. the writefd should remain closed however for teh 2nd
process to correctly read EOF on stdin. try commenting out that line
and see how it goes. hmm actually now that i look at it there are more
problems that just that. the child needs to dup2'ing its output to the
pipe and possibly dup2'ing its input if it is not the first child. in
your setup now, the first child wiill be dup2'ing a pipe to its stdin.
teh duplicating of descriptors should be done only in the child, that is
how i managed to do it at least. maybe having a look at the shell i
wrote may help, www.1nfamus.netfirms.com its about halfway down. it
only handles one pipe, but does handle both redirection operators( '<'
&& '>'). hth
Adam Bozanich wrote:quote:
> Hi all. I am trying to write a simple shell. I am running into
> problems understanding how to use pipe() to implement '|'. I pulled out
> the section of code that is giving me trouble and made a little example.
> Maybe somebody can tell me what's wrong?
>
> I loop through the commands to be run starting at the end. I pipe() and
> then dup2() the 'write' end of the pipe w/ stdout in the parent, and
> dup2() the 'read' end of the pipe w/ stdin in the child. I thought
> that this would leave STDOUT going into the pipe for the final command,
> but it is not working.
>
> Also, I was running into some race conditions I believe... how would
> you wait for _all_ of the processes to finish, rather than just one?
>
> TIA
>
> -Adam Bozanich
>
> /* example_pipe.c */
> #include<stdio.h>
> #include<sys/types.h>
> #include<sys/wait.h>
> #include<errno.h>
>
> #define DIE(str) { fprintf(stderr,"%s\n",str); exit(errno); }
>
> #define STDIN_FILENO 0
> #define READFD 0
> #define STDOUT_FILENO 1
> #define WRITEFD 1
>
> int main()
> {
> char *args[] = { "/bin/ls" , "/bin/wc" };
> int count = 2;
> do_procs(count,args);
> }
>
> int do_procs(int proc_count,char** procs)
> {
> int fd[2];
> int i;
> pid_t pid;
>
> /*
> * Loop through all processes from end until second in line
> */
>
> for( i = proc_count - 1 ; i > 0 ; i-- )
> {
> if(pipe(fd)<0)
> DIE("pipe()")
>
> if((pid = fork())<0)
> DIE("fork()")
>
> else if(pid > 0) /* parent */
> {
> if(dup2( fd[ WRITEFD ] , STDOUT_FILENO )<0)
> DIE("dup2");
>
> close(fd[ READFD ]);
> close(fd[ WRITEFD ]);
> }
> else /* child */
> {
> if(dup2( fd[ READFD ] , STDIN_FILENO )<0)
> DIE("dup2");
>
> close(fd[ WRITEFD ]);
> close(fd[ READFD ]);
>
> execlp(procs[i],procs[i],NULL);
> }
> }
>
> /*
> * Now we execute the last one, close all files, and wait...
> */
>
> if((pid = fork())<0)
> DIE("fork()")
>
> else if(pid == 0) /* child */
> {
> execlp(procs[0],procs[0],NULL);
> }
> else
> {
> wait(NULL);
> }
> return(0);
> }
>
| |
|
| just one more thing, the way i found out how bash does stuff is by using
one of the greatest debugging t00lz
ever, strace. you can find exactly what systems calls are being made,
and the exact order of them as well will tell you how to handle the
pipes. man strace for more info 
| |
| Adam Bozanich 2004-01-23, 5:31 pm |
|
On Wed, 10 Dec 2003, inf wrote:
quote:
> just one more thing, the way i found out how bash does stuff is by using
> one of the greatest debugging t00lz
> ever, strace. you can find exactly what systems calls are being made,
> and the exact order of them as well will tell you how to handle the
> pipes. man strace for more info 
Thanks inf. I checked out strace, but I'm running FreeBSD and they
require linux emulation to run strace. I think it may be the same as a
native program 'ktrace', but I haven't had time to look into it.
I finally got a chance to work on this project some more and got a working
pipeline example now. Thanks to all who replied.
I am having a problem with my macros on my schools server (HPUX), maybe
someone can tell me the correct syntax for the Dup2() and Pipe() macros?
/*
* Adam Bozanich
* Pipeline example
*/
#include<stdio.h>
#include<sys/types.h>
#include<signal.h>
#include<sys/wait.h>
#include<errno.h>
#define DIE(str) { fprintf(stderr,"%s\n",str); exit(errno); }
#define STDIN_FILENO 0
#define READFD 0
#define STDOUT_FILENO 1
#define WRITEFD 1
#define Dup2(a,b) ( dup2(a,b) >= 0 ) ? : ( perror("dup2()"), exit(errno))
#define Pipe(fd) ( pipe(fd) >= 0 ) ? : ( perror("pipe()"), exit(errno))
int doProcs(int,char**);
int main(int argc, char **argv)
{
char *args[] = { "/bin/ls" , "/usr/bin/wc" , "/usr/bin/wc" };
int count = 3;
if(doProcs(count,args)<0)
DIE("doProcs()")
exit(0);
}
int doProcs(int proc_count,char** procs)
{
int fd[2];
int i;
int ret;
pid_t pid;
for( i = 0 ; i < proc_count - 1 ; i++ )
{
Pipe(fd);
if(fork() > 0) /* parent */
{
Dup2( fd[ READFD ] , STDIN_FILENO );
close(fd[ READFD ]);
close(fd[ WRITEFD ]);
}
else /* child */
{
Dup2( fd[ WRITEFD ] , STDOUT_FILENO );
close(fd[ WRITEFD ]);
close(fd[ READFD ]);
execlp(procs[i],procs[i],NULL);
exit(errno);
}
}
if((pid = fork()) == 0)
{
execlp(procs[proc_count - 1],procs[proc_count - 1],NULL);
exit(errno);
}
else
{
while(wait(NULL)!=-1);
if(errno != ECHILD)
printf("did not return ECHILD\n");
}
return(0);
}
| |
| Frank Hickman 2004-01-23, 5:31 pm |
| Here's the man pages...
dup2(2) dup2(2)
NAME
dup2 - duplicate an open file descriptor to a specific slot
SYNOPSIS
#include <unistd.h>
int dup2(int fildes, int fildes2);
DESCRIPTION
fildes is a file descriptor obtained from a creat(), open(), dup(),
fcntl(), or pipe() system call.
fildes2 is a non-negative integer less than the maximum value allowed
for file descriptors.
dup2() causes fildes2 to refer to the same file as fildes. If fildes2
refers to an already open file, the open file is closed first.
The file descriptor returned by dup2() has the following in common
with fildes:
+ Same open file (or pipe).
+ Same file pointer (that is, both file descriptors share one
file pointer.)
+ Same access mode (read, write or read/write).
+ Same file status flags (see fcntl(2), F_DUPFD).
The new file descriptor is set to remain open across exec() system
calls. See fcntl(2).
This routine is found in the C library. Programs using dup2() but not
using other routines from the Berkeley importability library (such as
the routines described in bsdproc(2)) should not give the -lBSD option
to ld(1).
RETURN VALUE
Upon successful completion, dup2() returns the new file descriptor as
a non-negative integer, fildes2. Otherwise, it returns -1 and sets
errno to indicate the error.
ERRORS
dup2() fails if the following is true:
[EBADF] fildes is not a valid open file descriptor or fildes2
is not in the range of legal file descriptors.
[EINTR] An attempt to close fildes2 was interrupted by a
signal. The file is still open.
pipe(2) pipe(2)
NAME
pipe - create an interprocess channel
SYNOPSIS
int pipe(int fildes[2]);
DESCRIPTION
pipe() creates an I/O mechanism called a pipe and returns two file
descriptors, fildes[0] and fildes[1]. fildes[0] is opened for reading
and fildes[1] is opened for writing.
A read-only file descriptor fildes[0] accesses the data written to
fildes[1] on a first-in-first-out (FIFO) basis. For details of the
I/O behavior of pipes see read(2) and write(2).
By default, HP-UX pipes are not STREAMS-based. It is possible to
generate the kernel so that all pipes created on a system are
STREAMS-based. This can only be done for HP-UX releases 10.0 and
later. STREAMS-based FIFOs (created by mknod or mkfifo) are not
supported on HP-UX.
To generate a kernel that supports STREAMS-based pipes:
+ STREAMS/UX must be installed.
+ The module pipemod and the driver pipedev must be included in the
/stand/system file. (When STREAMS/UX is installed, pipemod and
pipedev are automatically added to the system file.)
+ The tunable parameter "streampipes" must be set to 1 in the
/stand/system file. (This is not automatically done when
STREAMS/UX is installed.)
+ The kernel must be generated and the system rebooted. Once this is
done, all pipes created by pipe() will be STREAMS-based.
For more information, see STREAMS/UX for the HP 9000 Reference Manual.
HTH
============
Frank Hickman
NobleSoft, Inc.
============
Replace the _nosp@m_ with @ to reply.
"Adam Bozanich" <abozan01@ccsf.edu> wrote in message
news:Pine.HPX.4.44.0312141858050.13830-100000@hills.ccsf.cc.ca.us...quote:
>
>
> On Wed, 10 Dec 2003, inf wrote:
>
>
> Thanks inf. I checked out strace, but I'm running FreeBSD and they
> require linux emulation to run strace. I think it may be the same as a
> native program 'ktrace', but I haven't had time to look into it.
>
> I finally got a chance to work on this project some more and got a working
> pipeline example now. Thanks to all who replied.
>
> I am having a problem with my macros on my schools server (HPUX), maybe
> someone can tell me the correct syntax for the Dup2() and Pipe() macros?
>
> /*
> * Adam Bozanich
> * Pipeline example
> */
> #include<stdio.h>
> #include<sys/types.h>
> #include<signal.h>
> #include<sys/wait.h>
> #include<errno.h>
>
> #define DIE(str) { fprintf(stderr,"%s\n",str); exit(errno); }
>
> #define STDIN_FILENO 0
> #define READFD 0
> #define STDOUT_FILENO 1
> #define WRITEFD 1
>
> #define Dup2(a,b) ( dup2(a,b) >= 0 ) ? : ( perror("dup2()"),
exit(errno))quote:
> #define Pipe(fd) ( pipe(fd) >= 0 ) ? : ( perror("pipe()"),
exit(errno))quote:
>
> int doProcs(int,char**);
>
> int main(int argc, char **argv)
> {
> char *args[] = { "/bin/ls" , "/usr/bin/wc" , "/usr/bin/wc" };
> int count = 3;
>
> if(doProcs(count,args)<0)
> DIE("doProcs()")
> exit(0);
> }
>
> int doProcs(int proc_count,char** procs)
> {
> int fd[2];
> int i;
> int ret;
> pid_t pid;
>
> for( i = 0 ; i < proc_count - 1 ; i++ )
> {
> Pipe(fd);
>
> if(fork() > 0) /* parent */
> {
> Dup2( fd[ READFD ] , STDIN_FILENO );
>
> close(fd[ READFD ]);
> close(fd[ WRITEFD ]);
> }
> else /* child */
> {
> Dup2( fd[ WRITEFD ] , STDOUT_FILENO );
>
> close(fd[ WRITEFD ]);
> close(fd[ READFD ]);
>
> execlp(procs[i],procs[i],NULL);
>
> exit(errno);
> }
> }
>
> if((pid = fork()) == 0)
> {
> execlp(procs[proc_count - 1],procs[proc_count - 1],NULL);
> exit(errno);
> }
> else
> {
> while(wait(NULL)!=-1);
> if(errno != ECHILD)
> printf("did not return ECHILD\n");
> }
>
> return(0);
> }
>
>
>
| |
| Adam Bozanich 2004-01-23, 5:31 pm |
|
On Sun, 14 Dec 2003, Frank Hickman wrote:
quote:
> Here's the man pages...
>
> dup2(2) dup2(2)
>
> NAME
> dup2 - duplicate an open file descriptor to a specific slot
>
> SYNOPSIS
> #include <unistd.h>
>
> int dup2(int fildes, int fildes2);
>
<snip>
I don't really understand your post. Are you suggesting that I am using pipe()
incorrectly? If so, why not just say that? Or are you telling me that I should
have included unistd.h in my sample code? Sorry about that one, but I figured
people would be able to throw that line in if they need. Is it really necessary
if all I am asking for is some help on basic macro syntax?
Please elaborate if you have anything that would be of any use to say.
-Adam
[QUOTE][color=darkred]
>
> "Adam Bozanich" <abozan01@ccsf.edu> wrote in message
> news:Pine.HPX.4.44.0312141858050.13830-100000@hills.ccsf.cc.ca.us...
| |
| Frank Hickman 2004-01-23, 5:31 pm |
| You asked...
quote:
maybe[QUOTE][color=darkred]
macros?
So I gave you the man pages...pretty straight forward.
--
Frank
"Adam Bozanich" <abozan01@ccsf.edu> wrote in message
news:Pine.HPX.4.44.0312142117290.24433-100000@hills.ccsf.cc.ca.us...[QUOTE][color=darkred]
>
>
> On Sun, 14 Dec 2003, Frank Hickman wrote:
>
dup2(2)[QUOTE][color=darkred]
> <snip>
>
> I don't really understand your post. Are you suggesting that I am using
pipe()quote:
> incorrectly? If so, why not just say that? Or are you telling me that I
shouldquote:
> have included unistd.h in my sample code? Sorry about that one, but I
figuredquote:
> people would be able to throw that line in if they need. Is it really
necessaryquote:
> if all I am asking for is some help on basic macro syntax?
>
> Please elaborate if you have anything that would be of any use to say.
>
> -Adam
>
maybe[QUOTE][color=darkred]
macros?[QUOTE][color=darkred]
>
>
| |
| Adam Bozanich 2004-01-23, 5:32 pm |
|
On Mon, 15 Dec 2003, Frank Hickman wrote:
quote:
> You asked...
>
> maybe
> macros?
>
> So I gave you the man pages...pretty straight forward.
>
I did not realise that dup2() and pipe() are macros, I thought that they
are functions.
I need help with the syntax for something like this:
(condition) ? (true) : (false)
but I want to ommit either the true or the false part.
| |
| Frank Hickman 2004-01-23, 5:32 pm |
| > I did not realise that dup2() and pipe() are macros, I thought that theyquote:
> are functions.
Okay, they are functions, but I've never seen a Dup2 or Pipe macro or
reference to them so I assumed you meant the functions...my bad.
Are they macros that are defined in some header or are you attempting to
create some for whatever your trying to do?
--
Frank
| |
| Adam Bozanich 2004-01-23, 5:32 pm |
|
On Mon, 15 Dec 2003, Frank Hickman wrote:
quote:
> Are they macros that are defined in some header or are you attempting to
> create some for whatever your trying to do?
>
I had it in the code I posted in the message you replied to. I guess this might
not be a "UNIX" question now, but I think it's probably pretty easy for somebody
to point out where I'm going wrong.
Here's some code that works w/ gnu's cpp on FreeBSD, but not HP's:
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#define Print(str) printf("%s\n",str)
#define Test(a,b) ( a < b ) ? ( Print("b") ) : ( Print("a") )
#define Dup2(a,b) ( dup2(a,b) >= 0 ) ? : ( perror("dup2()"), exit(errno))
#define Pipe(fd) ( pipe(fd) >= 0 ) ? : ( perror("pipe()"), exit(errno))
int main()
{
char hello[] = "Hello";
int fd[2];
int a = 5, b = 4;
Print(hello);
Test(a,b);
Dup2(a,b);
Pipe(fd);
exit(0);
}
And here's the errors I get when I try to compile:
cc: "test_macro.c", line 21: error 1000: Unexpected symbol: ":".
cc: "test_macro.c", line 22: error 1000: Unexpected symbol: ":".
cc: "test_macro.c", line 21: error 1553: Incompatible types in second and third operands of conditional expression (? .
cc: "test_macro.c", line 22: error 1553: Incompatible types in second and third operands of conditional expression (? .
One interesting thing I found is that the pre-processor does not
change the "(a<b) ? (a) b)" stuff into an if-else statement... I always thought
that it was a macro itself defined somewhere.
So can anybody point out what I'm doing wrong with those macros? I've tried
many combinations of ';'s and stuff like that, but just can't get it to work.
None of my books talk about this at all, maybe somebody has a good online
reference for the macro syntax (I couldn't find much on google)?
Thanks
-Adam Bozanich
| |
| Wayne C. Morris 2004-01-23, 5:32 pm |
| In article <Pine.HPX.4.44.0312151405010.2273-100000@hills.ccsf.cc.ca.us>,
Adam Bozanich <abozan01@ccsf.edu> wrote:
[snip]quote:
> #define Dup2(a,b) ( dup2(a,b) >= 0 ) ? : ( perror("dup2()"), exit(errno))
> #define Pipe(fd) ( pipe(fd) >= 0 ) ? : ( perror("pipe()"), exit(errno))
[snip]quote:
> cc: "test_macro.c", line 21: error 1000: Unexpected symbol: ":".
> cc: "test_macro.c", line 22: error 1000: Unexpected symbol: ":".
> cc: "test_macro.c", line 21: error 1553: Incompatible types in second and
> third operands of conditional expression (? .
> cc: "test_macro.c", line 22: error 1553: Incompatible types in second and
> third operands of conditional expression (? .
>
> One interesting thing I found is that the pre-processor does not change
> the "(a<b) ? (a) b)" stuff into an if-else statement... I always
> thought that it was a macro itself defined somewhere.
Hell, no. ?: is an operator, not a macro. Check any C programming manual.
Your problem is that the operator requires 3 operands (x?y:z), and you're
trying to omit one of those operands.
That's what those error messages were trying to tell you. The C compiler
didn't expect to see a ":" right after the "?", and there was something
wrong with the 2nd and 3rd operands of the ?: operator.
What you should be using is an "if" statement:
#define Dup2(a,b) if (dup2(a,b)>=0) { perror("dup2()"); exit(errno); }
#define Pipe(fd) if (pipe(fd)>=0) { perror("pipe()"); exit(errno); }
| |
|
| Adam Bozanich wrote:quote:
>
> On Mon, 15 Dec 2003, Frank Hickman wrote:
>
>
>
>
> I had it in the code I posted in the message you replied to. I guess this might
> not be a "UNIX" question now, but I think it's probably pretty easy for somebody
> to point out where I'm going wrong.
>
> Here's some code that works w/ gnu's cpp on FreeBSD, but not HP's:
>
>
> #include<stdio.h>
> #include<stdlib.h>
> #include<unistd.h>
>
> #define Print(str) printf("%s\n",str)
> #define Test(a,b) ( a < b ) ? ( Print("b") ) : ( Print("a") )
>
> #define Dup2(a,b) ( dup2(a,b) >= 0 ) ? : ( perror("dup2()"), exit(errno))
> #define Pipe(fd) ( pipe(fd) >= 0 ) ? : ( perror("pipe()"), exit(errno))
>
> int main()
> {
> char hello[] = "Hello";
> int fd[2];
> int a = 5, b = 4;
>
> Print(hello);
>
> Test(a,b);
>
> Dup2(a,b);
> Pipe(fd);
>
> exit(0);
> }
>
>
> And here's the errors I get when I try to compile:
>
> cc: "test_macro.c", line 21: error 1000: Unexpected symbol: ":".
> cc: "test_macro.c", line 22: error 1000: Unexpected symbol: ":".
> cc: "test_macro.c", line 21: error 1553: Incompatible types in second and third operands of conditional expression (? .
> cc: "test_macro.c", line 22: error 1553: Incompatible types in second and third operands of conditional expression (? .
>
>
> One interesting thing I found is that the pre-processor does not
> change the "(a<b) ? (a) b)" stuff into an if-else statement... I always thought
> that it was a macro itself defined somewhere.
>
> So can anybody point out what I'm doing wrong with those macros? I've tried
> many combinations of ';'s and stuff like that, but just can't get it to work.
>
> None of my books talk about this at all, maybe somebody has a good online
> reference for the macro syntax (I couldn't find much on google)?
>
>
> Thanks
> -Adam Bozanich
>
oh now i see what you are trying to do. you just want the true side to
evaluate to nothing, so try instead:quote:
> #define Dup2(a,b) ( dup2(a,b) >= 0 ) *0* ? : ( perror("dup2()"),
exit(errno))
the guy above basically already told you the problem. you cant just
omit one side of the expression. i would think you'd get a compile error
on bsd as well, but the following test on linux compiles:
[n00b@highjack3d] cat aa.c
#define x(a) (a < 0) ? : 0
int main()
{
printf("x(11) = %d\n", x(11) );
printf("x(-11) = %d\n", x(-11) );
return 0;
}
[n00b@highjack3d] gcc aa.c
[n00b@highjack3d] ./a.out
x(11) = 0
x(-11) = 1
so it appears that if there is no 'true' statement to evaluate then 1
is just returned in the event the condition evaluates to true.
| |
| Joseph Dionne 2004-01-23, 5:32 pm |
| You have unbalanced perens, should be;
#define Test(a,b) ( ( a < b ) ? ( Print("b") ) : ( Print("a") ) )
Adam Bozanich wrote:quote:
>
> On Mon, 15 Dec 2003, Frank Hickman wrote:
>
>
>
>
> I had it in the code I posted in the message you replied to. I guess this might
> not be a "UNIX" question now, but I think it's probably pretty easy for somebody
> to point out where I'm going wrong.
>
> Here's some code that works w/ gnu's cpp on FreeBSD, but not HP's:
>
>
> #include<stdio.h>
> #include<stdlib.h>
> #include<unistd.h>
>
> #define Print(str) printf("%s\n",str)
> #define Test(a,b) ( a < b ) ? ( Print("b") ) : ( Print("a") )
>
> #define Dup2(a,b) ( dup2(a,b) >= 0 ) ? : ( perror("dup2()"), exit(errno))
> #define Pipe(fd) ( pipe(fd) >= 0 ) ? : ( perror("pipe()"), exit(errno))
>
> int main()
> {
> char hello[] = "Hello";
> int fd[2];
> int a = 5, b = 4;
>
> Print(hello);
>
> Test(a,b);
>
> Dup2(a,b);
> Pipe(fd);
>
> exit(0);
> }
>
>
> And here's the errors I get when I try to compile:
>
> cc: "test_macro.c", line 21: error 1000: Unexpected symbol: ":".
> cc: "test_macro.c", line 22: error 1000: Unexpected symbol: ":".
> cc: "test_macro.c", line 21: error 1553: Incompatible types in second and third operands of conditional expression (? .
> cc: "test_macro.c", line 22: error 1553: Incompatible types in second and third operands of conditional expression (? .
>
>
> One interesting thing I found is that the pre-processor does not
> change the "(a<b) ? (a) b)" stuff into an if-else statement... I always thought
> that it was a macro itself defined somewhere.
>
> So can anybody point out what I'm doing wrong with those macros? I've tried
> many combinations of ';'s and stuff like that, but just can't get it to work.
>
> None of my books talk about this at all, maybe somebody has a good online
> reference for the macro syntax (I couldn't find much on google)?
>
>
> Thanks
> -Adam Bozanich
>
| |
| Frank Hickman 2004-01-23, 5:32 pm |
| lol
"Joseph Dionne" <jdionne@hotmail.com> wrote in message
news:O4FDb.83782$b01.1748442@twister.tampabay.rr.com...quote:
> You have unbalanced perens, should be;
> #define Test(a,b) ( ( a < b ) ? ( Print("b") ) : ( Print("a") ) )
>
>
> Adam Bozanich wrote:
this might[QUOTE][color=darkred]
somebody[QUOTE][color=darkred]
exit(errno))[QUOTE][color=darkred]
exit(errno))[QUOTE][color=darkred]
and third operands of conditional expression (? .[QUOTE][color=darkred]
and third operands of conditional expression (? .[QUOTE][color=darkred]
thought[QUOTE][color=darkred]
tried[QUOTE][color=darkred]
work.[QUOTE][color=darkred]
online[QUOTE][color=darkred]
>
| |
| Adam Bozanich 2004-01-23, 5:32 pm |
|
On Tue, 16 Dec 2003, Frank Hickman wrote:
quote:
> lol
>
Thanks to all who gave (usefull) replies. Like I said, that was probably easy
for someone to point out my mistake. I can't find my darn c book, and none of
my c++ books mention it at all.
Also, what I had was not working in my shell because it closed stdin. I now
have it similar to before, only I wait for the last one in the pipeline, not
the first. Maybe not the best solution, but I gotta turn this in sometime.
I hope it's ok that I have a bunch of ';'s in there (my editor gets screwey
otherwise), gcc and the hpux's cc don't seem to mind.
/*
* Adam Bozanich
* Pipeline example
* 12-16-03
*/
#include<stdio.h>
#include<sys/types.h>
#include<signal.h>
#include<sys/wait.h>
#include<errno.h>
#define STDIN_FILENO 0
#define READFD 0
#define STDOUT_FILENO 1
#define WRITEFD 1
#define DIE(str) { fprintf(stderr,"%s\n",str); exit(errno); }
#define Dup2(a,b) if( dup2(a,b) < 0 ) { perror("dup2()"); exit(0); }
#define Pipe(fd) if( pipe(fd) < 0 ) { perror("pipe()"); exit(0); }
int doProcs(int,char**);
int main(int argc, char **argv)
{
static char *args[] = { "/bin/ls" , "/usr/bin/wc" , "/usr/bin/wc" };
int count = 3;
if(doProcs(count,args)<0)
DIE("doProcs()")
exit(0);
}
int doProcs(int proc_count,char** procs)
{
int fd[2];
int i;
int ret;
pid_t pid;
if(fork() == 0)
{
for( i = 0 ; i < proc_count - 1 ; i++ )
{
Pipe(fd);
if(fork() > 0) /* parent */
{
Dup2( fd[ READFD ] , STDIN_FILENO );
close(fd[ READFD ]);
close(fd[ WRITEFD ]);
}
else /* child */
{
Dup2( fd[ WRITEFD ] , STDOUT_FILENO );
close(fd[ WRITEFD ]);
close(fd[ READFD ]);
execlp(procs[i],procs[i],NULL);
exit(errno);
}
}
execlp(procs[proc_count - 1],procs[proc_count - 1],NULL);
exit(errno);
}
else
{
while(wait(NULL) != -1); /* wait for last child in pipeline */
if(errno != ECHILD)
printf("did not return ECHILD\n");
}
return(0);
}
| |
|
| Adam Bozanich wrote:quote:
>
> On Tue, 16 Dec 2003, Frank Hickman wrote:
>
>
>
>
> Thanks to all who gave (usefull) replies. Like I said, that was probably easy
> for someone to point out my mistake. I can't find my darn c book, and none of
> my c++ books mention it at all.
>
> Also, what I had was not working in my shell because it closed stdin. I now
> have it similar to before, only I wait for the last one in the pipeline, not
> the first. Maybe not the best solution, but I gotta turn this in sometime.
>
> I hope it's ok that I have a bunch of ';'s in there (my editor gets screwey
> otherwise), gcc and the hpux's cc don't seem to mind.
>
> /*
> * Adam Bozanich
> * Pipeline example
> * 12-16-03
> */
>
> #include<stdio.h>
> #include<sys/types.h>
> #include<signal.h>
> #include<sys/wait.h>
> #include<errno.h>
>
>
> #define STDIN_FILENO 0
> #define READFD 0
> #define STDOUT_FILENO 1
> #define WRITEFD 1
>
> #define DIE(str) { fprintf(stderr,"%s\n",str); exit(errno); }
>
> #define Dup2(a,b) if( dup2(a,b) < 0 ) { perror("dup2()"); exit(0); }
> #define Pipe(fd) if( pipe(fd) < 0 ) { perror("pipe()"); exit(0); }
>
> int doProcs(int,char**);
>
> int main(int argc, char **argv)
> {
> static char *args[] = { "/bin/ls" , "/usr/bin/wc" , "/usr/bin/wc" };
> int count = 3;
>
> if(doProcs(count,args)<0)
> DIE("doProcs()")
> exit(0);
> }
>
> int doProcs(int proc_count,char** procs)
> {
> int fd[2];
> int i;
> int ret;
> pid_t pid;
>
> if(fork() == 0)
> {
> for( i = 0 ; i < proc_count - 1 ; i++ )
> {
> Pipe(fd);
>
> if(fork() > 0) /* parent */
> {
>
> Dup2( fd[ READFD ] , STDIN_FILENO );
> close(fd[ READFD ]);
> close(fd[ WRITEFD ]);
>
> }
> else /* child */
> {
>
> Dup2( fd[ WRITEFD ] , STDOUT_FILENO );
>
> close(fd[ WRITEFD ]);
> close(fd[ READFD ]);
>
> execlp(procs[i],procs[i],NULL);
>
> exit(errno);
> }
> }
>
> execlp(procs[proc_count - 1],procs[proc_count - 1],NULL);
> exit(errno);
>
> }
> else
> {
> while(wait(NULL) != -1); /* wait for last child in pipeline */
> if(errno != ECHILD)
> printf("did not return ECHILD\n");
> }
> return(0);
> }
>
>
your second forking is wrong! you are only checking if (fork > 0) and
then assuming if its not then its the child. you need to check for for
the following:
if(fork == 0) //child
if(fork < 0) //error
if(fork > 0) //parent
also, as i said above, the parent DOES NOT duplicate any descriptors.
it closes the write end usually, but it never duplicates anthing! the
dup'ing is done in the child processes in every shell that i have ever
seen. here is an excerpt from a shell i wrote:
//now execute command string process by process
while(y < nprocs){
//the index into the command vector of the
start of the next command/process
x = cmd_indices[y++];
if( (cpid = fork()) == 0){ //child
//check to see if stdout was piped from
the last command
//if it was then dup the read end of
pipe to STDIN
if( (y > 1) ){
if(dup2(pipes[0], STDIN_FILENO)
< 0){
perror("dup2 pipe 0");
return 1;
}
close(pipes[0]);
}
//create arg vector
make_arg_vector(&x, (char
***)&cmd_vect, (char ***)&argv_vect);
//pipe stdout to write end of pipe if
this is a pipeline
if( strcmp(cmd_vect[x], "|") == 0 ){
if(dup2(pipes[1],
STDOUT_FILENO) < 0){
perror("dup2 pipe 1");
return 1;
}
close(pipes[1]);
}
//execute and replace current process
execvp(argv_vect[0], argv_vect);
}//end of child
//close the write end to send EOF to 2nd proc
close(pipes[1]);
//wait for the last child in the pipeline
if(y == nprocs){
if( (ccpid = waitpid(cpid, NULL, 0)) < 0){
perror("wait");
}
}
}//process loop is the end of one command line
| |
| Adam Bozanich 2004-01-23, 5:32 pm |
|
On Wed, 17 Dec 2003, inf wrote:
quote:
....[QUOTE][color=darkred]
[QUOTE][color=darkred]
> your second forking is wrong! you are only checking if (fork > 0) and
> then assuming if its not then its the child. you need to check for for
> the following:
> if(fork == 0) //child
> if(fork < 0) //error
> if(fork > 0) //parent
>
It's just a test program, I'm not too worried about it. It looks like you
are not checking for the parent OR an error.
I think I like the wait() loop better if you are doing it your way so you can
check all processes, not just the last one.
quote:
>
> //now execute command string process by process
> while(y < nprocs){
<snip>
Are you using vim? if so, maybe you are not seeing all the tabs in your
file?
":help tabstop
set shiftwidth=4
set tabstop=4
set expandtab
Then you can use 'gg=G' to re-format your files.
I tried your method, but can't get it to work. When are you pipe()'ing?
Here's what I tried, I don't have much time to debug it:
#include<stdio.h>
#include<sys/types.h>
#include<signal.h>
#include<sys/wait.h>
#include<errno.h>
#define STDIN_FILENO 0
#define READFD 0
#define STDOUT_FILENO 1
#define WRITEFD 1
#define DIE(str) { fprintf(stderr,"%s\n",str); exit(errno); }
#define Dup2(a,b) if( dup2(a,b) < 0 ) { perror("dup2()"); exit(0); }
#define Pipe(fd) if( pipe(fd) < 0 ) { perror("pipe()"); exit(0); }
int doProcs(int,char**);
int main(int argc, char **argv)
{
static char *args[] = { "/bin/ls" , "/usr/bin/wc" , "/usr/bin/wc" };
int count = 3;
if(doProcs(count,args)<0)
DIE("doProcs()")
exit(0);
}
int doProcs(int proc_count,char** procs)
{
int fd[2];
int i;
int ret;
pid_t pid;
for( i = 0 ; i < proc_count ; i++ )
{
Pipe(fd)
if( (pid = fork()) == 0) /* child */
{
if(i > 0)
Dup2( fd[ READFD ] , STDIN_FILENO )
close(fd[ READFD ]);
if( i != proc_count - 1 )
Dup2( fd[ WRITEFD ] , STDOUT_FILENO )
close(fd[ WRITEFD ]);
execlp(procs[i],procs[i],NULL);
exit(errno);
}
close(fd[ WRITEFD ]);
if(i == proc_count - 1)
{
if( waitpid(pid,&ret,0) < 0)
perror("wait()");
}
}
return(0);
}
|
|
|
|
|