ron@sc50.UUCP ( Ron Winnacott ) (06/06/89)
Hello net. Can anyone tell me how to redirect stdin when I use execl to start a new program. The problem I am haveing is this, I am writing a C program that forks then execl's a new program, But I need to use a redirect "<" in the execl call. execl("/bin/mail","mail","ron","<","/tmp/tfile",NULL); The fork works fine, and mail starts and has a PPID of 1, but it just sits there waiting for the letter and EOF to come from stdin. If you can help me please email to !uunet!attcan!telly!sc50!ron Thanks ron winacott. -- Ron Winacott. Unisys Canada, Support center. phone- (416) 495-4585 uucp - uunet!attcan!telly!sc50!ron *** All comments/statements made are MINE and MINE alone. ***
pc@cs.keele.ac.uk (Phil Cornes) (06/08/89)
From article <414@sc50.UUCP>, by ron@sc50.UUCP ( Ron Winnacott ): > Hello net. > > Can anyone tell me how to redirect stdin when I use execl to > start a new program. The problem I am haveing is this, I am writing > a C program that forks then execl's a new program, But I need to > use a redirect "<" in the execl call. > > execl("/bin/mail","mail","ron","<","/tmp/tfile",NULL); > The exec() system call does not know anything about I/O redirection, that is all dealt with by the shell. If you want to redirect the input of mail as above then you will have to do it yourself in between your fork() call and your execl() call, something like this: if (fork()) { /* parent code */ } else { close(0); /* close child input */ open("/tmp/tfile",O_RDONLY); /* open() takes the first available file descriptor - here 0 - so any subsequent stdin reads will come from the file /tmp/tfile */ execl("/bin/mail","mail","ron",NULL); /* open file descriptors are preserved across exec() */ }
torsten@pcsbst.UUCP (torsten) (06/09/89)
In article <414@sc50.UUCP> ron@sc50.UUCP ( Ron Winnacott ) writes: >Hello net. > >Can anyone tell me how to redirect stdin when I use execl to >start a new program. The problem I am haveing is this, I am writing >a C program that forks then execl's a new program, But I need to >use a redirect "<" in the execl call. > >execl("/bin/mail","mail","ron","<","/tmp/tfile",NULL); I think this should do it: execl("/bin/sh","sh","/bin/mail ron < /tmp/tfile",NULL); Or you have to redirekt your stdin after fork and befor execl to /tmp/tfile. Hope that helps, Torsten. --- Name : Torsten Homeyer Company : PCS GmbH, Pfaelzer-Wald-Str. 36, 8000 Munich W-Germany. UUCP : ..[pyramid ;uunet!unido]!pcsbst!tho (PYRAMID PREFERRED!!) DOMAIN : tho@pcsbst.pcs.[ COM From rest of world; DE From Europe ]
mpl@cbnewsl.ATT.COM (michael.p.lindner) (06/10/89)
In article <414@sc50.UUCP>, ron@sc50.UUCP ( Ron Winnacott ) writes: > Hello net. > execl("/bin/mail","mail","ron","<","/tmp/tfile",NULL); > Ron Winacott. Unisys Canada, Support center. The problem is that the "<" meaning redirection is a feature of the shell, not the operating system execl() call. You can call system, described in section 3 of your programmer's guide, instead, such as: char buffer[32]; /* make sure it's big enough */ char *ron = "ron"; /* or whoever */ char *tempfile = "/tmp/tfile"; /* or whatever */ sprintf(buffer, "/bin/mail %s < %s", ron, tempfile); if (system(buffer) == 0) /* yay! I sent mail! */ ; else /* boo! It failed! */ ; Mike Lindner attunix!mpl AT&T 190 River Rd. Summit, NJ 17901
djones@megatest.UUCP (Dave Jones) (06/10/89)
> In article <414@sc50.UUCP> ron@sc50.UUCP ( Ron Winnacott ) writes: >>Hello net. >> >>Can anyone tell me how to redirect stdin when I use execl to >>start a new program. The problem I am haveing is this, I am writing >>a C program that forks then execl's a new program, But I need to >>use a redirect "<" in the execl call. >> Under BSD Unix, you use dup2. (All you folks who want only to see complete, production quality, QA-tested code, wine-soaked and sugar-cured, shut your eyes quick!) It goes something like this: if((pid = fork()) == 0) { /* This the the spawned process. */ int file_descriptor = open("foo/bar", "r"); if(file_descriptor == -1) { perror("foo/bar"); _exit(-1); } else { dup2(file_descriptor,0); /* make it the standard input */ close(file_descriptor); /* Here, close any of the parent process's file-descriptors that * will not be used by this process.. */ /* and now... */ execl("prog", "arg0", /* etc */ (char*)0); /* It's an error if we get to here.... */ /* etc.. */ _exit(-1); } } else { if(pid != -1) { /* provide for "reaping" the process. */ /* See man page for "wait" */ } else { /* Could not execl the program... */ } }
vlcek@mit-caf.MIT.EDU (Jim Vlcek) (06/11/89)
In article <5587@goofy.megatest.UUCP> djones@megatest.UUCP (Dave Jones) writes: >> In article <414@sc50.UUCP> ron@sc50.UUCP ( Ron Winnacott ) writes: >>>Can anyone tell me how to redirect stdin when I use execl to >>>start a new program. > >Under BSD Unix, you use dup2. plus a bit of code showing how to fork(), dup2(), and then execl() to get the desired effect. I think a much better way, under BSD, is to use freopen() to attach stdin to the redirected file. Such redirection is, in fact, precisely the intended usage of this function call. Is freopen() a Berklism, or do you have that in Sys V as well? I'm almost completely unfamiliar with the latter. The original example, passing the string "<" and the redirected file, was so innocently misguided I really got a laugh out of it. execl()'ing "/bin/sh" to parse the command, or using system(), on the other hand, were somewhat less amusing. Jim Vlcek (vlcek@caf.mit.edu uunet!mit-caf!vlcek)
guy@auspex.auspex.com (Guy Harris) (06/13/89)
(Followups redirected to "comp.unix.questions", which was the place where the original question should probably have appeared.) >I think a much better way, under BSD, is to use freopen() to attach >stdin to the redirected file. Such redirection is, in fact, precisely >the intended usage of this function call. When using "freopen()" in this case, the implementations on all the UNIX systems with which I'm familiar it will do: 1) an "fclose" of "stdin", which closes the standard input ("standard input" is file descriptor 0, to which "stdin" happens to refer; it's not "stdin" itself) by virtue of doing a "close" on "stdin"s file descriptor (as indicated, FD0, barring some unlikely train of events); 2) an "open" of the new file, which, if file descriptor 0 was recently closed, should yield 0 as the new file descriptor. The net result will, in fact, make FD0 point to the new file. "freopen()" also does some fiddling with standard I/O information for "stdin", which is not necessary here (since the "execl" will, on most if not all UNIX/POSIX implementations, cause the process's data space to be discarded, and thus discard all the standard I/O information for that process). So "freopen()" is basically a convenient wrapper for the underlying operations the program should do anyway. >Is freopen() a Berklism, No, it's been in UNIX for quite a while - V7 at least. >The original example, passing the string "<" and the redirected file, >was so innocently misguided I really got a laugh out of it. >execl()'ing "/bin/sh" to parse the command, or using system(), on the >other hand, were somewhat less amusing. I'd certainly say they were less amusing, since they actually form a fairly convenient wrapper for these kinds of operations, and would seriously consider using them for this sort of thing. If the guy wanted to redirect the input of "mail" to a pipe from some other program, for example, using "system" (or an "execl()" of "/bin/sh" with the "-c" flag, which is what "system()" does after it does the "fork()") is a lot more convenient than constructing the pipeline yourself.
chris@mimsy.UUCP (Chris Torek) (06/14/89)
[Astounding, an article which actually belongs in both a C newsgroup and a Unix newsgroup.] In article <2489@mit-caf.MIT.EDU> vlcek@mit-caf.MIT.EDU (Jim Vlcek) writes: >... [someone gave] a bit of code showing how to fork(), dup2(), and then >execl() to get the desired effect. > >I think a much better way, under BSD, is to use freopen() to attach >stdin to the redirected file. Such redirection is, in fact, precisely >the intended usage of this function call. Is freopen() a Berklism, or >do you have that in Sys V as well? freopen() is a standard <stdio.h> function and appears in the pANS; most existing implementations should already provide it: FILE *freopen(const char *name, const char *type, FILE *stream) replaces the current instance of `stream' (whatever it may be connected to) with one connected to the given file `name', opened according to `type'. The type argument has the same format as for fopen ("r", "w", "a", "rb", "wb", "r+", and so forth). If the named file cannot be connected to the given stream, the current connection is closed and freopen() returns (FILE *)NULL; otherwise, the return value is equal to `stream'. [End C-specific topic; on to Unix-specific topic.] This is not really a better way to redirect input after a fork(), because freopen() makes no promises as to how it goes about its job. In particular, it does *not* guarantee that fileno(stream) will be the same after the operation as it was before. There are, however, a number of Unix utility programs whose source assume that it will, so it probably will; but relying on this is a bad idea. I found out about the various naughty programs when I changed freopen() to open the new file before closing the old. In particular, this is necessary to make freopen("/dev/stdin", "r", stdin) work. I had to add code to dup2() the new descriptor over the old one (after my first change, the above line caused fileno(stdin) to be 3). This does, however, change the behaviour from the original, in which f1 = fopen("something", "r"); ... error checking deleted ... f2 = fopen("somethingelse", "r"); ... fclose(f1); freopen("yetanother", "r", f2); caused fileno(f2) to decrease, e.g., from 4 to 3. (This is not as bad as a few programs which have code like fileno(fp) = 2; Yow!) Anyway, freopen() will probably work, but makes no guarantees, and does more work than necessary. In addition, if you use vfork() rather than fork(), freopen() will clobber data in the parent process. Stick with dup2(). But use it correctly (note in particular the line marked with an arrow): /* initial error checking occurs in parent process */ newfd = open(newfile, 0); if (newfd < 0) ... error ... switch (pid = fork()) { case -1: ... error ... case 0: /* child */ -> if (newfd != 0) { if (dup2(newfd, 0) < 0) ... error ... if (close(newfd)) ... error ... } /* else it was already fd 0 */ execl(pathname, argv0, argv1, argv2, ..., (char *)NULL); ... error ... } /* parent */ (void) close(newfd); /* if it fails, what would we do differently? */ while ((w = wait(&status)) != pid) if (w == -1 && errno != EINTR) ... error ... -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris
mhoffman@infocenter.UUCP (Mike Hoffman) (06/15/89)
in article <352.nlhp3@oracle.nl>, bengsig@oracle.nl (Bjorn Engsig) says: | In article <3709@tank.uchicago.edu> matt@oddjob.uchicago.edu (Matt Crawford) writes: |>In article <414@sc50.UUCP>, ron@sc50 ( Ron Winnacott ) writes: |>) Can anyone tell me how to redirect stdin when I use execl ... |>) execl("/bin/mail","mail","ron","<","/tmp/tfile",NULL); |> |>So help me, if I see even ONE answer to this question posted in |>comp.unix.WIZARDS, I'll scream! | Hey come on, there is no need to flame this in this way. | Maybe you should ask the administrator of the coming monthly posting to add | a few short examples of how to use fork and exec. Then, in article <851@pcsbst.UUCP>, torsten@pcsbst.UUCP (torsten) says: | I think this should do it: | execl("/bin/sh","sh","/bin/mail ron < /tmp/tfile",NULL); I think Bjorn may be right. . .let's hope we don't see any more of this :-) ____ Michael J. Hoffman Manufacturing Engineering Encore Computer Corporation UUCP: {uunet,codas!novavax,sun,pur-ee}!gould!mhoffman "My opinions are my own and are not to be employed with those of my confuser."
john@frog.UUCP (John Woods) (07/22/89)
In article <851@pcsbst.UUCP>, torsten@pcsbst.UUCP (torsten) writes: > In article <414@sc50.UUCP> ron@sc50.UUCP ( Ron Winnacott ) writes: > >Hello net. > >execl("/bin/mail","mail","ron","<","/tmp/tfile",NULL); > I think this should do it: > execl("/bin/sh","sh","/bin/mail ron < /tmp/tfile",NULL); Or, you might try something general-purpose like: fexecve(sin, sout, serr, av, ev) int sin, sout, serr; char **av, *ev; { dup2(sin, 0); /* note: dup2(0, 0) is a no-op */ dup2(sout, 1); dup2(serr, 2); if (sin > 2) close(sin); /* delete extra file handles */ if (sout > 2) close(sout); if (serr > 2) close(serr); return execve(av, ev); } Two provisos: System V users will want to use fcntl(, F_DUPFD, ) instead of dup2() (and note that it is a little tricky to do that correctly), and this doesn't quite work if you do silly things like fexecve(1, 2, 0, argvec, envp); though it can be made to work if need be. (Left to the student as an exercise :-) -- John Woods, Charles River Data Systems, Framingham MA, (508) 626-1101 ...!decvax!frog!john, john@frog.UUCP, ...!mit-eddie!jfw, jfw@eddie.mit.edu People...How you gonna FIGURE 'em? Don't bother, S.L.--Just stand back and enjoy the EVOLUTIONARY PROCESS...
djones@megatest.UUCP (Dave Jones) (07/23/89)
From article <2489@mit-caf.MIT.EDU>, by vlcek@mit-caf.MIT.EDU (Jim Vlcek): > In article <5587@goofy.megatest.UUCP> djones@megatest.UUCP (Dave Jones) writes: >>> In article <414@sc50.UUCP> ron@sc50.UUCP ( Ron Winnacott ) writes: >>>>Can anyone tell me how to redirect stdin when I use execl to >>>>start a new program. >> >>Under BSD Unix, you use dup2. > > plus a bit of code showing how to fork(), dup2(), and then execl() to > get the desired effect. > > I think a much better way, under BSD, is to use freopen() to attach > stdin to the redirected file. Maybe. But that wasn't the question. The question was how to redirect stdin when using execl, not how to rebind stdin after the execl. Anyway, using freopen is only possible if you have access to the source code of all the programs which will be execled, are already responsible for their content, and can easily modify and dependably distribute the modified version to all sites which will use the execling program. It may be much much easier to redirect it using dup2 on the execling side -- I presume that's what the various shells do. -- Dave
guy@auspex.auspex.com (Guy Harris) (08/03/89)
>Two provisos: System V users will want to use fcntl(, F_DUPFD, ) instead of >dup2() Although: 1) S5R3 has "dup2()" and 2) 4.[23]BSD has "fcntl(F_DUPFD)" so if you're willing to rule out older systems you can avoid polluting your code with "#ifdef"s.