mersenneforum.org arguments to main
 Register FAQ Search Today's Posts Mark Forums Read

 2008-12-04, 18:36 #1 bsquared     "Ben" Feb 2007 2×17×97 Posts arguments to main 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.
 2008-12-04, 18:43 #2 bsquared     "Ben" Feb 2007 2·17·97 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.
 2008-12-04, 19:41 #3 bsquared     "Ben" Feb 2007 1100111000102 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; } . . .
 2008-12-04, 20:59 #4 jasonp Tribal Bullet     Oct 2004 DA116 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.
 2008-12-04, 21:26 #5 akruppa     "Nancy" Aug 2002 Alexandria 246410 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
 2008-12-04, 22:46 #6 bsquared     "Ben" Feb 2007 2·17·97 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; } } In that exceptional case, fseek says that there is nothing to read (returns -1), but if the very next thing I do is attempt to read stdin, it finds the string!! WTF!!
 2008-12-04, 22:50 #7 akruppa     "Nancy" Aug 2002 Alexandria 25·7·11 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
 2008-12-04, 23:00 #8 bsquared     "Ben" Feb 2007 CE216 Posts . yeah, -1 means an error... sorry. 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
 2008-12-04, 23:09 #9 akruppa     "Nancy" Aug 2002 Alexandria 25·7·11 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
 2008-12-04, 23:13 #10 jasonp Tribal Bullet     Oct 2004 DA116 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)
 2008-12-04, 23:14 #11 bsquared     "Ben" Feb 2007 2·17·97 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...

 Similar Threads Thread Thread Starter Forum Replies Last Post Sutton Shin mersennewiki 0 2012-09-29 08:03 MooooMoo Lounge 17 2009-04-10 22:36 jasong GMP-ECM 18 2006-07-17 00:23 alpertron mersennewiki 0 2006-01-03 13:23 Prime95 Hardware 11 2004-11-02 22:29

All times are UTC. The time now is 01:26.

Sat Oct 24 01:26:26 UTC 2020 up 43 days, 22:37, 0 users, load averages: 1.34, 1.31, 1.26