107 lines
2.5 KiB
C
107 lines
2.5 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#define STDIN_NAME "<stdin>"
|
|
#define STDOUT_NAME "<stdout>"
|
|
|
|
/* these are the predicted errors that could occur */
|
|
enum error_type{
|
|
FILE_ACCESS,
|
|
FILE_CLOSE,
|
|
FILE_WRITE
|
|
};
|
|
|
|
/* this is an error function that will print to standard error the error that
|
|
* occurred in the program and exit */
|
|
void
|
|
error(enum error_type type, char *argv0, char *file_name){
|
|
switch(type){
|
|
case FILE_ACCESS:
|
|
fprintf(stderr, "%s: %s: cannot open file\n", argv0, file_name);
|
|
break;
|
|
case FILE_CLOSE:
|
|
fprintf(stderr, "%s: %s: cannot close file\n", argv0, file_name);
|
|
break;
|
|
case FILE_WRITE:
|
|
fprintf(stderr, "%s: %s: cannot write to file\n", argv0, file_name);
|
|
break;
|
|
}
|
|
exit(1);
|
|
}
|
|
|
|
/* print input to output, returns 0 if successful and 1 if unsuccessful */
|
|
int
|
|
file_copy(FILE *input, FILE *output){
|
|
char c;
|
|
while((c = getc(input)) != EOF)
|
|
if(putc(c, output) == EOF)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
main(int argc, char *argv[]){
|
|
/* the name of the file being printed (for diagnostics) */
|
|
char *file_name;
|
|
|
|
/* allocate this ahead of time */
|
|
char *stdin_file_name = STDIN_NAME;
|
|
|
|
/* the file pointer of the file being printed */
|
|
FILE *input;
|
|
|
|
/* this will always be stdout */
|
|
FILE *output = stdout;
|
|
|
|
int i;
|
|
|
|
/* whether or not options are being parsed */
|
|
int parsing_opts = 1;
|
|
|
|
/* usage with 0 arguments - print standard input to standard output */
|
|
if(argc == 1 && file_copy(stdin, stdout))
|
|
error(FILE_WRITE, argv[0], STDOUT_NAME);
|
|
else if(argc == 1)
|
|
return 0;
|
|
|
|
for(i = 1; i < argc; ++i){
|
|
/* parsing options */
|
|
|
|
/* after `--`, interpret `--`, `-`, and `-u` as literal
|
|
* filenames */
|
|
if(parsing_opts && !strcmp(argv[i], "--")){
|
|
parsing_opts = 0;
|
|
continue;
|
|
|
|
/* ignore `-u` if still parsing options */
|
|
}else if(parsing_opts && !strcmp(argv[i], "-u"))
|
|
continue;
|
|
|
|
/* take `-` to mean standard input if still parsing options */
|
|
else if(parsing_opts && !strcmp(argv[i], "-")){
|
|
file_name = stdin_file_name;
|
|
input = stdin;
|
|
|
|
/* non-option; open the file and make sure file_name points to
|
|
* the right string */
|
|
}else{
|
|
file_name = argv[i];
|
|
input = fopen(file_name, "r");
|
|
if(input == NULL)
|
|
error(FILE_ACCESS, argv[0], file_name);
|
|
}
|
|
|
|
/* print input to output */
|
|
if(file_copy(input, output))
|
|
error(FILE_WRITE, argv[0], STDOUT_NAME);
|
|
|
|
/* close input file if it's not stdin */
|
|
if(input != stdin && fclose(input))
|
|
error(FILE_CLOSE, argv[0], file_name);
|
|
}
|
|
|
|
/* exit successfully */
|
|
return 0;
|
|
}
|