Print this page
    
OS-3280 need a way to specify the root of a native system in the lx brand
OS-3279 lx brand should allow delegated datasets
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/cmd/ptools/preap/preap.c
          +++ new/usr/src/cmd/ptools/preap/preap.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License, Version 1.0 only
   6    6   * (the "License").  You may not use this file except in compliance
   7    7   * with the License.
   8    8   *
   9    9   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10   10   * or http://www.opensolaris.org/os/licensing.
  11   11   * See the License for the specific language governing permissions
  12   12   * and limitations under the License.
  13   13   *
  14   14   * When distributing Covered Code, include this CDDL HEADER in each
  15   15   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16   16   * If applicable, add the following below this CDDL HEADER, with the
  
    | 
      ↓ open down ↓ | 
    16 lines elided | 
    
      ↑ open up ↑ | 
  
  17   17   * fields enclosed by brackets "[]" replaced with your own identifying
  18   18   * information: Portions Copyright [yyyy] [name of copyright owner]
  19   19   *
  20   20   * CDDL HEADER END
  21   21   */
  22   22  /*
  23   23   * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
  24   24   * Use is subject to license terms.
  25   25   */
  26   26  
  27      -#pragma ident   "%Z%%M% %I%     %E% SMI"
  28      -
  29   27  #include <stdio.h>
  30   28  #include <stdlib.h>
  31   29  #include <unistd.h>
  32   30  #include <fcntl.h>
  33   31  #include <ctype.h>
  34   32  #include <string.h>
  35   33  #include <signal.h>
  36   34  #include <errno.h>
  37   35  #include <sys/types.h>
  38   36  #include <sys/wait.h>
  39   37  #include <libproc.h>
       38 +#include <limits.h>
       39 +#include "ptools_common.h"
  40   40  
  41   41  #define NOREAP_TIME 60          /* wait 60 seconds before allow a reap */
  42   42  
  43   43  static volatile int interrupt;
  44   44  static int Fflag;
  45   45  static char *command;
  46   46  
  47   47  static void
  48   48  intr(int sig)
  49   49  {
  50   50          interrupt = sig;
  51   51  }
  52   52  
  53   53  static int
  54   54  open_usage(pid_t pid, int *perr)
  55   55  {
  56      -        char path[64];
       56 +        char path[PATH_MAX];
  57   57          struct stat64 st;
  58   58          int fd;
  59   59  
  60      -        (void) snprintf(path, sizeof (path), "/proc/%d/usage", (int)pid);
       60 +        (void) proc_snprintf(path, sizeof (path), "/proc/%d/usage", (int)pid);
  61   61  
  62   62          /*
  63   63           * Attempt to open the usage file, and return the fd if we can
  64   64           * confirm this is a regular file provided by /proc.
  65   65           */
  66   66          if ((fd = open64(path, O_RDONLY)) >= 0) {
  67   67                  if (fstat64(fd, &st) != 0 || !S_ISREG(st.st_mode) ||
  68   68                      strcmp(st.st_fstype, "proc") != 0) {
  69   69                          (void) close(fd);
  70   70                          fd = -1;
  71   71                  }
  72   72          } else if (errno == EACCES || errno == EPERM)
  73   73                  *perr = G_PERM;
  74   74  
  75   75          return (fd);
  76   76  }
  77   77  
  78   78  static int
  79   79  proc_usage(pid_t pid, prusage_t *pup, int *perr)
  80   80  {
  81   81          int fd;
  82   82  
  83   83          *perr = G_NOPROC;
  84   84  
  85   85          if ((fd = open_usage(pid, perr)) != -1) {
  86   86                  if (read(fd, pup, sizeof (prusage_t)) == sizeof (prusage_t)) {
  87   87                          *perr = 0;
  88   88                          (void) close(fd);
  89   89                          return (0);
  90   90                  }
  91   91  
  92   92                  /*
  93   93                   * If the read failed, the process may have gone away.
  94   94                   */
  95   95                  (void) close(fd);
  96   96          }
  97   97          return (-1);
  98   98  }
  99   99  
 100  100  /*
 101  101   * Force the parent process (ppid) to wait for its child process (pid).
 102  102   */
 103  103  static int
 104  104  reap(char *arg, pid_t *reap_pid, int *exit_status)
 105  105  {
 106  106          struct ps_prochandle *Pr;
 107  107          siginfo_t siginfo;
 108  108          psinfo_t psinfo;
 109  109          prusage_t usage;
 110  110          pid_t pid, ppid;
 111  111          time_t elapsed;
 112  112          int gret;
 113  113  
 114  114          /*
 115  115           * get the specified pid and the psinfo struct
 116  116           */
 117  117          if ((pid = proc_arg_psinfo(arg, PR_ARG_PIDS, &psinfo, &gret)) == -1) {
 118  118                  (void) fprintf(stderr, "%s: cannot examine %s: %s\n",
 119  119                      command, arg, Pgrab_error(gret));
 120  120                  return (1);
 121  121          }
 122  122  
 123  123          if (psinfo.pr_nlwp != 0) {
 124  124                  (void) fprintf(stderr, "%s: process not defunct: %d\n",
 125  125                      command, (int)pid);
 126  126                  return (1);
 127  127          }
 128  128  
 129  129          *exit_status = psinfo.pr_wstat;
 130  130          *reap_pid = psinfo.pr_pid;
 131  131          ppid = psinfo.pr_ppid;
 132  132  
 133  133          if (ppid == 1) {
 134  134                  (void) fprintf(stderr, "%s: Failed to reap %d: the only "
 135  135                      "non-defunct ancestor is 'init'\n", command,
 136  136                      (int)pid);
 137  137                  return (1);
 138  138          }
 139  139  
 140  140          if (proc_usage(pid, &usage, &gret) == 0) {
 141  141                  elapsed = usage.pr_tstamp.tv_sec - usage.pr_term.tv_sec;
 142  142          } else {
 143  143                  (void) fprintf(stderr, "%s: cannot examine %d: %s\n",
 144  144                      command, (int)pid, Pgrab_error(gret));
 145  145                  return (1);
 146  146          }
 147  147  
 148  148          if ((Fflag == 0) && (elapsed < NOREAP_TIME)) {
 149  149                  (void) fprintf(stderr, "%s: unsafe to reap %d; it has been "
 150  150                      "defunct less than %d seconds\n", command, (int)pid,
 151  151                      NOREAP_TIME);
 152  152                  return (1);
 153  153          }
 154  154  
 155  155          if ((Pr = Pgrab(ppid, Fflag | PGRAB_NOSTOP, &gret)) == NULL) {
 156  156                  (void) fprintf(stderr, "%s: cannot examine %d: %s\n", command,
 157  157                      (int)ppid, Pgrab_error(gret));
 158  158                  return (1);
 159  159          }
 160  160  
 161  161          if ((Fflag == 0) && (Pstate(Pr) == PS_STOP)) {
 162  162                  Prelease(Pr, 0);
 163  163                  (void) fprintf(stderr, "%s: unsafe to reap %d; parent is "
 164  164                      "stopped and may reap status upon restart\n", command,
 165  165                      (int)pid);
 166  166                  return (1);
 167  167          }
 168  168  
 169  169          /*
 170  170           * Pstop() will fail if the process to be stopped has become a zombie.
 171  171           * This means that we can say with certainty that the child of this
 172  172           * process has not changed parents (i.e. been reparented to init) once
 173  173           * the Pstop() succeeds.
 174  174           */
 175  175          if (Pstop(Pr, 1000) != 0) {
 176  176                  Prelease(Pr, 0);
 177  177                  (void) fprintf(stderr, "%s: failed to stop %d: %s", command,
 178  178                      (int)ppid, strerror(errno));
 179  179                  return (1);
 180  180          }
 181  181  
 182  182          if (pr_waitid(Pr, P_PID, pid, &siginfo, WEXITED|WNOHANG) != 0) {
 183  183                  Prelease(Pr, 0);
 184  184                  (void) fprintf(stderr, "%s: waitid() in process %d failed: %s",
 185  185                      command, (int)ppid, strerror(errno));
 186  186                  return (1);
 187  187          }
 188  188  
 189  189          Prelease(Pr, 0);
 190  190          return (0);
 191  191  }
 192  192  
 193  193  static void
 194  194  print_exit_status(pid_t pid, int wstat)
 195  195  {
 196  196          (void) printf("%d: ", (int)pid);
 197  197          if (WIFSIGNALED(wstat)) {
 198  198                  char buf[SIG2STR_MAX];
 199  199                  int sig = WTERMSIG(wstat);
 200  200  
 201  201                  if (sig2str(sig, buf) == 0)
 202  202                          (void) printf("killed by signal %s", buf);
 203  203                  else
 204  204                          (void) printf("killed by signal %d", sig);
 205  205  
 206  206                  if (WCOREDUMP(wstat))
 207  207                          (void) printf(" (core dumped)");
 208  208          } else {
 209  209                  (void) printf("exited with status %d", WEXITSTATUS(wstat));
 210  210          }
 211  211          (void) printf("\n");
 212  212  }
 213  213  
 214  214  int
 215  215  main(int argc, char *argv[])
 216  216  {
 217  217          int retc = 0;
 218  218          int opt;
 219  219          int errflg = 0;
 220  220  
 221  221          if ((command = strrchr(argv[0], '/')) != NULL)
 222  222                  command++;
 223  223          else
 224  224                  command = argv[0];
 225  225  
 226  226          while ((opt = getopt(argc, argv, "F")) != EOF) {
 227  227                  switch (opt) {
 228  228                  case 'F':               /* force grabbing (no O_EXCL) */
 229  229                          Fflag = PGRAB_FORCE;
 230  230                          break;
 231  231                  default:
 232  232                          errflg = 1;
 233  233                          break;
 234  234                  }
 235  235          }
 236  236  
 237  237          argc -= optind;
 238  238          argv += optind;
 239  239  
 240  240          if (errflg || argc <= 0) {
 241  241                  (void) fprintf(stderr, "usage:  %s pid ...\n", command);
 242  242                  (void) fprintf(stderr, "  (Reap a defunct process by forcing "
 243  243                      "its parent to wait(2) for it)\n");
 244  244                  exit(2);
 245  245          }
 246  246  
 247  247          /* catch signals from terminal */
 248  248          if (sigset(SIGHUP, SIG_IGN) == SIG_DFL)
 249  249                  (void) sigset(SIGHUP, intr);
 250  250          if (sigset(SIGINT, SIG_IGN) == SIG_DFL)
 251  251                  (void) sigset(SIGINT, intr);
 252  252          if (sigset(SIGPIPE, SIG_IGN) == SIG_DFL)
 253  253                  (void) sigset(SIGPIPE, intr);
 254  254          if (sigset(SIGQUIT, SIG_IGN) == SIG_DFL)
 255  255                  (void) sigset(SIGQUIT, intr);
 256  256          (void) sigset(SIGTERM, intr);
 257  257  
 258  258          while (--argc >= 0 && !interrupt) {
 259  259                  pid_t pid;
 260  260                  int wstat, r;
 261  261  
 262  262                  retc += r = reap(*argv++, &pid, &wstat);
 263  263  
 264  264                  if (r == 0)
 265  265                          print_exit_status(pid, wstat);
 266  266          }
 267  267  
 268  268          if (interrupt && retc == 0)
 269  269                  retc++;
 270  270          return (retc == 0 ? 0 : 1);
 271  271  }
  
    | 
      ↓ open down ↓ | 
    201 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX