An answer:

#include <stdio.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    int c, status = 0, n = 10;
    FILE *fp;
    extern void process(FILE *fp, int lines);

    while ((c = getopt(argc, argv, "n:")) != EOF) {
        if (c == 'n') {
            /* (for this exam question, calling atoi() was fine) */
            char tmp;
            if (sscanf(optarg, "%d%c", &n, &tmp) != 1)
                status = 1;
        } else {
            status = 1;
        }
    }
    if (status) {
        fprintf(stderr, "usage: %s [-n num] [file ...]\n", argv[0]);
        return(1);
    }

    if (optind == argc) {
        process(stdin, n);
    } else {
        for (; optind < argc; optind++) {
            if ((fp = fopen(argv[optind], "r")) == NULL) {
                perror(argv[optind]);
                status = 1;
            } else {
                process(fp, n);
                fclose(fp);
            }
        }
    }

    return(status);
}

Now for the process() function:
First, the way which is probably much more straightforward but has the serious disadvantage that it pointlessly stores whole lines at a time, and breaks extremely long lines thus miscounting:

void process(FILE *fp, int lines)
{
    char buf[500];
    for (; lines > 0 && fgets(buf, sizeof buf, fp); lines--)
        printf("%s", buf);
}

Or, here is a better version which does not store whole lines and simply counts \n characters:

void process(FILE *fp, int lines)
{
    int c;
    while (lines > 0 && (c = getc(fp)) != EOF) {
        putchar(c);
        if (c == '\n')
            lines--;
    }
}


[press 'back' in your web browser to return to where you were in the exam]