From: Phred Phungus on 6 Mar 2010 20:23 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 6 Mar 2010 21:25 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 6 Mar 2010 22:53 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 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 7 Mar 2010 00:08 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 7 Mar 2010 03:33
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" |