master xplshn/aruu / cmd / posix / sh / jobs.c
   1/*-
   2 * SPDX-License-Identifier: BSD-3-Clause
   3 *
   4 * Copyright (c) 1991, 1993
   5 *	The Regents of the University of California.  All rights reserved.
   6 *
   7 * This code is derived from software contributed to Berkeley by
   8 * Kenneth Almquist.
   9 *
  10 * Redistribution and use in source and binary forms, with or without
  11 * modification, are permitted provided that the following conditions
  12 * are met:
  13 * 1. Redistributions of source code must retain the above copyright
  14 *    notice, this list of conditions and the following disclaimer.
  15 * 2. Redistributions in binary form must reproduce the above copyright
  16 *    notice, this list of conditions and the following disclaimer in the
  17 *    documentation and/or other materials provided with the distribution.
  18 * 3. Neither the name of the University nor the names of its contributors
  19 *    may be used to endorse or promote products derived from this software
  20 *    without specific prior written permission.
  21 *
  22 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  25 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  32 * SUCH DAMAGE.
  33 */
  34
  35#include <errno.h>
  36#include <fcntl.h>
  37#include <signal.h>
  38#include <stddef.h>
  39#include <stdlib.h>
  40#include <sys/ioctl.h>
  41#include <sys/param.h>
  42#include <sys/resource.h>
  43#include <sys/time.h>
  44#include <sys/wait.h>
  45#include <unistd.h>
  46
  47#include "../../../shared/paths.h"
  48#include "shell.h"
  49#if JOBS
  50#include <termios.h>
  51#undef CEOF /* syntax.h redefines this */
  52#endif
  53#include "builtins.h"
  54#include "error.h"
  55#include "eval.h"
  56#include "exec.h"
  57#include "input.h"
  58#include "jobs.h"
  59#include "main.h"
  60#include "memalloc.h"
  61#include "mystring.h"
  62#include "nodes.h"
  63#include "options.h"
  64#include "output.h"
  65#include "parser.h"
  66#include "redir.h"
  67#include "show.h"
  68#include "syntax.h"
  69#include "trap.h"
  70#include "var.h"
  71
  72/*
  73 * A job structure contains information about a job.  A job is either a
  74 * single process or a set of processes contained in a pipeline.  In the
  75 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
  76 * array of pids.
  77 */
  78
  79struct procstat {
  80  pid_t pid;    /* process id */
  81  int   status; /* status flags (defined above) */
  82  char *cmd;    /* text of command being run */
  83};
  84
  85/* states */
  86#define JOBSTOPPED 1 /* all procs are stopped */
  87#define JOBDONE    2 /* all procs are completed */
  88
  89struct job {
  90  struct procstat  ps0;        /* status of process */
  91  struct procstat *ps;         /* status or processes when more than one */
  92  short            nprocs;     /* number of processes */
  93  pid_t            pgrp;       /* process group of this job */
  94  char             state;      /* true if job is finished */
  95  char             used;       /* true if this entry is in use */
  96  char             changed;    /* true if status has changed */
  97  char             foreground; /* true if running in the foreground */
  98  char             remembered; /* true if $! referenced */
  99  char             pipefail;   /* pass any non-zero status */
 100#if JOBS
 101  char        jobctl; /* job running under job control */
 102  struct job *next;   /* job used after this one */
 103#endif
 104};
 105
 106static struct job *jobtab;            /* array of jobs */
 107static int         njobs;             /* size of array */
 108static pid_t       backgndpid = -1;   /* pid of last background process */
 109static struct job *bgjob      = NULL; /* last background process */
 110#if JOBS
 111static struct job *jobmru;      /* most recently used job list */
 112static pid_t       initialpgrp; /* pgrp of shell on invocation */
 113#endif
 114static int ttyfd = -1;
 115
 116/* mode flags for dowait */
 117#define DOWAIT_BLOCK    0x1 /* wait until a child exits */
 118#define DOWAIT_SIG      0x2 /* if DOWAIT_BLOCK, abort on signal */
 119#define DOWAIT_SIG_TRAP 0x4 /* if DOWAIT_SIG, abort on trapped signal only */
 120
 121#if JOBS
 122static void restartjob(struct job *);
 123#endif
 124static void        freejob(struct job *);
 125static int         waitcmdloop(struct job *);
 126static struct job *getjob_nonotfound(const char *);
 127static struct job *getjob(const char *);
 128pid_t              killjob(const char *, int);
 129static pid_t       dowait(int, struct job *);
 130static void        checkzombies(void);
 131static void        cmdtxt(union node *);
 132static void        cmdputs(const char *);
 133#if JOBS
 134static void        setcurjob(struct job *);
 135static void        deljob(struct job *);
 136static struct job *getcurjob(struct job *);
 137#endif
 138static int  getjobstatus(const struct job *);
 139static void printjobcmd(struct job *);
 140static void showjob(struct job *, int);
 141
 142/*
 143 * Turn job control on and off.
 144 */
 145
 146static int jobctl;
 147
 148#if JOBS
 149static void
 150jobctl_notty(void)
 151{
 152  if (ttyfd >= 0) {
 153    close(ttyfd);
 154    ttyfd = -1;
 155  }
 156  if (!iflag) {
 157    setsignal(SIGTSTP);
 158    setsignal(SIGTTOU);
 159    setsignal(SIGTTIN);
 160    jobctl = 1;
 161    return;
 162  }
 163  out2fmt_flush("sh: can't access tty; job control turned off\n");
 164  mflag = 0;
 165}
 166
 167void
 168setjobctl(int on)
 169{
 170  int i;
 171
 172  if (on == jobctl || rootshell == 0)
 173    return;
 174  if (on) {
 175    if (ttyfd != -1)
 176      close(ttyfd);
 177    if ((ttyfd = open(ARUU_PATH_DEVTTY, O_RDWR | O_CLOEXEC)) < 0) {
 178      i = 0;
 179      while (i <= 2 && !isatty(i))
 180        i++;
 181      if (i > 2 || (ttyfd = fcntl(i, F_DUPFD_CLOEXEC, 10)) < 0) {
 182        jobctl_notty();
 183        return;
 184      }
 185    }
 186    if (ttyfd < 10) {
 187      /*
 188       * Keep our TTY file descriptor out of the way of
 189       * the user's redirections.
 190       */
 191      if ((i = fcntl(ttyfd, F_DUPFD_CLOEXEC, 10)) < 0) {
 192        jobctl_notty();
 193        return;
 194      }
 195      close(ttyfd);
 196      ttyfd = i;
 197    }
 198    do { /* while we are in the background */
 199      initialpgrp = tcgetpgrp(ttyfd);
 200      if (initialpgrp < 0) {
 201        jobctl_notty();
 202        return;
 203      }
 204      if (initialpgrp != getpgrp()) {
 205        if (!iflag) {
 206          initialpgrp = -1;
 207          jobctl_notty();
 208          return;
 209        }
 210        kill(0, SIGTTIN);
 211        continue;
 212      }
 213    } while (0);
 214    setsignal(SIGTSTP);
 215    setsignal(SIGTTOU);
 216    setsignal(SIGTTIN);
 217    setpgid(0, rootpid);
 218    tcsetpgrp(ttyfd, rootpid);
 219  } else { /* turning job control off */
 220    setpgid(0, initialpgrp);
 221    if (ttyfd >= 0) {
 222      tcsetpgrp(ttyfd, initialpgrp);
 223      close(ttyfd);
 224      ttyfd = -1;
 225    }
 226    setsignal(SIGTSTP);
 227    setsignal(SIGTTOU);
 228    setsignal(SIGTTIN);
 229  }
 230  jobctl = on;
 231}
 232#endif
 233
 234#if JOBS
 235int
 236fgcmd(int argc __unused, char **argv __unused)
 237{
 238  struct job *jp;
 239  pid_t       pgrp;
 240  int         status;
 241
 242  nextopt("");
 243  jp = getjob(*argptr);
 244  if (jp->jobctl == 0)
 245    error("job not created under job control");
 246  printjobcmd(jp);
 247  flushout(&output);
 248  pgrp = jp->ps[0].pid;
 249  if (ttyfd >= 0)
 250    tcsetpgrp(ttyfd, pgrp);
 251  restartjob(jp);
 252  jp->foreground = 1;
 253  INTOFF;
 254  status = waitforjob(jp, (int *)NULL);
 255  INTON;
 256  return status;
 257}
 258
 259int
 260bgcmd(int argc __unused, char **argv __unused)
 261{
 262  struct job *jp;
 263
 264  nextopt("");
 265  do {
 266    jp = getjob(*argptr);
 267    if (jp->jobctl == 0)
 268      error("job not created under job control");
 269    if (jp->state == JOBDONE)
 270      continue;
 271    restartjob(jp);
 272    jp->foreground = 0;
 273    out1fmt("[%td] ", jp - jobtab + 1);
 274    printjobcmd(jp);
 275  } while (*argptr != NULL && *++argptr != NULL);
 276  return 0;
 277}
 278
 279static void
 280restartjob(struct job *jp)
 281{
 282  struct procstat *ps;
 283  int              i;
 284
 285  if (jp->state == JOBDONE)
 286    return;
 287  setcurjob(jp);
 288  INTOFF;
 289  kill(-jp->ps[0].pid, SIGCONT);
 290  for (ps = jp->ps, i = jp->nprocs; --i >= 0; ps++) {
 291    if (WIFSTOPPED(ps->status)) {
 292      ps->status = -1;
 293      jp->state  = 0;
 294    }
 295  }
 296  INTON;
 297}
 298#endif
 299
 300int
 301jobscmd(int argc __unused, char *argv[] __unused)
 302{
 303  char *id;
 304  int   ch, mode;
 305
 306  mode = SHOWJOBS_DEFAULT;
 307  while ((ch = nextopt("lps")) != '\0') {
 308    switch (ch) {
 309      case 'l':
 310        mode = SHOWJOBS_VERBOSE;
 311        break;
 312      case 'p':
 313        mode = SHOWJOBS_PGIDS;
 314        break;
 315      case 's':
 316        mode = SHOWJOBS_PIDS;
 317        break;
 318    }
 319  }
 320
 321  if (*argptr == NULL)
 322    showjobs(0, mode);
 323  else
 324    while ((id = *argptr++) != NULL)
 325      showjob(getjob(id), mode);
 326
 327  return (0);
 328}
 329
 330static int
 331getjobstatus(const struct job *jp)
 332{
 333  int i, status;
 334
 335  if (!jp->pipefail)
 336    return (jp->ps[jp->nprocs - 1].status);
 337  for (i = jp->nprocs - 1; i >= 0; i--) {
 338    status = jp->ps[i].status;
 339    if (status != 0)
 340      return (status);
 341  }
 342  return (0);
 343}
 344
 345static void
 346printjobcmd(struct job *jp)
 347{
 348  struct procstat *ps;
 349  int              i;
 350
 351  for (ps = jp->ps, i = jp->nprocs; --i >= 0; ps++) {
 352    out1str(ps->cmd);
 353    if (i > 0)
 354      out1str(" | ");
 355  }
 356  out1c('\n');
 357}
 358
 359static void
 360showjob(struct job *jp, int mode)
 361{
 362  char             s[64];
 363  char             statebuf[16];
 364  const char      *statestr, *coredump;
 365  struct procstat *ps;
 366  struct job      *j;
 367  int              col, curr, i, jobno, prev, procno, status;
 368  char             c;
 369
 370  procno = (mode == SHOWJOBS_PGIDS) ? 1 : jp->nprocs;
 371  jobno  = jp - jobtab + 1;
 372  curr = prev = 0;
 373#if JOBS
 374  if ((j = getcurjob(NULL)) != NULL) {
 375    curr = j - jobtab + 1;
 376    if ((j = getcurjob(j)) != NULL)
 377      prev = j - jobtab + 1;
 378  }
 379#endif
 380  coredump = "";
 381  status   = getjobstatus(jp);
 382  if (jp->state == 0) {
 383    statestr = "Running";
 384#if JOBS
 385  } else if (jp->state == JOBSTOPPED) {
 386    ps = jp->ps + jp->nprocs - 1;
 387    while (!WIFSTOPPED(ps->status) && ps > jp->ps)
 388      ps--;
 389    if (WIFSTOPPED(ps->status))
 390      i = WSTOPSIG(ps->status);
 391    else
 392      i = -1;
 393    statestr = strsignal(i);
 394    if (statestr == NULL)
 395      statestr = "Suspended";
 396#endif
 397  } else if (WIFEXITED(status)) {
 398    if (WEXITSTATUS(status) == 0)
 399      statestr = "Done";
 400    else {
 401      fmtstr(statebuf, sizeof(statebuf), "Done(%d)", WEXITSTATUS(status));
 402      statestr = statebuf;
 403    }
 404  } else {
 405    i        = WTERMSIG(status);
 406    statestr = strsignal(i);
 407    if (statestr == NULL)
 408      statestr = "Unknown signal";
 409    if (WCOREDUMP(status))
 410      coredump = " (core dumped)";
 411  }
 412
 413  for (ps = jp->ps; procno > 0; ps++, procno--) { /* for each process */
 414    if (mode == SHOWJOBS_PIDS || mode == SHOWJOBS_PGIDS) {
 415      out1fmt("%d\n", (int)ps->pid);
 416      continue;
 417    }
 418    if (mode != SHOWJOBS_VERBOSE && ps != jp->ps)
 419      continue;
 420    if (jobno == curr && ps == jp->ps)
 421      c = '+';
 422    else if (jobno == prev && ps == jp->ps)
 423      c = '-';
 424    else
 425      c = ' ';
 426    if (ps == jp->ps)
 427      fmtstr(s, 64, "[%d] %c ", jobno, c);
 428    else
 429      fmtstr(s, 64, "    %c ", c);
 430    out1str(s);
 431    col = strlen(s);
 432    if (mode == SHOWJOBS_VERBOSE) {
 433      fmtstr(s, 64, "%d ", (int)ps->pid);
 434      out1str(s);
 435      col += strlen(s);
 436    }
 437    if (ps == jp->ps) {
 438      out1str(statestr);
 439      out1str(coredump);
 440      col += strlen(statestr) + strlen(coredump);
 441    }
 442    do {
 443      out1c(' ');
 444      col++;
 445    } while (col < 30);
 446    if (mode == SHOWJOBS_VERBOSE) {
 447      out1str(ps->cmd);
 448      out1c('\n');
 449    } else
 450      printjobcmd(jp);
 451  }
 452}
 453
 454/*
 455 * Print a list of jobs.  If "change" is nonzero, only print jobs whose
 456 * statuses have changed since the last call to showjobs.
 457 *
 458 * If the shell is interrupted in the process of creating a job, the
 459 * result may be a job structure containing zero processes.  Such structures
 460 * will be freed here.
 461 */
 462
 463void
 464showjobs(int change, int mode)
 465{
 466  int         jobno;
 467  struct job *jp;
 468
 469  TRACE(("showjobs(%d) called\n", change));
 470  checkzombies();
 471  for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) {
 472    if (!jp->used)
 473      continue;
 474    if (jp->nprocs == 0) {
 475      freejob(jp);
 476      continue;
 477    }
 478    if (change && !jp->changed)
 479      continue;
 480    showjob(jp, mode);
 481    if (mode == SHOWJOBS_DEFAULT || mode == SHOWJOBS_VERBOSE) {
 482      jp->changed = 0;
 483      /* Hack: discard jobs for which $! has not been
 484       * referenced in interactive mode when they terminate.
 485       */
 486      if (jp->state == JOBDONE && !jp->remembered && (iflag || jp != bgjob)) {
 487        freejob(jp);
 488      }
 489    }
 490  }
 491}
 492
 493/*
 494 * Mark a job structure as unused.
 495 */
 496
 497static void
 498freejob(struct job *jp)
 499{
 500  struct procstat *ps;
 501  int              i;
 502
 503  INTOFF;
 504  if (bgjob == jp)
 505    bgjob = NULL;
 506  for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
 507    if (ps->cmd != nullstr)
 508      ckfree(ps->cmd);
 509  }
 510  if (jp->ps != &jp->ps0)
 511    ckfree(jp->ps);
 512  jp->used = 0;
 513#if JOBS
 514  deljob(jp);
 515#endif
 516  INTON;
 517}
 518
 519int
 520waitcmd(int argc __unused, char **argv __unused)
 521{
 522  struct job *job;
 523  int         retval;
 524
 525  nextopt("");
 526  if (*argptr == NULL)
 527    return (waitcmdloop(NULL));
 528
 529  do {
 530    job = getjob_nonotfound(*argptr);
 531    if (job == NULL)
 532      retval = 127;
 533    else
 534      retval = waitcmdloop(job);
 535    argptr++;
 536  } while (*argptr != NULL);
 537
 538  return (retval);
 539}
 540
 541static int
 542waitcmdloop(struct job *job)
 543{
 544  int         status, retval, sig;
 545  struct job *jp;
 546
 547  /*
 548   * Loop until a process is terminated or stopped, or a SIGINT is
 549   * received.
 550   */
 551
 552  do {
 553    if (job != NULL) {
 554      if (job->state == JOBDONE) {
 555        status = getjobstatus(job);
 556        if (WIFEXITED(status))
 557          retval = WEXITSTATUS(status);
 558        else
 559          retval = WTERMSIG(status) + 128;
 560        if (!iflag || !job->changed)
 561          freejob(job);
 562        else {
 563          job->remembered = 0;
 564          deljob(job);
 565          if (job == bgjob)
 566            bgjob = NULL;
 567        }
 568        return retval;
 569      }
 570    } else {
 571      if (njobs == 0)
 572        return 0;
 573      for (jp = jobtab; jp < jobtab + njobs; jp++)
 574        if (jp->used && jp->state == JOBDONE) {
 575          if (!iflag || !jp->changed)
 576            freejob(jp);
 577          else {
 578            jp->remembered = 0;
 579            if (jp == bgjob)
 580              bgjob = NULL;
 581          }
 582        }
 583      for (jp = jobtab;; jp++) {
 584        if (jp >= jobtab + njobs) { /* no running procs */
 585          return 0;
 586        }
 587        if (jp->used && jp->state == 0)
 588          break;
 589      }
 590    }
 591  } while (dowait(DOWAIT_BLOCK | DOWAIT_SIG, job) != -1);
 592
 593  sig                = pendingsig_waitcmd;
 594  pendingsig_waitcmd = 0;
 595  return sig + 128;
 596}
 597
 598int
 599jobidcmd(int argc __unused, char **argv __unused)
 600{
 601  struct job *jp;
 602  int         i;
 603
 604  nextopt("");
 605  jp = getjob(*argptr);
 606  for (i = 0; i < jp->nprocs;) {
 607    out1fmt("%d", (int)jp->ps[i].pid);
 608    out1c(++i < jp->nprocs ? ' ' : '\n');
 609  }
 610  return 0;
 611}
 612
 613/*
 614 * Convert a job name to a job structure.
 615 */
 616
 617static struct job *
 618getjob_nonotfound(const char *name)
 619{
 620  int         jobno;
 621  struct job *found, *jp;
 622  size_t      namelen;
 623  pid_t       pid;
 624  int         i;
 625
 626  if (name == NULL) {
 627#if JOBS
 628    name = "%+";
 629#else
 630    error("No current job");
 631#endif
 632  }
 633  if (name[0] == '%') {
 634    if (is_digit(name[1])) {
 635      jobno = number(name + 1);
 636      if (jobno > 0 && jobno <= njobs && jobtab[jobno - 1].used != 0)
 637        return &jobtab[jobno - 1];
 638#if JOBS
 639    } else if ((name[1] == '%' || name[1] == '+') && name[2] == '\0') {
 640      if ((jp = getcurjob(NULL)) == NULL)
 641        error("No current job");
 642      return (jp);
 643    } else if (name[1] == '-' && name[2] == '\0') {
 644      if ((jp = getcurjob(NULL)) == NULL || (jp = getcurjob(jp)) == NULL)
 645        error("No previous job");
 646      return (jp);
 647#endif
 648    } else if (name[1] == '?') {
 649      found = NULL;
 650      for (jp = jobtab, i = njobs; --i >= 0; jp++) {
 651        if (jp->used && jp->nprocs > 0 && strstr(jp->ps[0].cmd, name + 2) != NULL) {
 652          if (found)
 653            error("%s: ambiguous", name);
 654          found = jp;
 655        }
 656      }
 657      if (found != NULL)
 658        return (found);
 659    } else {
 660      namelen = strlen(name);
 661      found   = NULL;
 662      for (jp = jobtab, i = njobs; --i >= 0; jp++) {
 663        if (jp->used && jp->nprocs > 0 && strncmp(jp->ps[0].cmd, name + 1, namelen - 1) == 0) {
 664          if (found)
 665            error("%s: ambiguous", name);
 666          found = jp;
 667        }
 668      }
 669      if (found)
 670        return found;
 671    }
 672  } else if (is_number(name)) {
 673    pid = (pid_t)number(name);
 674    for (jp = jobtab, i = njobs; --i >= 0; jp++) {
 675      if (jp->used && jp->nprocs > 0 && jp->ps[jp->nprocs - 1].pid == pid)
 676        return jp;
 677    }
 678  }
 679  return NULL;
 680}
 681
 682static struct job *
 683getjob(const char *name)
 684{
 685  struct job *jp;
 686
 687  jp = getjob_nonotfound(name);
 688  if (jp == NULL)
 689    error("No such job: %s", name);
 690  return (jp);
 691}
 692
 693int
 694killjob(const char *name, int sig)
 695{
 696  struct job *jp;
 697  int         i, ret;
 698
 699  jp = getjob(name);
 700  if (jp->state == JOBDONE)
 701    return 0;
 702  if (jp->jobctl)
 703    return kill(-jp->ps[0].pid, sig);
 704  ret   = -1;
 705  errno = ESRCH;
 706  for (i = 0; i < jp->nprocs; i++)
 707    if (jp->ps[i].status == -1 || WIFSTOPPED(jp->ps[i].status)) {
 708      if (kill(jp->ps[i].pid, sig) == 0)
 709        ret = 0;
 710    } else
 711      ret = 0;
 712  return ret;
 713}
 714
 715/*
 716 * Return a new job structure,
 717 */
 718
 719struct job *
 720makejob(union node *node __unused, int nprocs)
 721{
 722  int         i;
 723  struct job *jp;
 724
 725  for (i = njobs, jp = jobtab;; jp++) {
 726    if (--i < 0) {
 727      INTOFF;
 728      if (njobs == 0) {
 729        jobtab = ckmalloc(4 * sizeof jobtab[0]);
 730#if JOBS
 731        jobmru = NULL;
 732#endif
 733      } else {
 734        jp = ckmalloc((njobs + 4) * sizeof jobtab[0]);
 735        memcpy(jp, jobtab, njobs * sizeof jp[0]);
 736#if JOBS
 737        /* Relocate `next' pointers and list head */
 738        if (jobmru != NULL)
 739          jobmru = &jp[jobmru - jobtab];
 740        for (i = 0; i < njobs; i++)
 741          if (jp[i].next != NULL)
 742            jp[i].next = &jp[jp[i].next - jobtab];
 743#endif
 744        if (bgjob != NULL)
 745          bgjob = &jp[bgjob - jobtab];
 746        /* Relocate `ps' pointers */
 747        for (i = 0; i < njobs; i++)
 748          if (jp[i].ps == &jobtab[i].ps0)
 749            jp[i].ps = &jp[i].ps0;
 750        ckfree(jobtab);
 751        jobtab = jp;
 752      }
 753      jp = jobtab + njobs;
 754      for (i = 4; --i >= 0; jobtab[njobs++].used = 0)
 755        ;
 756      INTON;
 757      break;
 758    }
 759    if (jp->used == 0)
 760      break;
 761  }
 762  INTOFF;
 763  jp->state      = 0;
 764  jp->used       = 1;
 765  jp->changed    = 0;
 766  jp->nprocs     = 0;
 767  jp->foreground = 0;
 768  jp->remembered = 0;
 769  jp->pipefail   = pipefailflag;
 770#if JOBS
 771  jp->jobctl = jobctl;
 772  jp->next   = NULL;
 773#endif
 774  if (nprocs > 1) {
 775    jp->ps = ckmalloc(nprocs * sizeof(struct procstat));
 776  } else {
 777    jp->ps = &jp->ps0;
 778  }
 779  INTON;
 780  TRACE(("makejob(%p, %d) returns %%%td\n", (void *)node, nprocs, jp - jobtab + 1));
 781  return jp;
 782}
 783
 784#if JOBS
 785static void
 786setcurjob(struct job *cj)
 787{
 788  struct job *jp, *prev;
 789
 790  for (prev = NULL, jp = jobmru; jp != NULL; prev = jp, jp = jp->next) {
 791    if (jp == cj) {
 792      if (prev != NULL)
 793        prev->next = jp->next;
 794      else
 795        jobmru = jp->next;
 796      jp->next = jobmru;
 797      jobmru   = cj;
 798      return;
 799    }
 800  }
 801  cj->next = jobmru;
 802  jobmru   = cj;
 803}
 804
 805static void
 806deljob(struct job *j)
 807{
 808  struct job *jp, *prev;
 809
 810  for (prev = NULL, jp = jobmru; jp != NULL; prev = jp, jp = jp->next) {
 811    if (jp == j) {
 812      if (prev != NULL)
 813        prev->next = jp->next;
 814      else
 815        jobmru = jp->next;
 816      return;
 817    }
 818  }
 819}
 820
 821/*
 822 * Return the most recently used job that isn't `nj', and preferably one
 823 * that is stopped.
 824 */
 825static struct job *
 826getcurjob(struct job *nj)
 827{
 828  struct job *jp;
 829
 830  /* Try to find a stopped one.. */
 831  for (jp = jobmru; jp != NULL; jp = jp->next)
 832    if (jp->used && jp != nj && jp->state == JOBSTOPPED)
 833      return (jp);
 834  /* Otherwise the most recently used job that isn't `nj' */
 835  for (jp = jobmru; jp != NULL; jp = jp->next)
 836    if (jp->used && jp != nj)
 837      return (jp);
 838
 839  return (NULL);
 840}
 841
 842#endif
 843
 844/*
 845 * Fork of a subshell.  If we are doing job control, give the subshell its
 846 * own process group.  Jp is a job structure that the job is to be added to.
 847 * N is the command that will be evaluated by the child.  Both jp and n may
 848 * be NULL.  The mode parameter can be one of the following:
 849 *	FORK_FG - Fork off a foreground process.
 850 *	FORK_BG - Fork off a background process.
 851 *	FORK_NOJOB - Like FORK_FG, but don't give the process its own
 852 *		     process group even if job control is on.
 853 *
 854 * When job control is turned off, background processes have their standard
 855 * input redirected to /dev/null (except for the second and later processes
 856 * in a pipeline).
 857 */
 858
 859pid_t
 860forkshell(struct job *jp, union node *n, int mode)
 861{
 862  pid_t pid;
 863  pid_t pgrp;
 864
 865  TRACE(("forkshell(%%%td, %p, %d) called\n", jp - jobtab, (void *)n, mode));
 866  INTOFF;
 867  if (mode == FORK_BG && (jp == NULL || jp->nprocs == 0))
 868    checkzombies();
 869  flushall();
 870  pid = fork();
 871  if (pid == -1) {
 872    TRACE(("Fork failed, errno=%d\n", errno));
 873    INTON;
 874    error("Cannot fork: %s", strerror(errno));
 875  }
 876  if (pid == 0) {
 877    struct job *p;
 878    int         wasroot;
 879    int         i;
 880
 881    TRACE(("Child shell %d\n", (int)getpid()));
 882    wasroot   = rootshell;
 883    rootshell = 0;
 884    handler   = &main_handler;
 885    closescript();
 886    INTON;
 887    forcelocal = 0;
 888    clear_traps();
 889#if JOBS
 890    jobctl = 0; /* do job control only in root shell */
 891    if (wasroot && mode != FORK_NOJOB && mflag) {
 892      if (jp == NULL || jp->nprocs == 0)
 893        pgrp = getpid();
 894      else
 895        pgrp = jp->ps[0].pid;
 896      if (setpgid(0, pgrp) == 0 && mode == FORK_FG && ttyfd >= 0) {
 897        /*
 898         * Each process in a pipeline must have the tty
 899         * pgrp set before running its code.
 900         * Only for pipelines of three or more processes
 901         * could this be reduced to two calls.
 902         */
 903        if (tcsetpgrp(ttyfd, pgrp) < 0)
 904          error("tcsetpgrp failed, errno=%d", errno);
 905      }
 906      setsignal(SIGTSTP);
 907      setsignal(SIGTTOU);
 908    } else if (mode == FORK_BG) {
 909      ignoresig(SIGINT);
 910      ignoresig(SIGQUIT);
 911      if ((jp == NULL || jp->nprocs == 0) && !fd0_redirected_p()) {
 912        close(0);
 913        if (open(ARUU_PATH_DEVNULL, O_RDONLY) != 0)
 914          error("cannot open %s: %s", ARUU_PATH_DEVNULL, strerror(errno));
 915      }
 916    }
 917#else
 918    if (mode == FORK_BG) {
 919      ignoresig(SIGINT);
 920      ignoresig(SIGQUIT);
 921      if ((jp == NULL || jp->nprocs == 0) && !fd0_redirected_p()) {
 922        close(0);
 923        if (open(ARUU_PATH_DEVNULL, O_RDONLY) != 0)
 924          error("cannot open %s: %s", ARUU_PATH_DEVNULL, strerror(errno));
 925      }
 926    }
 927#endif
 928    INTOFF;
 929    for (i = njobs, p = jobtab; --i >= 0; p++)
 930      if (p->used)
 931        freejob(p);
 932    INTON;
 933    if (wasroot && iflag) {
 934      setsignal(SIGINT);
 935      setsignal(SIGQUIT);
 936      setsignal(SIGTERM);
 937    }
 938    return pid;
 939  }
 940  if (rootshell && mode != FORK_NOJOB && mflag) {
 941    if (jp == NULL || jp->nprocs == 0)
 942      pgrp = pid;
 943    else
 944      pgrp = jp->ps[0].pid;
 945    setpgid(pid, pgrp);
 946  }
 947  if (mode == FORK_BG) {
 948    if (bgjob != NULL && bgjob->state == JOBDONE && !bgjob->remembered && !iflag)
 949      freejob(bgjob);
 950    backgndpid = pid; /* set $! */
 951    bgjob      = jp;
 952  }
 953  if (jp) {
 954    struct procstat *ps = &jp->ps[jp->nprocs++];
 955    ps->pid             = pid;
 956    ps->status          = -1;
 957    ps->cmd             = nullstr;
 958    if (iflag && rootshell && n)
 959      ps->cmd = commandtext(n);
 960    jp->foreground = mode == FORK_FG;
 961#if JOBS
 962    setcurjob(jp);
 963#endif
 964  }
 965  INTON;
 966  TRACE(("In parent shell:  child = %d\n", (int)pid));
 967  return pid;
 968}
 969
 970pid_t
 971vforkexecshell(struct job *jp, char **argv, char **envp, const char *path, int idx, int pip[2])
 972{
 973  pid_t          pid;
 974  struct jmploc  jmploc;
 975  struct jmploc *savehandler;
 976  int            inton;
 977
 978  TRACE(("vforkexecshell(%%%td, %s, %p) called\n", jp - jobtab, argv[0], (void *)pip));
 979  inton = is_int_on();
 980  INTOFF;
 981  flushall();
 982  savehandler = handler;
 983  pid         = vfork();
 984  if (pid == -1) {
 985    TRACE(("Vfork failed, errno=%d\n", errno));
 986    INTON;
 987    error("Cannot fork: %s", strerror(errno));
 988  }
 989  if (pid == 0) {
 990    TRACE(("Child shell %d\n", (int)getpid()));
 991    if (setjmp(jmploc.loc))
 992      _exit(exitstatus);
 993    if (pip != NULL) {
 994      close(pip[0]);
 995      if (pip[1] != 1) {
 996        dup2(pip[1], 1);
 997        close(pip[1]);
 998      }
 999    }
1000    handler = &jmploc;
1001    shellexec(argv, envp, path, idx);
1002  }
1003  handler = savehandler;
1004  if (jp) {
1005    struct procstat *ps = &jp->ps[jp->nprocs++];
1006    ps->pid             = pid;
1007    ps->status          = -1;
1008    ps->cmd             = nullstr;
1009    jp->foreground      = 1;
1010#if JOBS
1011    setcurjob(jp);
1012#endif
1013  }
1014  SETINTON(inton);
1015  TRACE(("In parent shell:  child = %d\n", (int)pid));
1016  return pid;
1017}
1018
1019/*
1020 * Wait for job to finish.
1021 *
1022 * Under job control we have the problem that while a child process is
1023 * running interrupts generated by the user are sent to the child but not
1024 * to the shell.  This means that an infinite loop started by an inter-
1025 * active user may be hard to kill.  With job control turned off, an
1026 * interactive user may place an interactive program inside a loop.  If
1027 * the interactive program catches interrupts, the user doesn't want
1028 * these interrupts to also abort the loop.  The approach we take here
1029 * is to have the shell ignore interrupt signals while waiting for a
1030 * foreground process to terminate, and then send itself an interrupt
1031 * signal if the child process was terminated by an interrupt signal.
1032 * Unfortunately, some programs want to do a bit of cleanup and then
1033 * exit on interrupt; unless these processes terminate themselves by
1034 * sending a signal to themselves (instead of calling exit) they will
1035 * confuse this approach.
1036 */
1037
1038int
1039waitforjob(struct job *jp, int *signaled)
1040{
1041#if JOBS
1042  int propagate_int = jp->jobctl && jp->foreground;
1043#endif
1044  int jobindex;
1045  int status;
1046  int st;
1047
1048  INTOFF;
1049  TRACE(("waitforjob(%%%td) called\n", jp - jobtab + 1));
1050  while (jp->state == 0)
1051    if (dowait(DOWAIT_BLOCK | (Tflag ? DOWAIT_SIG | DOWAIT_SIG_TRAP : 0), jp) == -1) {
1052      jobindex = jp - jobtab;
1053      dotrap();
1054      jp = jobtab + jobindex;
1055    }
1056#if JOBS
1057  if (jp->jobctl) {
1058    if (ttyfd >= 0 && tcsetpgrp(ttyfd, rootpid) < 0)
1059      error("tcsetpgrp failed, errno=%d\n", errno);
1060  }
1061  if (jp->state == JOBSTOPPED)
1062    setcurjob(jp);
1063#endif
1064  status = getjobstatus(jp);
1065  if (signaled != NULL)
1066    *signaled = WIFSIGNALED(status);
1067  /* convert to 8 bits */
1068  if (WIFEXITED(status))
1069    st = WEXITSTATUS(status);
1070#if JOBS
1071  else if (WIFSTOPPED(status))
1072    st = WSTOPSIG(status) + 128;
1073#endif
1074  else
1075    st = WTERMSIG(status) + 128;
1076  if (!JOBS || jp->state == JOBDONE)
1077    freejob(jp);
1078  if (int_pending()) {
1079    if (!WIFSIGNALED(status) || WTERMSIG(status) != SIGINT)
1080      CLEAR_PENDING_INT;
1081  }
1082#if JOBS
1083  else if (rootshell && propagate_int && WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
1084    kill(getpid(), SIGINT);
1085#endif
1086  INTON;
1087  return st;
1088}
1089
1090static void
1091dummy_handler(int sig __unused)
1092{
1093}
1094
1095/*
1096 * Wait for a process to terminate.
1097 */
1098
1099static pid_t
1100dowait(int mode, struct job *job)
1101{
1102  struct sigaction sa, osa;
1103  sigset_t         mask, omask;
1104  pid_t            pid;
1105  int              status;
1106  struct procstat *sp;
1107  struct job      *jp;
1108  struct job      *thisjob;
1109  const char      *sigstr;
1110  int              done;
1111  int              stopped;
1112  int              sig;
1113  int              coredump;
1114  int              wflags;
1115  int              restore_sigchld;
1116
1117  TRACE(("dowait(%d, %p) called\n", mode, job));
1118  restore_sigchld = 0;
1119  if ((mode & DOWAIT_SIG) != 0) {
1120    sigfillset(&mask);
1121    sigprocmask(SIG_BLOCK, &mask, &omask);
1122    INTOFF;
1123    if (!issigchldtrapped()) {
1124      restore_sigchld = 1;
1125      sa.sa_handler   = dummy_handler;
1126      sa.sa_flags     = 0;
1127      sigemptyset(&sa.sa_mask);
1128      sigaction(SIGCHLD, &sa, &osa);
1129    }
1130  }
1131  do {
1132#if JOBS
1133    if (iflag)
1134      wflags = WUNTRACED | WCONTINUED;
1135    else
1136#endif
1137      wflags = 0;
1138    if ((mode & (DOWAIT_BLOCK | DOWAIT_SIG)) != DOWAIT_BLOCK)
1139      wflags |= WNOHANG;
1140    pid = wait3(&status, wflags, (struct rusage *)NULL);
1141    TRACE(("wait returns %d, status=%d\n", (int)pid, status));
1142    if (pid == 0 && (mode & DOWAIT_SIG) != 0) {
1143      pid = -1;
1144      if (((mode & DOWAIT_SIG_TRAP) != 0 ? pendingsig : pendingsig_waitcmd) != 0) {
1145        errno = EINTR;
1146        break;
1147      }
1148      sigsuspend(&omask);
1149      if (int_pending())
1150        break;
1151    }
1152  } while (pid == -1 && errno == EINTR);
1153  if (pid == -1 && errno == ECHILD && job != NULL)
1154    job->state = JOBDONE;
1155  if ((mode & DOWAIT_SIG) != 0) {
1156    if (restore_sigchld)
1157      sigaction(SIGCHLD, &osa, NULL);
1158    sigprocmask(SIG_SETMASK, &omask, NULL);
1159    INTON;
1160  }
1161  if (pid <= 0)
1162    return pid;
1163  INTOFF;
1164  thisjob = NULL;
1165  for (jp = jobtab; jp < jobtab + njobs; jp++) {
1166    if (jp->used && jp->nprocs > 0) {
1167      done    = 1;
1168      stopped = 1;
1169      for (sp = jp->ps; sp < jp->ps + jp->nprocs; sp++) {
1170        if (sp->pid == -1)
1171          continue;
1172        if (sp->pid == pid && (sp->status == -1 || WIFSTOPPED(sp->status))) {
1173          TRACE(
1174              ("Changing status of proc %d "
1175               "from 0x%x to 0x%x\n",
1176               (int)pid,
1177               sp->status,
1178               status)
1179          );
1180          if (WIFCONTINUED(status)) {
1181            sp->status = -1;
1182            jp->state  = 0;
1183          } else
1184            sp->status = status;
1185          thisjob = jp;
1186        }
1187        if (sp->status == -1)
1188          stopped = 0;
1189        else if (WIFSTOPPED(sp->status))
1190          done = 0;
1191      }
1192      if (stopped) { /* stopped or done */
1193        int state = done ? JOBDONE : JOBSTOPPED;
1194        if (jp->state != state) {
1195          TRACE(
1196              ("Job %td: changing state from "
1197               "%d to %d\n",
1198               jp - jobtab + 1,
1199               jp->state,
1200               state)
1201          );
1202          jp->state = state;
1203          if (jp != job) {
1204            if (done && !jp->remembered && !iflag && jp != bgjob)
1205              freejob(jp);
1206#if JOBS
1207            else if (done)
1208              deljob(jp);
1209#endif
1210          }
1211        }
1212      }
1213    }
1214  }
1215  INTON;
1216  if (!thisjob || thisjob->state == 0)
1217    ;
1218  else if (
1219      (!rootshell || !iflag || thisjob == job) && thisjob->foreground
1220      && thisjob->state != JOBSTOPPED
1221  ) {
1222    sig      = 0;
1223    coredump = 0;
1224    for (sp = thisjob->ps; sp < thisjob->ps + thisjob->nprocs; sp++)
1225      if (WIFSIGNALED(sp->status)) {
1226        sig      = WTERMSIG(sp->status);
1227        coredump = WCOREDUMP(sp->status);
1228      }
1229    if (sig > 0 && sig != SIGINT && sig != SIGPIPE) {
1230      sigstr = strsignal(sig);
1231      if (sigstr != NULL)
1232        out2str(sigstr);
1233      else
1234        out2str("Unknown signal");
1235      if (coredump)
1236        out2str(" (core dumped)");
1237      out2c('\n');
1238      flushout(out2);
1239    }
1240  } else {
1241    TRACE(("Not printing status, rootshell=%d, job=%p\n", rootshell, job));
1242    thisjob->changed = 1;
1243  }
1244  return pid;
1245}
1246
1247/*
1248 * return 1 if there are stopped jobs, otherwise 0
1249 */
1250int job_warning = 0;
1251int
1252stoppedjobs(void)
1253{
1254  int         jobno;
1255  struct job *jp;
1256
1257  if (job_warning)
1258    return (0);
1259  for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) {
1260    if (jp->used == 0)
1261      continue;
1262    if (jp->state == JOBSTOPPED) {
1263      out2fmt_flush("You have stopped jobs.\n");
1264      job_warning = 2;
1265      return (1);
1266    }
1267  }
1268
1269  return (0);
1270}
1271
1272static void
1273checkzombies(void)
1274{
1275  while (njobs > 0 && dowait(0, NULL) > 0)
1276    ;
1277}
1278
1279int
1280backgndpidset(void)
1281{
1282  return backgndpid != -1;
1283}
1284
1285pid_t
1286backgndpidval(void)
1287{
1288  if (bgjob != NULL && !forcelocal)
1289    bgjob->remembered = 1;
1290  return backgndpid;
1291}
1292
1293/*
1294 * Return a string identifying a command (to be printed by the
1295 * jobs command.
1296 */
1297
1298static char *cmdnextc;
1299static int   cmdnleft;
1300#define MAXCMDTEXT 200
1301
1302char *
1303commandtext(union node *n)
1304{
1305  char *name;
1306
1307  cmdnextc = name = ckmalloc(MAXCMDTEXT);
1308  cmdnleft        = MAXCMDTEXT - 4;
1309  cmdtxt(n);
1310  *cmdnextc = '\0';
1311  return name;
1312}
1313
1314static void
1315cmdtxtdogroup(union node *n)
1316{
1317  cmdputs("; do ");
1318  cmdtxt(n);
1319  cmdputs("; done");
1320}
1321
1322static void
1323cmdtxtredir(union node *n, const char *op, int deffd)
1324{
1325  char s[2];
1326
1327  if (n->nfile.fd != deffd) {
1328    s[0] = n->nfile.fd + '0';
1329    s[1] = '\0';
1330    cmdputs(s);
1331  }
1332  cmdputs(op);
1333  if (n->type == NTOFD || n->type == NFROMFD) {
1334    if (n->ndup.dupfd >= 0)
1335      s[0] = n->ndup.dupfd + '0';
1336    else
1337      s[0] = '-';
1338    s[1] = '\0';
1339    cmdputs(s);
1340  } else {
1341    cmdtxt(n->nfile.fname);
1342  }
1343}
1344
1345static void
1346cmdtxt(union node *n)
1347{
1348  union node      *np;
1349  struct nodelist *lp;
1350
1351  if (n == NULL)
1352    return;
1353  switch (n->type) {
1354    case NSEMI:
1355      cmdtxt(n->nbinary.ch1);
1356      cmdputs("; ");
1357      cmdtxt(n->nbinary.ch2);
1358      break;
1359    case NAND:
1360      cmdtxt(n->nbinary.ch1);
1361      cmdputs(" && ");
1362      cmdtxt(n->nbinary.ch2);
1363      break;
1364    case NOR:
1365      cmdtxt(n->nbinary.ch1);
1366      cmdputs(" || ");
1367      cmdtxt(n->nbinary.ch2);
1368      break;
1369    case NPIPE:
1370      for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1371        cmdtxt(lp->n);
1372        if (lp->next)
1373          cmdputs(" | ");
1374      }
1375      break;
1376    case NSUBSHELL:
1377      cmdputs("(");
1378      cmdtxt(n->nredir.n);
1379      cmdputs(")");
1380      break;
1381    case NREDIR:
1382    case NBACKGND:
1383      cmdtxt(n->nredir.n);
1384      break;
1385    case NIF:
1386      cmdputs("if ");
1387      cmdtxt(n->nif.test);
1388      cmdputs("; then ");
1389      cmdtxt(n->nif.ifpart);
1390      cmdputs("...");
1391      break;
1392    case NWHILE:
1393      cmdputs("while ");
1394      cmdtxt(n->nbinary.ch1);
1395      cmdtxtdogroup(n->nbinary.ch2);
1396      break;
1397    case NUNTIL:
1398      cmdputs("until ");
1399      cmdtxt(n->nbinary.ch1);
1400      cmdtxtdogroup(n->nbinary.ch2);
1401      break;
1402    case NFOR:
1403      cmdputs("for ");
1404      cmdputs(n->nfor.var);
1405      cmdputs(" in ...");
1406      break;
1407    case NCASE:
1408      cmdputs("case ");
1409      cmdputs(n->ncase.expr->narg.text);
1410      cmdputs(" in ...");
1411      break;
1412    case NDEFUN:
1413      cmdputs(n->narg.text);
1414      cmdputs("() ...");
1415      break;
1416    case NNOT:
1417      cmdputs("! ");
1418      cmdtxt(n->nnot.com);
1419      break;
1420    case NCMD:
1421      for (np = n->ncmd.args; np; np = np->narg.next) {
1422        cmdtxt(np);
1423        if (np->narg.next)
1424          cmdputs(" ");
1425      }
1426      for (np = n->ncmd.redirect; np; np = np->nfile.next) {
1427        cmdputs(" ");
1428        cmdtxt(np);
1429      }
1430      break;
1431    case NARG:
1432      cmdputs(n->narg.text);
1433      break;
1434    case NTO:
1435      cmdtxtredir(n, ">", 1);
1436      break;
1437    case NAPPEND:
1438      cmdtxtredir(n, ">>", 1);
1439      break;
1440    case NTOFD:
1441      cmdtxtredir(n, ">&", 1);
1442      break;
1443    case NCLOBBER:
1444      cmdtxtredir(n, ">|", 1);
1445      break;
1446    case NFROM:
1447      cmdtxtredir(n, "<", 0);
1448      break;
1449    case NFROMTO:
1450      cmdtxtredir(n, "<>", 0);
1451      break;
1452    case NFROMFD:
1453      cmdtxtredir(n, "<&", 0);
1454      break;
1455    case NHERE:
1456    case NXHERE:
1457      cmdputs("<<...");
1458      break;
1459    default:
1460      cmdputs("???");
1461      break;
1462  }
1463}
1464
1465static void
1466cmdputs(const char *s)
1467{
1468  const char *p;
1469  char       *q;
1470  char        c;
1471  int         subtype = 0;
1472
1473  if (cmdnleft <= 0)
1474    return;
1475  p = s;
1476  q = cmdnextc;
1477  while ((c = *p++) != '\0') {
1478    if (c == CTLESC)
1479      *q++ = *p++;
1480    else if (c == CTLVAR) {
1481      *q++ = '$';
1482      if (--cmdnleft > 0)
1483        *q++ = '{';
1484      subtype = *p++;
1485      if ((subtype & VSTYPE) == VSLENGTH && --cmdnleft > 0)
1486        *q++ = '#';
1487    } else if (c == '=' && subtype != 0) {
1488      *q = "}-+?=##%%\0X"[(subtype & VSTYPE) - VSNORMAL];
1489      if (*q)
1490        q++;
1491      else
1492        cmdnleft++;
1493      if (((subtype & VSTYPE) == VSTRIMLEFTMAX || (subtype & VSTYPE) == VSTRIMRIGHTMAX)
1494          && --cmdnleft > 0)
1495        *q = q[-1], q++;
1496      subtype = 0;
1497    } else if (c == CTLENDVAR) {
1498      *q++ = '}';
1499    } else if (c == CTLBACKQ || c == CTLBACKQ + CTLQUOTE) {
1500      cmdnleft -= 5;
1501      if (cmdnleft > 0) {
1502        *q++ = '$';
1503        *q++ = '(';
1504        *q++ = '.';
1505        *q++ = '.';
1506        *q++ = '.';
1507        *q++ = ')';
1508      }
1509    } else if (c == CTLARI) {
1510      cmdnleft -= 2;
1511      if (cmdnleft > 0) {
1512        *q++ = '$';
1513        *q++ = '(';
1514        *q++ = '(';
1515      }
1516      p++;
1517    } else if (c == CTLENDARI) {
1518      if (--cmdnleft > 0) {
1519        *q++ = ')';
1520        *q++ = ')';
1521      }
1522    } else if (c == CTLQUOTEMARK || c == CTLQUOTEEND)
1523      cmdnleft++; /* ignore */
1524    else
1525      *q++ = c;
1526    if (--cmdnleft <= 0) {
1527      *q++ = '.';
1528      *q++ = '.';
1529      *q++ = '.';
1530      break;
1531    }
1532  }
1533  cmdnextc = q;
1534}