1 /* $OpenBSD: tty_subs.c,v 1.17 2016/08/26 04:22:13 guenther Exp $ */ 2 /* $NetBSD: tty_subs.c,v 1.5 1995/03/21 09:07:52 cgd Exp $ */ 3 4 /*- 5 * Copyright (c) 1992 Keith Muller. 6 * Copyright (c) 1992, 1993 7 * The Regents of the University of California. All rights reserved. 8 * 9 * This code is derived from software contributed to Berkeley by 10 * Keith Muller of the University of California, San Diego. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 #include <sys/types.h> 38 #include <sys/stat.h> 39 #include <fcntl.h> 40 #include <stdarg.h> 41 #include <stdio.h> 42 #include <string.h> 43 #include <unistd.h> 44 45 #include "pax.h" 46 #include "extern.h" 47 48 /* 49 * routines that deal with I/O to and from the user 50 */ 51 52 #define DEVTTY "/dev/tty" /* device for interactive i/o */ 53 static FILE *ttyoutf = NULL; /* output pointing at control tty */ 54 static FILE *ttyinf = NULL; /* input pointing at control tty */ 55 56 /* 57 * tty_init() 58 * try to open the controlling terminal (if any) for this process. if the 59 * open fails, future ops that require user input will get an EOF 60 */ 61 62 int 63 tty_init(void) 64 { 65 int ttyfd; 66 67 if ((ttyfd = open(DEVTTY, O_RDWR | O_CLOEXEC)) >= 0) { 68 if ((ttyoutf = fdopen(ttyfd, "w")) != NULL) { 69 if ((ttyinf = fdopen(ttyfd, "r")) != NULL) 70 return(0); 71 (void)fclose(ttyoutf); 72 } 73 (void)close(ttyfd); 74 } 75 76 if (iflag) { 77 paxwarn(1, "Fatal error, cannot open %s", DEVTTY); 78 return(-1); 79 } 80 return(0); 81 } 82 83 /* 84 * tty_prnt() 85 * print a message using the specified format to the controlling tty 86 * if there is no controlling terminal, just return. 87 */ 88 89 void 90 tty_prnt(const char *fmt, ...) 91 { 92 va_list ap; 93 94 va_start(ap, fmt); 95 if (ttyoutf == NULL) { 96 va_end(ap); 97 return; 98 } 99 (void)vfprintf(ttyoutf, fmt, ap); 100 va_end(ap); 101 (void)fflush(ttyoutf); 102 } 103 104 /* 105 * tty_read() 106 * read a string from the controlling terminal if it is open into the 107 * supplied buffer 108 * Return: 109 * 0 if data was read, -1 otherwise. 110 */ 111 112 int 113 tty_read(char *str, int len) 114 { 115 if (ttyinf == NULL || fgets(str, len, ttyinf) == NULL) 116 return(-1); 117 118 /* 119 * strip off that trailing newline 120 */ 121 str[strcspn(str, "\n")] = '\0'; 122 return(0); 123 } 124 125 /* 126 * paxwarn() 127 * write a warning message to stderr. if "set" the exit value of pax 128 * will be non-zero. 129 */ 130 131 void 132 paxwarn(int set, const char *fmt, ...) 133 { 134 va_list ap; 135 136 va_start(ap, fmt); 137 if (set) 138 exit_val = 1; 139 /* 140 * when vflag we better ship out an extra \n to get this message on a 141 * line by itself 142 */ 143 if (vflag && vfpart) { 144 (void)fflush(listf); 145 (void)fputc('\n', stderr); 146 vfpart = 0; 147 } 148 (void)fprintf(stderr, "%s: ", argv0); 149 (void)vfprintf(stderr, fmt, ap); 150 va_end(ap); 151 (void)fputc('\n', stderr); 152 } 153 154 /* 155 * syswarn() 156 * write a warning message to stderr. if "set" the exit value of pax 157 * will be non-zero. 158 */ 159 160 void 161 syswarn(int set, int errnum, const char *fmt, ...) 162 { 163 va_list ap; 164 165 va_start(ap, fmt); 166 if (set) 167 exit_val = 1; 168 /* 169 * when vflag we better ship out an extra \n to get this message on a 170 * line by itself 171 */ 172 if (vflag && vfpart) { 173 (void)fflush(listf); 174 (void)fputc('\n', stderr); 175 vfpart = 0; 176 } 177 (void)fprintf(stderr, "%s: ", argv0); 178 (void)vfprintf(stderr, fmt, ap); 179 va_end(ap); 180 181 /* 182 * format and print the errno 183 */ 184 if (errnum > 0) 185 (void)fprintf(stderr, ": %s", strerror(errnum)); 186 (void)fputc('\n', stderr); 187 } 188