// 1.4CopyStandardInputToStandardOutput.cpp #include "../apuesunyj.h" #define BUFFSIZE 4096 int main() { int n; char buf[BUFFSIZE]; // By convention, all shells open three descriptors whenever a new program is run: // standard input, standard output, and standard error. // STDIN_FILENO specify the file descriptor for standard input // Unbuffered I/O is provided by the functions open, read, write, lseek, and close. // These functions all work with file descriptors. // The read function returns the number of bytes that are read, and this value is used // as the number of bytes to write. When the end of the input file is encountered, read // returns 0 and the program stops. If a read error occurs, read returns -1. while ((n = read(STDIN_FILENO, buf, BUFFSIZE)) > 0) { if (write(STDOUT_FILENO, buf, n) != n) { err_sys("write error"); } } // usually n is bigger than 0, if input ctrl + d // then n is equal to 0 if (n < 0) { err_sys("read error"); } return 0; } // The standard I/O functions provide a buffered interface to the unbuffered I/O // functions. Using standard I/O relieves us from having to choose optimal buffer sizes, // such as the BUFFSIZE constant in Figure 1.4. The standard I/O functions also simplify // dealing with lines of input (a common occurrence in UNIX applications). The fgets // function, for example, reads an entire line. The read function, in contrast, reads a // specified number of bytes. As we shall see in Section 5.4, the standard I/O library // provides functions that let us control the style of buffering used by the library. // The most common standard I/O function is printf. In programs that call // printf, we'll always include <stdio.h> normally by including apue.h as this // header contains the function prototypes for all the standard I/O functions.
1 // apuesunyj.h 2 #ifndef APUE_SUNYJ 3 #define APUE_SUNYJ 4 5 #include <errno.h> 6 #include <stdio.h> 7 #include <string.h> 8 #include <stdarg.h> 9 #include <stdlib.h> 10 #include <stdint.h> 11 #include <unistd.h> 12 13 void err_quit(const char *fmt, ...); 14 void err_sys(const char *fmt, ...); 15 16 17 #endif
1 // error.cpp 2 #include "apuesunyj.h" 3 4 int64_t const MAXLINE = 4096; // max line length 5 /* 6 * * Print a message and return to caller. 7 * * Caller specifies "errnoflag". 8 * */ 9 static void err_doit(int errnoflag, int error, const char *fmt, va_list ap) 10 { 11 char buf[MAXLINE]; 12 13 vsnprintf(buf, MAXLINE, fmt, ap); 14 if (errnoflag) 15 snprintf(buf + strlen(buf), MAXLINE - strlen(buf), ": %s", strerror( 16 error)); 17 strcat(buf, " "); 18 fflush(stdout);/* in case stdout and stderr are the same */ 19 fputs(buf, stderr); 20 fflush(NULL);/* flushes all stdio output streams */ 21 } 22 23 /* 24 * * Fatal error unrelated to a system call. 25 * * Print a message and terminate. 26 * */ 27 void err_quit(const char *fmt, ...) 28 { 29 va_list ap; 30 31 va_start(ap, fmt); 32 err_doit(0, 0, fmt, ap); 33 va_end(ap); 34 exit(1) ; // process terminate, not just like return, totally different 35 } 36 37 /* 38 * * Fatal error related to a system call. 39 * * Print a message and terminate. 40 * */ 41 void err_sys(const char *fmt, ...) 42 { 43 va_list ap; 44 45 va_start(ap, fmt); 46 err_doit(1, errno, fmt, ap); 47 va_end(ap); 48 exit(1) ; 49 }