From: Phred Phungus on
Glen Hermannsfeldt posted this in comp.lang.fortran:

#include <stdio.h>
int main() {
printf("%d\n",system("ls | grep ."));
}



// gcc -D_GNU_SOURCE -Wall -Wextra rr1.c -o out

Output seemed typical:

$ ./out
9vx-0.12
9vx-0.12.tar.bz2
a2.c
....
winter1.c~
z
0

Apparently, the zero is expected.

q1) What exactly is happening with "ls | grep ." ?

I changed the directory and get 256, which seems to indicate failure:
$ gcc -D_GNU_SOURCE -Wall -Wextra rr2.c -o out
$ ./out
256
$ cat rr2.c
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("%d\n",system("ls | grep /etc/"));
return 0;
}



// gcc -D_GNU_SOURCE -Wall -Wextra rr2.c -o out

$


q2) Why didn't this work?

q3) In the unix environment, is 'system' the best way to make a system
call?

Thanks for your comment and cheers,
From: Lew Pitcher on
On Mar 6, 8:23 pm, Phred Phungus <Ph...(a)example.invalid> wrote:
> Glen Hermannsfeldt posted this in comp.lang.fortran:
>
> #include <stdio.h>
> int main() {
>      printf("%d\n",system("ls | grep ."));
>
> }
>
> // gcc -D_GNU_SOURCE -Wall -Wextra rr1.c -o out
>
> Output seemed typical:
>
> $ ./out
> 9vx-0.12
> 9vx-0.12.tar.bz2
> a2.c
> ...
> winter1.c~
> z
> 0
>
> Apparently, the zero is expected.
>
> q1) What exactly is happening with "ls | grep ." ?

ls(1) is listing the filenames in the current working directory
| copies the output of ls(1) to the input of grep(1)
grep(1) looks through all it's input for anything that has a period in
it, and writes those lines to it's output, which is the same output
stream as your program.

system("ls | grep .") starts a shell, with output directed to the same
destination as your stdout, and then runs the pipeline
ls | grep .
in that shell. When the pipeline finishes, the returncode from the
shell is passed back through the system() call and on to your program
as it's return value.

> I changed the directory and get 256, which seems to indicate failure:
> $ gcc -D_GNU_SOURCE -Wall -Wextra rr2.c -o out
> $ ./out
> 256
> $ cat rr2.c
> #include <stdio.h>
> #include <stdlib.h>
> int main()
> {
>     printf("%d\n",system("ls | grep /etc/"));
>     return 0;
>
> }
>
> // gcc -D_GNU_SOURCE -Wall -Wextra rr2.c -o out
>
> $
>
> q2)  Why didn't this work?

Because your current working directory didn't have any files with a
name that included the characters
/etc/
in it.

I /would/ have expected your program to still print the number,
representing the return value from the system() call.


> q3)  In the unix environment, is 'system' the best way to make a system
> call?

In Unix, a system call (or syscall) is /not/ that which you get when
you call the system(1) function. system(1) is a good way to have your
program initiate other programs, but not the best way (popen(3) or
fork(2)/exec(2) would be better, for some values of "better").


>
> Thanks for your comment and cheers,

From: Phred Phungus on
Lew Pitcher wrote:
> On Mar 6, 8:23 pm, Phred Phungus <Ph...(a)example.invalid> wrote:

>> q1) What exactly is happening with "ls | grep ." ?
>
> ls(1) is listing the filenames in the current working directory
> | copies the output of ls(1) to the input of grep(1)
> grep(1) looks through all it's input for anything that has a period in
> it, and writes those lines to it's output, which is the same output
> stream as your program.
>
> system("ls | grep .") starts a shell, with output directed to the same
> destination as your stdout, and then runs the pipeline
> ls | grep .
> in that shell. When the pipeline finishes, the returncode from the
> shell is passed back through the system() call and on to your program
> as it's return value.

Does the grep'ing in this line fall under this criticism of it:

http://ubuntard.com/2009/12/command-line-idiocy/
>> I changed the directory and get 256, which seems to indicate failure:
>> $ gcc -D_GNU_SOURCE -Wall -Wextra rr2.c -o out
>> $ ./out
>> 256
>> $ cat rr2.c
>> #include <stdio.h>
>> #include <stdlib.h>
>> int main()
>> {
>> printf("%d\n",system("ls | grep /etc/"));
>> return 0;
>>
>> }
>>
>> // gcc -D_GNU_SOURCE -Wall -Wextra rr2.c -o out
>>
>> $
>>
>> q2) Why didn't this work?
>
> Because your current working directory didn't have any files with a
> name that included the characters
> /etc/
> in it.

$ gcc -D_GNU_SOURCE -Wall -Wextra rr2.c -o out
$ ./out
256
$ cat rr2.c
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("%d\n",system("ls | grep ~/etc/"));
return 0;
}



// gcc -D_GNU_SOURCE -Wall -Wextra rr2.c -o out

$

What am I trying to do here?

>
> I /would/ have expected your program to still print the number,
> representing the return value from the system() call.

