Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

C++-wrapper around popen

7 views
Skip to first unread message

Alex Vinokur

unread,
Oct 18, 1999, 3:00:00 AM10/18/99
to
In article <7ub4ga$uo$1...@nnrp1.deja.com>,
lew...@my-deja.com wrote:
> How can I obtain a directory listing and dump it to a file in C?
>
> Dan
>
> Sent via Deja.com http://www.deja.com/
> Before you buy.
>

Use popen () function.

Here is a C++-wrapper around the popen () function.

Alex

//#########################################################
//------------------- C++ code : BEGIN -------------------

// File main.C
//================
#include <stdio.h>
#include <assert.h>
#include <errno.h>

//================
#include <iostream>
#include <string>
#include <vector>

//=====================================
#define FATAL_MSG(msg) \
cout << msg \
<< " : " \
<< (strerror (errno)) \
<< " [ " \
<< __FILE__ \
<< ", #" \
<< __LINE__ \
<< " ]" \
<< endl

#define ERROR_MSG(msg) \
cout << msg \
<< " : " \
<< " [ " \
<< __FILE__ \
<< ", #" \
<< __LINE__ \
<< " ]" \
<< endl


//=====================================
bool popen_cplusplus (
const string& command_i,
vector<string>& result_o
)
{
bool ret_boolValue = true;
FILE* fp;
const int SIZEBUF = 1234;
char buf [SIZEBUF];

//================================
result_o = vector<string> ();
//================================

if ((fp = popen(command_i.c_str (), "r")) == NULL)
{
FATAL_MSG ("Files or processes cannot be created");
ret_boolValue = false;
return ret_boolValue;
}

//================================
string cur_string;
while (fgets(buf, sizeof (buf), fp))
{
cur_string = buf;
if (cur_string [cur_string.size () - 1] != '\n')
{
ERROR_MSG ("SIZEBUF too small (" << SIZEBUF <<
")");
ret_boolValue = false;
return ret_boolValue;
}
assert (cur_string [cur_string.size () - 1] == '\n');
result_o.push_back (cur_string.substr (0,
cur_string.size () - 1));
}

//================================
if (pclose(fp) == -1)
{
FATAL_MSG ("Cannot execute pclose");
ret_boolValue = false;
}

return ret_boolValue;

} // bool popen_cplusplus (...)

//==========================
int main ()
{
string command = "ls /tools/EGCS/include/g++/std";
vector<string> result;

//====================================
if (!popen_cplusplus (command, result))
{
cout << "Cannot execute popen_cplusplus" << endl;
return 1;
}

//====================================
for (int i = 0; i < result.size (); i++)
{
cout << "[" << i << "]\t : " << result [i] << endl;
}
return 0;
}

//------------------- C++ code : END ----------------------

//#########################################################
//------------ Results of the Running : BEGIN -------------

[0] : bastring.cc
[1] : bastring.h
[2] : complext.cc
[3] : complext.h
[4] : dcomplex.h
[5] : fcomplex.h
[6] : ldcomplex.h
[7] : straits.h

//------------ Results of the Running : END ---------------

//#########################################################
//------------------- Environment -------------------------

g++ -v : gcc version egcs-2.91.57 19980901
(egcs-1.1 release)

uname -sr : SunOS 5.6

//---------------------------------------------------------

//#########################################################

Sent via Deja.com http://www.deja.com/
Before you buy.

Bart v Ingen Schenau

unread,
Oct 18, 1999, 3:00:00 AM10/18/99
to
On Mon, 18 Oct 1999 09:47:27 GMT, Alex Vinokur
<alexande...@telrad.co.il> wrote:

>In article <7ub4ga$uo$1...@nnrp1.deja.com>,
> lew...@my-deja.com wrote:
>> How can I obtain a directory listing and dump it to a file in C?
>>
>> Dan
>>
>> Sent via Deja.com http://www.deja.com/
>> Before you buy.
>>
>
>Use popen () function.

What popen() function, I don't have one.

<snip - unix specific code >

Bart v Ingen Schenau

Owen Lawrence

unread,
Oct 18, 1999, 3:00:00 AM10/18/99
to
>>Use popen () function.
>
>What popen() function, I don't have one.
>
><snip - unix specific code >
>


Try _popen() for MS-Specific code.

- Owen -

Lord Williams

unread,
Oct 18, 1999, 3:00:00 AM10/18/99
to
Owen Lawrence <ow...@davis-eng.on.ca> wrote in article
<XMEO3.25024$m4.91...@news.magma.ca>...

Neither of which that were mentioned, are useful......

Im interested in solving the same problem but I want to use
C or C++ conventions that are ANSI / ISO portable.


--
Williams

FIAT JUSTITIA


>
> - Owen -
>
>
>

Juergen Heinzl

