1/* 2 * jobs.c - job control 3 * 4 * This file is part of zsh, the Z shell. 5 * 6 * Copyright (c) 1992-1997 Paul Falstad 7 * All rights reserved. 8 * 9 * Permission is hereby granted, without written agreement and without 10 * license or royalty fees, to use, copy, modify, and distribute this 11 * software and to distribute modified versions of this software for any 12 * purpose, provided that the above copyright notice and the following 13 * two paragraphs appear in all copies of this software. 14 * 15 * In no event shall Paul Falstad or the Zsh Development Group be liable 16 * to any party for direct, indirect, special, incidental, or consequential 17 * damages arising out of the use of this software and its documentation, 18 * even if Paul Falstad and the Zsh Development Group have been advised of 19 * the possibility of such damage. 20 * 21 * Paul Falstad and the Zsh Development Group specifically disclaim any 22 * warranties, including, but not limited to, the implied warranties of 23 * merchantability and fitness for a particular purpose. The software 24 * provided hereunder is on an "as is" basis, and Paul Falstad and the 25 * Zsh Development Group have no obligation to provide maintenance, 26 * support, updates, enhancements, or modifications. 27 * 28 */ 29 30#include "zsh.mdh" 31#include "jobs.pro" 32 33/* the process group of the shell at startup (equal to mypgprp, except 34 when we started without being process group leader */ 35 36/**/ 37mod_export pid_t origpgrp; 38 39/* the process group of the shell */ 40 41/**/ 42mod_export pid_t mypgrp; 43 44/* the job we are working on */ 45 46/**/ 47mod_export int thisjob; 48 49/* the current job (+) */ 50 51/**/ 52mod_export int curjob; 53 54/* the previous job (-) */ 55 56/**/ 57mod_export int prevjob; 58 59/* the job table */ 60 61/**/ 62mod_export struct job *jobtab; 63 64/* Size of the job table. */ 65 66/**/ 67mod_export int jobtabsize; 68 69/* The highest numbered job in the jobtable */ 70 71/**/ 72mod_export int maxjob; 73 74/* If we have entered a subshell, the original shell's job table. */ 75static struct job *oldjobtab; 76 77/* The size of that. */ 78static int oldmaxjob; 79 80/* shell timings */ 81 82/**/ 83#ifdef HAVE_GETRUSAGE 84/**/ 85static struct rusage child_usage; 86/**/ 87#else 88/**/ 89static struct tms shtms; 90/**/ 91#endif 92 93/* 1 if ttyctl -f has been executed */ 94 95/**/ 96mod_export int ttyfrozen; 97 98/* Previous values of errflag and breaks if the signal handler had to 99 * change them. And a flag saying if it did that. */ 100 101/**/ 102int prev_errflag, prev_breaks, errbrk_saved; 103 104/**/ 105int numpipestats, pipestats[MAX_PIPESTATS]; 106 107/* 108 * The status associated with the process lastpid. 109 * -1 if not set and no associated lastpid 110 * -2 if lastpid is set and status isn't yet 111 * else the value returned by wait(). 112 */ 113/**/ 114long lastpid_status; 115 116/* Diff two timevals for elapsed-time computations */ 117 118/**/ 119static struct timeval * 120dtime(struct timeval *dt, struct timeval *t1, struct timeval *t2) 121{ 122 dt->tv_sec = t2->tv_sec - t1->tv_sec; 123 dt->tv_usec = t2->tv_usec - t1->tv_usec; 124 if (dt->tv_usec < 0) { 125 dt->tv_usec += 1000000.0; 126 dt->tv_sec -= 1.0; 127 } 128 return dt; 129} 130 131/* change job table entry from stopped to running */ 132 133/**/ 134void 135makerunning(Job jn) 136{ 137 Process pn; 138 139 jn->stat &= ~STAT_STOPPED; 140 for (pn = jn->procs; pn; pn = pn->next) 141#if 0 142 if (WIFSTOPPED(pn->status) && 143 (!(jn->stat & STAT_SUPERJOB) || pn->next)) 144 pn->status = SP_RUNNING; 145#endif 146 if (WIFSTOPPED(pn->status)) 147 pn->status = SP_RUNNING; 148 149 if (jn->stat & STAT_SUPERJOB) 150 makerunning(jobtab + jn->other); 151} 152 153/* Find process and job associated with pid. * 154 * Return 1 if search was successful, else return 0. */ 155 156/**/ 157int 158findproc(pid_t pid, Job *jptr, Process *pptr, int aux) 159{ 160 Process pn; 161 int i; 162 163 *jptr = NULL; 164 *pptr = NULL; 165 for (i = 1; i <= maxjob; i++) 166 { 167 /* 168 * We are only interested in jobs with processes still 169 * marked as live. Careful in case there's an identical 170 * process number in a job we haven't quite got around 171 * to deleting. 172 */ 173 if (jobtab[i].stat & STAT_DONE) 174 continue; 175 176 for (pn = aux ? jobtab[i].auxprocs : jobtab[i].procs; 177 pn; pn = pn->next) 178 { 179 /* 180 * Make sure we match a process that's still running. 181 * 182 * When a job contains two pids, one terminated pid and one 183 * running pid, then the condition (jobtab[i].stat & 184 * STAT_DONE) will not stop these pids from being candidates 185 * for the findproc result (which is supposed to be a 186 * RUNNING pid), and if the terminated pid is an identical 187 * process number for the pid identifying the running 188 * process we are trying to find (after pid number 189 * wrapping), then we need to avoid returning the terminated 190 * pid, otherwise the shell would block and wait forever for 191 * the termination of the process which pid we were supposed 192 * to return in a different job. 193 */ 194 if (pn->pid == pid) { 195 *pptr = pn; 196 *jptr = jobtab + i; 197 if (pn->status == SP_RUNNING) 198 return 1; 199 } 200 } 201 } 202 203 return (*pptr && *jptr); 204} 205 206/* Does the given job number have any processes? */ 207 208/**/ 209int 210hasprocs(int job) 211{ 212 Job jn; 213 214 if (job < 0) { 215 DPUTS(1, "job number invalid in hasprocs"); 216 return 0; 217 } 218 jn = jobtab + job; 219 220 return jn->procs || jn->auxprocs; 221} 222 223/* Find the super-job of a sub-job. */ 224 225/**/ 226static int 227super_job(int sub) 228{ 229 int i; 230 231 for (i = 1; i <= maxjob; i++) 232 if ((jobtab[i].stat & STAT_SUPERJOB) && 233 jobtab[i].other == sub && 234 jobtab[i].gleader) 235 return i; 236 return 0; 237} 238 239/**/ 240static int 241handle_sub(int job, int fg) 242{ 243 Job jn = jobtab + job, sj = jobtab + jn->other; 244 245 if ((sj->stat & STAT_DONE) || (!sj->procs && !sj->auxprocs)) { 246 struct process *p; 247 248 for (p = sj->procs; p; p = p->next) 249 if (WIFSIGNALED(p->status)) { 250 if (jn->gleader != mypgrp && jn->procs->next) 251 killpg(jn->gleader, WTERMSIG(p->status)); 252 else 253 kill(jn->procs->pid, WTERMSIG(p->status)); 254 kill(sj->other, SIGCONT); 255 kill(sj->other, WTERMSIG(p->status)); 256 break; 257 } 258 if (!p) { 259 int cp; 260 261 jn->stat &= ~STAT_SUPERJOB; 262 jn->stat |= STAT_WASSUPER; 263 264 if ((cp = ((WIFEXITED(jn->procs->status) || 265 WIFSIGNALED(jn->procs->status)) && 266 killpg(jn->gleader, 0) == -1))) { 267 Process p; 268 for (p = jn->procs; p->next; p = p->next); 269 jn->gleader = p->pid; 270 } 271 /* This deleted the job too early if the parent 272 shell waited for a command in a list that will 273 be executed by the sub-shell (e.g.: if we have 274 `ls|if true;then sleep 20;cat;fi' and ^Z the 275 sleep, the rest will be executed by a sub-shell, 276 but the parent shell gets notified for the 277 sleep. 278 deletejob(sj, 0); */ 279 /* If this super-job contains only the sub-shell, 280 we have to attach the tty to its process group 281 now. */ 282 if ((fg || thisjob == job) && 283 (!jn->procs->next || cp || jn->procs->pid != jn->gleader)) 284 attachtty(jn->gleader); 285 kill(sj->other, SIGCONT); 286 } 287 curjob = jn - jobtab; 288 } else if (sj->stat & STAT_STOPPED) { 289 struct process *p; 290 291 jn->stat |= STAT_STOPPED; 292 for (p = jn->procs; p; p = p->next) 293 if (p->status == SP_RUNNING || 294 (!WIFEXITED(p->status) && !WIFSIGNALED(p->status))) 295 p->status = sj->procs->status; 296 curjob = jn - jobtab; 297 printjob(jn, !!isset(LONGLISTJOBS), 1); 298 return 1; 299 } 300 return 0; 301} 302 303 304/* Get the latest usage information */ 305 306/**/ 307void 308get_usage(void) 309{ 310#ifdef HAVE_GETRUSAGE 311 getrusage(RUSAGE_CHILDREN, &child_usage); 312#else 313 times(&shtms); 314#endif 315} 316 317 318#if !defined HAVE_WAIT3 || !defined HAVE_GETRUSAGE 319/* Update status of process that we have just WAIT'ed for */ 320 321/**/ 322void 323update_process(Process pn, int status) 324{ 325 struct timezone dummy_tz; 326#ifdef HAVE_GETRUSAGE 327 struct timeval childs = child_usage.ru_stime; 328 struct timeval childu = child_usage.ru_utime; 329#else 330 long childs = shtms.tms_cstime; 331 long childu = shtms.tms_cutime; 332#endif 333 334 /* get time-accounting info */ 335 get_usage(); 336 gettimeofday(&pn->endtime, &dummy_tz); /* record time process exited */ 337 338 pn->status = status; /* save the status returned by WAIT */ 339#ifdef HAVE_GETRUSAGE 340 dtime(&pn->ti.ru_stime, &childs, &child_usage.ru_stime); 341 dtime(&pn->ti.ru_utime, &childu, &child_usage.ru_utime); 342#else 343 pn->ti.st = shtms.tms_cstime - childs; /* compute process system space time */ 344 pn->ti.ut = shtms.tms_cutime - childu; /* compute process user space time */ 345#endif 346} 347#endif 348 349/* 350 * Called when the current shell is behaving as if it received 351 * a interactively generated signal (sig). 352 * 353 * As we got the signal or are pretending we did, we need to pretend 354 * anything attached to a CURSH process got it, too. 355 */ 356/**/ 357void 358check_cursh_sig(int sig) 359{ 360 int i, j; 361 362 if (!errflag) 363 return; 364 for (i = 1; i <= maxjob; i++) { 365 if ((jobtab[i].stat & (STAT_CURSH|STAT_DONE)) == 366 STAT_CURSH) { 367 for (j = 0; j < 2; j++) { 368 Process pn = j ? jobtab[i].auxprocs : jobtab[i].procs; 369 for (; pn; pn = pn->next) { 370 if (pn->status == SP_RUNNING) { 371 kill(pn->pid, sig); 372 } 373 } 374 } 375 } 376 } 377} 378 379/**/ 380void 381storepipestats(Job jn, int inforeground, int fixlastval) 382{ 383 int i, pipefail = 0, jpipestats[MAX_PIPESTATS]; 384 Process p; 385 386 for (p = jn->procs, i = 0; p && i < MAX_PIPESTATS; p = p->next, i++) { 387 jpipestats[i] = ((WIFSIGNALED(p->status)) ? 388 0200 | WTERMSIG(p->status) : 389 WEXITSTATUS(p->status)); 390 if (jpipestats[i]) 391 pipefail = jpipestats[i]; 392 } 393 if (inforeground) { 394 memcpy(pipestats, jpipestats, sizeof(int)*i); 395 if ((jn->stat & STAT_CURSH) && i < MAX_PIPESTATS) 396 pipestats[i++] = lastval; 397 numpipestats = i; 398 } 399 400 if (fixlastval) { 401 if (jn->stat & STAT_CURSH) { 402 if (!lastval && isset(PIPEFAIL)) 403 lastval = pipefail; 404 } else if (isset(PIPEFAIL)) 405 lastval = pipefail; 406 } 407} 408 409/* Update status of job, possibly printing it */ 410 411/**/ 412void 413update_job(Job jn) 414{ 415 Process pn; 416 int job; 417 int val = 0, status = 0; 418 int somestopped = 0, inforeground = 0; 419 420 for (pn = jn->auxprocs; pn; pn = pn->next) { 421#ifdef WIFCONTINUED 422 if (WIFCONTINUED(pn->status)) 423 pn->status = SP_RUNNING; 424#endif 425 if (pn->status == SP_RUNNING) 426 return; 427 } 428 429 for (pn = jn->procs; pn; pn = pn->next) { 430#ifdef WIFCONTINUED 431 if (WIFCONTINUED(pn->status)) 432 pn->status = SP_RUNNING; 433#endif 434 if (pn->status == SP_RUNNING) /* some processes in this job are running */ 435 return; /* so no need to update job table entry */ 436 if (WIFSTOPPED(pn->status)) /* some processes are stopped */ 437 somestopped = 1; /* so job is not done, but entry needs updating */ 438 if (!pn->next) /* last job in pipeline determines exit status */ 439 val = (WIFSIGNALED(pn->status)) ? 0200 | WTERMSIG(pn->status) : 440 WEXITSTATUS(pn->status); 441 if (pn->pid == jn->gleader) /* if this process is process group leader */ 442 status = pn->status; 443 } 444 445 job = jn - jobtab; /* compute job number */ 446 447 if (somestopped) { 448 if (jn->stty_in_env && !jn->ty) { 449 jn->ty = (struct ttyinfo *) zalloc(sizeof(struct ttyinfo)); 450 gettyinfo(jn->ty); 451 } 452 if (jn->stat & STAT_STOPPED) { 453 if (jn->stat & STAT_SUBJOB) { 454 /* If we have `cat foo|while read a; grep $a bar;done' 455 * and have hit ^Z, the sub-job is stopped, but the 456 * super-job may still be running, waiting to be stopped 457 * or to exit. So we have to send it a SIGTSTP. */ 458 int i; 459 460 if ((i = super_job(job))) 461 killpg(jobtab[i].gleader, SIGTSTP); 462 } 463 return; 464 } 465 } 466 { /* job is done or stopped, remember return value */ 467 lastval2 = val; 468 /* If last process was run in the current shell, keep old status 469 * and let it handle its own traps, but always allow the test 470 * for the pgrp. 471 */ 472 if (jn->stat & STAT_CURSH) 473 inforeground = 1; 474 else if (job == thisjob) { 475 lastval = val; 476 inforeground = 2; 477 } 478 } 479 480 if (shout && shout != stderr && !ttyfrozen && !jn->stty_in_env && 481 !zleactive && job == thisjob && !somestopped && 482 !(jn->stat & STAT_NOSTTY)) 483 gettyinfo(&shttyinfo); 484 485 if (isset(MONITOR)) { 486 pid_t pgrp = gettygrp(); /* get process group of tty */ 487 488 /* is this job in the foreground of an interactive shell? */ 489 if (mypgrp != pgrp && inforeground && 490 (jn->gleader == pgrp || (pgrp > 1 && kill(-pgrp, 0) == -1))) { 491 if (list_pipe) { 492 if (somestopped || (pgrp > 1 && kill(-pgrp, 0) == -1)) { 493 attachtty(mypgrp); 494 /* check window size and adjust if necessary */ 495 adjustwinsize(0); 496 } else { 497 /* 498 * Oh, dear, we're right in the middle of some confusion 499 * of shell jobs on the righthand side of a pipeline, so 500 * it's death to call attachtty() just yet. Mark the 501 * fact in the job, so that the attachtty() will be called 502 * when the job is finally deleted. 503 */ 504 jn->stat |= STAT_ATTACH; 505 } 506 /* If we have `foo|while true; (( x++ )); done', and hit 507 * ^C, we have to stop the loop, too. */ 508 if ((val & 0200) && inforeground == 1 && 509 ((val & ~0200) == SIGINT || (val & ~0200) == SIGQUIT)) { 510 if (!errbrk_saved) { 511 errbrk_saved = 1; 512 prev_breaks = breaks; 513 prev_errflag = errflag; 514 } 515 breaks = loops; 516 errflag = 1; 517 inerrflush(); 518 } 519 } else { 520 attachtty(mypgrp); 521 /* check window size and adjust if necessary */ 522 adjustwinsize(0); 523 } 524 } 525 } else if (list_pipe && (val & 0200) && inforeground == 1 && 526 ((val & ~0200) == SIGINT || (val & ~0200) == SIGQUIT)) { 527 if (!errbrk_saved) { 528 errbrk_saved = 1; 529 prev_breaks = breaks; 530 prev_errflag = errflag; 531 } 532 breaks = loops; 533 errflag = 1; 534 inerrflush(); 535 } 536 if (somestopped && jn->stat & STAT_SUPERJOB) 537 return; 538 jn->stat |= (somestopped) ? STAT_CHANGED | STAT_STOPPED : 539 STAT_CHANGED | STAT_DONE; 540 if (jn->stat & STAT_DONE) { 541 /* This may be redundant with printjob() but note that inforeground 542 * is true here for STAT_CURSH jobs even when job != thisjob, most 543 * likely because thisjob = -1 from exec.c:execsimple() trickery. 544 * However, if we reset lastval here we break it for printjob(). 545 */ 546 storepipestats(jn, inforeground, 0); 547 } 548 if (!inforeground && 549 (jn->stat & (STAT_SUBJOB | STAT_DONE)) == (STAT_SUBJOB | STAT_DONE)) { 550 int su; 551 552 if ((su = super_job(jn - jobtab))) 553 handle_sub(su, 0); 554 } 555 if ((jn->stat & (STAT_DONE | STAT_STOPPED)) == STAT_STOPPED) { 556 prevjob = curjob; 557 curjob = job; 558 } 559 if ((isset(NOTIFY) || job == thisjob) && (jn->stat & STAT_LOCKED)) { 560 if (printjob(jn, !!isset(LONGLISTJOBS), 0) && 561 zleactive) 562 zleentry(ZLE_CMD_REFRESH); 563 } 564 if (sigtrapped[SIGCHLD] && job != thisjob) 565 dotrap(SIGCHLD); 566 567 /* When MONITOR is set, the foreground process runs in a different * 568 * process group from the shell, so the shell will not receive * 569 * terminal signals, therefore we pretend that the shell got * 570 * the signal too. */ 571 if (inforeground == 2 && isset(MONITOR) && WIFSIGNALED(status)) { 572 int sig = WTERMSIG(status); 573 574 if (sig == SIGINT || sig == SIGQUIT) { 575 if (sigtrapped[sig]) { 576 dotrap(sig); 577 /* We keep the errflag as set or not by dotrap. 578 * This is to fulfil the promise to carry on 579 * with the jobs if trap returns zero. 580 * Setting breaks = loops ensures a consistent return 581 * status if inside a loop. Maybe the code in loops 582 * should be changed. 583 */ 584 if (errflag) 585 breaks = loops; 586 } else { 587 breaks = loops; 588 errflag = 1; 589 } 590 check_cursh_sig(sig); 591 } 592 } 593} 594 595/* set the previous job to something reasonable */ 596 597/**/ 598static void 599setprevjob(void) 600{ 601 int i; 602 603 for (i = maxjob; i; i--) 604 if ((jobtab[i].stat & STAT_INUSE) && (jobtab[i].stat & STAT_STOPPED) && 605 !(jobtab[i].stat & STAT_SUBJOB) && i != curjob && i != thisjob) { 606 prevjob = i; 607 return; 608 } 609 610 for (i = maxjob; i; i--) 611 if ((jobtab[i].stat & STAT_INUSE) && !(jobtab[i].stat & STAT_SUBJOB) && 612 i != curjob && i != thisjob) { 613 prevjob = i; 614 return; 615 } 616 617 prevjob = -1; 618} 619 620/**/ 621#ifndef HAVE_GETRUSAGE 622static long clktck = 0; 623 624/**/ 625static void 626set_clktck(void) 627{ 628#ifdef _SC_CLK_TCK 629 if (!clktck) 630 /* fetch clock ticks per second from * 631 * sysconf only the first time */ 632 clktck = sysconf(_SC_CLK_TCK); 633#else 634# ifdef __NeXT__ 635 /* NeXTStep 3.3 defines CLK_TCK wrongly */ 636 clktck = 60; 637# else 638# ifdef CLK_TCK 639 clktck = CLK_TCK; 640# else 641# ifdef HZ 642 clktck = HZ; 643# else 644 clktck = 60; 645# endif 646# endif 647# endif 648#endif 649} 650/**/ 651#endif 652 653/**/ 654static void 655printhhmmss(double secs) 656{ 657 int mins = (int) secs / 60; 658 int hours = mins / 60; 659 660 secs -= 60 * mins; 661 mins -= 60 * hours; 662 if (hours) 663 fprintf(stderr, "%d:%02d:%05.2f", hours, mins, secs); 664 else if (mins) 665 fprintf(stderr, "%d:%05.2f", mins, secs); 666 else 667 fprintf(stderr, "%.3f", secs); 668} 669 670static void 671printtime(struct timeval *real, child_times_t *ti, char *desc) 672{ 673 char *s; 674 double elapsed_time, user_time, system_time; 675#ifdef HAVE_GETRUSAGE 676 double total_time; 677#endif 678 int percent, desclen; 679 680 if (!desc) 681 { 682 desc = ""; 683 desclen = 0; 684 } 685 else 686 { 687 desc = dupstring(desc); 688 unmetafy(desc, &desclen); 689 } 690 691 /* go ahead and compute these, since almost every TIMEFMT will have them */ 692 elapsed_time = real->tv_sec + real->tv_usec / 1000000.0; 693 694#ifdef HAVE_GETRUSAGE 695 user_time = ti->ru_utime.tv_sec + ti->ru_utime.tv_usec / 1000000.0; 696 system_time = ti->ru_stime.tv_sec + ti->ru_stime.tv_usec / 1000000.0; 697 total_time = user_time + system_time; 698 percent = 100.0 * total_time 699 / (real->tv_sec + real->tv_usec / 1000000.0); 700#else 701 set_clktck(); 702 user_time = ti->ut / (double) clktck; 703 system_time = ti->st / (double) clktck; 704 percent = 100.0 * (ti->ut + ti->st) 705 / (clktck * real->tv_sec + clktck * real->tv_usec / 1000000.0); 706#endif 707 708 queue_signals(); 709 if (!(s = getsparam("TIMEFMT"))) 710 s = DEFAULT_TIMEFMT; 711 712 for (; *s; s++) 713 if (*s == '%') 714 switch (*++s) { 715 case 'E': 716 fprintf(stderr, "%4.2fs", elapsed_time); 717 break; 718 case 'U': 719 fprintf(stderr, "%4.2fs", user_time); 720 break; 721 case 'S': 722 fprintf(stderr, "%4.2fs", system_time); 723 break; 724 case '*': 725 switch (*++s) { 726 case 'E': 727 printhhmmss(elapsed_time); 728 break; 729 case 'U': 730 printhhmmss(user_time); 731 break; 732 case 'S': 733 printhhmmss(system_time); 734 break; 735 default: 736 fprintf(stderr, "%%*"); 737 s--; 738 break; 739 } 740 break; 741 case 'P': 742 fprintf(stderr, "%d%%", percent); 743 break; 744#ifdef HAVE_STRUCT_RUSAGE_RU_NSWAP 745 case 'W': 746 fprintf(stderr, "%ld", ti->ru_nswap); 747 break; 748#endif 749#ifdef HAVE_STRUCT_RUSAGE_RU_IXRSS 750 case 'X': 751 fprintf(stderr, "%ld", 752 total_time ? 753 (long)(ti->ru_ixrss / total_time) : 754 (long)0); 755 break; 756#endif 757#ifdef HAVE_STRUCT_RUSAGE_RU_IDRSS 758 case 'D': 759 fprintf(stderr, "%ld", 760 total_time ? 761 (long) ((ti->ru_idrss 762#ifdef HAVE_STRUCT_RUSAGE_RU_ISRSS 763 + ti->ru_isrss 764#endif 765 ) / total_time) : 766 (long)0); 767 break; 768#endif 769#if defined(HAVE_STRUCT_RUSAGE_RU_IDRSS) || \ 770 defined(HAVE_STRUCT_RUSAGE_RU_ISRSS) || \ 771 defined(HAVE_STRUCT_RUSAGE_RU_IXRSS) 772 case 'K': 773 /* treat as D if X not available */ 774 fprintf(stderr, "%ld", 775 total_time ? 776 (long) (( 777#ifdef HAVE_STRUCT_RUSAGE_RU_IXRSS 778 ti->ru_ixrss 779#else 780 0 781#endif 782#ifdef HAVE_STRUCT_RUSAGE_RU_IDRSS 783 + ti->ru_idrss 784#endif 785#ifdef HAVE_STRUCT_RUSAGE_RU_ISRSS 786 + ti->ru_isrss 787#endif 788 ) / total_time) : 789 (long)0); 790 break; 791#endif 792#ifdef HAVE_STRUCT_RUSAGE_RU_MAXRSS 793 case 'M': 794 fprintf(stderr, "%ld", ti->ru_maxrss / 1024); 795 break; 796#endif 797#ifdef HAVE_STRUCT_RUSAGE_RU_MAJFLT 798 case 'F': 799 fprintf(stderr, "%ld", ti->ru_majflt); 800 break; 801#endif 802#ifdef HAVE_STRUCT_RUSAGE_RU_MINFLT 803 case 'R': 804 fprintf(stderr, "%ld", ti->ru_minflt); 805 break; 806#endif 807#ifdef HAVE_STRUCT_RUSAGE_RU_INBLOCK 808 case 'I': 809 fprintf(stderr, "%ld", ti->ru_inblock); 810 break; 811#endif 812#ifdef HAVE_STRUCT_RUSAGE_RU_OUBLOCK 813 case 'O': 814 fprintf(stderr, "%ld", ti->ru_oublock); 815 break; 816#endif 817#ifdef HAVE_STRUCT_RUSAGE_RU_MSGRCV 818 case 'r': 819 fprintf(stderr, "%ld", ti->ru_msgrcv); 820 break; 821#endif 822#ifdef HAVE_STRUCT_RUSAGE_RU_MSGSND 823 case 's': 824 fprintf(stderr, "%ld", ti->ru_msgsnd); 825 break; 826#endif 827#ifdef HAVE_STRUCT_RUSAGE_RU_NSIGNALS 828 case 'k': 829 fprintf(stderr, "%ld", ti->ru_nsignals); 830 break; 831#endif 832#ifdef HAVE_STRUCT_RUSAGE_RU_NVCSW 833 case 'w': 834 fprintf(stderr, "%ld", ti->ru_nvcsw); 835 break; 836#endif 837#ifdef HAVE_STRUCT_RUSAGE_RU_NIVCSW 838 case 'c': 839 fprintf(stderr, "%ld", ti->ru_nivcsw); 840 break; 841#endif 842 case 'J': 843 fwrite(desc, sizeof(char), desclen, stderr); 844 break; 845 case '%': 846 putc('%', stderr); 847 break; 848 case '\0': 849 s--; 850 break; 851 default: 852 fprintf(stderr, "%%%c", *s); 853 break; 854 } else 855 putc(*s, stderr); 856 unqueue_signals(); 857 putc('\n', stderr); 858 fflush(stderr); 859} 860 861/**/ 862static void 863dumptime(Job jn) 864{ 865 Process pn; 866 struct timeval dtimeval; 867 868 if (!jn->procs) 869 return; 870 for (pn = jn->procs; pn; pn = pn->next) 871 printtime(dtime(&dtimeval, &pn->bgtime, &pn->endtime), &pn->ti, 872 pn->text); 873} 874 875/* Check whether shell should report the amount of time consumed * 876 * by job. This will be the case if we have preceded the command * 877 * with the keyword time, or if REPORTTIME is non-negative and the * 878 * amount of time consumed by the job is greater than REPORTTIME */ 879 880/**/ 881static int 882should_report_time(Job j) 883{ 884 struct value vbuf; 885 Value v; 886 char *s = "REPORTTIME"; 887 zlong reporttime; 888 889 /* if the time keyword was used */ 890 if (j->stat & STAT_TIMED) 891 return 1; 892 893 queue_signals(); 894 if (!(v = getvalue(&vbuf, &s, 0)) || 895 (reporttime = getintvalue(v)) < 0) { 896 unqueue_signals(); 897 return 0; 898 } 899 unqueue_signals(); 900 /* can this ever happen? */ 901 if (!j->procs) 902 return 0; 903 if (zleactive) 904 return 0; 905 906#ifdef HAVE_GETRUSAGE 907 reporttime -= j->procs->ti.ru_utime.tv_sec + j->procs->ti.ru_stime.tv_sec; 908 if (j->procs->ti.ru_utime.tv_usec + 909 j->procs->ti.ru_stime.tv_usec >= 1000000) 910 reporttime--; 911 return reporttime <= 0; 912#else 913 set_clktck(); 914 return ((j->procs->ti.ut + j->procs->ti.st) / clktck >= reporttime); 915#endif 916} 917 918/* !(lng & 3) means jobs * 919 * (lng & 1) means jobs -l * 920 * (lng & 2) means jobs -p 921 * (lng & 4) means jobs -d 922 * 923 * synch = 0 means asynchronous 924 * synch = 1 means synchronous 925 * synch = 2 means called synchronously from jobs 926 * synch = 3 means called synchronously from bg or fg 927 * 928 * Returns 1 if some output was done. 929 * 930 * The function also deletes the job if it was done, even it 931 * is not printed. 932 */ 933 934/**/ 935int 936printjob(Job jn, int lng, int synch) 937{ 938 Process pn; 939 int job, len = 9, sig, sflag = 0, llen; 940 int conted = 0, lineleng = zterm_columns, skip = 0, doputnl = 0; 941 int doneprint = 0, skip_print = 0; 942 FILE *fout = (synch == 2 || !shout) ? stdout : shout; 943 944 if (synch > 1 && oldjobtab != NULL) 945 job = jn - oldjobtab; 946 else 947 job = jn - jobtab; 948 DPUTS3(job < 0 || job > (oldjobtab && synch > 1 ? oldmaxjob : maxjob), 949 "bogus job number, jn = %L, jobtab = %L, oldjobtab = %L", 950 (long)jn, (long)jobtab, (long)oldjobtab); 951 952 if (jn->stat & STAT_NOPRINT) { 953 skip_print = 1; 954 } 955 956 if (lng < 0) { 957 conted = 1; 958 lng = !!isset(LONGLISTJOBS); 959 } 960 961/* find length of longest signame, check to see */ 962/* if we really need to print this job */ 963 964 for (pn = jn->procs; pn; pn = pn->next) { 965 if (jn->stat & STAT_SUPERJOB && 966 jn->procs->status == SP_RUNNING && !pn->next) 967 pn->status = SP_RUNNING; 968 if (pn->status != SP_RUNNING) { 969 if (WIFSIGNALED(pn->status)) { 970 sig = WTERMSIG(pn->status); 971 llen = strlen(sigmsg(sig)); 972 if (WCOREDUMP(pn->status)) 973 llen += 14; 974 if (llen > len) 975 len = llen; 976 if (sig != SIGINT && sig != SIGPIPE) 977 sflag = 1; 978 if (job == thisjob && sig == SIGINT) 979 doputnl = 1; 980 if (isset(PRINTEXITVALUE) && isset(SHINSTDIN)) { 981 sflag = 1; 982 skip_print = 0; 983 } 984 } else if (WIFSTOPPED(pn->status)) { 985 sig = WSTOPSIG(pn->status); 986 if ((int)strlen(sigmsg(sig)) > len) 987 len = strlen(sigmsg(sig)); 988 if (job == thisjob && sig == SIGTSTP) 989 doputnl = 1; 990 } else if (isset(PRINTEXITVALUE) && isset(SHINSTDIN) && 991 WEXITSTATUS(pn->status)) { 992 sflag = 1; 993 skip_print = 0; 994 } 995 } 996 } 997 998 if (skip_print) { 999 if (jn->stat & STAT_DONE) { 1000 /* This looks silly, but see update_job() */ 1001 if (synch <= 1) 1002 storepipestats(jn, job == thisjob, job == thisjob); 1003 if (should_report_time(jn)) 1004 dumptime(jn); 1005 deletejob(jn, 0); 1006 if (job == curjob) { 1007 curjob = prevjob; 1008 prevjob = job; 1009 } 1010 if (job == prevjob) 1011 setprevjob(); 1012 } 1013 return 0; 1014 } 1015 1016 /* 1017 * - Always print if called from jobs 1018 * - Otherwise, require MONITOR option ("jobbing") and some 1019 * change of state 1020 * - also either the shell is interactive or this is synchronous. 1021 */ 1022 if (synch == 2 || 1023 ((interact || synch) && jobbing && 1024 ((jn->stat & STAT_STOPPED) || sflag || job != thisjob))) { 1025 int len2, fline = 1; 1026 /* POSIX requires just the job text for bg and fg */ 1027 int plainfmt = (synch == 3) && isset(POSIXJOBS); 1028 /* use special format for current job, except in `jobs' */ 1029 int thisfmt = job == thisjob && synch != 2; 1030 Process qn; 1031 1032 if (!synch) 1033 zleentry(ZLE_CMD_TRASH); 1034 if (doputnl && !synch) { 1035 doneprint = 1; 1036 putc('\n', fout); 1037 } 1038 for (pn = jn->procs; pn;) { 1039 len2 = (thisfmt ? 5 : 10) + len; /* 2 spaces */ 1040 if (lng & 3) 1041 qn = pn->next; 1042 else 1043 for (qn = pn->next; qn; qn = qn->next) { 1044 if (qn->status != pn->status) 1045 break; 1046 if ((int)strlen(qn->text) + len2 + ((qn->next) ? 3 : 0) 1047 > lineleng) 1048 break; 1049 len2 += strlen(qn->text) + 2; 1050 } 1051 doneprint = 1; 1052 if (!plainfmt) { 1053 if (!thisfmt || lng) { 1054 if (fline) 1055 fprintf(fout, "[%ld] %c ", 1056 (long)job, 1057 (job == curjob) ? '+' 1058 : (job == prevjob) ? '-' : ' '); 1059 else 1060 fprintf(fout, (job > 9) ? " " : " "); 1061 } else 1062 fprintf(fout, "zsh: "); 1063 if (lng & 1) 1064 fprintf(fout, "%ld ", (long) pn->pid); 1065 else if (lng & 2) { 1066 pid_t x = jn->gleader; 1067 1068 fprintf(fout, "%ld ", (long) x); 1069 do 1070 skip++; 1071 while ((x /= 10)); 1072 skip++; 1073 lng &= ~3; 1074 } else 1075 fprintf(fout, "%*s", skip, ""); 1076 if (pn->status == SP_RUNNING) { 1077 if (!conted) 1078 fprintf(fout, "running%*s", len - 7 + 2, ""); 1079 else 1080 fprintf(fout, "continued%*s", len - 9 + 2, ""); 1081 } 1082 else if (WIFEXITED(pn->status)) { 1083 if (WEXITSTATUS(pn->status)) 1084 fprintf(fout, "exit %-4d%*s", WEXITSTATUS(pn->status), 1085 len - 9 + 2, ""); 1086 else 1087 fprintf(fout, "done%*s", len - 4 + 2, ""); 1088 } else if (WIFSTOPPED(pn->status)) 1089 fprintf(fout, "%-*s", len + 2, 1090 sigmsg(WSTOPSIG(pn->status))); 1091 else if (WCOREDUMP(pn->status)) 1092 fprintf(fout, "%s (core dumped)%*s", 1093 sigmsg(WTERMSIG(pn->status)), 1094 (int)(len - 14 + 2 - 1095 strlen(sigmsg(WTERMSIG(pn->status)))), ""); 1096 else 1097 fprintf(fout, "%-*s", len + 2, 1098 sigmsg(WTERMSIG(pn->status))); 1099 } 1100 for (; pn != qn; pn = pn->next) { 1101 char *txt = dupstring(pn->text); 1102 int txtlen; 1103 unmetafy(txt, &txtlen); 1104 fwrite(txt, sizeof(char), txtlen, fout); 1105 if (pn->next) 1106 fputs(" | ", fout); 1107 } 1108 putc('\n', fout); 1109 fline = 0; 1110 } 1111 fflush(fout); 1112 } else if (doputnl && interact && !synch) { 1113 doneprint = 1; 1114 putc('\n', fout); 1115 fflush(fout); 1116 } 1117 1118 /* print "(pwd now: foo)" messages: with (lng & 4) we are printing 1119 * the directory where the job is running, otherwise the current directory 1120 */ 1121 1122 if ((lng & 4) || (interact && job == thisjob && 1123 jn->pwd && strcmp(jn->pwd, pwd))) { 1124 doneprint = 1; 1125 fprintf(fout, "(pwd %s: ", (lng & 4) ? "" : "now"); 1126 fprintdir(((lng & 4) && jn->pwd) ? jn->pwd : pwd, fout); 1127 fprintf(fout, ")\n"); 1128 fflush(fout); 1129 } 1130 1131 /* delete job if done */ 1132 1133 if (jn->stat & STAT_DONE) { 1134 /* This looks silly, but see update_job() */ 1135 if (synch <= 1) 1136 storepipestats(jn, job == thisjob, job == thisjob); 1137 if (should_report_time(jn)) 1138 dumptime(jn); 1139 deletejob(jn, 0); 1140 if (job == curjob) { 1141 curjob = prevjob; 1142 prevjob = job; 1143 } 1144 if (job == prevjob) 1145 setprevjob(); 1146 } else 1147 jn->stat &= ~STAT_CHANGED; 1148 1149 return doneprint; 1150} 1151 1152/* Add a file to be deleted or fd to be closed to the current job */ 1153 1154/**/ 1155void 1156addfilelist(const char *name, int fd) 1157{ 1158 Jobfile jf = (Jobfile)zalloc(sizeof(struct jobfile)); 1159 LinkList ll = jobtab[thisjob].filelist; 1160 1161 if (!ll) 1162 ll = jobtab[thisjob].filelist = znewlinklist(); 1163 if (name) 1164 { 1165 jf->u.name = ztrdup(name); 1166 jf->is_fd = 0; 1167 } 1168 else 1169 { 1170 jf->u.fd = fd; 1171 jf->is_fd = 1; 1172 } 1173 zaddlinknode(ll, jf); 1174} 1175 1176/* Clean up pipes no longer needed associated with a job */ 1177 1178/**/ 1179void 1180pipecleanfilelist(LinkList filelist) 1181{ 1182 LinkNode node; 1183 1184 if (!filelist) 1185 return; 1186 node = firstnode(filelist); 1187 while (node) { 1188 Jobfile jf = (Jobfile)getdata(node); 1189 if (jf->is_fd) { 1190 LinkNode next = nextnode(node); 1191 zclose(jf->u.fd); 1192 (void)remnode(filelist, node); 1193 zfree(jf, sizeof(*jf)); 1194 node = next; 1195 } else 1196 incnode(node); 1197 } 1198} 1199 1200/* Finished with list of files for a job */ 1201 1202/**/ 1203void 1204deletefilelist(LinkList file_list, int disowning) 1205{ 1206 Jobfile jf; 1207 if (file_list) { 1208 while ((jf = (Jobfile)getlinknode(file_list))) { 1209 if (jf->is_fd) { 1210 if (!disowning) 1211 zclose(jf->u.fd); 1212 } else { 1213 if (!disowning) 1214 unlink(jf->u.name); 1215 zsfree(jf->u.name); 1216 } 1217 zfree(jf, sizeof(*jf)); 1218 } 1219 zfree(file_list, sizeof(struct linklist)); 1220 } 1221} 1222 1223/**/ 1224void 1225freejob(Job jn, int deleting) 1226{ 1227 struct process *pn, *nx; 1228 1229 pn = jn->procs; 1230 jn->procs = NULL; 1231 for (; pn; pn = nx) { 1232 nx = pn->next; 1233 zfree(pn, sizeof(struct process)); 1234 } 1235 1236 pn = jn->auxprocs; 1237 jn->auxprocs = NULL; 1238 for (; pn; pn = nx) { 1239 nx = pn->next; 1240 zfree(pn, sizeof(struct process)); 1241 } 1242 1243 if (jn->ty) 1244 zfree(jn->ty, sizeof(struct ttyinfo)); 1245 if (jn->pwd) 1246 zsfree(jn->pwd); 1247 jn->pwd = NULL; 1248 if (jn->stat & STAT_WASSUPER) { 1249 /* careful in case we shrink and move the job table */ 1250 int job = jn - jobtab; 1251 if (deleting) 1252 deletejob(jobtab + jn->other, 0); 1253 else 1254 freejob(jobtab + jn->other, 0); 1255 jn = jobtab + job; 1256 } 1257 jn->gleader = jn->other = 0; 1258 jn->stat = jn->stty_in_env = 0; 1259 jn->filelist = NULL; 1260 jn->ty = NULL; 1261 1262 /* Find the new highest job number. */ 1263 if (maxjob == jn - jobtab) { 1264 while (maxjob && !(jobtab[maxjob].stat & STAT_INUSE)) 1265 maxjob--; 1266 } 1267} 1268 1269/* 1270 * We are actually finished with this job, rather 1271 * than freeing it to make space. 1272 * 1273 * If "disowning" is set, files associated with the job are not 1274 * actually deleted --- and won't be as there is nothing left 1275 * to clear up. 1276 */ 1277 1278/**/ 1279void 1280deletejob(Job jn, int disowning) 1281{ 1282 deletefilelist(jn->filelist, disowning); 1283 if (jn->stat & STAT_ATTACH) { 1284 attachtty(mypgrp); 1285 adjustwinsize(0); 1286 } 1287 1288 freejob(jn, 1); 1289} 1290 1291/* 1292 * Add a process to the current job. 1293 * The third argument is 1 if we are adding a process which is not 1294 * part of the main pipeline but an auxiliary process used for 1295 * handling MULTIOS or process substitution. We will wait for it 1296 * but not display job information about it. 1297 */ 1298 1299/**/ 1300void 1301addproc(pid_t pid, char *text, int aux, struct timeval *bgtime) 1302{ 1303 Process pn, *pnlist; 1304 1305 if (pid == lastpid && lastpid_status != -2L) { 1306 /* 1307 * The status for the previous lastpid is invalid. 1308 * Presumably process numbers have wrapped. 1309 */ 1310 lastpid_status = -1L; 1311 } 1312 1313 DPUTS(thisjob == -1, "No valid job in addproc."); 1314 pn = (Process) zshcalloc(sizeof *pn); 1315 pn->pid = pid; 1316 if (text) 1317 strcpy(pn->text, text); 1318 else 1319 *pn->text = '\0'; 1320 pn->status = SP_RUNNING; 1321 pn->next = NULL; 1322 1323 if (!aux) 1324 { 1325 pn->bgtime = *bgtime; 1326 /* if this is the first process we are adding to * 1327 * the job, then it's the group leader. */ 1328 if (!jobtab[thisjob].gleader) 1329 jobtab[thisjob].gleader = pid; 1330 /* attach this process to end of process list of current job */ 1331 pnlist = &jobtab[thisjob].procs; 1332 } 1333 else 1334 pnlist = &jobtab[thisjob].auxprocs; 1335 1336 if (*pnlist) { 1337 Process n; 1338 1339 for (n = *pnlist; n->next; n = n->next); 1340 n->next = pn; 1341 } else { 1342 /* first process for this job */ 1343 *pnlist = pn; 1344 } 1345 /* If the first process in the job finished before any others were * 1346 * added, maybe STAT_DONE got set incorrectly. This can happen if * 1347 * a $(...) was waited for and the last existing job in the * 1348 * pipeline was already finished. We need to be very careful that * 1349 * there was no call to printjob() between then and now, else * 1350 * the job will already have been deleted from the table. */ 1351 jobtab[thisjob].stat &= ~STAT_DONE; 1352} 1353 1354/* Check if we have files to delete. We need to check this to see * 1355 * if it's all right to exec a command without forking in the last * 1356 * component of subshells or after the `-c' option. */ 1357 1358/**/ 1359int 1360havefiles(void) 1361{ 1362 int i; 1363 1364 for (i = 1; i <= maxjob; i++) 1365 if (jobtab[i].stat && jobtab[i].filelist) 1366 return 1; 1367 return 0; 1368 1369} 1370 1371/* 1372 * Wait for a particular process. 1373 * wait_cmd indicates this is from the interactive wait command, 1374 * in which case the behaviour is a little different: the command 1375 * itself can be interrupted by a trapped signal. 1376 */ 1377 1378/**/ 1379int 1380waitforpid(pid_t pid, int wait_cmd) 1381{ 1382 int first = 1, q = queue_signal_level(); 1383 1384 /* child_block() around this loop in case #ifndef WNOHANG */ 1385 dont_queue_signals(); 1386 child_block(); /* unblocked in signal_suspend() */ 1387 queue_traps(wait_cmd); 1388 while (!errflag && (kill(pid, 0) >= 0 || errno != ESRCH)) { 1389 if (first) 1390 first = 0; 1391 else 1392 kill(pid, SIGCONT); 1393 1394 last_signal = -1; 1395 signal_suspend(SIGCHLD, wait_cmd); 1396 if (last_signal != SIGCHLD && wait_cmd && last_signal >= 0 && 1397 (sigtrapped[last_signal] & ZSIG_TRAPPED)) { 1398 /* wait command interrupted, but no error: return */ 1399 restore_queue_signals(q); 1400 return 128 + last_signal; 1401 } 1402 child_block(); 1403 } 1404 unqueue_traps(); 1405 child_unblock(); 1406 restore_queue_signals(q); 1407 1408 return 0; 1409} 1410 1411/* 1412 * Wait for a job to finish. 1413 * wait_cmd indicates this is from the wait builtin; see 1414 * wait_cmd in waitforpid(). 1415 */ 1416 1417/**/ 1418static int 1419zwaitjob(int job, int wait_cmd) 1420{ 1421 int q = queue_signal_level(); 1422 Job jn = jobtab + job; 1423 1424 dont_queue_signals(); 1425 child_block(); /* unblocked during signal_suspend() */ 1426 queue_traps(wait_cmd); 1427 if (jn->procs || jn->auxprocs) { /* if any forks were done */ 1428 jn->stat |= STAT_LOCKED; 1429 if (jn->stat & STAT_CHANGED) 1430 printjob(jn, !!isset(LONGLISTJOBS), 1); 1431 if (jn->filelist) { 1432 /* 1433 * The main shell is finished with any file descriptors used 1434 * for process substitution associated with this job: close 1435 * them to indicate to listeners there's no more input. 1436 * 1437 * Note we can't safely delete temporary files yet as these 1438 * are directly visible to other processes. However, 1439 * we can't deadlock on the fact that those still exist, so 1440 * that's not a problem. 1441 */ 1442 pipecleanfilelist(jn->filelist); 1443 } 1444 while (!errflag && jn->stat && 1445 !(jn->stat & STAT_DONE) && 1446 !(interact && (jn->stat & STAT_STOPPED))) { 1447 signal_suspend(SIGCHLD, wait_cmd); 1448 if (last_signal != SIGCHLD && wait_cmd && last_signal >= 0 && 1449 (sigtrapped[last_signal] & ZSIG_TRAPPED)) 1450 { 1451 /* builtin wait interrupted by trapped signal */ 1452 restore_queue_signals(q); 1453 return 128 + last_signal; 1454 } 1455 /* Commenting this out makes ^C-ing a job started by a function 1456 stop the whole function again. But I guess it will stop 1457 something else from working properly, we have to find out 1458 what this might be. --oberon 1459 1460 errflag = 0; */ 1461 if (subsh) { 1462 killjb(jn, SIGCONT); 1463 jn->stat &= ~STAT_STOPPED; 1464 } 1465 if (jn->stat & STAT_SUPERJOB) 1466 if (handle_sub(jn - jobtab, 1)) 1467 break; 1468 child_block(); 1469 } 1470 } else { 1471 deletejob(jn, 0); 1472 pipestats[0] = lastval; 1473 numpipestats = 1; 1474 } 1475 unqueue_traps(); 1476 child_unblock(); 1477 restore_queue_signals(q); 1478 1479 return 0; 1480} 1481 1482/* wait for running job to finish */ 1483 1484/**/ 1485void 1486waitjobs(void) 1487{ 1488 Job jn = jobtab + thisjob; 1489 DPUTS(thisjob == -1, "No valid job in waitjobs."); 1490 1491 if (jn->procs || jn->auxprocs) 1492 zwaitjob(thisjob, 0); 1493 else { 1494 deletejob(jn, 0); 1495 pipestats[0] = lastval; 1496 numpipestats = 1; 1497 } 1498 thisjob = -1; 1499} 1500 1501/* clear job table when entering subshells */ 1502 1503/**/ 1504mod_export void 1505clearjobtab(int monitor) 1506{ 1507 int i; 1508 1509 if (isset(POSIXJOBS)) 1510 oldmaxjob = 0; 1511 for (i = 1; i <= maxjob; i++) { 1512 /* 1513 * See if there is a jobtable worth saving. 1514 * We never free the saved version; it only happens 1515 * once for each subshell of a shell with job control, 1516 * so doesn't create a leak. 1517 */ 1518 if (monitor && !isset(POSIXJOBS) && jobtab[i].stat) 1519 oldmaxjob = i+1; 1520 else if (jobtab[i].stat & STAT_INUSE) 1521 freejob(jobtab + i, 0); 1522 } 1523 1524 if (monitor && oldmaxjob) { 1525 int sz = oldmaxjob * sizeof(struct job); 1526 if (oldjobtab) 1527 free(oldjobtab); 1528 oldjobtab = (struct job *)zalloc(sz); 1529 memcpy(oldjobtab, jobtab, sz); 1530 1531 /* Don't report any job we're part of */ 1532 if (thisjob != -1 && thisjob < oldmaxjob) 1533 memset(oldjobtab+thisjob, 0, sizeof(struct job)); 1534 } 1535 1536 memset(jobtab, 0, jobtabsize * sizeof(struct job)); /* zero out table */ 1537 maxjob = 0; 1538 1539 /* 1540 * Although we don't have job control in subshells, we 1541 * sometimes needs control structures for other purposes such 1542 * as multios. Grab a job for this purpose; any will do 1543 * since we've freed them all up (so there's no question 1544 * of problems with the job table size here). 1545 */ 1546 thisjob = initjob(); 1547} 1548 1549static int initnewjob(int i) 1550{ 1551 jobtab[i].stat = STAT_INUSE; 1552 if (jobtab[i].pwd) { 1553 zsfree(jobtab[i].pwd); 1554 jobtab[i].pwd = NULL; 1555 } 1556 jobtab[i].gleader = 0; 1557 1558 if (i > maxjob) 1559 maxjob = i; 1560 1561 return i; 1562} 1563 1564/* Get a free entry in the job table and initialize it. */ 1565 1566/**/ 1567int 1568initjob(void) 1569{ 1570 int i; 1571 1572 for (i = 1; i <= maxjob; i++) 1573 if (!jobtab[i].stat) 1574 return initnewjob(i); 1575 if (maxjob + 1 < jobtabsize) 1576 return initnewjob(maxjob+1); 1577 1578 if (expandjobtab()) 1579 return initnewjob(i); 1580 1581 zerr("job table full or recursion limit exceeded"); 1582 return -1; 1583} 1584 1585/**/ 1586void 1587setjobpwd(void) 1588{ 1589 int i; 1590 1591 for (i = 1; i <= maxjob; i++) 1592 if (jobtab[i].stat && !jobtab[i].pwd) 1593 jobtab[i].pwd = ztrdup(pwd); 1594} 1595 1596/* print pids for & */ 1597 1598/**/ 1599void 1600spawnjob(void) 1601{ 1602 Process pn; 1603 1604 DPUTS(thisjob == -1, "No valid job in spawnjob."); 1605 /* if we are not in a subshell */ 1606 if (!subsh) { 1607 if (curjob == -1 || !(jobtab[curjob].stat & STAT_STOPPED)) { 1608 curjob = thisjob; 1609 setprevjob(); 1610 } else if (prevjob == -1 || !(jobtab[prevjob].stat & STAT_STOPPED)) 1611 prevjob = thisjob; 1612 if (jobbing && jobtab[thisjob].procs) { 1613 FILE *fout = shout ? shout : stdout; 1614 fprintf(fout, "[%d]", thisjob); 1615 for (pn = jobtab[thisjob].procs; pn; pn = pn->next) 1616 fprintf(fout, " %ld", (long) pn->pid); 1617 fprintf(fout, "\n"); 1618 fflush(fout); 1619 } 1620 } 1621 if (!hasprocs(thisjob)) 1622 deletejob(jobtab + thisjob, 0); 1623 else 1624 jobtab[thisjob].stat |= STAT_LOCKED; 1625 thisjob = -1; 1626} 1627 1628/**/ 1629void 1630shelltime(void) 1631{ 1632 struct timezone dummy_tz; 1633 struct timeval dtimeval, now; 1634 child_times_t ti; 1635#ifndef HAVE_GETRUSAGE 1636 struct tms buf; 1637#endif 1638 1639 gettimeofday(&now, &dummy_tz); 1640 1641#ifdef HAVE_GETRUSAGE 1642 getrusage(RUSAGE_SELF, &ti); 1643#else 1644 times(&buf); 1645 1646 ti.ut = buf.tms_utime; 1647 ti.st = buf.tms_stime; 1648#endif 1649 printtime(dtime(&dtimeval, &shtimer, &now), &ti, "shell"); 1650 1651#ifdef HAVE_GETRUSAGE 1652 getrusage(RUSAGE_CHILDREN, &ti); 1653#else 1654 ti.ut = buf.tms_cutime; 1655 ti.st = buf.tms_cstime; 1656#endif 1657 printtime(&dtimeval, &ti, "children"); 1658 1659} 1660 1661/* see if jobs need printing */ 1662 1663/**/ 1664void 1665scanjobs(void) 1666{ 1667 int i; 1668 1669 for (i = 1; i <= maxjob; i++) 1670 if (jobtab[i].stat & STAT_CHANGED) 1671 printjob(jobtab + i, !!isset(LONGLISTJOBS), 1); 1672} 1673 1674/**** job control builtins ****/ 1675 1676/* This simple function indicates whether or not s may represent * 1677 * a number. It returns true iff s consists purely of digits and * 1678 * minuses. Note that minus may appear more than once, and the empty * 1679 * string will produce a `true' response. */ 1680 1681/**/ 1682static int 1683isanum(char *s) 1684{ 1685 while (*s == '-' || idigit(*s)) 1686 s++; 1687 return *s == '\0'; 1688} 1689 1690/* Make sure we have a suitable current and previous job set. */ 1691 1692/**/ 1693static void 1694setcurjob(void) 1695{ 1696 if (curjob == thisjob || 1697 (curjob != -1 && !(jobtab[curjob].stat & STAT_INUSE))) { 1698 curjob = prevjob; 1699 setprevjob(); 1700 if (curjob == thisjob || 1701 (curjob != -1 && !((jobtab[curjob].stat & STAT_INUSE) && 1702 curjob != thisjob))) { 1703 curjob = prevjob; 1704 setprevjob(); 1705 } 1706 } 1707} 1708 1709/* Convert a job specifier ("%%", "%1", "%foo", "%?bar?", etc.) * 1710 * to a job number. */ 1711 1712/**/ 1713mod_export int 1714getjob(const char *s, const char *prog) 1715{ 1716 int jobnum, returnval, mymaxjob; 1717 Job myjobtab; 1718 1719 if (oldjobtab) { 1720 myjobtab = oldjobtab; 1721 mymaxjob = oldmaxjob; 1722 } else { 1723 myjobtab= jobtab; 1724 mymaxjob = maxjob; 1725 } 1726 1727 /* if there is no %, treat as a name */ 1728 if (*s != '%') 1729 goto jump; 1730 s++; 1731 /* "%%", "%+" and "%" all represent the current job */ 1732 if (*s == '%' || *s == '+' || !*s) { 1733 if (curjob == -1) { 1734 if (prog) 1735 zwarnnam(prog, "no current job"); 1736 returnval = -1; 1737 goto done; 1738 } 1739 returnval = curjob; 1740 goto done; 1741 } 1742 /* "%-" represents the previous job */ 1743 if (*s == '-') { 1744 if (prevjob == -1) { 1745 if (prog) 1746 zwarnnam(prog, "no previous job"); 1747 returnval = -1; 1748 goto done; 1749 } 1750 returnval = prevjob; 1751 goto done; 1752 } 1753 /* a digit here means we have a job number */ 1754 if (idigit(*s)) { 1755 jobnum = atoi(s); 1756 if (jobnum && jobnum <= mymaxjob && myjobtab[jobnum].stat && 1757 !(myjobtab[jobnum].stat & STAT_SUBJOB) && 1758 /* 1759 * If running jobs in a subshell, we are allowed to 1760 * refer to the "current" job (it's not really the 1761 * current job in the subshell). It's possible we 1762 * should reset thisjob to -1 on entering the subshell. 1763 */ 1764 (myjobtab == oldjobtab || jobnum != thisjob)) { 1765 returnval = jobnum; 1766 goto done; 1767 } 1768 if (prog) 1769 zwarnnam(prog, "%%%s: no such job", s); 1770 returnval = -1; 1771 goto done; 1772 } 1773 /* "%?" introduces a search string */ 1774 if (*s == '?') { 1775 struct process *pn; 1776 1777 for (jobnum = mymaxjob; jobnum >= 0; jobnum--) 1778 if (myjobtab[jobnum].stat && 1779 !(myjobtab[jobnum].stat & STAT_SUBJOB) && 1780 jobnum != thisjob) 1781 for (pn = myjobtab[jobnum].procs; pn; pn = pn->next) 1782 if (strstr(pn->text, s + 1)) { 1783 returnval = jobnum; 1784 goto done; 1785 } 1786 if (prog) 1787 zwarnnam(prog, "job not found: %s", s); 1788 returnval = -1; 1789 goto done; 1790 } 1791 jump: 1792 /* anything else is a job name, specified as a string that begins the 1793 job's command */ 1794 if ((jobnum = findjobnam(s)) != -1) { 1795 returnval = jobnum; 1796 goto done; 1797 } 1798 /* if we get here, it is because none of the above succeeded and went 1799 to done */ 1800 zwarnnam(prog, "job not found: %s", s); 1801 returnval = -1; 1802 done: 1803 return returnval; 1804} 1805 1806#ifndef HAVE_SETPROCTITLE 1807/* For jobs -Z (which modifies the shell's name as seen in ps listings). * 1808 * hackzero is the start of the safely writable space, and hackspace is * 1809 * its length, excluding a final NUL terminator that will always be left. */ 1810 1811static char *hackzero; 1812static int hackspace; 1813#endif 1814 1815 1816/* Initialise job handling. */ 1817 1818/**/ 1819void 1820init_jobs(char **argv, char **envp) 1821{ 1822 char *p, *q; 1823 size_t init_bytes = MAXJOBS_ALLOC*sizeof(struct job); 1824 1825 /* 1826 * Initialise the job table. If this fails, we're in trouble. 1827 */ 1828 jobtab = (struct job *)zalloc(init_bytes); 1829 if (!jobtab) { 1830 zerr("failed to allocate job table, aborting."); 1831 exit(1); 1832 } 1833 jobtabsize = MAXJOBS_ALLOC; 1834 memset(jobtab, 0, init_bytes); 1835 1836#ifndef HAVE_SETPROCTITLE 1837 /* 1838 * Initialise the jobs -Z system. The technique is borrowed from 1839 * perl: check through the argument and environment space, to see 1840 * how many of the strings are in contiguous space. This determines 1841 * the value of hackspace. 1842 */ 1843 hackzero = *argv; 1844 p = strchr(hackzero, 0); 1845 while(*++argv) { 1846 q = *argv; 1847 if(q != p+1) 1848 goto done; 1849 p = strchr(q, 0); 1850 } 1851#if !defined(HAVE_PUTENV) && !defined(USE_SET_UNSET_ENV) 1852 for(; *envp; envp++) { 1853 q = *envp; 1854 if(q != p+1) 1855 goto done; 1856 p = strchr(q, 0); 1857 } 1858#endif 1859 done: 1860 hackspace = p - hackzero; 1861#endif 1862} 1863 1864 1865/* 1866 * We have run out of space in the job table. 1867 * Expand it by an additional MAXJOBS_ALLOC slots. 1868 */ 1869 1870/* 1871 * An arbitrary limit on the absolute maximum size of the job table. 1872 * This prevents us taking over the entire universe. 1873 * Ought to be a multiple of MAXJOBS_ALLOC, but doesn't need to be. 1874 */ 1875#define MAX_MAXJOBS 1000 1876 1877/**/ 1878int 1879expandjobtab(void) 1880{ 1881 int newsize = jobtabsize + MAXJOBS_ALLOC; 1882 struct job *newjobtab; 1883 1884 if (newsize > MAX_MAXJOBS) 1885 return 0; 1886 1887 newjobtab = (struct job *)zrealloc(jobtab, newsize * sizeof(struct job)); 1888 if (!newjobtab) 1889 return 0; 1890 1891 /* 1892 * Clear the new section of the table; this is necessary for 1893 * the jobs to appear unused. 1894 */ 1895 memset(newjobtab + jobtabsize, 0, MAXJOBS_ALLOC * sizeof(struct job)); 1896 1897 jobtab = newjobtab; 1898 jobtabsize = newsize; 1899 1900 return 1; 1901} 1902 1903 1904/* 1905 * See if we can reduce the job table. We can if we go over 1906 * a MAXJOBS_ALLOC boundary. However, we leave a boundary, 1907 * currently 20 jobs, so that we have a place for immediate 1908 * expansion and don't play ping pong with the job table size. 1909 */ 1910 1911/**/ 1912void 1913maybeshrinkjobtab(void) 1914{ 1915 int jobbound; 1916 1917 queue_signals(); 1918 jobbound = maxjob + MAXJOBS_ALLOC - (maxjob % MAXJOBS_ALLOC); 1919 if (jobbound < jobtabsize && jobbound > maxjob + 20) { 1920 struct job *newjobtab; 1921 1922 /* Hope this can't fail, but anyway... */ 1923 newjobtab = (struct job *)zrealloc(jobtab, 1924 jobbound*sizeof(struct job)); 1925 1926 if (newjobtab) { 1927 jobtab = newjobtab; 1928 jobtabsize = jobbound; 1929 } 1930 } 1931 unqueue_signals(); 1932} 1933 1934 1935/* bg, disown, fg, jobs, wait: most of the job control commands are * 1936 * here. They all take the same type of argument. Exception: wait can * 1937 * take a pid or a job specifier, whereas the others only work on jobs. */ 1938 1939/**/ 1940int 1941bin_fg(char *name, char **argv, Options ops, int func) 1942{ 1943 int job, lng, firstjob = -1, retval = 0, ofunc = func; 1944 1945 if (OPT_ISSET(ops,'Z')) { 1946 int len; 1947 1948 if(isset(RESTRICTED)) { 1949 zwarnnam(name, "-Z is restricted"); 1950 return 1; 1951 } 1952 if(!argv[0] || argv[1]) { 1953 zwarnnam(name, "-Z requires one argument"); 1954 return 1; 1955 } 1956 queue_signals(); 1957 unmetafy(*argv, &len); 1958#ifdef HAVE_SETPROCTITLE 1959 setproctitle("%s", *argv); 1960#else 1961 if(len > hackspace) 1962 len = hackspace; 1963 memcpy(hackzero, *argv, len); 1964 memset(hackzero + len, 0, hackspace - len); 1965#endif 1966 unqueue_signals(); 1967 return 0; 1968 } 1969 1970 if (func == BIN_JOBS) { 1971 lng = (OPT_ISSET(ops,'l')) ? 1 : (OPT_ISSET(ops,'p')) ? 2 : 0; 1972 if (OPT_ISSET(ops,'d')) 1973 lng |= 4; 1974 } else { 1975 lng = !!isset(LONGLISTJOBS); 1976 } 1977 1978 if ((func == BIN_FG || func == BIN_BG) && !jobbing) { 1979 /* oops... maybe bg and fg should have been disabled? */ 1980 zwarnnam(name, "no job control in this shell."); 1981 return 1; 1982 } 1983 1984 queue_signals(); 1985 /* 1986 * In case any processes changed state recently, wait for them. 1987 * This updates stopped processes (but we should have been 1988 * signalled about those, up to inevitable races), and also 1989 * continued processes if that feature is available. 1990 */ 1991 wait_for_processes(); 1992 1993 /* If necessary, update job table. */ 1994 if (unset(NOTIFY)) 1995 scanjobs(); 1996 1997 if (func != BIN_JOBS || isset(MONITOR) || !oldmaxjob) 1998 setcurjob(); 1999 2000 if (func == BIN_JOBS) 2001 /* If you immediately type "exit" after "jobs", this * 2002 * will prevent zexit from complaining about stopped jobs */ 2003 stopmsg = 2; 2004 if (!*argv) { 2005 /* This block handles all of the default cases (no arguments). bg, 2006 fg and disown act on the current job, and jobs and wait act on all the 2007 jobs. */ 2008 if (func == BIN_FG || func == BIN_BG || func == BIN_DISOWN) { 2009 /* W.r.t. the above comment, we'd better have a current job at this 2010 point or else. */ 2011 if (curjob == -1 || (jobtab[curjob].stat & STAT_NOPRINT)) { 2012 zwarnnam(name, "no current job"); 2013 unqueue_signals(); 2014 return 1; 2015 } 2016 firstjob = curjob; 2017 } else if (func == BIN_JOBS) { 2018 /* List jobs. */ 2019 struct job *jobptr; 2020 int curmaxjob, ignorejob; 2021 if (unset(MONITOR) && oldmaxjob) { 2022 jobptr = oldjobtab; 2023 curmaxjob = oldmaxjob ? oldmaxjob - 1 : 0; 2024 ignorejob = 0; 2025 } else { 2026 jobptr = jobtab; 2027 curmaxjob = maxjob; 2028 ignorejob = thisjob; 2029 } 2030 for (job = 0; job <= curmaxjob; job++, jobptr++) 2031 if (job != ignorejob && jobptr->stat) { 2032 if ((!OPT_ISSET(ops,'r') && !OPT_ISSET(ops,'s')) || 2033 (OPT_ISSET(ops,'r') && OPT_ISSET(ops,'s')) || 2034 (OPT_ISSET(ops,'r') && 2035 !(jobptr->stat & STAT_STOPPED)) || 2036 (OPT_ISSET(ops,'s') && jobptr->stat & STAT_STOPPED)) 2037 printjob(jobptr, lng, 2); 2038 } 2039 unqueue_signals(); 2040 return 0; 2041 } else { /* Must be BIN_WAIT, so wait for all jobs */ 2042 for (job = 0; job <= maxjob; job++) 2043 if (job != thisjob && jobtab[job].stat) 2044 retval = zwaitjob(job, 1); 2045 unqueue_signals(); 2046 return retval; 2047 } 2048 } 2049 2050 /* Defaults have been handled. We now have an argument or two, or three... 2051 In the default case for bg, fg and disown, the argument will be provided by 2052 the above routine. We now loop over the arguments. */ 2053 for (; (firstjob != -1) || *argv; (void)(*argv && argv++)) { 2054 int stopped, ocj = thisjob, jstat; 2055 2056 func = ofunc; 2057 2058 if (func == BIN_WAIT && isanum(*argv)) { 2059 /* wait can take a pid; the others can't. */ 2060 pid_t pid = (long)atoi(*argv); 2061 Job j; 2062 Process p; 2063 2064 if (findproc(pid, &j, &p, 0)) { 2065 if (j->stat & STAT_STOPPED) { 2066 retval = (killjb(j, SIGCONT) != 0); 2067 if (retval == 0) 2068 makerunning(j); 2069 } 2070 if (retval == 0) { 2071 /* 2072 * returns 0 for normal exit, else signal+128 2073 * in which case we should return that status. 2074 */ 2075 retval = waitforpid(pid, 1); 2076 } 2077 if (retval == 0) 2078 retval = lastval2; 2079 } else if (isset(POSIXJOBS) && 2080 pid == lastpid && lastpid_status >= 0L) { 2081 retval = (int)lastpid_status; 2082 } else { 2083 zwarnnam(name, "pid %d is not a child of this shell", pid); 2084 /* presumably lastval2 doesn't tell us a heck of a lot? */ 2085 retval = 1; 2086 } 2087 thisjob = ocj; 2088 continue; 2089 } 2090 if (func != BIN_JOBS && oldjobtab != NULL) { 2091 zwarnnam(name, "can't manipulate jobs in subshell"); 2092 unqueue_signals(); 2093 return 1; 2094 } 2095 /* The only type of argument allowed now is a job spec. Check it. */ 2096 job = (*argv) ? getjob(*argv, name) : firstjob; 2097 firstjob = -1; 2098 if (job == -1) { 2099 retval = 1; 2100 break; 2101 } 2102 jstat = oldjobtab ? oldjobtab[job].stat : jobtab[job].stat; 2103 if (!(jstat & STAT_INUSE) || 2104 (jstat & STAT_NOPRINT)) { 2105 zwarnnam(name, "%s: no such job", *argv); 2106 unqueue_signals(); 2107 return 1; 2108 } 2109 /* If AUTO_CONTINUE is set (automatically make stopped jobs running 2110 * on disown), we actually do a bg and then delete the job table entry. */ 2111 2112 if (isset(AUTOCONTINUE) && func == BIN_DISOWN && 2113 jstat & STAT_STOPPED) 2114 func = BIN_BG; 2115 2116 /* We have a job number. Now decide what to do with it. */ 2117 switch (func) { 2118 case BIN_FG: 2119 case BIN_BG: 2120 case BIN_WAIT: 2121 if (func == BIN_BG) 2122 jobtab[job].stat |= STAT_NOSTTY; 2123 if ((stopped = (jobtab[job].stat & STAT_STOPPED))) { 2124 makerunning(jobtab + job); 2125 if (func == BIN_BG) { 2126 /* Set $! to indicate this was backgrounded */ 2127 Process pn = jobtab[job].procs; 2128 for (;;) { 2129 Process next = pn->next; 2130 if (!next) { 2131 lastpid = (zlong) pn->pid; 2132 break; 2133 } 2134 pn = next; 2135 } 2136 } 2137 } else if (func == BIN_BG) { 2138 /* Silly to bg a job already running. */ 2139 zwarnnam(name, "job already in background"); 2140 thisjob = ocj; 2141 unqueue_signals(); 2142 return 1; 2143 } 2144 /* It's time to shuffle the jobs around! Reset the current job, 2145 and pick a sensible secondary job. */ 2146 if (curjob == job) { 2147 curjob = prevjob; 2148 prevjob = (func == BIN_BG) ? -1 : job; 2149 } 2150 if (prevjob == job || prevjob == -1) 2151 setprevjob(); 2152 if (curjob == -1) { 2153 curjob = prevjob; 2154 setprevjob(); 2155 } 2156 if (func != BIN_WAIT) 2157 /* for bg and fg -- show the job we are operating on */ 2158 printjob(jobtab + job, (stopped) ? -1 : lng, 3); 2159 if (func != BIN_BG) { /* fg or wait */ 2160 if (jobtab[job].pwd && strcmp(jobtab[job].pwd, pwd)) { 2161 FILE *fout = (func == BIN_JOBS || !shout) ? stdout : shout; 2162 fprintf(fout, "(pwd : "); 2163 fprintdir(jobtab[job].pwd, fout); 2164 fprintf(fout, ")\n"); 2165 fflush(fout); 2166 } 2167 if (func != BIN_WAIT) { /* fg */ 2168 thisjob = job; 2169 if ((jobtab[job].stat & STAT_SUPERJOB) && 2170 ((!jobtab[job].procs->next || 2171 (jobtab[job].stat & STAT_SUBLEADER) || 2172 killpg(jobtab[job].gleader, 0) == -1)) && 2173 jobtab[jobtab[job].other].gleader) 2174 attachtty(jobtab[jobtab[job].other].gleader); 2175 else 2176 attachtty(jobtab[job].gleader); 2177 } 2178 } 2179 if (stopped) { 2180 if (func != BIN_BG && jobtab[job].ty) 2181 settyinfo(jobtab[job].ty); 2182 killjb(jobtab + job, SIGCONT); 2183 } 2184 if (func == BIN_WAIT) 2185 { 2186 retval = zwaitjob(job, 1); 2187 if (!retval) 2188 retval = lastval2; 2189 } 2190 else if (func != BIN_BG) { 2191 /* 2192 * HERE: there used not to be an "else" above. How 2193 * could it be right to wait for the foreground job 2194 * when we've just been told to wait for another 2195 * job (and done it)? 2196 */ 2197 waitjobs(); 2198 retval = lastval2; 2199 } else if (ofunc == BIN_DISOWN) 2200 deletejob(jobtab + job, 1); 2201 break; 2202 case BIN_JOBS: 2203 printjob(job + (oldjobtab ? oldjobtab : jobtab), lng, 2); 2204 break; 2205 case BIN_DISOWN: 2206 if (jobtab[job].stat & STAT_STOPPED) { 2207 char buf[20], *pids = ""; 2208 2209 if (jobtab[job].stat & STAT_SUPERJOB) { 2210 Process pn; 2211 2212 for (pn = jobtab[jobtab[job].other].procs; pn; pn = pn->next) { 2213 sprintf(buf, " -%d", pn->pid); 2214 pids = dyncat(pids, buf); 2215 } 2216 for (pn = jobtab[job].procs; pn->next; pn = pn->next) { 2217 sprintf(buf, " %d", pn->pid); 2218 pids = dyncat(pids, buf); 2219 } 2220 if (!jobtab[jobtab[job].other].procs && pn) { 2221 sprintf(buf, " %d", pn->pid); 2222 pids = dyncat(pids, buf); 2223 } 2224 } else { 2225 sprintf(buf, " -%d", jobtab[job].gleader); 2226 pids = buf; 2227 } 2228 zwarnnam(name, 2229#ifdef USE_SUSPENDED 2230 "warning: job is suspended, use `kill -CONT%s' to resume", 2231#else 2232 "warning: job is stopped, use `kill -CONT%s' to resume", 2233#endif 2234 pids); 2235 } 2236 deletejob(jobtab + job, 1); 2237 break; 2238 } 2239 thisjob = ocj; 2240 } 2241 unqueue_signals(); 2242 return retval; 2243} 2244 2245const struct { 2246 const char *name; 2247 int num; 2248} alt_sigs[] = { 2249#if defined(SIGCHLD) && defined(SIGCLD) 2250#if SIGCHLD == SIGCLD 2251 { "CLD", SIGCLD }, 2252#endif 2253#endif 2254#if defined(SIGPOLL) && defined(SIGIO) 2255#if SIGPOLL == SIGIO 2256 { "IO", SIGIO }, 2257#endif 2258#endif 2259#if !defined(SIGERR) 2260 /* 2261 * If SIGERR is not defined by the operating system, use it 2262 * as an alias for SIGZERR. 2263 */ 2264 { "ERR", SIGZERR }, 2265#endif 2266 { NULL, 0 } 2267}; 2268 2269/* kill: send a signal to a process. The process(es) may be specified * 2270 * by job specifier (see above) or pid. A signal, defaulting to * 2271 * SIGTERM, may be specified by name or number, preceded by a dash. */ 2272 2273/**/ 2274int 2275bin_kill(char *nam, char **argv, UNUSED(Options ops), UNUSED(int func)) 2276{ 2277 int sig = SIGTERM; 2278 int returnval = 0; 2279 2280 /* check for, and interpret, a signal specifier */ 2281 if (*argv && **argv == '-') { 2282 if (idigit((*argv)[1])) { 2283 char *endp; 2284 /* signal specified by number */ 2285 sig = zstrtol(*argv + 1, &endp, 10); 2286 if (*endp) { 2287 zwarnnam(nam, "invalid signal number: %s", *argv); 2288 return 1; 2289 } 2290 } else if ((*argv)[1] != '-' || (*argv)[2]) { 2291 char *signame; 2292 2293 /* with argument "-l" display the list of signal names */ 2294 if ((*argv)[1] == 'l' && (*argv)[2] == '\0') { 2295 if (argv[1]) { 2296 while (*++argv) { 2297 sig = zstrtol(*argv, &signame, 10); 2298 if (signame == *argv) { 2299 if (!strncmp(signame, "SIG", 3)) 2300 signame += 3; 2301 for (sig = 1; sig <= SIGCOUNT; sig++) 2302 if (!strcasecmp(sigs[sig], signame)) 2303 break; 2304 if (sig > SIGCOUNT) { 2305 int i; 2306 2307 for (i = 0; alt_sigs[i].name; i++) 2308 if (!strcasecmp(alt_sigs[i].name, signame)) 2309 { 2310 sig = alt_sigs[i].num; 2311 break; 2312 } 2313 } 2314 if (sig > SIGCOUNT) { 2315 zwarnnam(nam, "unknown signal: SIG%s", 2316 signame); 2317 returnval++; 2318 } else 2319 printf("%d\n", sig); 2320 } else { 2321 if (*signame) { 2322 zwarnnam(nam, "unknown signal: SIG%s", 2323 signame); 2324 returnval++; 2325 } else { 2326 if (WIFSIGNALED(sig)) 2327 sig = WTERMSIG(sig); 2328 else if (WIFSTOPPED(sig)) 2329 sig = WSTOPSIG(sig); 2330 if (1 <= sig && sig <= SIGCOUNT) 2331 printf("%s\n", sigs[sig]); 2332 else 2333 printf("%d\n", sig); 2334 } 2335 } 2336 } 2337 return returnval; 2338 } 2339 printf("%s", sigs[1]); 2340 for (sig = 2; sig <= SIGCOUNT; sig++) 2341 printf(" %s", sigs[sig]); 2342 putchar('\n'); 2343 return 0; 2344 } 2345 2346 if ((*argv)[1] == 'n' && (*argv)[2] == '\0') { 2347 char *endp; 2348 2349 if (!*++argv) { 2350 zwarnnam(nam, "-n: argument expected"); 2351 return 1; 2352 } 2353 sig = zstrtol(*argv, &endp, 10); 2354 if (*endp) { 2355 zwarnnam(nam, "invalid signal number: %s", *argv); 2356 return 1; 2357 } 2358 } else { 2359 if (!((*argv)[1] == 's' && (*argv)[2] == '\0')) 2360 signame = *argv + 1; 2361 else if (!(*++argv)) { 2362 zwarnnam(nam, "-s: argument expected"); 2363 return 1; 2364 } else 2365 signame = *argv; 2366 if (!*signame) { 2367 zwarnnam(nam, "-: signal name expected"); 2368 return 1; 2369 } 2370 signame = casemodify(signame, CASMOD_UPPER); 2371 if (!strncmp(signame, "SIG", 3)) 2372 signame+=3; 2373 2374 /* check for signal matching specified name */ 2375 for (sig = 1; sig <= SIGCOUNT; sig++) 2376 if (!strcmp(*(sigs + sig), signame)) 2377 break; 2378 if (*signame == '0' && !signame[1]) 2379 sig = 0; 2380 if (sig > SIGCOUNT) { 2381 int i; 2382 2383 for (i = 0; alt_sigs[i].name; i++) 2384 if (!strcmp(alt_sigs[i].name, signame)) 2385 { 2386 sig = alt_sigs[i].num; 2387 break; 2388 } 2389 } 2390 if (sig > SIGCOUNT) { 2391 zwarnnam(nam, "unknown signal: SIG%s", signame); 2392 zwarnnam(nam, "type kill -l for a list of signals"); 2393 return 1; 2394 } 2395 } 2396 } 2397 argv++; 2398 } 2399 2400 if (!*argv) { 2401 zwarnnam(nam, "not enough arguments"); 2402 return 1; 2403 } 2404 2405 queue_signals(); 2406 setcurjob(); 2407 2408 /* Remaining arguments specify processes. Loop over them, and send the 2409 signal (number sig) to each process. */ 2410 for (; *argv; argv++) { 2411 if (**argv == '%') { 2412 /* job specifier introduced by '%' */ 2413 int p; 2414 2415 if ((p = getjob(*argv, nam)) == -1) { 2416 returnval++; 2417 continue; 2418 } 2419 if (killjb(jobtab + p, sig) == -1) { 2420 zwarnnam("kill", "kill %s failed: %e", *argv, errno); 2421 returnval++; 2422 continue; 2423 } 2424 /* automatically update the job table if sending a SIGCONT to a 2425 job, and send the job a SIGCONT if sending it a non-stopping 2426 signal. */ 2427 if (jobtab[p].stat & STAT_STOPPED) { 2428#ifndef WIFCONTINUED 2429 /* With WIFCONTINUED we find this out properly */ 2430 if (sig == SIGCONT) 2431 makerunning(jobtab + p); 2432#endif 2433 if (sig != SIGKILL && sig != SIGCONT && sig != SIGTSTP 2434 && sig != SIGTTOU && sig != SIGTTIN && sig != SIGSTOP) 2435 killjb(jobtab + p, SIGCONT); 2436 } 2437 } else if (!isanum(*argv)) { 2438 zwarnnam("kill", "illegal pid: %s", *argv); 2439 returnval++; 2440 } else { 2441 int pid = atoi(*argv); 2442 if (kill(pid, sig) == -1) { 2443 zwarnnam("kill", "kill %s failed: %e", *argv, errno); 2444 returnval++; 2445 } 2446#ifndef WIFCONTINUED 2447 else if (sig == SIGCONT) { 2448 Job jn; 2449 Process pn; 2450 /* With WIFCONTINUED we find this out properly */ 2451 if (findproc(pid, &jn, &pn, 0)) { 2452 if (WIFSTOPPED(pn->status)) 2453 pn->status = SP_RUNNING; 2454 } 2455 } 2456#endif 2457 } 2458 } 2459 unqueue_signals(); 2460 2461 return returnval < 126 ? returnval : 1; 2462} 2463/* Get a signal number from a string */ 2464 2465/**/ 2466mod_export int 2467getsignum(const char *s) 2468{ 2469 int x, i; 2470 2471 /* check for a signal specified by number */ 2472 x = atoi(s); 2473 if (idigit(*s) && x >= 0 && x < VSIGCOUNT) 2474 return x; 2475 2476 /* search for signal by name */ 2477 if (!strncmp(s, "SIG", 3)) 2478 s += 3; 2479 2480 for (i = 0; i < VSIGCOUNT; i++) 2481 if (!strcmp(s, sigs[i])) 2482 return i; 2483 2484 for (i = 0; alt_sigs[i].name; i++) 2485 { 2486 if (!strcmp(s, alt_sigs[i].name)) 2487 return alt_sigs[i].num; 2488 } 2489 2490 /* no matching signal */ 2491 return -1; 2492} 2493 2494/* Get the name for a signal. */ 2495 2496/**/ 2497mod_export const char * 2498getsigname(int sig) 2499{ 2500 if (sigtrapped[sig] & ZSIG_ALIAS) 2501 { 2502 int i; 2503 for (i = 0; alt_sigs[i].name; i++) 2504 if (sig == alt_sigs[i].num) 2505 return alt_sigs[i].name; 2506 } 2507 else 2508 return sigs[sig]; 2509 2510 /* shouldn't reach here */ 2511#ifdef DEBUG 2512 dputs("Bad alias flag for signal"); 2513#endif 2514 return ""; 2515} 2516 2517 2518/* Get the function node for a trap, taking care about alternative names */ 2519/**/ 2520HashNode 2521gettrapnode(int sig, int ignoredisable) 2522{ 2523 char fname[20]; 2524 HashNode hn; 2525 HashNode (*getptr)(HashTable ht, const char *name); 2526 int i; 2527 if (ignoredisable) 2528 getptr = shfunctab->getnode2; 2529 else 2530 getptr = shfunctab->getnode; 2531 2532 sprintf(fname, "TRAP%s", sigs[sig]); 2533 if ((hn = getptr(shfunctab, fname))) 2534 return hn; 2535 2536 for (i = 0; alt_sigs[i].name; i++) { 2537 if (alt_sigs[i].num == sig) { 2538 sprintf(fname, "TRAP%s", alt_sigs[i].name); 2539 if ((hn = getptr(shfunctab, fname))) 2540 return hn; 2541 } 2542 } 2543 2544 return NULL; 2545} 2546 2547/* Remove a TRAP function under any name for the signal */ 2548 2549/**/ 2550void 2551removetrapnode(int sig) 2552{ 2553 HashNode hn = gettrapnode(sig, 1); 2554 if (hn) { 2555 shfunctab->removenode(shfunctab, hn->nam); 2556 shfunctab->freenode(hn); 2557 } 2558} 2559 2560/* Suspend this shell */ 2561 2562/**/ 2563int 2564bin_suspend(char *name, UNUSED(char **argv), Options ops, UNUSED(int func)) 2565{ 2566 /* won't suspend a login shell, unless forced */ 2567 if (islogin && !OPT_ISSET(ops,'f')) { 2568 zwarnnam(name, "can't suspend login shell"); 2569 return 1; 2570 } 2571 if (jobbing) { 2572 /* stop ignoring signals */ 2573 signal_default(SIGTTIN); 2574 signal_default(SIGTSTP); 2575 signal_default(SIGTTOU); 2576 2577 /* Move ourselves back to the process group we came from */ 2578 release_pgrp(); 2579 } 2580 2581 /* suspend ourselves with a SIGTSTP */ 2582 killpg(origpgrp, SIGTSTP); 2583 2584 if (jobbing) { 2585 acquire_pgrp(); 2586 /* restore signal handling */ 2587 signal_ignore(SIGTTOU); 2588 signal_ignore(SIGTSTP); 2589 signal_ignore(SIGTTIN); 2590 } 2591 return 0; 2592} 2593 2594/* find a job named s */ 2595 2596/**/ 2597int 2598findjobnam(const char *s) 2599{ 2600 int jobnum; 2601 2602 for (jobnum = maxjob; jobnum >= 0; jobnum--) 2603 if (!(jobtab[jobnum].stat & (STAT_SUBJOB | STAT_NOPRINT)) && 2604 jobtab[jobnum].stat && jobtab[jobnum].procs && jobnum != thisjob && 2605 jobtab[jobnum].procs->text && strpfx(s, jobtab[jobnum].procs->text)) 2606 return jobnum; 2607 return -1; 2608} 2609 2610 2611/* make sure we are a process group leader by creating a new process 2612 group if necessary */ 2613 2614/**/ 2615void 2616acquire_pgrp(void) 2617{ 2618 long ttpgrp; 2619 sigset_t blockset, oldset; 2620 2621 if ((mypgrp = GETPGRP()) > 0) { 2622 long lastpgrp = mypgrp; 2623 sigemptyset(&blockset); 2624 sigaddset(&blockset, SIGTTIN); 2625 sigaddset(&blockset, SIGTTOU); 2626 sigaddset(&blockset, SIGTSTP); 2627 oldset = signal_block(blockset); 2628 while ((ttpgrp = gettygrp()) != -1 && ttpgrp != mypgrp) { 2629 mypgrp = GETPGRP(); 2630 if (mypgrp == mypid) { 2631 if (!interact) 2632 break; /* attachtty() will be a no-op, give up */ 2633 signal_setmask(oldset); 2634 attachtty(mypgrp); /* Might generate SIGT* */ 2635 signal_block(blockset); 2636 } 2637 if (mypgrp == gettygrp()) 2638 break; 2639 signal_setmask(oldset); 2640 if (read(0, NULL, 0) != 0) {} /* Might generate SIGT* */ 2641 signal_block(blockset); 2642 mypgrp = GETPGRP(); 2643 if (mypgrp == lastpgrp && !interact) 2644 break; /* Unlikely that pgrp will ever change */ 2645 lastpgrp = mypgrp; 2646 } 2647 if (mypgrp != mypid) { 2648 if (setpgrp(0, 0) == 0) { 2649 mypgrp = mypid; 2650 attachtty(mypgrp); 2651 } else 2652 opts[MONITOR] = 0; 2653 } 2654 signal_setmask(oldset); 2655 } else 2656 opts[MONITOR] = 0; 2657} 2658 2659/* revert back to the process group we came from (before acquire_pgrp) */ 2660 2661/**/ 2662void 2663release_pgrp(void) 2664{ 2665 if (origpgrp != mypgrp) { 2666 attachtty(origpgrp); 2667 setpgrp(0, origpgrp); 2668 mypgrp = origpgrp; 2669 } 2670} 2671