![]() |
![]() |
#1 |
"Ben"
Feb 2007
25·3·5·7 Posts |
![]()
Ok, so I understand how arguments to a C program are handled in main; they show up as char array elements in a char array, of size 'argc'. What I can't figure out is how you can get at data passed into a program through the unix pipe, for instance, or redirected from a file.
For example, if from the command line I type % echo "2+2" | yafu where yafu is the C program receiving the string from echo, then "2+2" does not show up in **argv, and argc == 1. Same if I do % yafu < in.txt where in.txt contains "2+2" Anyone here know how to get at data through arguments to main in these cases? A non-trivial amount of googling didn't get me anywhere... maybe I'm just a bad googler ![]() - ben. |
![]() |
![]() |
![]() |
#2 |
"Ben"
Feb 2007
64408 Posts |
![]()
10 seconds after posting the above, I figured something out, I think. The answer is you scan it in from stdin!
So, new question: how can I tell if what I got from scanf came from a pipe or a redirection rather than from the keyboard? My problem is that I'm building in the ability for yafu to take a command line expression, evaluate it, and exit. In addition to the normal mode of operation which is open, wait for manual input, evaulate, wait for next input, etc. If I scanf in a string from a pipe, because I can't tell it came from a pipe, the program doesn't exit like I want it to, it just waits for the next input. - ben. |
![]() |
![]() |
![]() |
#3 |
"Ben"
Feb 2007
25·3·5·7 Posts |
![]()
Ok, here's my hackish workaround. I'd still like to know how to do this right...
Code:
start = clock(); //wait for input from user while (1) { //get a new random seed after every transaction srand((unsignedint)time(&tt)); //if there are command line arguments, don't wait for user input //the expression to be evaluated is already in 's' if (argc <= 1) { printf("\n"); fflush(stdout); scanf("%[^\n]",s); //read everything up to carriage return stop = clock(); //hack. if no time has elapsed, this must have come from //the pipe or a redirect. treat the same as a command line expression. if (((double)(stop - start)/(double)CLOCKS_PER_SEC) < 0.01) do_once = 1; } . . . |
![]() |
![]() |
![]() |
#4 |
Tribal Bullet
Oct 2004
2×3×19×31 Posts |
![]()
The msieve demo application uses a switch (-m) to determine whether to expect inputs from a pipe or from file. In principle you can assign a FILE * to either stdin or the result of fopen() and then proceed like normal, but IIRC when I tried that there were problems determining when a list of numbers was finished.
|
![]() |
![]() |
![]() |
#5 |
"Nancy"
Aug 2002
Alexandria
2,467 Posts |
![]()
There is some function to query open file descriptors that tells, among other things, whether the fd points to a tty or to a disk file. That's the usual way of determining whether stdio has been redirected, afaik. But for the life of me, I can't remember what the function is called... can someone help out here?
Btw, assigning something to stdin or stdout usually works, but is non-portable, strictly speaking... freopen() should be used instead. Alex Last fiddled with by akruppa on 2008-12-04 at 21:27 Reason: typo |
![]() |
![]() |
![]() |
#6 |
"Ben"
Feb 2007
1101001000002 Posts |
![]()
This is getting bizarre.
The following works for everything (windows, linux, gcc, MSVC, pipes, redirects, normal operation) *except* pipes in linux. Code:
fseek(in,-1,SEEK_END); if (argc > 1) { //handle the case where we have command line arguments do_once = 1; strcpy(s,argv[1]); } else { //on linux, gcc-3.2.3, this works for redirects but not for pipes //works fine for both on win, MSVC express edition 2008 if (ftell(stdin) >= 0) { rewind(stdin); fgets(s,1024,in); do_once = 1; } } |
![]() |
![]() |
![]() |
#7 |
"Nancy"
Aug 2002
Alexandria
46438 Posts |
![]()
Return value of -1 means an error. Does the global variable errno get set to something? According to "man 3 fseek", if the stream is not seekable (and I would expect a pipe not to be), errno should be set to EBADF.
Alex |
![]() |
![]() |
![]() |
#8 |
"Ben"
Feb 2007
25·3·5·7 Posts |
![]() ![]() So the bizarre thing is that windows is fine with seeking in a pipe. In windows I do echo "2+2" | yafu and get fseek returned 0, errno = 0 while in linux I get fseek returned -1, errno = 29 |
![]() |
![]() |
![]() |
#9 |
"Nancy"
Aug 2002
Alexandria
2,467 Posts |
![]()
I think in MS-DOS times, redirection didn't really do piping but created temporary files since the programs could not run concurrently (no multi tasking), so in MS-DOS an fseek() call on a pipe may have worked. I don't know if the temp file thing is still the case in multi-tasking capable Windows versions, but even if it isn't, MS may have decided to make fseek() not return an error in Windows if it didn't in MS-DOS. At any rate, I would expect fseek() on pipes not to be portable at all.
I'll try to find out again how to determine whether a file descriptor points to a tty. Alex Last fiddled with by akruppa on 2008-12-04 at 23:10 |
![]() |
![]() |
![]() |
#10 |
Tribal Bullet
Oct 2004
DCE16 Posts |
![]()
Alex,
Do you mean fstat() ? The man page seems to indicate it almost gets you what you need, but it works with unix file descriptors and not FILE structures. BTW I meant that stdin and stdout are lvalues and can be used as the RHS in an assignment (they are not compile-time constants though) |
![]() |
![]() |
![]() |
#11 |
"Ben"
Feb 2007
25×3×5×7 Posts |
![]()
I could also make it work if there were such a thing as a non-blocking read of a character from a stream. I'm showcasing my C ignorance here, but is there such a function? If so then I could just test a read, and handle the error if there was nothing there, rather than have the program sit there waiting for input. No beans for fgetc, getc, fgets, scanf...
|
![]() |
![]() |
![]() |
Thread Tools | |
![]() |
||||
Thread | Thread Starter | Forum | Replies | Last Post |
More User friendly main page | Sutton Shin | mersennewiki | 0 | 2012-09-29 08:03 |
What is the main cause of the high oil prices? | MooooMoo | Lounge | 17 | 2009-04-10 22:36 |
Question about RAM usage for dual-core for OPN's main effort. | jasong | GMP-ECM | 18 | 2006-07-17 00:23 |
[Problem] Going to main page when logging in | alpertron | mersennewiki | 0 | 2006-01-03 13:23 |
Main Computer Dead | Prime95 | Hardware | 11 | 2004-11-02 22:29 |