unread,
Oct 18, 1999, 3:00:00 AM10/18/99
to
In article <01bf1987$a42c28a0$490d1ad8@rlatiola>, Lord Williams wrote:
>Owen Lawrence <ow...@davis-eng.on.ca> wrote in article
><XMEO3.25024$m4.91...@news.magma.ca>...
>> >>Use popen () function.
>> >
>> >What popen() function, I don't have one.
>> >
>> ><snip - unix specific code >
[...]

>> Try _popen() for MS-Specific code.
>
>Neither of which that were mentioned, are useful......
>
>Im interested in solving the same problem but I want to use
>C or C++ conventions that are ANSI / ISO portable.

Do a dejanews search in comp.std.c++, subject was ...
"What does the standard say about file descriptors"
... and there are some follow ups.

Ta',
Juergen

--
\ Real name : Jürgen Heinzl \ no flames /
\ EMail Private : jue...@monocerus.demon.co.uk \ send money instead /

Alex Vinokur

unread,
Oct 19, 1999, 3:00:00 AM10/19/99
to
In article <380b13c8...@news.student.utwente.nl>,
b.vaning...@NOSPAM.student.utwente.nl (Bart v Ingen Schenau)
wrote:

> On Mon, 18 Oct 1999 09:47:27 GMT, Alex Vinokur
> <alexande...@telrad.co.il> wrote:
>
> >In article <7ub4ga$uo$1...@nnrp1.deja.com>,
> > lew...@my-deja.com wrote:
> >> How can I obtain a directory listing and dump it to a file in C?
> >>
> >> Dan
> >>
> >> Sent via Deja.com http://www.deja.com/
> >> Before you buy.
> >>
> >
> >Use popen () function.
>
> What popen() function, I don't have one.
>
> <snip - unix specific code >
>
> Bart v Ingen Schenau
>

SunOS 5.6
man popen

=======================================================

Standard I/O Functions popen(3S)

NAME
popen, pclose - initiate pipe to/from a process

SYNOPSIS
#include <stdio.h>

FILE *popen(const char *command, const char *type);

int pclose (FILE *stream);

DESCRIPTION
The popen() function creates a pipe between the calling pro-
gram and the command to be executed. The arguments to
popen() are pointers to null-terminated strings. command
consists of a shell command line. type is an I/O mode,
either r for reading or w for writing. The value returned
is a stream pointer such that one can write to the standard
input of the command, if the I/O mode is w, by writing to
the file stream (see intro(3)); and one can read from the
standard output of the command, if the I/O mode is r, by
reading from the file stream. Because open files are
shared, a type r command may be used as an input filter and
a type w as an output filter.

The environment of the executed command will be as if a
child process were created within the popen() call using
fork(2). If the application is standard-conforming (see
standards(5)), the child is invoked with the call:

execl("/usr/bin/ksh", "ksh", "-c", command, (char *)0);

otherwise, the child is invoked with the call:

execl("/usr/bin/sh", "sh", "-c", command, (char *)0);

A stream opened by popen() should be closed by pclose(),
which closes the pipe, and waits for the associated process
to terminate and returns the termination status of the pro-
cess running the command language interpreter. This is the
value returned by waitpid(2). See wstat(5) for more details
on termination status.

RETURN VALUES
The popen() function returns a null pointer if files or
processes cannot be created.

The pclose() function returns the termination status of the
command. The pclose() function returns -1 if stream is not
associated with a popen() command and sets errno to indicate
the error.

SunOS 5.6 Last change: 26 Feb 1997 1


Standard I/O Functions popen(3S)

EXAMPLES
The following is an example of a typical call:

#include <stdio.h>
#include <stdlib.h>
main()
{
char *cmd = "/usr/bin/ls *.c";
char buf[BUFSIZ];
FILE *ptr;

if ((ptr = popen(cmd, "r")) != NULL)
while (fgets(buf, BUFSIZ, ptr) != NULL)
(void) printf("%s", buf);
return 0;
}

This program will print on the standard output (see
stdio(3S)) all the file names in the current directory that
have a .c suffix.

ATTRIBUTES
See attributes(5) for descriptions of the following attri-
butes:

__________________________________
| ATTRIBUTE TYPE| ATTRIBUTE VALUE|
|__________________________________
| MT-Level | Unsafe |
|_______________|_________________|

SEE ALSO
ksh(1), pipe(2), wait(2), waitpid(2), fclose(3S), fopen(3S),
stdio(3S), system(3S), attributes(5), wstat(5), standards(5)

