Print this page
6535 Add pbind -e
Reviewed by: Mohamed Khalfella <khalfella@gmail.com>
Reviewed by: Cody Mello <melloc@joyent.com>
Reviewed by: Albert Lee <trisk@omniti.com>

@@ -18,16 +18,15 @@
  * information: Portions Copyright [yyyy] [name of copyright owner]
  *
  * CDDL HEADER END
  */
 /*
+ * Copyright 2015 Ryan Zezeski
  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident   "%Z%%M% %I%     %E% SMI"
-
 /*
  * pbind - bind a process to a processor (non-exclusively)
  */
 
 #include <sys/types.h>

@@ -52,10 +51,11 @@
 #define ERR_FAIL        1               /* exit status for errors */
 #define ERR_USAGE       2               /* exit status for usage errors */
 
 static char     *progname;
 static char     bflag;
+static char     eflag;
 static char     qflag;
 static char     Qflag;
 static char     uflag;
 static char     Uflag;
 static int      errors;

@@ -343,15 +343,49 @@
             (cpuid == NULL && binding != PBIND_NONE))
                 query_out(pid, lwpid, binding);
         return (0);
 }
 
+/*
+ * Execute the cmd with args while bound to cpu. Does not return:
+ * either executes cmd successfully or dies trying.
+ */
+static void
+exec_cmd(processorid_t cpu, char *cmd, char **args)
+{
+        if (processor_bind(P_PID, P_MYID, cpu, NULL) == -1) {
+                bind_err(cpu, getpid(), -1, errno);
+                exit(ERR_FAIL);
+        }
+
+        if (execvp(cmd, args) == -1)
+                die(gettext("failed to exec %s\n"), cmd);
+}
+
+/*
+ * Attempt to parse str as a CPU identifier. Return the identifier or
+ * die.
+ */
+static processorid_t
+parse_cpu(char *str)
+{
+        processorid_t cpu;
+        char *endstr;
+
+        cpu = strtol(str, &endstr, 10);
+        if (endstr != NULL && *endstr != '\0' || cpu < 0)
+                die(gettext("invalid processor ID %s\n"), optarg);
+
+        return (cpu);
+}
+
 static int
 usage(void)
 {
         (void) fprintf(stderr,
             gettext("usage: \n\t%1$s -b processor_id pid[/lwpids] ...\n"
+            "\t%1$s -e processor_id cmd [args...]\n"
             "\t%1$s -U [processor_id] ...\n"
             "\t%1$s -Q [processor_id] ...\n"
             "\t%1$s -u pid[/lwpids] ...\n"
             "\t%1$s [-q] [pid[/lwpids] ...]\n"),
             progname);

@@ -370,21 +404,23 @@
         progname = argv[0];     /* put actual command name in messages */
 
         (void) setlocale(LC_ALL, "");   /* setup localization */
         (void) textdomain(TEXT_DOMAIN);
 
-        while ((c = getopt(argc, argv, "b:qQuU")) != EOF) {
+        while ((c = getopt(argc, argv, "b:e:qQuU")) != EOF) {
                 switch (c) {
 
                 case 'b':
                         bflag = 1;
-                        cpu = strtol(optarg, &endstr, 10);
-                        if (endstr != NULL && *endstr != '\0' || cpu < 0)
-                                die(gettext("invalid processor ID %s\n"),
-                                    optarg);
+                        cpu = parse_cpu(optarg);
                         break;
 
+                case 'e':
+                        eflag = 1;
+                        cpu = parse_cpu(optarg);
+                        break;
+
                 case 'q':
                         qflag = 1;
                         cpu = PBIND_QUERY;
                         break;
 

@@ -407,19 +443,19 @@
                 }
         }
 
 
         /*
-         * Make sure that at most one of the options b, q, Q, u, or U
-         * was specified.
+         * Make sure that at most one of the options b, e, q, Q, u, or
+         * U was specified.
          */
-        c = bflag + qflag + Qflag + uflag + Uflag;
+        c = bflag + eflag + qflag + Qflag + uflag + Uflag;
         if (c < 1) {                            /* nothing specified */
                 qflag = 1;                      /* default to query */
                 cpu = PBIND_QUERY;
         } else if (c > 1) {
-                warn(gettext("options -b, -q, -Q, -u and -U "
+                warn(gettext("options -b, -e, -q, -Q, -u and -U "
                     "are mutually exclusive\n"));
                 return (usage());
         }
 
         errors = 0;

@@ -432,10 +468,14 @@
         if (argc == 0) {
                 if (bflag || uflag) {
                         warn(gettext("must specify at least one pid\n"));
                         return (usage());
                 }
+                if (eflag) {
+                        warn(gettext("must specify command\n"));
+                        return (usage());
+                }
                 if (Uflag) {
                         if (processor_bind(P_ALL, 0, PBIND_NONE, &old_cpu) != 0)
                                 die(gettext("failed to unbind some LWPs"));
                 }
                 if (Qflag) {

@@ -445,10 +485,13 @@
                         (void) proc_walk(query_all_proc, NULL, PR_WALK_PROC);
                         return (errors);
                 }
         }
 
+        if (eflag)
+                exec_cmd(cpu, argv[0], argv);
+
         if (Qflag || Uflag) {
                 /*
                  * Go through listed processor IDs.
                  */
                 for (; argc > 0; argv++, argc--) {