jtanner@jack.sns.com (Jason Tanner) (04/28/91)
I have been programming C for a while on IBM compats. using Turbo-C from Borland. Now I would like to move up to programing C in the UNIX enviroment. I know how to use all the regular C commands but I would like to know how to use UNIX commands from within a C program. For example to have the option to show who is online from within a program. I dont want this done with a shell escape I want it to be an potion like from a menu/list. Thank you in advance. Please Email or post all replies. -- |----------------------------------------------------------------------------| | jtanner@jack.sns.com - - Coke IS it! - - Ask me, I don't work here | | This space was intentionally left filled. | |------------------------------Dare to think!--------------------------------|
glenn@curie.ces.cwru.edu (Glenn Crocker) (04/29/91)
jtanner@jack.sns.com (Jason Tanner) writes:
...
I know how to use all the regular C commands but I would like
to know how to use UNIX commands from within a C program. For example
to have the option to show who is online from within a program. I dont
want this done with a shell escape I want it to be an potion like from a
menu/list.
Check out the popen() function. It allows you to open a pipe to a
specified program and then read from it or write to it just like a
normal file descriptor (FILE *). If you'd like an example program
that uses it, mail me.
--
Glenn Crocker | Your milage may vary.
glenn@ces.cwru.edu | Light bar not for occupant protection.
CWRU, Cleveland, OH | Don't drive on frozen lakes.
W (216)368-6133 H (216)754-1314 | Do not taunt Happy Fun Ball.
weimer@garden.ssd.kodak.com (Gary Weimer (253-7796)) (04/29/91)
In article <1991Apr28.153127.24926@jack.sns.com> you write: |> |> I have been programming C for a while on IBM compats. using Turbo-C |> from Borland. Now I would like to move up to programing C in the UNIX |> enviroment. I know how to use all the regular C commands but I would like |> to know how to use UNIX commands from within a C program. For example |> to have the option to show who is online from within a program. I dont |> want this done with a shell escape I want it to be an potion like from a |> menu/list. Since I don't see any other posts, I'll post and maybe save you some mail. The easiest thing to do is use system(3). Since you're new to UNIX, this means the system command in section 3 of the man pages. If you want to see the man page entry for this, type 'man 3 system' (without the quotes). You might also want to look at fork(2V) (use 'man 2 fork', not 'man 2V fork') and execl(3V). weimer@ssd.kodak.com ( Gary Weimer )
shap@shasta.Stanford.EDU (shap) (04/29/91)
In article <GLENN.91Apr29104336@curie.ces.cwru.edu> glenn@curie.ces.cwru.edu (Glenn Crocker) writes: > >Check out the popen() function. It allows you to open a pipe to a >specified program and then read from it or write to it just like a >normal file descriptor (FILE *). If you'd like an example program >that uses it, mail me. popen(3) also has an interesting "feature." It is essentially useless unless the program you run from it doesn't read from stdin. Here's why. A typical filter works, logically, on the model read all input process (churn churn) write all output A real UNIX filter, on the other hand, frequently operates on the model read some input process it write result read some more input process it ... So here's what can happen if you aren't careful: 1. Parent program does a popen(3), and happily starts writing to the pipe, assuming that it should dump the whole of the input into the child program. 2. Child program (the filter) processes some input and writes results to it's output (which the parent will eventually read). 3. Pipe buffer on the child output fills, because the parent hasn't done any reads of the results yet. 4. Child blocks, trying to write output to the pipe. 5. Pipe buffer on the child input fills, because the child is no longer reading it. 6. Parent blocks. Et Voilla! instant deadlock. For those of you who don't believe this happens, talk to some people who have had to port various window managers. Now here's the bad news. To work around this limitation, you either have to 1. Know the pipe buffer size and operate accordingly 2. Use asynchronous IO and buffer up the return stuff yourself both of which are machine dependent (buf size clearly, not all machines have asynch I/O). The portable solution is to check how many bytes are writeable to the pipe at any given time and if there aren't enough switch to buffering up the input for a while to allow the child to run. Needless to say, this solution is UGLY. Expert quiz question for the week: write a version of popen(3) that doesn't have this feature. [This problem was first brought to my attention by Mike Bianchi. I think he may have been the author of popen(3).] Jonathan Shapiro
torek@elf.ee.lbl.gov (Chris Torek) (04/30/91)
(Having just written a new man page for popen, I cannot resist following up, even though I should be off getting some food....) In article <174@shasta.Stanford.EDU> shap@shasta.Stanford.EDU (shap) writes: >popen(3) also has an interesting "feature." ... Et Voilla! instant deadlock. This cannot happen directly because of popen(). The reason is trivially simple: popen opens either for reading or for writing, never both. Thus popen() is unable to create a loop, and deadlock occurs only in the presence of a pipe loop. (The situation described in `...' is the simplest case, where A writes to B and then reads back from B: A->B->A. The problem also occurs in longer loops such as A->B->C->D->A.) >For those of you who don't believe this happens, talk to some people >who have had to port various window managers. These generally use bidirectional entities such as ptys and must therefore provide their own synchronization mechanisms. -- In-Real-Life: Chris Torek, Lawrence Berkeley Lab CSE/EE (+1 415 486 5427) Berkeley, CA Domain: torek@ee.lbl.gov
ron@well.sf.ca.us (Ronald Hayden) (05/01/91)
jtanner@jack.sns.com (Jason Tanner) writes: > I have been programming C for a while on IBM compats. using Turbo-C >from Borland. Now I would like to move up to programing C in the UNIX >enviroment. I know how to use all the regular C commands but I would like >to know how to use UNIX commands from within a C program. For example >to have the option to show who is online from within a program. I dont >want this done with a shell escape I want it to be an potion like from a >menu/list. > Thank you in advance. Please Email or post all replies. >-- There are actually several ways to do this (check out the book C Programming In a UNIX Environment for a complete discussion), but for a simple command such as "who", you can simply: #include <stdio.h> main () { printf("\nTesting the UNIX 'who' command --\n"); system("who"); printf("\nDone.\n"); exit(1); }
rearl@gnu.ai.mit.edu (Robert Earl) (05/01/91)
In article <24527@well.sf.ca.us> ron@well.sf.ca.us (Ronald Hayden) writes: | | There are actually several ways to do this (check out the book C | Programming In a UNIX Environment for a complete discussion), but for | a simple command such as "who", you can simply: | | | #include <stdio.h> | | main () | { | printf("\nTesting the UNIX 'who' command --\n"); | system("who"); | printf("\nDone.\n"); | exit(1); | } Since system() [and popen()] does an implicit fork, it's good practice to explicitly flush output buffers before you call this routine; otherwise you end up with possibly duplicated or misleading output. For instance, here's what I get when I redirect the output of this program to a file (block buffered): guest ttyp1 May 1 09:59 (192.35.86.25) rearl ttyp4 May 1 11:05 (dialin.ucsd.edu) ggray ttyp6 May 1 10:43 (geech) guest ttyp8 May 1 11:20 (192.35.86.26) Testing the UNIX 'who' command -- Done. Probably not what you intended. Add "fflush(stdout)" or "fflush(NULL)" (to flush all buffers) before calling system(). I think this is a FAQ in one group or another... By the way, any reason why this program was made to return failure? --robert rearl@gnu.ai.mit.edu rearl@watnxt3.ucr.edu
mike@bria.UUCP (Michael Stefanik) (05/02/91)
In article <174@shasta.Stanford.EDU> you write: |1. Parent program does a popen(3), and happily starts writing | to the pipe, assuming that it should dump the whole of the | input into the child program. | | [ etc, etc on how the process will eventually block ] The popen() will either create the pipe for reading *or* for writing, not both. Therefore, unless your popened command does some pipelining or is blocked on a device, the deadlock situation that you describe cannot occur. (ie: if the parent popens a filter for writing, the parent may only write and never read on the pipe, while the child may only read and never write on the pipe). Michael Stefanik, MGI Inc, Los Angeles | Opinions stated are never realistic Title of the week: Systems Engineer | UUCP: ...!uunet!bria!mike ------------------------------------------------------------------------------- If MS-DOS didn't exist, who would UNIX programmers have to make fun of?
shap@shasta.Stanford.EDU (shap) (05/03/91)
Save postage - the function I was thinking of was a local hack. Not popen(3). sorry for the confusion
imc@prg.ox.ac.uk (Ian Collier) (05/04/91)
In article <REARL.91May1113957@nutrimat.gnu.ai.mit.edu>, rearl@gnu.ai.mit.edu (Robert Earl) wrote: >In article <24527@well.sf.ca.us> ron@well.sf.ca.us (Ronald Hayden) writes: >| #include <stdio.h> >| >| main () >| { >| printf("\nTesting the UNIX 'who' command --\n"); >| system("who"); >| printf("\nDone.\n"); >| exit(1); >| } >Since system() [and popen()] does an implicit fork, it's good practice >to explicitly flush output buffers before you call this routine; [etc] Also, that should really be "/bin/who" rather than just "who", unless you are going to set the path explicitly in the program. Otherwise the program could break on someone else's machine if they do not have /bin in their path (unlikely) or if some other random program called "who" appears before /bin/who in the path. If you do this in an suid program be absolutely certain to specify the path, or else this creates a security loophole. Ian Collier Ian.Collier@prg.ox.ac.uk | imc@ecs.ox.ac.uk
subbarao@phoenix.Princeton.EDU (Kartik Subbarao) (05/09/91)
In article <751.imc@uk.ac.ox.prg> imc@prg.ox.ac.uk (Ian Collier) writes: >In article <REARL.91May1113957@nutrimat.gnu.ai.mit.edu>, rearl@gnu.ai.mit.edu (Robert Earl) wrote: >>In article <24527@well.sf.ca.us> ron@well.sf.ca.us (Ronald Hayden) writes: >>| #include <stdio.h> >>| >>| main () >>| { >>| printf("\nTesting the UNIX 'who' command --\n"); >>| system("who"); >>| printf("\nDone.\n"); >>| exit(1); >>| } >Also, that should really be "/bin/who" rather than just "who", unless >you are going to set the path explicitly in the program. Otherwise the >program could break on someone else's machine if they do not have /bin >in their path (unlikely) or if some other random program called "who" >appears before /bin/who in the path. If you do this in an suid program >be absolutely certain to specify the path, or else this creates a >security loophole. Ha! Using system() in any setuid program itself, regardless of how you invoke the program, leaves a major security hole. -Kartik -- internet% ypwhich subbarao@phoenix.Princeton.EDU -| Internet kartik@silvertone.Princeton.EDU (NeXT mail) SUBBARAO@PUCC.BITNET - Bitnet
les@chinet.chi.il.us (Leslie Mikesell) (05/11/91)
In article <azXkYHbe/UUYI@idunno.Princeton.EDU> subbarao@phoenix.Princeton.EDU (Kartik Subbarao) writes: >Ha! Using system() in any setuid program itself, regardless of how you invoke >the program, leaves a major security hole. In what way is doing a fork() and having the child do a setuid(getuid()) before the system() call any less secure than it would be if the program were not setuid? Some unix versions offer less drastic ways to do it, but that way should work even from a setuid root program under SysV. Les Mikesell les@chinet.chi.il.us