NOTES
If the original and popen() processes concurrently read or
write a common file, neither should use buffered I/O. Prob-
lems with an output filter may be forestalled by careful
buffer flushing, for example, with fflush() (see
fclose(3S)). A security hole exists through the IFS and
PATH environment variables. Full pathnames should be used
(or PATH reset) and IFS should be set to space and tab ("
\t").

SunOS 5.6 Last change: 26 Feb 1997 2


=======================================================

mb...@my-deja.com

unread,
Oct 19, 1999, 3:00:00 AM10/19/99
to
I suggest another approach.
under unix use the:
opendir() and readdir() functions.
Under windows use the
findfirst() and findnext() functions

to populate a linked list.
If you want to open the files later, store the size in
a struct member as well to ease up the reading using
fread().

Enclose the platform specific code within preprocessor directives
like
#ifdef WIN32
Windows code
#else
Unix code
#endif

You could even create a generic interface function that internally
call these platform specific code segments to hide the mess.

popen feels like the backdoor.
//Bengt


In article <7uh2cj$o7c$1...@nnrp1.deja.com>,

Erik Aronesty

unread,
Oct 19, 1999, 3:00:00 AM10/19/99
to
funny how the C++ version is vastly more complicated than just... popen()

Alex Vinokur <alexande...@telrad.co.il> wrote in message
news:7ueqbe$8ph$1...@nnrp1.deja.com...


> In article <7ub4ga$uo$1...@nnrp1.deja.com>,
> lew...@my-deja.com wrote:
> > How can I obtain a directory listing and dump it to a file in C?
> >
> > Dan
> >
> > Sent via Deja.com http://www.deja.com/
> > Before you buy.
> >
>
> Use popen () function.
>
>
>

> Here is a C++-wrapper around the popen () function.
>
> Alex
>

> file://#########################################################
> file://------------------- C++ code : BEGIN -------------------
>
> // File main.C
> file://================


> #include <stdio.h>
> #include <assert.h>
> #include <errno.h>
>

> file://================


> #include <iostream>
> #include <string>
> #include <vector>
>

> file://=====================================


> #define FATAL_MSG(msg) \
> cout << msg \
> << " : " \
> << (strerror (errno)) \
> << " [ " \
> << __FILE__ \
> << ", #" \
> << __LINE__ \
> << " ]" \
> << endl
>
> #define ERROR_MSG(msg) \
> cout << msg \
> << " : " \
> << " [ " \
> << __FILE__ \
> << ", #" \
> << __LINE__ \
> << " ]" \
> << endl
>
>

> file://=====================================


> bool popen_cplusplus (
> const string& command_i,
> vector<string>& result_o
> )
> {
> bool ret_boolValue = true;
> FILE* fp;
> const int SIZEBUF = 1234;
> char buf [SIZEBUF];
>

> file://================================


> result_o = vector<string> ();

> file://================================


>
> if ((fp = popen(command_i.c_str (), "r")) == NULL)
> {
> FATAL_MSG ("Files or processes cannot be created");
> ret_boolValue = false;
> return ret_boolValue;
> }
>

> file://================================


> string cur_string;
> while (fgets(buf, sizeof (buf), fp))
> {
> cur_string = buf;
> if (cur_string [cur_string.size () - 1] != '\n')
> {
> ERROR_MSG ("SIZEBUF too small (" << SIZEBUF <<
> ")");
> ret_boolValue = false;
> return ret_boolValue;
> }
> assert (cur_string [cur_string.size () - 1] == '\n');
> result_o.push_back (cur_string.substr (0,
> cur_string.size () - 1));
> }
>

> file://================================


> if (pclose(fp) == -1)
> {
> FATAL_MSG ("Cannot execute pclose");
> ret_boolValue = false;
> }
>
> return ret_boolValue;
>
> } // bool popen_cplusplus (...)
>

> file://==========================


> int main ()
> {
> string command = "ls /tools/EGCS/include/g++/std";
> vector<string> result;
>

> file://====================================


> if (!popen_cplusplus (command, result))
> {
> cout << "Cannot execute popen_cplusplus" << endl;
> return 1;
> }
>

> file://====================================


> for (int i = 0; i < result.size (); i++)
> {
> cout << "[" << i << "]\t : " << result [i] << endl;
> }
> return 0;
> }
>
>
>

> file://------------------- C++ code : END ----------------------
>
>
>
>
>
> file://#########################################################
> file://------------ Results of the Running : BEGIN -------------


>
> [0] : bastring.cc
> [1] : bastring.h
> [2] : complext.cc
> [3] : complext.h
> [4] : dcomplex.h
> [5] : fcomplex.h
> [6] : ldcomplex.h
> [7] : straits.h
>

> file://------------ Results of the Running : END ---------------
>
>
>
>
>
> file://#########################################################
> file://------------------- Environment -------------------------


>
> g++ -v : gcc version egcs-2.91.57 19980901
> (egcs-1.1 release)
>
> uname -sr : SunOS 5.6
>

> file://---------------------------------------------------------
>
>
>
> file://#########################################################

Greg Comeau

unread,
Oct 19, 1999, 3:00:00 AM10/19/99
to
In article <7ui7uj$312$1...@maceo.dti.net> "Erik Aronesty" <er...@primedata.org> writes:
>funny how the C++ version is vastly more complicated than just... popen()

What's funny IMO is that you do not even take the time to read
or understand Alex's code. Surely the code is more complicated
than popen(), because HE ISN'T JUST POPEN()ING!!!
If he did the same thing in C it would be as complicated.


--
Comeau Computing, 91-34 120th Street, Richmond Hill, NY, 11418-3214
Producers of Comeau C/C++ 4.2.38 -- NOTE 4.2.42 BETAS NOW AVAILABLE
Email: com...@comeaucomputing.com / Voice:718-945-0009 / Fax:718-441-2310
*** WEB: http://www.comeaucomputing.com ***

Guy Harrison

unread,
Oct 21, 1999, 3:00:00 AM10/21/99
to
On Tue, 19 Oct 1999 14:34:29 GMT, mb...@my-deja.com wrote:

>I suggest another approach.
>under unix use the:
>opendir() and readdir() functions.
>Under windows use the
>findfirst() and findnext() functions

You may not have to: open/readdir may exist in a windoze compiler
anyway.

--
g...@swampdog.demon.co.uk
http://www.swampdog.demon.co.uk

Mark Wooding

unread,
Oct 29, 1999, 3:00:00 AM10/29/99
to
Greg Comeau <com...@panix.com> wrote:
> In article <7ui7uj$312$1...@maceo.dti.net> "Erik Aronesty"
> <er...@primedata.org> writes:
> >funny how the C++ version is vastly more complicated than just... popen()
>
> What's funny IMO is that you do not even take the time to read or
> understand Alex's code. Surely the code is more complicated than
> popen(), because HE ISN'T JUST POPEN()ING!!! If he did the same thing
> in C it would be as complicated.

Not really. I append a version of the same program written in C using
my standard tools library. (The library is available at

http://www.excessus.demon.co.uk/misc-hacks/index.html#mLib

).

My opinion, at least, is that the code is simpler than the C++ version.
It certainly looks that way because it's not cluttered with useless
comments. I also note that, unlike the C++ version, mine has no line
length limit. And finally, I note that this isn't really a clever way
of using popen(3) except in extremely simple circumstances.


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <mLib/dstr.h>
#include <mLib/darray.h>

/* --- Declare a dynamic array of dynamic strings --- */

DA_DECL(dstrv, dstr);

/* --- @popenthing@ --- *
*
* Arguments: @const char *cmd@ = shell command to execute
* @dstrv *v@ = vector in which to write the results
*
* Returns: Exit status from command if successful; @-1@ if it
* failed to start (and @errno@ set).
*
* Use: Executes a shell command and appends the lines of its
* standard output to a vector of dynamic strings. The
* lines have no trailing newlines.
*/

static int popenthing(const char *cmd, dstrv *v)
{
FILE *fp = popen(cmd, "r");

if (!fp)
return (-1);
for (;;) {
dstr d = DSTR_INIT;
if (dstr_putline(&d, fp) == EOF)
break;
dstr_tidy(&d);
DA_PUSH(v, d);
}
return (pclose(fp));
}

/* --- @main@ --- */

int main(int argc, char *argv[])
{
dstrv v = DA_INIT;
int i;

if (argc != 2) {
fprintf(stderr, "bad arguments\n");
exit(1);
}
if (popenthing(argv[1], &v) == -1) {
perror("popen");
exit(1);
}
for (i = 0; i < DA_LEN(&v); i++)
printf("[%i] %s\n", i, DA(&v)[i].buf);
for (i = 0; i < DA_LEN(&v); i++)
DDESTROY(&DA(&v)[i]);
DA_DESTROY(&v);
return (0);
}

-- [mdw]

Greg Comeau

unread,
Oct 29, 1999, 3:00:00 AM10/29/99
to
In article <slrn81it2...@catbert.ebi.ac.uk> m...@ebi.ac.uk writes:

>Greg Comeau <com...@panix.com> wrote:
>> In article <7ui7uj$312$1...@maceo.dti.net> "Erik Aronesty"
>> <er...@primedata.org> writes:
>> >funny how the C++ version is vastly more complicated than just... popen()
>>
>> What's funny IMO is that you do not even take the time to read or
>> understand Alex's code. Surely the code is more complicated than
>> popen(), because HE ISN'T JUST POPEN()ING!!! If he did the same thing
>> in C it would be as complicated.
>
>My opinion, at least, is that the [C] code is simpler than the C++ version.

As I recall the code, your C version doesn't do what the C++ version did,
so your point is not one.

>It certainly looks that way because it's not cluttered with useless
>comments.

That's clearly a language neutral issue and so that somebody added
useless comments (assuming this is true) is neither here nor there.

- Greg

Mark Wooding

unread,
Oct 29, 1999, 3:00:00 AM10/29/99
to
Greg Comeau <com...@panix.com> wrote:

> As I recall the code, your C version doesn't do what the C++ version did,
> so your point is not one.

The C++ function `popen_cplusplus', as I read it, opens a read pipe to a
named shell command, reads lines from the command and appends them to a
an array, closes the pipe and returns an indication of success.

Shall we look in more detail, to see whether I'm right? I've ground the
code through `indent' to make it more visually appealing, but nothing
`of substance' has changed.

bool popen_cplusplus(const string &command_i,
vector<string> &result_o)

So far, so good. We've got the command (as a C++ string), and the
destination vector.

{
bool ret_boolValue = true;
FILE *fp;
const int SIZEBUF = 1234;
char buf[SIZEBUF];

result_o = vector<string>();

OK. Here's a difference. It's not an interesting one, but it's a
difference. This code empties the vector before it starts.

if ((fp = popen(command_i.c_str(), "r")) == NULL) {
FATAL_MSG("Files or processes cannot be created");


ret_boolValue = false;
return ret_boolValue;
}

We open the pipe to the command. The emission of a message in this case
is probably not actually a good idea -- it assumes too much of the
surrounding program. Best to leave it to the caller to decide how to
respond to a failure. The fiddling with `ret_boolValue' adds visual
clutter.

string cur_string;
while (fgets(buf, sizeof(buf), fp)) {
cur_string = buf;
if (cur_string[cur_string.size() - 1] != '\n') {
ERROR_MSG("SIZEBUF too small (" << SIZEBUF <<


")");
ret_boolValue = false;
return ret_boolValue;
}

assert(cur_string[cur_string.size() - 1] == '\n');
result_o.push_back(cur_string.substr(0, cur_string.size() - 1));
}

A merry little dance, this. While there are lines to read, read them
and stick 'em in the array. (I admit it: I guessed at this behaviour.
I'm not an STL user. However, it looks like I guessed right.) The
dance is made interesting by the mixing of C++ and boring ol' C strings.

The assertion is interesting. I assume that's there to catch errors in
the compiler. (My preference here would probably be to remove the `if'
test and just leave the assertion. Bombing here if a line is too long
is probably better than trying to soldier on.)

if (pclose(fp) == -1) {
FATAL_MSG("Cannot execute pclose");
ret_boolValue = false;
}

Checking the return value of `pclose' is good. Ignoring the exit status
of the process is silly, though. Again, the fiddling with
`ret_boolValue' is cluttery.

return ret_boolValue;
}

Done. Phew.

OK. That concludes my dissection of the original. Where's my version?

static int popenthing(const char *cmd, dstrv *v)

I like short argument names. There's the command, `cmd', and the output
vector, `v'. Good.

{
FILE *fp = popen(cmd, "r");

Open the pipe.

if (!fp)
return (-1);

If the pipe didn't open, we failed, so return an indication.

for (;;) {
dstr d = DSTR_INIT;

Initialize a string. The string is initially empty.

if (dstr_putline(&d, fp) == EOF)
break;

Read a `line' from the pipe and `put' it on the end of the string. If
there wasn't a string to read then stop the loop here. It doesn't
matter how long the line is: dstr_putline will cope anyway.

DA_PUSH(v, d);

Push the string on the end of the vector.

}
return (pclose(fp));

Then return either -1 if the close failed (probably a `wait' problem),
or the exit status of the process. This seems a sensible interface.

}

Nice and simple. No?

Both driver programs are fairly trivial. Mine's slightly more
complicated because it reads the command as an argument. The formatting
is very subtly different, but can be modified in mine by editing a
`printf' format string (from "[%i] %s\n" to "[%s]\t : %s\n", if you must
know). Oh, well.

So, where were these massive differences, then? I hardly think that the
difference between appending to an existing array and clearing an
existing array before starting is ever-so significant.

-- [mdw]

Greg Comeau

unread,
Oct 29, 1999, 3:00:00 AM10/29/99
to
In article <slrn81jrb...@catbert.ebi.ac.uk> m...@ebi.ac.uk writes:
>Greg Comeau <com...@panix.com> wrote:
>> As I recall the code, your C version doesn't do what the C++ version did,
>> so your point is not one.
>
>The C++ function `popen_cplusplus', as I read it, opens a read pipe to a
>named shell command, reads lines from the command and appends them to a
>an array, closes the pipe and returns an indication of success.
>
>Shall we look in more detail, to see whether I'm right?
>....

>So, where were these massive differences, then? I hardly think that the
>difference between appending to an existing array and clearing an
>existing array before starting is ever-so significant.

Unfortunately, you do not address the issues which were raised.
Let's back off and revisit the situation. Alex made a suggestion to
somebody to use popen() in order to get a directory listing. But
instead of just suggesting popen() and leaving it at that, he also
provided a wrapper for it. His wrapper did two things:
1) Some error checking
i) Using assert()s
ii) Using return value checking
2) Specifically "collected" the output from the popen.
i) Using vector<string>
ii) Using char buf[]

Ok, this is given.

Upon which "Erik Aronesty"<er...@primedata.org> wrote:
|>funny how the C++ version is vastly more complicated than just... popen()

The implication to me here was that Erik felt that C++ itself introduced
some type of "burden" and failed to noticed that it was Alex who did (and
justly so). I find that not the case (that it was C++'s fault), because
the error checking is a neutral issue, and that you would need to collect
the output even in the C version. Therefore I responded:

|>> What's funny IMO is that you do not even take the time to read or
|>> understand Alex's code. Surely the code is more complicated than
|>> popen(), because HE ISN'T JUST POPEN()ING!!! If he did the same thing
|>> in C it would be as complicated.

Which is true: he isn't just popen()ing, he's doing (1) and (2) too.
Again, if a C program did (1) and (2) too, it would ALSO BE more
complicated than just popen()ing _as your example clearly shows_.

However, you responded to my remark to Erik saying:
|>Not really.
|>My opinion, at least, is that the code is simpler than the C++ version.


|>It certainly looks that way because it's not cluttered with useless

|>comments. I also note that, unlike the C++ version, mine has no line
|>length limit. And finally, I note that this isn't really a clever way
|>of using popen(3) except in extremely simple circumstances.

Of course it's simpler: you don't as much of (1).
Furthermore, the he went overboard w.r.t (2)(ii) (especially combo'd
with the line length limit you point out (so I agree)) but this again is
not a language fault. Last but not least, he comments his and you don't.


This is to say: THERE ARE DIFFERENCES. Therefore I said:

|>As I recall the code, your C version doesn't do what the C++ version
|>did, so your point is not one.

As even you just noted, it doesn't do the same things.
If you added (1), I think things would be closer
(probably not in the function, but with a way to pass the error back).

So, either add (1) to yours (or remove it from his).
That still leave his (2)(ii) but it can be smoothed out.

>Both driver programs are fairly trivial.

Agreed. And I still bet they can be made equal, which again shows the
original point since for the most part we're dealing with language
neutral issues so far.

Mark Wooding

unread,
Nov 1, 1999, 3:00:00 AM11/1/99
to
Greg Comeau <com...@panix.com> wrote:

> Let's back off and revisit the situation. Alex made a suggestion to
> somebody to use popen() in order to get a directory listing.

I'd forgotten that piece of context. Of course, it means that using
`popen' is completely wrongheaded to start with. The right thing to use
is `diropen':

* It's quicker.
* It doesn't run a shell and then another program.
* It's actually easier.
* You don't get confused when you find a filename with a newline in it.

> But instead of just suggesting popen() and leaving it at that, he also
> provided a wrapper for it. His wrapper did two things:
>
> 1) Some error checking
> i) Using assert()s
> ii) Using return value checking
> 2) Specifically "collected" the output from the popen.
> i) Using vector<string>
> ii) Using char buf[]
>

> Again, if a C program did (1) and (2) too, it would ALSO BE more
> complicated than just popen()ing _as your example clearly shows_.

Yes, the code was more complicated than a raw `popen'. On the other
hand, it was still a sight simpler.

I freely admit that my code used no asserts. I couldn't see any use for
them given the problem. It's all blindingly obvious anyway.

> Of course it's simpler: you don't as much of (1).

I do *enough* error checking. There's not an error which can occur
which my code doesn't notice. (Out-of-memory conditions are signalled
using an exception mechanism which you can't see but is still there.)
Doing more than enough error checking is a waste of everybody's time.

> Furthermore, the he went overboard w.r.t (2)(ii) (especially combo'd
> with the line length limit you point out (so I agree)) but this again is
> not a language fault. Last but not least, he comments his and you
> don't.

I believe I actually provided more useful comments. My interface was
clearly defined, and I described what the function did. Its behaviour
was obvious and needed no extra comments. I assert that a moderately
competent C programmer could understand the code even though I'm using a
library he's never come across before.

> This is to say: THERE ARE DIFFERENCES. Therefore I said:

THERE [oh, I can't be bothered with caps lock] may be differences, but
they're not worth worrying about.

> As even you just noted, it doesn't do the same things.
> If you added (1), I think things would be closer
> (probably not in the function, but with a way to pass the error back).

Ahh. You can't read. My function's comment explained that it returned
the exit status of the command on success and -1 if it failed. (Note
that the original C++ version failed to check for an important
condition, namely failure of the child process, which my version traps
correctly.) It checks for every error which can happen:

* popen fails, either because it couldn't allocate a FILE or a buffer,
or because fork() failed.

* pclose fails.

* The child process fails.

* There's not enough memory.

The last condition is signalled in an out-of-band way so you never
noticed; however I don't think this was actually what you're talking
about. The others are signalled either by returning -1 or the child's
exit status.

Can you think of something else which can go wrong, and which my code
doesn't spot?

> So, either add (1) to yours (or remove it from his).
> That still leave his (2)(ii) but it can be smoothed out.

But the mix of char arrays and C++ strings is wrongheaded to begin with,
isn't it? Why would anyone want to do the job like that? I think I've
dealt with the error handling thing enough.

I think my point's been lost, or was never actually stated. It was that
the C++ code looked about fifteen times more complicated than it had any
right to, partly because it *was* about five times more complicated than
necessary, and partly because it was cluttered and ugly.

-- [mdw]

Skalatone

unread,
Nov 1, 1999, 3:00:00 AM11/1/99
to
Mark Wooding wrote:

> Greg Comeau <com...@panix.com> wrote:
>
> > Let's back off and revisit the situation. Alex made a suggestion to
> > somebody to use popen() in order to get a directory listing.
>
> I'd forgotten that piece of context. Of course, it means that using
> `popen' is completely wrongheaded to start with. The right thing to use
> is `diropen':
>

Isn't that 'opendir' ?
I did a small program on Linux couple of weeks ago and if I remember well the
functions were opendir, readdir and closedir.
But since you're the expert here, it's just a question :-)

J-P
---
behe...@total.net


Erik Max Francis

unread,
Nov 1, 1999, 3:00:00 AM11/1/99
to
Skalatone wrote:

> Isn't that 'opendir' ?
> I did a small program on Linux couple of weeks ago and if I remember
> well the
> functions were opendir, readdir and closedir.

Yes, you are correct.

--
Erik Max Francis | icq 16063900 | whois mf303 | email m...@alcyone.com
Alcyone Systems | irc maxxon (efnet) | web http://www.alcyone.com/max/
San Jose, CA | languages en, eo | icbm 37 20 07 N 121 53 38 W
USA | 426 days and counting | &tSftDotIotE
__
/ \ Life is a zoo in a jungle.
\__/ Peter de Vries

Mark Wooding

unread,
Nov 2, 1999, 3:00:00 AM11/2/99
to
Skalatone <behe...@total.net> wrote:

> Isn't that 'opendir' ? I did a small program on Linux couple of weeks
> ago and if I remember well the functions were opendir, readdir and

> closedir. But since you're the expert here, it's just a question :-)

