0

My overall objective (motivation for the question):

To provide an executable ìo, from C/C++ compilation/linking, so that a user can execute it alternatively as:

  1. io 3> myout.txt. In this case myout.txt would contain whatever I explicitly send to FD=3 from within my code.

  2. io. In this case an error message is displayed indicating the user the need for 3> .... (Another option is simply losing that output, I still have to decide which is the best option).

I also need to be able to write to stdout/stderr at the same time.

As I see it, if I cannot tell the user "hey, the FD you have to redirect is #3", he cannot be certain he will actually capture the output. So, I conclude I have to hardcode FD=3 (wrong conclusion? how to achieve the objective otherwise?).

That was asked in Smart-write to arbitrary file descriptor from C/C++, and I am following here the indication of SO: "Your post has been associated with similar questions. If these questions don’t resolve your question, ask a new one." ... and here I am.

I admit to being frustrated by my inability to effectively convey my doubts, or otherwise to understand the comments. I could not find a solution to the description above, and this is hopefully a fruitful alternative attempt.


There are quite a few issues that were brought by this, and I asked a few related questions (listed at the bottom). Even if none of the questions received an answer, from the comments posted I ended up quite confused. In particular, I summarized here a specific fundamental question (and that is why I think this is not a dupe):

Can one write C/C++ code that safely and successfully writes to a hand picked file descriptor number, other than FD=0,1,2? (I guess this is the only way to satisfy the objective stated at the top). That would be something like

