|
Home > Archive > Unix Programming > April 2004 > Question about popen
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]
| Author |
Question about popen
|
|
| Madhusudan Singh 2004-04-21, 4:34 pm |
| Hi
I am trying to create a POSIX library for a language other than C by
calling the C routines in a wrapper routine.
I think I have run up against a problem with popen.
A fragment of the code :
errno=0;
cmdpipe=popen(command,type);
if(cmdpipe==NULL)
{
perror("Failed : popen in posixwrapper:popen");
exit(1);
}
perror("popen");
printf("%d %s\n",errno,strerror(errno));
Now, when I test this, I get :
popen: Success
29 Illegal seek
man popen yields :
NAME
popen, pclose - process I/O
SYNOPSIS
#include <stdio.h>
FILE *popen(const char *command, const char *type);
int pclose(FILE *stream);
The argument needs to be a const char * and I am passing char *.
Questions :
1. Why does perror return "Success" ?
2. Is the error condition 29 (Illegal seek) caused by my not using the const
char* ?
Questions 3, 4 and 5 apply only if you answered 2 in affirmative.
3. If so, can I declare a const char * inside the routine with the fragment
above and set it to the input value of command ? (I am not very savvy with
C syntax, having had done no C programming for almost 7-8 years, but this
kind of thing is usually illegal in many other programming languages.).
4. Since the code is (obviously) going to run on Linux, can the above effect
be achieved somehow by setting the value of some export'ed variable ?
5. Any other suggestions ?
Thanks,
MS
| |
| Rich Teer 2004-04-21, 4:34 pm |
| On Wed, 21 Apr 2004, Madhusudan Singh wrote:
> A fragment of the code :
>
> errno=0;
> cmdpipe=popen(command,type);
> if(cmdpipe==NULL)
> {
> perror("Failed : popen in posixwrapper:popen");
> exit(1);
> }
Urgh! Super ugly FSF coding style.
> perror("popen");
> printf("%d %s\n",errno,strerror(errno));
>
> Now, when I test this, I get :
>
> popen: Success
> 29 Illegal seek
You're calling perror(), even if no error is returned, so you
are getting garbage. Library functions are not required to set
errno to 0 if there isn't an error.
> 1. Why does perror return "Success" ?
Presumably because is was successful.
> 2. Is the error condition 29 (Illegal seek) caused by my not using the const
> char* ?
No; see above.
> 4. Since the code is (obviously) going to run on Linux, can the above effect
Nothing obvious about that at all; this IS comp.unix.programmer,
not comp.linux.programmer, after all.
> 5. Any other suggestions ?
Call popen onli in the event of an error. And
don't use FSF coding style, of GPL type licenses!
--
Rich Teer, SCNA, SCSA
President,
Rite Online Inc.
Voice: +1 (250) 979-1638
URL: http://www.rite-online.net
| |
| Dragan Cvetkovic 2004-04-21, 4:34 pm |
| Rich Teer <rich.teer@rite-group.com> writes:
> Call popen onli in the event of an error.
s/open/error/
(other typo ignored).
Bye, Dragan
--
Dragan Cvetkovic,
To be or not to be is true. G. Boole No it isn't. L. E. J. Brouwer
!!! Sender/From address is bogus. Use reply-to one !!!
| |
| Madhusudan Singh 2004-04-21, 5:34 pm |
| On Wednesday 21 April 2004 16:38, Rich Teer (rich.teer@rite-group.com) held
forth in comp.unix.programmer
(<Pine.SOL.4.58.0404211334380.27166@zaphod.rite-group.com> ):
> On Wed, 21 Apr 2004, Madhusudan Singh wrote:
>
>
> Urgh! Super ugly FSF coding style.
>
Ugly as C coding usually is, I do not see how the above is any more ugly
than other stuff in C.
Maybe if((cmdpipe=popen(command,type))==NULL) is a little more compact.
But lets pass over that.
>
> You're calling perror(), even if no error is returned, so you
> are getting garbage. Library functions are not required to set
> errno to 0 if there isn't an error.
*I* had set errno=0 just prior to invoking popen (see the first line of the
code fragment). Would it not stand to reason that it changed from 0 to 29
because popen changed it ?
>
>
> Presumably because is was successful.
Does not seem to be the case. When I try to fflush the pipe after an fputs,
I get an illegal seek. Maybe I need to set errno=0 before each of those
invocations to see if this is merely a matter of flawed error detection.
>
>
> No; see above.
I surely hope that you are right !!
But why the admonition to use a const char* and then allow the use of char*
like this ?
>
>
> Nothing obvious about that at all; this IS comp.unix.programmer,
> not comp.linux.programmer, after all.
I apologize.
>
>
> Call popen onli in the event of an error. And
> don't use FSF coding style, of GPL type licenses!
>
Well, I intend to release the code under LGPL, but I am open to suggestions
regarding the aesthetics. Not that I find any C code itself to be a
particularly "beautiful" thing 
| |
| DeMarcus 2004-04-21, 5:34 pm |
|
Madhusudan Singh wrote:
> Hi
> I am trying to create a POSIX library for a language other than C by
> calling the C routines in a wrapper routine.
>
I met some strange errno problems when making a multithreaded plugin for
Tcl/Tk a long time ago. I think they've fix it now though.
> I think I have run up against a problem with popen.
>
> A fragment of the code :
>
> errno=0;
> cmdpipe=popen(command,type);
> if(cmdpipe==NULL)
> {
> perror("Failed : popen in posixwrapper:popen");
> exit(1);
> }
>
> perror("popen");
> printf("%d %s\n",errno,strerror(errno));
>
> Now, when I test this, I get :
>
> popen: Success
> 29 Illegal seek
>
I would concider using oserror() instead. Like this:
fprintf( stderr, "%d %s\n", oserror(), strerror( oserror() ) );
> man popen yields :
>
> NAME
> popen, pclose - process I/O
>
> SYNOPSIS
> #include <stdio.h>
>
> FILE *popen(const char *command, const char *type);
>
> int pclose(FILE *stream);
>
> The argument needs to be a const char * and I am passing char *.
>
> Questions :
>
> 1. Why does perror return "Success" ?
>
> 2. Is the error condition 29 (Illegal seek) caused by my not using the const
> char* ?
>
> Questions 3, 4 and 5 apply only if you answered 2 in affirmative.
>
> 3. If so, can I declare a const char * inside the routine with the fragment
> above and set it to the input value of command ? (I am not very savvy with
> C syntax, having had done no C programming for almost 7-8 years, but this
> kind of thing is usually illegal in many other programming languages.).
>
> 4. Since the code is (obviously) going to run on Linux, can the above effect
> be achieved somehow by setting the value of some export'ed variable ?
>
> 5. Any other suggestions ?
>
> Thanks,
>
> MS
| |
| Eric Sosman 2004-04-21, 5:34 pm |
| Madhusudan Singh wrote:
> [...]
> Does not seem to be the case. When I try to fflush the pipe after an fputs,
> I get an illegal seek. Maybe I need to set errno=0 before each of those
> invocations to see if this is merely a matter of flawed error detection.
It might be. This is wrong:
errno = 0;
fputs ("hello\n", fp);
fflush (fp);
if (errno != 0) {
perror ("There may or may not be an error");
...
because a library function can change `errno' even if there
is no failure. This is better:
if (fputs("hello", fp) == EOF || fflush(fp) == EOF) {
perror ("There really was an error");
...
That is, fputs() and fflush() tell you whether a failure has
occurred. `errno' provides additional information about the
failure, *if* something actually went wrong -- but `errno'
itself doesn't tell you whether there was a failure.
Sometimes it is more convenient to gather all the error
tests together:
fputs ("hello\n", fp);
fputs ("world\n", fp);
fprintf (fp, "The answer is %d\n", 052);
fflush (fp);
if (ferror(fp)) {
perror ("There was an error");
...
By the way, this is also wrong:
if (fputs("hello\n", fp) == EOF) {
pclose (fp);
perror ("There was an error");
...
because the pclose() might change `errno' before perror()
has a chance to interpret it. Either do your cleanup after
calling perror(), or save and restore `errno':
if (...) {
int errno_save = errno;
lots_of_cleanup();
errno = errno_save;
perror ("There was an error");
...
--
Eric.Sosman@sun.com
| |
| joe@invalid.address 2004-04-21, 5:34 pm |
| Rich Teer <rich.teer@rite-group.com> writes:
> On Wed, 21 Apr 2004, Madhusudan Singh wrote:
>
> You're calling perror(), even if no error is returned, so you
> are getting garbage. Library functions are not required to set
> errno to 0 if there isn't an error.
But why would perror() change it? If the perror() call says errno is
0, why would a subsequent call to strerror() say something else? He
did set errno to 0 before calling popen() after all.
Joe
--
If people don't want to come out to the ballpark, nobody's going
to stop them.
- Yogi Berra
| |
| Eric Sosman 2004-04-21, 6:36 pm |
| joe@invalid.address wrote:
>
> Rich Teer <rich.teer@rite-group.com> writes:
>
>
>
> But why would perror() change it?
perror() must generate output on stderr. To do so,
it most likely calls other functions, directly or indirectly.
The obvious perror() implementation calls fprintf(), and
fprintf() will in turn call a whole bunch of other things.
Any of these might change errno, even if there's no "failure."
There's a concrete example of this in Question 12.24 of the
comp.lang.c Frequently Asked Questions list
http://www.eskimo.com/~scs/C-faq/top.html
> If the perror() call says errno is
> 0, why would a subsequent call to strerror() say something else?
Because the value has been changed. errno can hold only
one value at a time (multithreaded programs have multiple
errno's, but each has only one value at a time), so if the
perror() causes errno to change, its old value is forgotten.
> He
> did set errno to 0 before calling popen() after all.
Yep. And errno was zero when the program began execution
in main(). But that was a long time ago, and things have
been happening.
--
Eric.Sosman@sun.com
| |
| Brian Raiter 2004-04-21, 7:36 pm |
| >> You're calling perror(), even if no error is returned, so you
>
> *I* had set errno=0 just prior to invoking popen (see the first line
> of the code fragment). Would it not stand to reason that it changed
> from 0 to 29 because popen changed it ?
Doesn't matter. ANSI/ISO/POSIX are very clear that the value of errno
is unreliable UNLESS you have just called a library function whose
return value indicated an error took place. If no error has taken
place, library functions are explicitly permitted to fiddle with
errno's value as much as they please.
b
| |
| Martien Verbruggen 2004-04-21, 7:36 pm |
| On Wed, 21 Apr 2004 23:07:09 +0200,
DeMarcus <nobody@tellus.orb> wrote:
>
>
> Madhusudan Singh wrote:
[vbcol=seagreen]
> I would concider using oserror() instead. Like this:
> fprintf( stderr, "%d %s\n", oserror(), strerror( oserror() ) );
Why?
What do you believe the advantage to be?
I'd say it is less preferable, because it's less portable. It's not,
for example, available on the GNU/Linux or Solaris systems I have just
checked it on. No man page, and no header entries (except in the
sybase header files, but that doesn't count).
Martien
--
|
Martien Verbruggen |
Trading Post Australia | 42.6% of statistics is made up on the spot.
|
| |
| Jem Berkes 2004-04-21, 9:34 pm |
| > Questions :
>
> 1. Why does perror return "Success" ?
popen() launches a shell using sh; it pretty much always succeeds.
--
Jem Berkes
http://www.sysdesign.ca/
| |
| Rich Teer 2004-04-21, 10:35 pm |
| On Wed, 21 Apr 2004, Madhusudan Singh wrote:
>
> Ugly as C coding usually is, I do not see how the above is any more ugly
> than other stuff in C.
>
> Maybe if((cmdpipe=popen(command,type))==NULL) is a little more compact.
I was talking about the placement of the braces. I find this:
if (cmdpipe == NULL) {
perror ("Failed : popen in posixwrapper:popen");
exit (1);
}
more legible. At a pinch, put the opening brace on a line
of its own at the same indent level as the "if".
> *I* had set errno=0 just prior to invoking popen (see the first line of the
> code fragment). Would it not stand to reason that it changed from 0 to 29
> because popen changed it ?
Yes, but just because popen changed it, doen't mean that an error
occurred. You should only call perror if you know an error has
occurred - and inspecting errno isn't the way to do that.
> But why the admonition to use a const char* and then allow the use of char*
> like this ?
const char * means that the function you're calling doesn't
change the string.
> Well, I intend to release the code under LGPL, but I am open to suggestions
How about a BSD-like license?
> regarding the aesthetics. Not that I find any C code itself to be a
> particularly "beautiful" thing 
That's true!
--
Rich Teer, SCNA, SCSA
President,
Rite Online Inc.
Voice: +1 (250) 979-1638
URL: http://www.rite-online.net
| |
| Casper H.S. Dik 2004-04-22, 5:34 am |
| Madhusudan Singh <spammers-go-here@yahoo.com> writes:
>Well, I intend to release the code under LGPL, but I am open to suggestions
>regarding the aesthetics. Not that I find any C code itself to be a
>particularly "beautiful" thing 
There's only one proper way to format C code, it's the "one-true-brace-style".
Also, please use a space after "if" and don't use spaces after function
identifiers. (Just like you would do in mathematics; the way the FSF
coding style uses white space around function and keywords is has no parallel
in the world)
Casper
--
Expressed in this posting are my opinions. They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.
| |
| Casper H.S. Dik 2004-04-22, 5:34 am |
| Rich Teer <rich.teer@rite-group.com> writes:
>At a pinch, put the opening brace on a line
>of its own at the same indent level as the "if".
Rich, you should know better than to allow people to leave the narrow
path of the "one-true-brace-style".
Casper
--
Expressed in this posting are my opinions. They are in no way related
to opinions held by my employer, Sun Microsystems.
Statements on Sun products included here are not gospel and may
be fiction rather than truth.
| |
| Rich Teer 2004-04-22, 12:36 pm |
| On Thu, 22 Apr 2004, Casper H.S. Dik wrote:
> Rich, you should know better than to allow people to leave the narrow
> path of the "one-true-brace-style".
That's very true; please forget my momentary lapse of reason. :-)
(Cue Pink Floyd music...)
--
Rich Teer, SCNA, SCSA
President,
Rite Online Inc.
Voice: +1 (250) 979-1638
URL: http://www.rite-online.net
| |
| Bill Marcum 2004-04-23, 2:34 am |
| On Wed, 21 Apr 2004 16:18:24 -0400, Madhusudan Singh
<spammers-go-here@yahoo.com> wrote:
>
> 1. Why does perror return "Success" ?
>
I don't know, maybe because popen succeeded?
> 2. Is the error condition 29 (Illegal seek) caused by my not using the const
> char* ?
>
Read the perror man page. errno is undefined after a successful library
call.
--
Giraffe: a ruminant with a view.
|
|
|
|
|