Duh. You're absolutely right. I've used the functions quite a lot
myself. My memory failed at the last moment, though, and I assumed that
they were named the way I'd name them, rather than the way they're
actually named. Oh, well.

Apologies for the confusion.

-- [mdw]

Greg Comeau

unread,
Nov 2, 1999, 3:00:00 AM11/2/99
to
In article <slrn81s46...@catbert.ebi.ac.uk> m...@ebi.ac.uk writes:
>Greg Comeau <com...@panix.com> wrote:
>> Let's back off and revisit the situation. Alex made a suggestion to
>> somebody to use popen() in order to get a directory listing.
>
>I'd forgotten that piece of context...

Actually, the context is the only thing driving this thread,
and I suspect you've repeatedly missed it.

>Of course, it means that using
>`popen' is completely wrongheaded to start with. The right thing to use
>is `diropen':
>

> * It's quicker.
> * It doesn't run a shell and then another program.
> * It's actually easier.
> * You don't get confused when you find a filename with a newline in it.

This may all be true, but wasn't the point being addressed.

(Actually, on this point, it assumes a diropen() exists, and that
may not tbe the case, so.......

>> But instead of just suggesting popen() and leaving it at that, he also
>> provided a wrapper for it. His wrapper did two things:
>>
>> 1) Some error checking
>> i) Using assert()s
>> ii) Using return value checking
>> 2) Specifically "collected" the output from the popen.
>> i) Using vector<string>
>> ii) Using char buf[]
>>
>> Again, if a C program did (1) and (2) too, it would ALSO BE more
>> complicated than just popen()ing _as your example clearly shows_.
>
>Yes, the code was more complicated than a raw `popen'. On the other
>hand, it was still a sight simpler.
>
>I freely admit that my code used no asserts. I couldn't see any use for
>them given the problem. It's all blindingly obvious anyway.

Again, that wasn't the original point.

>> Of course it's simpler: you don't as much of (1).
>
>I do *enough* error checking. There's not an error which can occur
>which my code doesn't notice. (Out-of-memory conditions are signalled
>using an exception mechanism which you can't see but is still there.)
>Doing more than enough error checking is a waste of everybody's time.

That's indeed often so, but again, that wasn't the orignal point.

>> Furthermore, the he went overboard w.r.t (2)(ii) (especially combo'd
>> with the line length limit you point out (so I agree)) but this again is
>> not a language fault. Last but not least, he comments his and you
>> don't.
>
>I believe I actually provided more useful comments. My interface was
>clearly defined, and I described what the function did. Its behaviour
>was obvious and needed no extra comments. I assert that a moderately
>competent C programmer could understand the code even though I'm using a
>library he's never come across before.

Again, may be so, but wasn't the point.

>> This is to say: THERE ARE DIFFERENCES. Therefore I said:
>
>THERE [oh, I can't be bothered with caps lock] may be differences, but
>they're not worth worrying about.

I would have written the code differently myself, but again, wasn't the point.

>> As even you just noted, it doesn't do the same things.
>> If you added (1), I think things would be closer
>> (probably not in the function, but with a way to pass the error back).
>
>Ahh. You can't read.

Hey, speak for yourself. If you could read, you would have been
able to see what my original point was about, especailly since I've
clarified it (though that's been snipped it seems).

>My function's comment explained that it returned
>the exit status of the command on success and -1 if it failed.

Ahh. You can't read. I did not say your version didn't do this.

> (Note
>that the original C++ version failed to check for an important
>condition, namely failure of the child process, which my version traps
>correctly.) It checks for every error which can happen:
>
> * popen fails, either because it couldn't allocate a FILE or a buffer,
> or because fork() failed.
>
> * pclose fails.
>
> * The child process fails.
>
> * There's not enough memory.
>
>The last condition is signalled in an out-of-band way so you never
>noticed;

Nor have I cared yet, because these things were never the point.

>however I don't think this was actually what you're talking
>about.

No, it's not, and hasn't been. So why are we discussig them as
responses to my point! Sigh....

>The others are signalled either by returning -1 or the child's
>exit status.
>
>Can you think of something else which can go wrong, and which my code
>doesn't spot?

Probably, but hasn't been yet what my point has been about.

>> So, either add (1) to yours (or remove it from his).
>> That still leave his (2)(ii) but it can be smoothed out.
>
>But the mix of char arrays and C++ strings is wrongheaded to begin with,
>isn't it?

Yes, and I said so.. Sigh.

>Why would anyone want to do the job like that?

I've said the code wans't perfect IMO. But that's was never my point.

>I think I've dealt with the error handling thing enough.
>
>I think my point's been lost,

Oddly, my point's been lost before yours! :)

>or was never actually stated. It was that
>the C++ code looked about fifteen times more complicated than it had any
>right to, partly because it *was* about five times more complicated than
>necessary, and partly because it was cluttered and ugly.

Right, which has nothing per se to do with C++ itself.
Which, if I can recall myself at this point, was my point.

Let's move on??

Mark Wooding

unread,
Nov 2, 1999, 3:00:00 AM11/2/99
to
Greg Comeau <com...@panix.com> wrote:

> Again, that wasn't the original point.

Sigh. Let's take a look at that original point. In article
<7uia06$fts$1...@panix3.panix.com>, you said (and I quote the entire
original portion of the message body):

: What's funny IMO is that you do not even take the time to read or


: understand Alex's code. Surely the code is more complicated than
: popen(), because HE ISN'T JUST POPEN()ING!!! If he did the same thing
: in C it would be as complicated.

I can interpret this last sentence in two ways, basically hinging on the
meaning of the pronoun `he':