int main() {
    const int fd = 3;

and then writing to fd with either

    ssize_t nbytes = write(fd, ...

or

    FILE * fp = fdopen(fd, "a");  /* or some other mode */
    fprintf(fp, ...

(and there may be other ways).

In Smart-write to arbitrary file descriptor from C/C++, I posted code that included this usage, and comments posted suggested a way of completing code (even though I did not manage to make it work). In any case, it would be ok to use a hand picked fd number.

In Safety check prior to using fdopen, comments posted suggested I shouldn't ever use a hand picked fd number.

I am then confused about this.

My third related question is Correct way of using fdopen

  • 1
    Any answers you get will be opinion-based, so voting to close. My opinion: Choosing FD numbers by hand is fine. That is the contract between your program and the environment. File descriptors can be shuffled around prior to `exec` if necessary. – Botje May 18 '20 at 09:29
  • From the glibc documentation: "Given an **open** file descriptor, you can create a stream for it with the fdopen function.". Say you would call `fdopen(2374, "a")`, how dou you guarantee that 2374 actually is an open file descriptor (given that it's not a descriptor returned by a call to `open()`)? – Felix G May 18 '20 at 09:41
  • To placate the "never do this" people, you could add command-line options to specify which file descriptors to use, like `fsck -C` does. – Botje May 18 '20 at 09:41
  • The file handle can be inherited in Windows, you should create the handle with bInheritHandle in SECURITY_ATTRIBUTES set to TRUE, and call CreateProcess with inheritHandler parameter set to TRUE. Only the child process can inherit handle. It will be passed in command line, and child process can call DuplicateHandle. – armagedescu May 18 '20 at 09:47
  • @Botje - My guess (I am not sure, that is why I ask!) is that, if there is a safe way to write to a hand picked FD, then it is ok to use it. If there is no safe way to write to a hand picked FD, then it is not ok to use it. That would be it. I am not asking if it is elegant, or if there are other options that one would rather use in various circumstances. So I am puzzled about why this is opinion-based. Would you care for clarifying? I rephrased the question to try "killing" ambiguity. – sancho.s ReinstateMonicaCellio May 18 '20 at 10:04
  • @FelixG - I don't know, and that is why I posted all the related questions... so far, I could not put together a whole picture. – sancho.s ReinstateMonicaCellio May 18 '20 at 10:08
  • 2
    You can only do this reliably if the descriptors are 0, 1, or 2, corresponding to `stdin`, `stdout`, and `stderr`, which are always assigned to those values unless you intervene. You can't rely on any other values being reliably assigned. There is nothing opinion-based about this elementary fact of Unix programming. – user207421 May 18 '20 at 10:11
  • 2
    `Is it ok to use a hand-picked file descriptor number?` Please define the state "ok to use". How does a file descriptor number becomes "ok to use"? When doesn't it is "ok to use"? Unless you define that term, your question is opinion based - everyone interprets "ok to use" differently. – KamilCuk May 18 '20 at 10:12
  • @KamilCuk - I rephrased the question, please check if ambiguity is now gone. And if you have an answer, I would certainly appreciate it!! – sancho.s ReinstateMonicaCellio May 18 '20 at 10:14
  • `Can one write C/C++ code that safely writes to a hand picked file descriptor number?` You can write safely to any number - the function will just return an error and set errno to EBADF... Still _your code_ can be unsafe - if you don't check for such error. How is your question not a duplicate of https://stackoverflow.com/questions/12340695/how-to-check-if-a-given-file-descriptor-stored-in-a-variable-is-still-valid ? – KamilCuk May 18 '20 at 10:17
  • 1
    @KamilCuk Come off it. 'OK to use' doesn't mean anything if you're going to include the failure cases. It is only OK to use by any sensible definition if it's going to work, and there is nothing opinion-based about the conditions required for that. – user207421 May 18 '20 at 10:19
  • @KamilCuk - Yet another edit... I mean to write safely, **and** get in the FD the info I want. I added that explicitly (didn't think it was needed). – sancho.s ReinstateMonicaCellio May 18 '20 at 10:20
  • `and successfully writes` Write your own operating system on which you give that guarantee. What if someone pulls out the harddrive in mid of your program? You can never guarantee an I/O will success. – KamilCuk May 18 '20 at 10:21
  • @user207421 - Just to double check I understand... Your answer to this is a plain NO. Is that correct? – sancho.s ReinstateMonicaCellio May 18 '20 at 10:23
  • @sancho.sReinstateMonicaCellio My answer is stated clearly above, and it is not a 'plain NO', it is, in essence, what I already wrote: You can only do this reliably if the descriptors are 0, 1, or 2.' – user207421 May 18 '20 at 10:24
  • @user207421 - You are right... except for FD=0,1,2 (the cases I already know, and I was not asking about; I have clarified that), the answer is NO. But then I conclude that my stated objective is not attainable. Did I get it right? – sancho.s ReinstateMonicaCellio May 18 '20 at 10:29
  • 2
    Hand-picking a filedescriptor is about as sensible as hand-picking a pointer. You don't. You call `new` and `open`. And the runtime knows you're done when you call `delete` and `close`. Different resource, same pattern. – MSalters May 18 '20 at 10:36
  • @MSalters - I understand, and it made sense to me from the beginning. But then I conclude that my stated objective at the top is not attainable. Did I get it right? Note that it seems MUMPS allows for this hand-picking of FD values, with flags mat_mumps_icntl_(x) with x=1,2,3 (which do not mean FD=1,2,3), see https://www.mcs.anl.gov/petsc/petsc-current/docs/manualpages/Mat/MATSOLVERMUMPS.html – sancho.s ReinstateMonicaCellio May 18 '20 at 11:01
  • "Can one write C/C++ code that safely and successfully writes to a hand picked file descriptor number, other than FD=0,1,2?" - If a caller opens those file descriptors, then you may "safely and successfully" write into them. Otherwise I don't understand the meaning of "safely" and "successfully" words in your question. And your question post don't describe them. Not sure whether your question is a duplicate of your previous one or not, but I am sure your current question is unclear. – Tsyvarev May 18 '20 at 15:17
  • @Tsyvarev - Ok, I will try to explain here, and account for any further comment by editing. I admit to being frustrated by my inability to effectively convey my doubts, or otherwise to understand the comments. I want to provide an executable `ìo` that a user can execute alternatively as: 1) `io 3> myout.txt`, in which case `myout.txt` would contain whatever I explicitly send to FD=3 from within my code, or 2) `io`, in which case either an error message indicating the need for `3> ...` is presented, or the corresponding output is simply lost (still have to decide which is the best option). – sancho.s ReinstateMonicaCellio May 18 '20 at 16:07
  • The essential point is being able to hand pick the number 3, so I can instruct the user how to redirect if he wants to. I think I have to know this number. I mean to have this FD separate from stdout or stderr. There are a number of specific issues around this need, and I meant to split them among various questions. All in all, I couldn't figure out if this is even possible. Moreover, from what I could understand (possibly wrongfully), there are some experts saying it is not possible and there are some saying it is possible. So, I am at a loss... – sancho.s ReinstateMonicaCellio May 18 '20 at 16:15
  • PS: I do not see either how my questions are dupe of those indicated, and how the answers/comments in the other questions actually answer the "dupes" (of course, I see they are related, but that is not enough). Again, I feel I could not convey clearly the fact they are specifically different questions. – sancho.s ReinstateMonicaCellio May 18 '20 at 16:31
  • Your [1 of 3 comment](https://stackoverflow.com/questions/61866342/is-there-any-way-to-safely-and-successfully-write-to-a-hand-picked-file-descript?noredirect=1#comment109437789_61866342) has much more sense than all text in your current question post including the links. Please, incorporate that comment it into the question post. – Tsyvarev May 18 '20 at 16:35
  • You [2 of 3 comment](https://stackoverflow.com/questions/61866342/is-there-any-way-to-safely-and-successfully-write-to-a-hand-picked-file-descript?noredirect=1#comment109438055_61866342) is not so clear. "I think I have to know this number." - Yes, but what other ways do you expect? Do you expect your program iterate over all descriptors to find the one provided by a user? Or should the user guess what number the program expects from him? – Tsyvarev May 18 '20 at 16:39
  • Hmm, assuming both a user and the program **know** the file descriptor number, the problem stated in your [1 of 3 comment](https://stackoverflow.com/questions/61866342/is-there-any-way-to-safely-and-successfully-write-to-a-hand-picked-file-descript?noredirect=1#comment109437789_61866342) is just about checking in the program, whether given file descriptor exists or not. And seems [duplicate to duplicate question](https://stackoverflow.com/questions/12340695/how-to-check-if-a-given-file-descriptor-stored-in-a-variable-is-still-valid) provides answers for that problem... – Tsyvarev May 18 '20 at 16:50
  • @Tsyvarev - 1) Done (I am not sure I did it right, though). 2) My idea (perhaps not doable) is the opposite. I should tell the user which number he has to use, that is why the number has to be hardcoded, and I added that. Any other means of achieving the objective is probably ok, though. 3) I understand that, but I am not sure my case is covered there. I will try thinking and tinkering a bit to make sure it is (or it is not). – sancho.s ReinstateMonicaCellio May 18 '20 at 17:49
  • 1
    You are going about this completely backward. Do not attempt to tell the user what FD they must use. Instead, provide a way for them to tell *you* which one they have chosen. Then just use whatever they tell you (including if it is 1 or 2, or even 0). If they don't specify, then default to 1 (or maybe 2), or else fail with an appropriate diagnostic. Report normally on any I/O errors, such as might arise if the user specifies the FD wrongly. – John Bollinger May 18 '20 at 17:52
  • @JohnBollinger - So the user would run, e.g., `io 3 3> myout.txt`? (the first 3 to tell `io` that is the FD to use, and the second one to redirect it). – sancho.s ReinstateMonicaCellio May 18 '20 at 17:56
  • Yes. Or to make it a little nicer, maybe you set up option processing so that the user would use `io -d 3 3>output` or `io --fd 3 3>output`. But option processing is just a usability consideration. The key idea is to accept the FD number as a program argument, or from a configuration file or some other input source. – John Bollinger May 18 '20 at 17:59
  • @JohnBollinger - Rethinking about it... If I use your proposal, the user has to somehow open whatever FD passes to `io` prior to calling it, correct? Otherwise, `io` would still need to open an FD with a prescribed no. How can I offer the user something that does not need such an operation on his side? – sancho.s ReinstateMonicaCellio May 18 '20 at 21:14
  • Yes, that's a large part of the point. It is *the user* that needs to open the FD in any case, so it is better in just about every way to let them do that however they want, and just report on what they have done. Or to put it a different way, it is almost always better to allow the user to tell their software what to do, instead of having the software tell the user what to do. – John Bollinger May 18 '20 at 21:25
  • @JohnBollinger - I have just learned a simple and key point that I guess it solves the whole issue: running `io 3> myout.txt` opens FD=3 for `io`. This provides an easy way for achieving my objective with either my proposal (hand picking/hardcoding the FD no., and telling the user which number that is) or yours (letting the user choose that number). – sancho.s ReinstateMonicaCellio May 19 '20 at 02:05
  • So with my choice, I would simply: 1) Use a hardcoded value fd=3 (e.g.), 2) Ask the user to execute as `io 3> myout.txt`, 3) Check as shown [here](https://stackoverflow.com/a/12340730/2707864). With your choice, I would: 1) Get the value of fd from `argv`, 2) Ask the user to execute as `io > myout.txt`, 3) Check as shown [here](https://stackoverflow.com/a/12340730/2707864). I would have to think in both cases about possible error situations in order to prevent them. At this point, which one to choose is a matter of taste. – sancho.s ReinstateMonicaCellio May 19 '20 at 02:05
  • @user207421 - Please see my comments to John Bollinger. I guess I can reliably write to any fd of my choice, in any case of practical interest that I can think of. Whenever the user redirects that fd, it automatically opens that fd so I can write to it. If the user does not redirect it, it is because he does not care about its output, and then I don't care about where it goes either. I am not sure other cases may take place... – sancho.s ReinstateMonicaCellio May 19 '20 at 02:10
  • Most utility programs which feel the need to avoid standard input or output provide the user with an option which lets them elect an fd to use. See, for example, `dialog --output-fd` or `read -u` (bash/zsh), just as a couple of examples off the top of my head. – rici May 19 '20 at 03:36
  • @rici - I do not mean `io` to avoid stdout. I mean it to provide (optional) extra output, on top of what is printed to stdout. Moreover, I conceive providing more than one "channel" (FD) of extra output, so the user can select what he actually gets. – sancho.s ReinstateMonicaCellio May 19 '20 at 08:39
  • @sancho.sReinstateMonicaCellio, I did not recognize that you did not understand the full significance of the (Bourne) shell redirection operator `3>`. That seemed to have been implicit in the question. But yes, it opens the designated file for output *and assigns it to FD 3* for the process being launched. It cannot work the other way around. A child process can inherit FDs from its parent (e.g. from a shell), but other than by that mechanism, one process does not ordinarily have access to the open file descriptions of another. – John Bollinger May 19 '20 at 15:41
  • @JohnBollinger - Well, it seems in my last questions I have been lambasted one way or another for not knowing what I was asking about (not your case...) – sancho.s ReinstateMonicaCellio May 19 '20 at 16:44

0 Answers0