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--) {