* Just a convenient placeholder, really meaning `anyone'; thus,
a function which did the same thing in C would be as complicated as
the C++ function written by Mr Vinokur.

* Really referring to Mr Vinokur; thus, if Mr Vinokur had written his
function in C, it would be as complicated as the C++ function he
did, in fact, write. [This I'd probably agree with.]

I originally interpreted the sentence in the former manner; hence my
desire to demonstrate, by means of a counterexample, the falsity of the
above-quoted statement.

Now, an exerpt from article <7vdjtj$48m$1...@panix3.panix.com>, also by
you:

: Again, if a C program did (1) and (2) too, it would ALSO BE more


: complicated than just popen()ing _as your example clearly shows_.

This appears to be a *different* point, namely that a C function which
did the same thing would be more complicated than just a call to
popen(3). This new point, different from both interpretations of your
original point, seems sufficiently self-evident that it's not worth
stating.

So, which of these three points is actually the one you wanted to make
originally?

-- [mdw]

Karl Heinz Buchegger

unread,
Nov 3, 1999, 3:00:00 AM11/3/99
to

>
> : Again, if a C program did (1) and (2) too, it would ALSO BE more

> : complicated than just popen()ing _as your example clearly shows_.
>
> This appears to be a *different* point, namely that a C function which
> did the same thing would be more complicated than just a call to
> popen(3). This new point, different from both interpretations of your
> original point, seems sufficiently self-evident that it's not worth
> stating.
>

As I followed the thread, this was IMHO *exactly* the point,
Greg wanted to point out. A simple call to popen is not
the whole story, there needs to be some checking around.
It has nothing to do with C++ versus C, as the original
reply tried to suggest. I don't have the original reply
on my news server any more, but it was something like:
"See how complicated a simple C-popen becomes, when the
C++ guys get a hand at it". He simply ignored the fact
that the C++ version contained a lot of error checking,
which would have to be done in a C-version too, as you
showed.
That's what Greg complained about.

-----------------------------------------------------------
Karl Heinz Buchegger
kbuc...@gascad.at

0 new messages