1 /* $OpenBSD: io.c,v 1.35 2016/03/20 00:01:21 krw Exp $ */ 2 3 /* 4 * shell buffered IO and formatted output 5 */ 6 7 #include <sys/stat.h> 8 9 #include <ctype.h> 10 #include <errno.h> 11 #include <fcntl.h> 12 #include <string.h> 13 #include <unistd.h> 14 15 #include "sh.h" 16 17 static int initio_done; 18 19 /* 20 * formatted output functions 21 */ 22 23 24 /* A shell error occurred (eg, syntax error, etc.) */ 25 void 26 errorf(const char *fmt, ...) 27 { 28 va_list va; 29 30 shl_stdout_ok = 0; /* debugging: note that stdout not valid */ 31 exstat = 1; 32 if (fmt != NULL && *fmt != '\0') { 33 error_prefix(true); 34 va_start(va, fmt); 35 shf_vfprintf(shl_out, fmt, va); 36 va_end(va); 37 shf_putchar('\n', shl_out); 38 } 39 shf_flush(shl_out); 40 unwind(LERROR); 41 } 42 43 /* like errorf(), but no unwind is done */ 44 void 45 warningf(bool show_lineno, const char *fmt, ...) 46 { 47 va_list va; 48 49 error_prefix(show_lineno); 50 va_start(va, fmt); 51 shf_vfprintf(shl_out, fmt, va); 52 va_end(va); 53 shf_putchar('\n', shl_out); 54 shf_flush(shl_out); 55 } 56 57 /* Used by built-in utilities to prefix shell and utility name to message 58 * (also unwinds environments for special builtins). 59 */ 60 void 61 bi_errorf(const char *fmt, ...) 62 { 63 va_list va; 64 65 shl_stdout_ok = 0; /* debugging: note that stdout not valid */ 66 exstat = 1; 67 if (fmt != NULL && *fmt != '\0') { 68 error_prefix(true); 69 /* not set when main() calls parse_args() */ 70 if (builtin_argv0) 71 shf_fprintf(shl_out, "%s: ", builtin_argv0); 72 va_start(va, fmt); 73 shf_vfprintf(shl_out, fmt, va); 74 va_end(va); 75 shf_putchar('\n', shl_out); 76 } 77 shf_flush(shl_out); 78 /* POSIX special builtins and ksh special builtins cause 79 * non-interactive shells to exit. 80 * XXX odd use of KEEPASN; also may not want LERROR here 81 */ 82 if ((builtin_flag & SPEC_BI) || 83 (Flag(FPOSIX) && (builtin_flag & KEEPASN))) { 84 builtin_argv0 = NULL; 85 unwind(LERROR); 86 } 87 } 88 89 /* Called when something that shouldn't happen does */ 90 void 91 internal_errorf(int jump, const char *fmt, ...) 92 { 93 va_list va; 94 95 error_prefix(true); 96 shf_fprintf(shl_out, "internal error: "); 97 va_start(va, fmt); 98 shf_vfprintf(shl_out, fmt, va); 99 va_end(va); 100 shf_putchar('\n', shl_out); 101 shf_flush(shl_out); 102 if (jump) 103 unwind(LERROR); 104 } 105 106 /* used by error reporting functions to print "ksh: .kshrc[25]: " */ 107 void 108 error_prefix(int fileline) 109 { 110 /* Avoid foo: foo[2]: ... */ 111 if (!fileline || !source || !source->file || 112 strcmp(source->file, kshname) != 0) 113 shf_fprintf(shl_out, "%s: ", kshname + (*kshname == '-')); 114 if (fileline && source && source->file != NULL) { 115 shf_fprintf(shl_out, "%s[%d]: ", source->file, 116 source->errline > 0 ? source->errline : source->line); 117 source->errline = 0; 118 } 119 } 120 121 /* printf to shl_out (stderr) with flush */ 122 void 123 shellf(const char *fmt, ...) 124 { 125 va_list va; 126 127 if (!initio_done) /* shl_out may not be set up yet... */ 128 return; 129 va_start(va, fmt); 130 shf_vfprintf(shl_out, fmt, va); 131 va_end(va); 132 shf_flush(shl_out); 133 } 134 135 /* printf to shl_stdout (stdout) */ 136 void 137 shprintf(const char *fmt, ...) 138 { 139 va_list va; 140 141 if (!shl_stdout_ok) 142 internal_errorf(1, "shl_stdout not valid"); 143 va_start(va, fmt); 144 shf_vfprintf(shl_stdout, fmt, va); 145 va_end(va); 146 } 147 148 #ifdef KSH_DEBUG 149 static struct shf *kshdebug_shf; 150 151 void 152 kshdebug_init_(void) 153 { 154 if (kshdebug_shf) 155 shf_close(kshdebug_shf); 156 kshdebug_shf = shf_open("/tmp/ksh-debug.log", 157 O_WRONLY|O_APPEND|O_CREAT, 0600, SHF_WR|SHF_MAPHI); 158 if (kshdebug_shf) { 159 shf_fprintf(kshdebug_shf, "\nNew shell[pid %d]\n", getpid()); 160 shf_flush(kshdebug_shf); 161 } 162 } 163 164 /* print to debugging log */ 165 void 166 kshdebug_printf_(const char *fmt, ...) 167 { 168 va_list va; 169 170 if (!kshdebug_shf) 171 return; 172 va_start(va, fmt); 173 shf_fprintf(kshdebug_shf, "[%d] ", getpid()); 174 shf_vfprintf(kshdebug_shf, fmt, va); 175 va_end(va); 176 shf_flush(kshdebug_shf); 177 } 178 179 void 180 kshdebug_dump_(const char *str, const void *mem, int nbytes) 181 { 182 int i, j; 183 int nprow = 16; 184 185 if (!kshdebug_shf) 186 return; 187 shf_fprintf(kshdebug_shf, "[%d] %s:\n", getpid(), str); 188 for (i = 0; i < nbytes; i += nprow) { 189 char c = '\t'; 190 191 for (j = 0; j < nprow && i + j < nbytes; j++) { 192 shf_fprintf(kshdebug_shf, "%c%02x", c, 193 ((const unsigned char *) mem)[i + j]); 194 c = ' '; 195 } 196 shf_fprintf(kshdebug_shf, "\n"); 197 } 198 shf_flush(kshdebug_shf); 199 } 200 #endif /* KSH_DEBUG */ 201 202 /* test if we can seek backwards fd (returns 0 or SHF_UNBUF) */ 203 int 204 can_seek(int fd) 205 { 206 struct stat statb; 207 208 return fstat(fd, &statb) == 0 && !S_ISREG(statb.st_mode) ? 209 SHF_UNBUF : 0; 210 } 211 212 struct shf shf_iob[3]; 213 214 void 215 initio(void) 216 { 217 shf_fdopen(1, SHF_WR, shl_stdout); /* force buffer allocation */ 218 shf_fdopen(2, SHF_WR, shl_out); 219 shf_fdopen(2, SHF_WR, shl_spare); /* force buffer allocation */ 220 initio_done = 1; 221 kshdebug_init(); 222 } 223 224 /* A dup2() with error checking */ 225 int 226 ksh_dup2(int ofd, int nfd, int errok) 227 { 228 int ret = dup2(ofd, nfd); 229 230 if (ret < 0 && errno != EBADF && !errok) 231 errorf("too many files open in shell"); 232 233 return ret; 234 } 235 236 /* 237 * move fd from user space (0<=fd<10) to shell space (fd>=10), 238 * set close-on-exec flag. 239 */ 240 int 241 savefd(int fd) 242 { 243 int nfd; 244 245 if (fd < FDBASE) { 246 nfd = fcntl(fd, F_DUPFD_CLOEXEC, FDBASE); 247 if (nfd < 0) { 248 if (errno == EBADF) 249 return -1; 250 else 251 errorf("too many files open in shell"); 252 } 253 } else { 254 nfd = fd; 255 fcntl(nfd, F_SETFD, FD_CLOEXEC); 256 } 257 return nfd; 258 } 259 260 void 261 restfd(int fd, int ofd) 262 { 263 if (fd == 2) 264 shf_flush(&shf_iob[fd]); 265 if (ofd < 0) /* original fd closed */ 266 close(fd); 267 else if (fd != ofd) { 268 ksh_dup2(ofd, fd, true); /* XXX: what to do if this fails? */ 269 close(ofd); 270 } 271 } 272 273 void 274 openpipe(int *pv) 275 { 276 int lpv[2]; 277 278 if (pipe(lpv) < 0) 279 errorf("can't create pipe - try again"); 280 pv[0] = savefd(lpv[0]); 281 if (pv[0] != lpv[0]) 282 close(lpv[0]); 283 pv[1] = savefd(lpv[1]); 284 if (pv[1] != lpv[1]) 285 close(lpv[1]); 286 } 287 288 void 289 closepipe(int *pv) 290 { 291 close(pv[0]); 292 close(pv[1]); 293 } 294 295 /* Called by iosetup() (deals with 2>&4, etc.), c_read, c_print to turn 296 * a string (the X in 2>&X, read -uX, print -uX) into a file descriptor. 297 */ 298 int 299 check_fd(char *name, int mode, const char **emsgp) 300 { 301 int fd, fl; 302 303 if (isdigit((unsigned char)name[0]) && !name[1]) { 304 fd = name[0] - '0'; 305 if ((fl = fcntl(fd, F_GETFL)) < 0) { 306 if (emsgp) 307 *emsgp = "bad file descriptor"; 308 return -1; 309 } 310 fl &= O_ACCMODE; 311 /* X_OK is a kludge to disable this check for dups (x<&1): 312 * historical shells never did this check (XXX don't know what 313 * posix has to say). 314 */ 315 if (!(mode & X_OK) && fl != O_RDWR && 316 (((mode & R_OK) && fl != O_RDONLY) || 317 ((mode & W_OK) && fl != O_WRONLY))) { 318 if (emsgp) 319 *emsgp = (fl == O_WRONLY) ? 320 "fd not open for reading" : 321 "fd not open for writing"; 322 return -1; 323 } 324 return fd; 325 } else if (name[0] == 'p' && !name[1]) 326 return coproc_getfd(mode, emsgp); 327 if (emsgp) 328 *emsgp = "illegal file descriptor name"; 329 return -1; 330 } 331 332 /* Called once from main */ 333 void 334 coproc_init(void) 335 { 336 coproc.read = coproc.readw = coproc.write = -1; 337 coproc.njobs = 0; 338 coproc.id = 0; 339 } 340 341 /* Called by c_read() when eof is read - close fd if it is the co-process fd */ 342 void 343 coproc_read_close(int fd) 344 { 345 if (coproc.read >= 0 && fd == coproc.read) { 346 coproc_readw_close(fd); 347 close(coproc.read); 348 coproc.read = -1; 349 } 350 } 351 352 /* Called by c_read() and by iosetup() to close the other side of the 353 * read pipe, so reads will actually terminate. 354 */ 355 void 356 coproc_readw_close(int fd) 357 { 358 if (coproc.readw >= 0 && coproc.read >= 0 && fd == coproc.read) { 359 close(coproc.readw); 360 coproc.readw = -1; 361 } 362 } 363 364 /* Called by c_print when a write to a fd fails with EPIPE and by iosetup 365 * when co-process input is dup'd 366 */ 367 void 368 coproc_write_close(int fd) 369 { 370 if (coproc.write >= 0 && fd == coproc.write) { 371 close(coproc.write); 372 coproc.write = -1; 373 } 374 } 375 376 /* Called to check for existence of/value of the co-process file descriptor. 377 * (Used by check_fd() and by c_read/c_print to deal with -p option). 378 */ 379 int 380 coproc_getfd(int mode, const char **emsgp) 381 { 382 int fd = (mode & R_OK) ? coproc.read : coproc.write; 383 384 if (fd >= 0) 385 return fd; 386 if (emsgp) 387 *emsgp = "no coprocess"; 388 return -1; 389 } 390 391 /* called to close file descriptors related to the coprocess (if any) 392 * Should be called with SIGCHLD blocked. 393 */ 394 void 395 coproc_cleanup(int reuse) 396 { 397 /* This to allow co-processes to share output pipe */ 398 if (!reuse || coproc.readw < 0 || coproc.read < 0) { 399 if (coproc.read >= 0) { 400 close(coproc.read); 401 coproc.read = -1; 402 } 403 if (coproc.readw >= 0) { 404 close(coproc.readw); 405 coproc.readw = -1; 406 } 407 } 408 if (coproc.write >= 0) { 409 close(coproc.write); 410 coproc.write = -1; 411 } 412 } 413 414 415 /* 416 * temporary files 417 */ 418 419 struct temp * 420 maketemp(Area *ap, Temp_type type, struct temp **tlist) 421 { 422 struct temp *tp; 423 int len; 424 int fd; 425 char *path; 426 const char *dir; 427 428 dir = tmpdir ? tmpdir : "/tmp"; 429 /* The 20 + 20 is a paranoid worst case for pid/inc */ 430 len = strlen(dir) + 3 + 20 + 20 + 1; 431 tp = alloc(sizeof(struct temp) + len, ap); 432 tp->name = path = (char *) &tp[1]; 433 tp->shf = NULL; 434 tp->type = type; 435 shf_snprintf(path, len, "%s/shXXXXXXXX", dir); 436 fd = mkstemp(path); 437 if (fd >= 0) 438 tp->shf = shf_fdopen(fd, SHF_WR, NULL); 439 tp->pid = procpid; 440 441 tp->next = *tlist; 442 *tlist = tp; 443 return tp; 444 } 445