It does. 256.
>
>
>> q3) In the unix environment, is 'system' the best way to make a system
>> call?
>
> In Unix, a system call (or syscall) is /not/ that which you get when
> you call the system(1) function. system(1) is a good way to have your
> program initiate other programs, but not the best way (popen(3) or
> fork(2)/exec(2) would be better, for some values of "better").

I'm not sure what I've done here:
$ gcc -D_GNU_SOURCE -Wall -Wextra rr3.c -o out
rr3.c: In function �main�:
rr3.c:15: warning: suggest braces around empty body in an �if� statement
$ ./out
9vx-0.12
9vx-0.12.tar.bz2
a2.c
a2.c~
a2.o
a.c
a.c~
a.o
b.f90
b.f90~
bits6.c
bits6.c~
bits7.c
bits7.c~
dw3.f90
f1.c
f1.c~
lc1.c
lc1.c~
mort1.c
mort1.c~
mort2.c
mort2.c~
mort3.c
mort3.c~
mort4.c
mort4.c~
mort5.c
mort5.c~
mort6.c
mort6.c~
mort7.c
mort7.c~
out
rd2.c
rd2.c~
rd3.c
rd3.c~
rd4.c
rd4.c~
rd5.c
rd5.c~
rd7.c
rd7.c~
rd8.c
rd8.c~
readdir_demo2.c~
readdir_demo.c
readdir_demo.c~
rr1.c
rr1.c~
rr2.c
rr2.c~
rr3.c
rr3.c~
ss1.c
ss1.c~
ss2.c
ss2.c~
ss3.c
ss3.c~
unleashed
winter1.c
winter1.c~
z
0
9vx-0.12.tar.bz2
a2.c
a2.c~
a2.o
a.c
a.c~
a.o
b.f90
b.f90~
bits6.c
bits6.c~
bits7.c
bits7.c~
dw3.f90
f1.c
f1.c~
lc1.c
lc1.c~
mort1.c
mort1.c~
mort2.c
mort2.c~
mort3.c
mort3.c~
mort4.c
mort4.c~
mort5.c
mort5.c~
mort6.c
mort6.c~
mort7.c
mort7.c~
out
rd2.c
rd2.c~
rd3.c
rd3.c~
rd4.c
rd4.c~
rd5.c
rd5.c~
rd7.c
rd7.c~
rd8.c
rd8.c~
readdir_demo2.c~
readdir_demo.c
readdir_demo.c~
rr1.c
rr1.c~
rr2.c
rr2.c~
rr3.c
rr3.c~
ss1.c
ss1.c~
ss2.c
ss2.c~
ss3.c
ss3.c~
winter1.c
winter1.c~
z

9vx-0.12:
386
68000
68020
9vx.FreeBSD
9vx.Linux
9vx.OSX
acme
adm
alpha
amd64
arm
cfg
cron
dist
env
fd
lib
LICENSE
LICENSE.afpl
LICENSE.gpl
lp
mail
mips
mnt
n
NOTICE
power
power64
rc
sparc
sparc64
sys
tmp
usr

unleashed:
Bonus
ch02
ch03
ch04
ch06
ch07
ch08
ch09
ch10
ch11
ch12
ch13
ch14
ch15
ch16
ch17
ch18
ch19
ch20
ch21
ch22
ch23
ch24
ch25
ch26
iaq
$ cat rr3.c
#include <stdio.h>
#include <stdlib.h>
#define PATH_MAX 4096
int
main ()
{

FILE *fp;
int status;
char path[PATH_MAX];

printf ("%d\n", system ("ls | grep ."));
fp = popen ("ls *", "r");
if (fp == NULL)
/* Handle error */ ;
while (fgets (path, PATH_MAX, fp) != NULL)
printf ("%s", path);
status = pclose (fp);
if (status == -1)
{
/* Error reported by pclose() */
}
else
{
/* Use macros described under wait() to inspect `status' in order
to determine success/failure of command executed by popen() */
}
return 0;
}
// gcc -D_GNU_SOURCE -Wall -Wextra rr3.c -o out
$

Can you say a few words about what precisely happens here:

fp = popen ("ls *", "r");
--
fred
From: Janis Papanagnou on
Phred Phungus wrote:
> Lew Pitcher wrote:
>> On Mar 6, 8:23 pm, Phred Phungus <Ph...(a)example.invalid> wrote:
>
>>> q1) What exactly is happening with "ls | grep ." ?
>>
>> ls(1) is listing the filenames in the current working directory
>> | copies the output of ls(1) to the input of grep(1)
>> grep(1) looks through all it's input for anything that has a period in

A period in grep(1) is a meta-character matching any character.
So empty lines won't be listed (as if that makes any sense here).

