4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
30 /* All Rights Reserved */
37 #include <sys/types.h>
38 #include <sys/procset.h>
39 #include <sys/priocntl.h>
40 #include <sys/iapriocntl.h>
48 * This file contains the class specific code implementing
49 * the interactive class priocntl sub-command.
52 #define ADDKEYVAL(p, k, v) { (p[0]) = (k); (p[1]) = (v); p += 2; }
54 #define IA_KEYCNT 3 /* maximal number of (key, value) pairs */
59 #define IA_DOUPRILIM 0x01 /* user priority limit */
60 #define IA_DOUPRI 0x02 /* user priority */
61 #define IA_DOMODE 0x04 /* interactive on/off */
63 static void print_iainfo(void);
64 static int print_iaprocs(void);
65 static int ia_priocntl(idtype_t
, id_t
, int, char *, uintptr_t *);
66 static int set_iaprocs(idtype_t
, int, char **, uint_t
, pri_t
, pri_t
, int);
67 static void exec_iacmd(char **, uint_t
, pri_t
, pri_t
, int);
70 "usage: priocntl -l\n\
71 priocntl -d [-i idtype] [idlist]\n\
72 priocntl -s [-c IA] [-m iauprilim] [-p iaupri] [-t iamode]\n\
73 [-i idtype] [idlist]\n\
74 priocntl -e [-c IA] [-m iauprilim] [-p iaupri] [-t iamode]\n\
75 command [argument(s)]\n";
77 static char cmdpath
[MAXPATHLEN
];
78 static char basenm
[BASENMSZ
];
82 main(int argc
, char *argv
[])
85 int lflag
, dflag
, sflag
, mflag
, pflag
, eflag
, iflag
, tflag
;
94 (void) strlcpy(cmdpath
, argv
[0], MAXPATHLEN
);
95 (void) strlcpy(basenm
, basename(argv
[0]), BASENMSZ
);
96 lflag
= dflag
= sflag
= mflag
= pflag
= eflag
= iflag
= tflag
= 0;
97 while ((c
= getopt(argc
, argv
, "ldsm:p:t:ec:i:")) != -1) {
114 iauprilim
= (pri_t
)str2num(optarg
, SHRT_MIN
, SHRT_MAX
);
116 fatalerr("%s: Specified user priority limit %s"
117 " out of configured range\n",
123 iaupri
= (pri_t
)str2num(optarg
, SHRT_MIN
, SHRT_MAX
);
125 fatalerr("%s: Specified user priority %s out of"
126 " configured range\n", basenm
, optarg
);
131 iamode
= (int)str2num(optarg
, INT_MIN
, INT_MAX
);
132 if (errno
|| (iamode
!= IA_INTERACTIVE_OFF
&&
133 iamode
!= IA_SET_INTERACTIVE
))
134 fatalerr("%s: Specified illegal mode %s\n",
143 if (strcmp(optarg
, "IA") != 0)
144 fatalerr("error: %s executed for %s class, %s"
145 " is actually sub-command for IA class\n",
146 cmdpath
, optarg
, cmdpath
);
163 if (dflag
|| sflag
|| mflag
|| pflag
|| tflag
|| eflag
|| iflag
)
169 if (lflag
|| sflag
|| mflag
|| pflag
|| tflag
|| eflag
)
172 return (print_iaprocs());
175 if (lflag
|| dflag
|| eflag
)
179 if (str2idtyp(idtypnm
, &idtype
) == -1)
180 fatalerr("%s: Bad idtype %s\n", basenm
,
186 cflags
= (pflag
? IA_DOUPRI
: 0);
189 cflags
|= IA_DOUPRILIM
;
195 idargc
= argc
- optind
;
199 return (set_iaprocs(idtype
, idargc
, &argv
[optind
], cflags
,
200 iauprilim
, iaupri
, iamode
));
203 if (lflag
|| dflag
|| sflag
|| iflag
)
206 cflags
= (pflag
? IA_DOUPRI
: 0);
209 cflags
|= IA_DOUPRILIM
;
214 exec_iacmd(&argv
[optind
], cflags
, iauprilim
, iaupri
, iamode
);
225 * Print our class name and the configured user priority range.
232 (void) strcpy(pcinfo
.pc_clname
, "IA");
234 (void) printf("IA (Interactive)\n");
236 if (priocntl(0, 0, PC_GETCID
, (caddr_t
)&pcinfo
) == -1)
237 fatalerr("\tCan't get configured IA user priority range\n");
239 (void) printf("\tConfigured IA User Priority Range: -%d through %d\n",
240 ((iainfo_t
*)pcinfo
.pc_clinfo
)->ia_maxupri
,
241 ((iainfo_t
*)pcinfo
.pc_clinfo
)->ia_maxupri
);
246 * Read a list of pids from stdin and print the user priority and user
247 * priority limit for each of the corresponding processes.
248 * print their interactive mode and nice values
256 char clname
[PC_CLNMSZ
];
263 * Read a list of pids from stdin.
265 if ((pidlist
= read_pidlist(&numread
, stdin
)) == NULL
)
266 fatalerr("%s: Can't read pidlist.\n", basenm
);
268 (void) printf("INTERACTIVE CLASS PROCESSES:");
269 (void) printf("\n PID IAUPRILIM IAUPRI IAMODE\n");
272 fatalerr("%s: No pids on input\n", basenm
);
274 for (i
= 0; i
< numread
; i
++) {
275 (void) printf("%7ld", pidlist
[i
]);
276 if (priocntl(P_PID
, pidlist
[i
], PC_GETXPARMS
, "IA",
277 IA_KY_UPRI
, &ia_upri
, IA_KY_UPRILIM
, &ia_uprilim
,
278 IA_KY_MODE
, &ia_mode
, 0) != -1) {
279 (void) printf(" %5d %5d %5d\n",
280 ia_uprilim
, ia_upri
, ia_mode
);
284 if (priocntl(P_PID
, pidlist
[i
], PC_GETXPARMS
, NULL
,
285 PC_KY_CLNAME
, clname
, 0) != -1 &&
286 strcmp(clname
, "IA"))
288 * Process from some class other than
289 * interactive. It has probably changed class
290 * while priocntl command was executing
291 * (otherwise we wouldn't have been passed its
292 * pid). Print the little we know about it.
294 (void) printf("\tChanged to class %s while"
295 " priocntl command executing\n", clname
);
297 (void) printf("\tCan't get IA user priority\n");
301 free_pidlist(pidlist
);
307 * Call priocntl() with command codes PC_SETXPARMS or PC_GETXPARMS.
308 * The first parameter behind the command code is always the class name.
309 * Each parameter is headed by a key, which determines the meaning of the
310 * following value. There are maximal IA_KEYCNT = 3 (key, value) pairs.
313 ia_priocntl(idtype_t idtype
, id_t id
, int cmd
, char *clname
, uintptr_t *argsp
)
315 return (priocntl(idtype
, id
, cmd
, clname
, argsp
[0], argsp
[1],
316 argsp
[2], argsp
[3], argsp
[4], argsp
[5], 0));
321 * Set all processes in the set specified by idtype/idargv to interactive
322 * (if they aren't already interactive ) and set their user priority limit
323 * and user priority to those specified by iauprilim and iaupri.
326 set_iaprocs(idtype_t idtype
, int idargc
, char **idargv
, uint_t cflags
,
327 pri_t iauprilim
, pri_t iaupri
, int iamode
)
330 uintptr_t args
[2*IA_KEYCNT
+1];
331 uintptr_t *argsp
= &args
[0];
333 char idtypnm
[PC_IDTYPNMSZ
];
339 * Get the interactive class ID and max configured user priority.
341 (void) strcpy(pcinfo
.pc_clname
, "IA");
342 if (priocntl(0, 0, PC_GETCID
, (caddr_t
)&pcinfo
) == -1)
343 fatalerr("%s: Can't get IA class ID, priocntl system call"
344 " failed with errno %d\n", basenm
, errno
);
345 maxupri
= ((iainfo_t
*)pcinfo
.pc_clinfo
)->ia_maxupri
;
348 * Validate the iauprilim and iaupri arguments.
350 if ((cflags
& IA_DOUPRILIM
) != 0) {
351 if (iauprilim
> maxupri
|| iauprilim
< -maxupri
)
352 fatalerr("%s: Specified user priority limit %d out of"
353 " configured range\n", basenm
, iauprilim
);
354 ADDKEYVAL(argsp
, IA_KY_UPRILIM
, iauprilim
);
357 if ((cflags
& IA_DOUPRI
) != 0) {
358 if (iaupri
> maxupri
|| iaupri
< -maxupri
)
359 fatalerr("%s: Specified user priority %d out of"
360 " configured range\n", basenm
, iaupri
);
361 ADDKEYVAL(argsp
, IA_KY_UPRI
, iaupri
);
364 if ((cflags
& IA_DOMODE
) != 0)
365 ADDKEYVAL(argsp
, IA_KY_MODE
, iamode
);
368 if (idtype
== P_ALL
) {
369 if (ia_priocntl(P_ALL
, 0, PC_SETXPARMS
, "IA", args
) == -1) {
370 if (errno
== EPERM
) {
371 (void) fprintf(stderr
,
372 "Permissions error encountered"
373 " on one or more processes.\n");
376 fatalerr("%s: Can't reset interactive"
377 " parameters\npriocntl system call failed"
378 " with errno %d\n", basenm
, errno
);
380 } else if ((cflags
& (IA_DOUPRILIM
|IA_DOUPRI
)) == IA_DOUPRI
) {
381 (void) verifyupri(idtype
, 0, "IA", IA_KY_UPRILIM
,
384 } else if (idargc
== 0) {
385 if (ia_priocntl(idtype
, P_MYID
, PC_SETXPARMS
, "IA",
387 if (errno
== EPERM
) {
388 (void) idtyp2str(idtype
, idtypnm
);
389 (void) fprintf(stderr
,
390 "Permissions error encountered"
391 " on current %s.\n", idtypnm
);
394 fatalerr("%s: Can't reset interactive"
395 " parameters\npriocntl system call failed"
396 " with errno %d\n", basenm
, errno
);
398 } else if ((cflags
& (IA_DOUPRILIM
|IA_DOUPRI
)) == IA_DOUPRI
&&
399 getmyid(idtype
, &id
) != -1) {
400 (void) verifyupri(idtype
, id
, "IA", IA_KY_UPRILIM
,
404 (void) idtyp2str(idtype
, idtypnm
);
405 for (i
= 0; i
< idargc
; i
++) {
406 if (idtype
== P_CID
) {
407 (void) strcpy(pcinfo
.pc_clname
, idargv
[i
]);
408 if (priocntl(0, 0, PC_GETCID
,
409 (caddr_t
)&pcinfo
) == -1)
410 fatalerr("%s: Invalid or unconfigured"
411 " class %s, priocntl system call"
412 " failed with errno %d\n",
413 basenm
, pcinfo
.pc_clname
, errno
);
416 id
= (id_t
)str2num(idargv
[i
], INT_MIN
, INT_MAX
);
418 fatalerr("%s: Invalid id \"%s\"\n",
422 if (ia_priocntl(idtype
, id
, PC_SETXPARMS
, "IA",
424 if (errno
== EPERM
) {
425 (void) fprintf(stderr
,
427 " encountered on %s %s.\n",
431 fatalerr("%s: Can't reset interactive"
432 " parameters\npriocntl system call"
433 " failed with errno %d\n",
436 } else if ((cflags
& (IA_DOUPRILIM
|IA_DOUPRI
)) ==
438 (void) verifyupri(idtype
, id
, "IA",
439 IA_KY_UPRILIM
, iaupri
, basenm
);
449 * Execute the command pointed to by cmdargv as a interactive process
450 * with the user priority limit given by iauprilim and user priority iaupri.
453 exec_iacmd(char **cmdargv
, uint_t cflags
, pri_t iauprilim
, pri_t iaupri
,
457 uintptr_t args
[2*IA_KEYCNT
+1];
458 uintptr_t *argsp
= &args
[0];
463 * Get the time sharing class ID and max configured user priority.
465 (void) strcpy(pcinfo
.pc_clname
, "IA");
466 if (priocntl(0, 0, PC_GETCID
, (caddr_t
)&pcinfo
) == -1)
467 fatalerr("%s: Can't get IA class ID, priocntl system call"
468 " failed with errno %d\n", basenm
, errno
);
469 maxupri
= ((iainfo_t
*)pcinfo
.pc_clinfo
)->ia_maxupri
;
472 * Validate the iauprilim and iaupri arguments.
474 if ((cflags
& IA_DOUPRILIM
) != 0) {
475 if (iauprilim
> maxupri
|| iauprilim
< -maxupri
)
476 fatalerr("%s: Specified user priority limit %d out of"
477 " configured range\n", basenm
, iauprilim
);
478 ADDKEYVAL(argsp
, IA_KY_UPRILIM
, iauprilim
);
481 if ((cflags
& IA_DOUPRI
) != 0) {
482 if (iaupri
> maxupri
|| iaupri
< -maxupri
)
483 fatalerr("%s: Specified user priority %d out of"
484 " configured range\n", basenm
, iaupri
);
485 ADDKEYVAL(argsp
, IA_KY_UPRI
, iaupri
);
488 if ((cflags
& IA_DOMODE
) != 0)
489 ADDKEYVAL(argsp
, IA_KY_MODE
, iamode
);
492 if (ia_priocntl(P_PID
, P_MYID
, PC_SETXPARMS
, "IA", args
) == -1)
493 fatalerr("%s: Can't reset interactive parameters\n"
494 "priocntl system call failed with errno %d\n",
497 if ((cflags
& (IA_DOUPRILIM
|IA_DOUPRI
)) == IA_DOUPRI
) {
498 if (priocntl(P_PID
, P_MYID
, PC_GETXPARMS
, "IA",
499 IA_KY_UPRILIM
, &uprilim
, 0) != -1 && iaupri
> uprilim
)
500 (void) fprintf(stderr
,
501 "%s: Specified user priority %d exceeds"
502 " limit %d; set to %d (pid %d)\n",
503 basenm
, iaupri
, uprilim
, uprilim
, (int)getpid());
506 (void) execvp(cmdargv
[0], cmdargv
);
507 fatalerr("%s: Can't execute %s, exec failed with errno %d\n",
508 basenm
, cmdargv
[0], errno
);