views:

168

answers:

4

Hi all...my question is how would I change the program below so that it takes a file descriptor number on the command line rather than a file name? Any help would be greatly appreciated. Thank You.

include "csapp.h"

int main (int argc, char **argv) 

{

    struct stat stat;
    char *type, *readok;

    /* $end statcheck */
    if (argc != 2) {
        fprintf(stderr, "usage: %s <filename>\n", argv[0]);
        exit(0);
    }
    /* $begin statcheck */
    Stat(argv[1], &stat);
    if (S_ISREG(stat.st_mode))     /* Determine file type */
        type = "regular";
    else if (S_ISDIR(stat.st_mode))
        type = "directory";
    else 
        type = "other";
    if ((stat.st_mode & S_IRUSR)) /* Check read access */
        readok = "yes";
    else
        readok = "no";

    printf("type: %s, read: %s\n", type, readok);
    exit(0);
}
/* $end statcheck */
+1  A: 

It's easy to do what you want. You would need to convert argv[1] from a string to an integer (using strtol) and then you would change the call from stat() to fstat(). If you don't care about verifying that the argument is actually a number (which is what a file descriptor is), you could simply change the stat() call to:

fstat(atoi(argv[1]), &stat);

That said, I have to ask, what is the purpose for this?

R Samuel Klatchko
I was actually playing around with different programs trying to learn some different system-level I/O techniques .
jingojango
But that would just return EBADF (fd is bad), since the file hasn't been opened beforehand.
Puppe
It does not have to return EBADF. Descriptors 0, 1 and 2 are usually valid (i.e. stdin, stdout, stderr). Using bash, you could use advanced I/O redirection to open other descriptors. If you write another program to exec() this program, you could have opened additional file descriptors as well
R Samuel Klatchko
A: 

Trying to do anything on a file descriptor that's not been opened from within your process or parent process won't work. The file descriptor is just unique within your process/parent process(es).

Puppe
That is incorrect. File descriptors are inherited from the parent process (unless the fd is marked as close-on-exec).
R Samuel Klatchko
Yeah that's true, but I don't see any indications of the questioner wanting to exec() this.
Puppe
He doesn't have to be exec()ing it. He could check 0, 1 or 2 which will be valid as a shell will have set those up as stdin, stdout and stderr.
R Samuel Klatchko
would I change this stat ...Stat(argv[1], ...to fstat and then how do I use the strtoI function?
jingojango
How do you intend to use this program? Where would you get the file desriptors from?
Puppe
@R Samuel Klatchko: Yes, but they have different context. Just think of pipelines.
Jurily
+1  A: 

File descriptors should be considered unique for a process. Even stdin/out/err are totally different in a pipe for two separate processes, while having the same fd.

Of course there are many ways to create a new process, but if you use one which preserves your fd's, you won't pass them in a command line anyway.

Jurily
A: 

Because that an FD number is a per process (and might its children) property, so only when a parent process had own an fd of an openning file, a child (forked in general) could accept the inherited fd number as command parameter and use it; otherwise no way unless using well-known "STDOUT" or "STDERR" etc.

EffoStaff Effo