Skip to content

Files

Latest commit

e3d8beb · Oct 15, 2023

History

History

hw10

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
Oct 15, 2023

10.6

It will print out "fd2 = 4".

Process: Unix processes begin life with open descriptors assigned to stdin (descriptor 0), stdout (descriptor 1), and stderr (descriptor 2). The open function always returns the lowest unopened descriptor, so the first call to open returns descriptor 3. The second call to open returns descriptor 4. The call to the close function frees up descriptor 4. The final call to open returns descriptor 4 again, and thus the output of the program is fd2 = 4.

10.7

#include "csapp.h"

int main(int argc, char **argv)
{
    ssize_t n;
    rio_t rio;
    char buf[MAXBUF];

    Rio_readinitb(&rio, STDIN_FILENO);
    while ((n = Rio_readnb(&rio, buf, MAXBUF)) != 0)
        Rio_writen(STDOUT_FILENO, buf, n);
}

10.8

#include "csapp.h"

int main(int argc, char **argv)
{
    struct stat stat;
    char *type, *readok;
    int fd;

    if (argc != 2) {
        fprintf(stderr, "Usage: %s <descriptor>\n", argv[0]);
        exit(1);
    }

    // Convert argument to integer
    fd = atoi(argv[1]);

    Fstat(fd, &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);
}

10.9

The pseudocode should be as follows:

if (Fork() == 0) { /* child */
    /* Pseudocode for the shell executing right here */
    
    int fd = Open("foo.txt", O_RDONLY, 0);  // Open the file for reading
    
    // Error check for file opening
    if (fd < 0) {
        // Handle error
    }
    
    Dup2(fd, 0);  // Using dup2 to explicitly set it to 0 
    Close(fd);    // Close the original file descriptor returned by open
    
    Execve("fstatcheck", argv, envp);
}
How to Fix

The issue with the command fstatcheck 3 < foo.txt is related to how shell handles file descriptor redirection and how file descriptors are passed to programs.

With < foo.txt, the shell sets up file descriptor 0 to be a read descriptor for the file foo.txt. However, when we specify 3 as an argument to fstatcheck, we're actually telling it to look at file descriptor 3.

  • 3: This is an argument to fstatcheck and does not directly correlate with the file descriptor being used by the shell for the redirection.
  • < foo.txt: This tells the shell to redirect foo.txt to standard input for fstatcheck.

So, when fstatcheck tries to use file descriptor 3, it's not associated with foo.txt (which is on file descriptor 0).

We can use shell features to duplicate the file descriptor so that foo.txt is also available on file descriptor 3, as shown in the below:

exec 3<foo.txt
fstatcheck 3

10.10

We can check argc. If argc > 1, an infile is provided, and it is opened with Open, which returns a file descriptor. Otherwise, no infile is provided, and fd is set to STDIN_FILENO.

int main(int argc, char **argv)
{
    ssize_t n;
    rio_t rio;
    char buf[MAXLINE];
    int fd;

    if (argc > 1)
        fd = Open(argv[1], O_RONLY, 0);
    else
        fd = STDIN_FILENO;

    Rio_readinitb(&rio, fd);
    while ((n = Rio_readlineb(&rio, buf, MAXLINE)) != 0)
        Rio_writen(STDOUT_FILENO, buf, n);

    /* Close fd if it's not standard input */
    if (fd != STDIN_FILENO) {
        Close(fd);
    }
}