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