From: Dominic Fandrey on
On 07/03/2010 03:25, Lew Pitcher wrote:
> 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, ...

Most certainly not. "grep ." will match anything. "grep \\." would
match lines with a period in it.

--
A: Because it fouls the order in which people normally read text.
Q: Why is top-posting such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?
From: Janis Papanagnou on
John Gordon wrote:
> 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/".

man 1 grep

Normally, exit status is 0 if selected lines are found and 1 otherwise.
But the exit status is 2 if an error occurred

man 3 system

The value returned is -1 on error (e.g. fork failed), and the return
status of the command otherwise. This latter return status is in the
format specified in wait(2). Thus, the exit code of the command will be
WEXITSTATUS(status). In case /bin/sh could not be executed, the exit
status will be that of a command that does exit(127).

man 2 wait

WEXITSTATUS(status)
evaluates to the least significant eight bits of the return code of the
child which terminated, which may have been set as the argument to a call
to exit() or as the argument for a return statement in the main program.

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

The shells alone return codes above 128 (resp. 256, depending on the shell)
to return signal numbers that lead to a process's termination. Just BTW.

I haven't fiddled much with system(3) - the value of 256 looks somewhat
strange to me - but I'd have anyway used the least significant eight bits
only in case that I am interested in the exit status of normal termination
of an external command through the C system() call, as described in the man
pages.

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

No, because it invokes an intermediate shell. If you're programming e.g. in
the C language use the system calls directly using the libraries. Check the
return code of the library functions and inspect ERRNO in case of errors.

Janis

>
> Often yes, but it depends exactly what you're trying to do.
>
From: John Gordon on
In <7viu6dFg7vU1(a)mid.individual.net> Phred Phungus <Phred(a)example.invalid> writes:

> Alright, I'm starting to see the light here but I'm struggling with grep
> a bit. For example, I don't see why the single quotes don't work:

> $ ls | grep '.c'
> a2.c
> a2.c~
> a.c
> a.c~
> backups1
> ...

The quotes worked just fine -- their purpose is to protect certain
metacharacters from being interpreted by the shell. But . is not such a
character, so the quotes had no effect.

> This looks right tho:

> $ ls | grep \\.c
> a2.c
> a2.c~
> a.c
> a.c~
> bits6.c
> bits6.c~
> bits7.c
> bits7.c~
> f1.c~
> lc1.c
> lc1.c~

> I'd like to herd files matching \\.c into backup1, a subdirectory. What
> am I not doing right here:

> $ ./out
> mv: missing file operand
> Try `mv --help' for more information.

> fp = popen ("mv | grep \\.c backups1/.", "r");

This command is all kinds of wrong. You're executing mv, with no arguments
or parameters at all, and passing the *output* of mv into grep. What did
you expect this to do, exactly?

Try this command instead:

mv *.c backups1/.

--
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"

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

>> 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 tried exec on the terminal, and it disappeared. My experiments with
other ways to invoke a shell aren't looking so good. In particular, I
see no output for one of the printf's and can't see for the life of me
why it is ls'ing twice:

$ gcc -D_GNU_SOURCE -Wall -Wextra rr5.c -o e
$ ./e
9vx-0.12
9vx-0.12.tar.bz2
a2.c
....
ss2.c~
ss3.c
ss3.c~
unleashed
winter1.c
winter1.c~
z
9vx-0.12
9vx-0.12.tar.bz2
a2.c
a2.c~
a2.o
a.c
a.c~
a.o
backups1
b.f90
b.f90~
....
ss3.c~
unleashed
winter1.c
winter1.c~
z
$ cat rr5.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#define PATH_MAX 4096
int
main ()
{

int ret;
pid_t ID;

ID = fork();
printf ("ID is %d", ID);
ret = execl ("/bin/ls", "ls", "-1", (char *)0);
printf ("ret is %d", ret);

return 0;
}
// gcc -D_GNU_SOURCE -Wall -Wextra rr5.c -o e
$

??
--
fred
From: Seebs on
On 2010-03-08, Phred Phungus <Phred(a)example.invalid> wrote:
> I tried exec on the terminal, and it disappeared. My experiments with
> other ways to invoke a shell aren't looking so good. In particular, I
> see no output for one of the printf's and can't see for the life of me
> why it is ls'ing twice:

You know, I've been watching you ignore any suggestion that maybe reading
documentation might help for a few months now.

Has it ever occurred to you that when you want to know what something does,
a good starting point might be to READ THE DOCUMENTATION?

> ID = fork();
> printf ("ID is %d", ID);

Problem number one: You aren't printing a newline. In general, you should
make sure that any message you want to see ends with a newline.

But here we are. You've called fork(), so you now have two programs running.
In one, ID is non-zero. In the other it's zero.

But, since you don't DO anything with that ID (say, make following behavior
conditional on it), BOTH OF THEM RUN ALL THE SAME CODE.

This is really, really, basic. You called fork(). You have two processes.
They are doing the same thing. The only difference between them is the
value stored in "ID", and you haven't tested it.

> ret = execl ("/bin/ls", "ls", "-1", (char *)0);

So now each of them executes ls. There is no reason for either of them not
to, so they both do.

If you can't see this, and you can't be bothered to read the documentation,
and you can't somehow be convinced not to randomly change things from the
examples you're working from and then complain that it doesn't make sense...

Why are you posting? You're taking every step possible to prevent yourself
from learning anything.

> printf ("ret is %d", ret);

Unless execl() fails, this is never reached.

Seriously, you need to start reading the man pages. Nothing here is not
CLEARLY explained in the documentation. If you would read the documentation
before asking questions, and ask questions that show that you've made some
kind of real effort to figure out what's going on, you'd get more helpful
responses.

-s
--
Copyright 2010, all wrongs reversed. Peter Seebach / usenet-nospam(a)seebs.net
http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!