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