/* * Are these two really the same inode? */ int samei(struct stat64 *sp, unsigned char *cp) { struct stat64 stb; if (stat64((char *)cp, &stb) < 0) return (0); return (IDENTICAL((*sp), stb)); }
int main(int argc, char **argv) { FILE *fi; int c; extern int optind; int errflg = 0; int stdinflg = 0; int status = 0; int estatus = 0; struct stat source, target; (void) setlocale(LC_ALL, ""); #if !defined(TEXT_DOMAIN) /* Should be defined by cc -D */ #define TEXT_DOMAIN "SYS_TEST" /* Use this only if it weren't */ #endif (void) textdomain(TEXT_DOMAIN); #ifdef STANDALONE /* * If the first argument is NULL, * discard arguments until we find cat. */ if (argv[0][0] == '\0') argc = getargv("cat", &argv, 0); #endif /* * Process the options for cat. */ while ((c = getopt(argc, argv, "usvtebn")) != EOF) { switch (c) { case 'u': /* * If not standalone, set stdout to * completely unbuffered I/O when * the 'u' option is used. */ #ifndef STANDALONE setbuf(stdout, (char *)NULL); #endif continue; case 's': /* * The 's' option requests silent mode * where no messages are written. */ silent++; continue; case 'v': /* * The 'v' option requests that non-printing * characters (with the exception of newlines, * form-feeds, and tabs) be displayed visibly. * * Control characters are printed as "^x". * DEL characters are printed as "^?". * Non-printable and non-contrlol characters with the * 8th bit set are printed as "M-x". */ visi_mode++; continue; case 't': /* * When in visi_mode, this option causes tabs * to be displayed as "^I". */ visi_tab++; continue; case 'e': /* * When in visi_mode, this option causes newlines * and form-feeds to be displayed as "$" at the end * of the line prior to the newline. */ visi_newline++; continue; case 'b': /* * Precede each line output with its line number, * but omit the line numbers from blank lines. */ bflg++; nflg++; continue; case 'n': /* * Precede each line output with its line number. */ nflg++; continue; case '?': errflg++; break; } break; } if (errflg) { if (!silent) (void) fprintf(stderr, gettext("usage: cat [ -usvtebn ] [-|file] ...\n")); exit(2); } /* * Stat stdout to be sure it is defined. */ if (fstat(fileno(stdout), &target) < 0) { if (!silent) (void) fprintf(stderr, gettext("cat: Cannot stat stdout\n")); exit(2); } obsize = target.st_blksize; /* * If no arguments given, then use stdin for input. */ if (optind == argc) { argc++; stdinflg++; } /* * Process each remaining argument, * unless there is an error with stdout. */ for (argv = &argv[optind]; optind < argc && !ferror(stdout); optind++, argv++) { /* * If the argument was '-' or there were no files * specified, take the input from stdin. */ if (stdinflg || ((*argv)[0] == '-' && (*argv)[1] == '\0')) fi = stdin; else { /* * Attempt to open each specified file. */ if ((fi = fopen(*argv, "r")) == NULL) { if (!silent) (void) fprintf(stderr, gettext("cat: cannot open %s: %s\n"), *argv, strerror(errno)); status = 2; continue; } } /* * Stat source to make sure it is defined. */ if (fstat(fileno(fi), &source) < 0) { if (!silent) (void) fprintf(stderr, gettext("cat: cannot stat %s: %s\n"), (stdinflg) ? "-" : *argv, strerror(errno)); status = 2; continue; } /* * If the source is not a character special file, socket or a * block special file, make sure it is not identical * to the target. */ if (!S_ISCHR(target.st_mode) && !S_ISBLK(target.st_mode) && !S_ISSOCK(target.st_mode) && IDENTICAL(target, source)) { if (!silent) (void) fprintf(stderr, gettext("cat: input/output files '%s' identical\n"), stdinflg?"-": *argv); if (fclose(fi) != 0) (void) fprintf(stderr, gettext("cat: close error: %s\n"), strerror(errno)); status = 2; continue; } ibsize = source.st_blksize; /* * If in visible mode and/or nflg, use vncat; * otherwise, use cat. */ if (visi_mode || nflg) estatus = vncat(fi); else estatus = cat(fi, &source, &target, fi != stdin ? *argv : "standard input"); if (estatus) status = estatus; /* * If the input is not stdin, close the source file. */ if (fi != stdin) { if (fclose(fi) != 0) if (!silent) (void) fprintf(stderr, gettext("cat: close error: %s\n"), strerror(errno)); } } /* * Display any error with stdout operations. */ if (fclose(stdout) != 0) { if (!silent) perror(gettext("cat: close error")); status = 2; } return (status); }