>> it, and writes those lines to it's output, which is the same output
>> stream as your program.
>>
>> system("ls | grep .") starts a shell, with output directed to the same
>> destination as your stdout, and then runs the pipeline
>> ls | grep .
>> in that shell. When the pipeline finishes, the returncode from the
>> shell is passed back through the system() call and on to your program
>> as it's return value.
>
> Does the grep'ing in this line fall under this criticism of it:
>
> http://ubuntard.com/2009/12/command-line-idiocy/
>>> I changed the directory and get 256, which seems to indicate failure:
>>> $ gcc -D_GNU_SOURCE -Wall -Wextra rr2.c -o out
>>> $ ./out
>>> 256
>>> $ cat rr2.c
>>> #include <stdio.h>
>>> #include <stdlib.h>
>>> int main()
>>> {
>>> printf("%d\n",system("ls | grep /etc/"));
>>> return 0;
>>>
>>> }
>>>
>>> // gcc -D_GNU_SOURCE -Wall -Wextra rr2.c -o out
>>>
>>> $
>>>
>>> q2) Why didn't this work?

Because ls(1) won't display the / characters? So grep(1) won't match anything.

>>
>> Because your current working directory didn't have any files with a
>> name that included the characters
>> /etc/
>> in it.
>
> $ gcc -D_GNU_SOURCE -Wall -Wextra rr2.c -o out
> $ ./out
> 256
> $ cat rr2.c
> #include <stdio.h>
> #include <stdlib.h>
> int main()
> {
> printf("%d\n",system("ls | grep ~/etc/"));
> return 0;
> }
>
>
>
> // gcc -D_GNU_SOURCE -Wall -Wextra rr2.c -o out
>
> $
>
> What am I trying to do here?

(You should answer that.)

>
>>
>> I /would/ have expected your program to still print the number,
>> representing the return value from the system() call.
>
> It does. 256.
>>
>>
>>> q3) In the unix environment, is 'system' the best way to make a system
>>> call?
>>
>> In Unix, a system call (or syscall) is /not/ that which you get when
>> you call the system(1) function. system(1) is a good way to have your
>> program initiate other programs, but not the best way (popen(3) or
>> fork(2)/exec(2) would be better, for some values of "better").
>
> I'm not sure what I've done here:
> $ gcc -D_GNU_SOURCE -Wall -Wextra rr3.c -o out
> rr3.c: In function �main�:
> rr3.c:15: warning: suggest braces around empty body in an �if� statement
> $ ./out
[snip data]
> $ cat rr3.c
> #include <stdio.h>
> #include <stdlib.h>
> #define PATH_MAX 4096
> int
> main ()
> {
>
> FILE *fp;
> int status;
> char path[PATH_MAX];
>
> printf ("%d\n", system ("ls | grep ."));
> fp = popen ("ls *", "r");
> if (fp == NULL)
> /* Handle error */ ;
> while (fgets (path, PATH_MAX, fp) != NULL)
> printf ("%s", path);
> status = pclose (fp);
> if (status == -1)
> {
> /* Error reported by pclose() */
> }
> else
> {
> /* Use macros described under wait() to inspect `status' in order
> to determine success/failure of command executed by popen() */
> }
> return 0;
> }
> // gcc -D_GNU_SOURCE -Wall -Wextra rr3.c -o out
> $
>
> Can you say a few words about what precisely happens here:
>
> fp = popen ("ls *", "r");

man 3 popen

The popen() function opens a process by creating a pipe, forking,
and invoking the shell. Since a pipe is by definition unidirectional,
the type argument may specify only reading or writing, not both; the
resulting stream is correspondingly read-only or write-only.

Let me add; the ls * command will be run in the above mentioned opened
shell. All output from that command can be read ("r") through consecutive
read operations on the file descriptor which was returned from the popen()
call.

Janis
From: John Gordon on
In <7vgdhcFcf5U1(a)mid.individual.net> Phred Phungus <Phred(a)example.invalid> writes:

> printf("%d\n",system("ls | grep ."));

> // gcc -D_GNU_SOURCE -Wall -Wextra rr1.c -o out

> Output seemed typical:

> $ ./out
> 9vx-0.12
> 9vx-0.12.tar.bz2
> a2.c
> ...
> winter1.c~
> z
> 0

> Apparently, the zero is expected.

You told printf to print a decimal number; the return value of sustem().
It returned zero, so printf printed it. Were you not expecting that?

> q1) What exactly is happening with "ls | grep ." ?

system() is performing an ls, then passing that output through grep,
only printing those lines which contain a character (and they all do,
so all the lines get printed.)

> I changed the directory and get 256, which seems to indicate failure:
> $ gcc -D_GNU_SOURCE -Wall -Wextra rr2.c -o out
> $ ./out
> 256
> $ cat rr2.c
> #include <stdio.h>
> #include <stdlib.h>
> int main()
> {
> printf("%d\n",system("ls | grep /etc/"));
> return 0;
> }

> // gcc -D_GNU_SOURCE -Wall -Wextra rr2.c -o out

> $

> q2) Why didn't this work?

256 represents the return code of grep, indicating that it did not find
any text lines matching its search pattern "/etc/".

(actually, I think 256 is the combined return code of the grep command
and the shell that was spawned to execute it.)

> q3) In the unix environment, is 'system' the best way to make a system
> call?

Often yes, but it depends exactly what you're trying to do.

--
John Gordon A is for Amy, who fell down the stairs
gordon(a)panix.com B is for Basil, assaulted by bears
-- Edward Gorey, "The Gashlycrumb Tinies"