PageRenderTime 28ms CodeModel.GetById 29ms RepoModel.GetById 1ms app.codeStats 0ms

/usr/src/cmd/priocntl/subr.c

https://bitbucket.org/a3217055/illumos-2
C | 729 lines | 472 code | 119 blank | 138 comment | 121 complexity | 867be0eb6eeef15dd5125227a4d7d963 MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.1, MPL-2.0-no-copyleft-exception, AGPL-3.0, BSD-3-Clause, LGPL-2.0, 0BSD, BSD-2-Clause, BSD-3-Clause-No-Nuclear-License-2014, AGPL-1.0, GPL-2.0
  1. /*
  2. * CDDL HEADER START
  3. *
  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
  7. * with the License.
  8. *
  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.
  13. *
  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]
  19. *
  20. * CDDL HEADER END
  21. */
  22. /*
  23. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  24. * Use is subject to license terms.
  25. */
  26. #pragma ident "%Z%%M% %I% %E% SMI"
  27. /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
  28. /* All Rights Reserved */
  29. #include <stdio.h>
  30. #include <string.h>
  31. #include <strings.h>
  32. #include <stdlib.h>
  33. #include <unistd.h>
  34. #include <sys/types.h>
  35. #include <limits.h>
  36. #include <dirent.h>
  37. #include <fcntl.h>
  38. #include <sys/time.h>
  39. #include <sys/procset.h>
  40. #include <sys/priocntl.h>
  41. #include <sys/task.h>
  42. #include <procfs.h>
  43. #include <project.h>
  44. #include <errno.h>
  45. #include <zone.h>
  46. #include <libcontract_priv.h>
  47. #include "priocntl.h"
  48. /*LINTLIBRARY*/
  49. /*
  50. * Utility functions for priocntl command.
  51. */
  52. static char *procdir = "/proc";
  53. /*PRINTFLIKE1*/
  54. void
  55. fatalerr(format, a1, a2, a3, a4, a5)
  56. char *format;
  57. int a1, a2, a3, a4, a5;
  58. {
  59. (void) fprintf(stderr, format, a1, a2, a3, a4, a5);
  60. exit(1);
  61. }
  62. /*
  63. * Structure defining idtypes known to the priocntl command
  64. * along with the corresponding names and a liberal guess
  65. * of the max number of procs sharing any given ID of that type.
  66. * The idtype values themselves are defined in <sys/procset.h>.
  67. */
  68. static struct idtypes {
  69. idtype_t idtype;
  70. char *idtypnm;
  71. } idtypes [] = {
  72. { P_PID, "pid" },
  73. { P_PPID, "ppid" },
  74. { P_PGID, "pgid" },
  75. { P_SID, "sid" },
  76. { P_CID, "class" },
  77. { P_UID, "uid" },
  78. { P_GID, "gid" },
  79. { P_PROJID, "projid" },
  80. { P_TASKID, "taskid" },
  81. { P_ZONEID, "zoneid" },
  82. { P_CTID, "ctid" },
  83. { P_ALL, "all" }
  84. };
  85. #define IDCNT (sizeof (idtypes) / sizeof (struct idtypes))
  86. int
  87. str2idtyp(idtypnm, idtypep)
  88. char *idtypnm;
  89. idtype_t *idtypep;
  90. {
  91. register struct idtypes *curp;
  92. register struct idtypes *endp;
  93. for (curp = idtypes, endp = &idtypes[IDCNT]; curp < endp; curp++) {
  94. if (strcmp(curp->idtypnm, idtypnm) == 0) {
  95. *idtypep = curp->idtype;
  96. return (0);
  97. }
  98. }
  99. return (-1);
  100. }
  101. int
  102. idtyp2str(idtype, idtypnm)
  103. idtype_t idtype;
  104. char *idtypnm;
  105. {
  106. register struct idtypes *curp;
  107. register struct idtypes *endp;
  108. for (curp = idtypes, endp = &idtypes[IDCNT]; curp < endp; curp++) {
  109. if (idtype == curp->idtype) {
  110. (void) strncpy(idtypnm, curp->idtypnm, PC_IDTYPNMSZ);
  111. return (0);
  112. }
  113. }
  114. return (-1);
  115. }
  116. /*
  117. * Compare two IDs for equality.
  118. */
  119. int
  120. idcompar(id1p, id2p)
  121. id_t *id1p;
  122. id_t *id2p;
  123. {
  124. if (*id1p == *id2p)
  125. return (0);
  126. else
  127. return (-1);
  128. }
  129. id_t
  130. clname2cid(clname)
  131. char *clname;
  132. {
  133. pcinfo_t pcinfo;
  134. (void) strncpy(pcinfo.pc_clname, clname, PC_CLNMSZ);
  135. if (priocntl(0, 0, PC_GETCID, (caddr_t)&pcinfo) == -1)
  136. return ((id_t)-1);
  137. return (pcinfo.pc_cid);
  138. }
  139. int
  140. getmyid(idtype, idptr)
  141. idtype_t idtype;
  142. id_t *idptr;
  143. {
  144. pcinfo_t pcinfo;
  145. switch (idtype) {
  146. case P_PID:
  147. *idptr = (id_t)getpid();
  148. break;
  149. case P_PPID:
  150. *idptr = (id_t)getppid();
  151. break;
  152. case P_PGID:
  153. *idptr = (id_t)getpgrp();
  154. break;
  155. case P_SID:
  156. *idptr = (id_t)getsid(getpid());
  157. break;
  158. case P_CID:
  159. if (priocntl(P_PID, P_MYID, PC_GETXPARMS, NULL,
  160. PC_KY_CLNAME, pcinfo.pc_clname, 0) == -1 ||
  161. priocntl(0, 0, PC_GETCID, (caddr_t)&pcinfo) == -1)
  162. return (-1);
  163. *idptr = pcinfo.pc_cid;
  164. break;
  165. case P_UID:
  166. *idptr = (id_t)getuid();
  167. break;
  168. case P_GID:
  169. *idptr = (id_t)getgid();
  170. break;
  171. case P_PROJID:
  172. *idptr = (id_t)getprojid();
  173. break;
  174. case P_TASKID:
  175. *idptr = (id_t)gettaskid();
  176. break;
  177. case P_ZONEID:
  178. *idptr = (id_t)getzoneid();
  179. break;
  180. case P_CTID: {
  181. ctid_t id = getctid();
  182. if (id == -1)
  183. return (-1);
  184. *idptr = id;
  185. break;
  186. }
  187. default:
  188. return (-1);
  189. }
  190. return (0);
  191. }
  192. int
  193. getmyidstr(idtype, idstr)
  194. idtype_t idtype;
  195. char *idstr;
  196. {
  197. char clname[PC_CLNMSZ];
  198. switch (idtype) {
  199. case P_PID:
  200. itoa((long)getpid(), idstr);
  201. break;
  202. case P_PPID:
  203. itoa((long)getppid(), idstr);
  204. break;
  205. case P_PGID:
  206. itoa((long)getpgrp(), idstr);
  207. break;
  208. case P_SID:
  209. itoa((long)getsid(getpid()), idstr);
  210. break;
  211. case P_CID:
  212. if (priocntl(P_PID, P_MYID, PC_GETXPARMS, NULL,
  213. PC_KY_CLNAME, clname, 0) == -1)
  214. return (-1);
  215. (void) strncpy(idstr, clname, PC_CLNMSZ);
  216. break;
  217. case P_UID:
  218. itoa((long)getuid(), idstr);
  219. break;
  220. case P_GID:
  221. itoa((long)getgid(), idstr);
  222. break;
  223. case P_PROJID:
  224. itoa((long)getprojid(), idstr);
  225. break;
  226. case P_TASKID:
  227. itoa((long)gettaskid(), idstr);
  228. break;
  229. case P_ZONEID:
  230. itoa((long)getzoneid(), idstr);
  231. break;
  232. case P_CTID: {
  233. id_t id;
  234. if ((id = getctid()) == -1)
  235. return (-1);
  236. itoa((long)id, idstr);
  237. break;
  238. }
  239. default:
  240. return (-1);
  241. }
  242. return (0);
  243. }
  244. /*
  245. * Look for pids with "upri > uprilim" in the set specified by idtype/id.
  246. * If upri exceeds uprilim then print a warning.
  247. */
  248. int
  249. verifyupri(idtype_t idtype, id_t id, char *clname, int key,
  250. pri_t upri, char *basenm)
  251. {
  252. psinfo_t prinfo;
  253. prcred_t prcred;
  254. DIR *dirp;
  255. struct dirent *dentp;
  256. char pname[MAXNAMLEN];
  257. char *fname;
  258. int procfd;
  259. int saverr;
  260. pri_t uprilim;
  261. int verify;
  262. int error = 0;
  263. if (idtype == P_PID) {
  264. if (priocntl(P_PID, id, PC_GETXPARMS, clname, key,
  265. &uprilim, 0) == -1)
  266. error = -1;
  267. else if (upri > uprilim)
  268. (void) fprintf(stderr,
  269. "%s: Specified user priority %d exceeds"
  270. " limit %d; set to %d (pid %d)\n",
  271. basenm, upri, uprilim, uprilim, (int)id);
  272. return (error);
  273. }
  274. /*
  275. * Look for the processes in the set specified by idtype/id.
  276. * We read the /proc/<pid>/psinfo file to get the necessary
  277. * process information.
  278. */
  279. if ((dirp = opendir(procdir)) == NULL)
  280. fatalerr("%s: Can't open PROC directory %s\n",
  281. basenm, procdir);
  282. while ((dentp = readdir(dirp)) != NULL) {
  283. if (dentp->d_name[0] == '.') /* skip . and .. */
  284. continue;
  285. (void) snprintf(pname, MAXNAMLEN, "%s/%s/",
  286. procdir, dentp->d_name);
  287. fname = pname + strlen(pname);
  288. retry:
  289. (void) strncpy(fname, "psinfo", strlen("psinfo") + 1);
  290. if ((procfd = open(pname, O_RDONLY)) < 0)
  291. continue;
  292. if (read(procfd, &prinfo, sizeof (prinfo)) != sizeof (prinfo)) {
  293. saverr = errno;
  294. (void) close(procfd);
  295. if (saverr == EAGAIN)
  296. goto retry;
  297. continue;
  298. }
  299. (void) close(procfd);
  300. if (idtype == P_UID || idtype == P_GID) {
  301. (void) strncpy(fname, "cred", strlen("cred") + 1);
  302. if ((procfd = open(pname, O_RDONLY)) < 0 ||
  303. read(procfd, &prcred, sizeof (prcred)) !=
  304. sizeof (prcred)) {
  305. saverr = errno;
  306. (void) close(procfd);
  307. if (saverr == EAGAIN)
  308. goto retry;
  309. continue;
  310. }
  311. (void) close(procfd);
  312. }
  313. if (prinfo.pr_lwp.pr_state == 0 || prinfo.pr_nlwp == 0)
  314. continue;
  315. /*
  316. * The lwp must be in the correct class.
  317. */
  318. if (strncmp(clname, prinfo.pr_lwp.pr_clname, PC_CLNMSZ) != 0)
  319. continue;
  320. verify = 0;
  321. switch (idtype) {
  322. case P_PPID:
  323. if (id == (id_t)prinfo.pr_ppid)
  324. verify++;
  325. break;
  326. case P_PGID:
  327. if (id == (id_t)prinfo.pr_pgid)
  328. verify++;
  329. break;
  330. case P_SID:
  331. if (id == (id_t)prinfo.pr_sid)
  332. verify++;
  333. break;
  334. case P_UID:
  335. if (id == (id_t)prcred.pr_euid)
  336. verify++;
  337. break;
  338. case P_GID:
  339. if (id == (id_t)prcred.pr_egid)
  340. verify++;
  341. break;
  342. case P_PROJID:
  343. if (id == (id_t)prinfo.pr_projid)
  344. verify++;
  345. break;
  346. case P_TASKID:
  347. if (id == (id_t)prinfo.pr_taskid)
  348. verify++;
  349. break;
  350. case P_ZONEID:
  351. if (id == (id_t)prinfo.pr_zoneid)
  352. verify++;
  353. break;
  354. case P_CTID:
  355. if (id == (id_t)prinfo.pr_contract)
  356. verify++;
  357. break;
  358. case P_CID:
  359. case P_ALL:
  360. verify++;
  361. break;
  362. default:
  363. fatalerr("%s: Bad idtype %d in verifyupri()\n",
  364. basenm, idtype);
  365. }
  366. if (verify) {
  367. if (priocntl(P_PID, prinfo.pr_pid, PC_GETXPARMS,
  368. clname, key, &uprilim, 0) == -1)
  369. error = -1;
  370. else if (upri > uprilim)
  371. (void) fprintf(stderr,
  372. "%s: Specified user priority %d exceeds"
  373. " limit %d; set to %d (pid %d)\n",
  374. basenm, upri, uprilim, uprilim,
  375. (int)prinfo.pr_pid);
  376. }
  377. }
  378. (void) closedir(dirp);
  379. return (error);
  380. }
  381. /*
  382. * Read a list of pids from a stream.
  383. */
  384. pid_t *
  385. read_pidlist(size_t *npidsp, FILE *filep)
  386. {
  387. size_t nitems;
  388. pid_t *pidlist = NULL;
  389. *npidsp = 0;
  390. do {
  391. if ((pidlist = (pid_t *)realloc(pidlist,
  392. (*npidsp + NPIDS) * sizeof (pid_t))) == NULL)
  393. return (NULL);
  394. nitems = fread(pidlist + *npidsp, sizeof (pid_t), NPIDS, filep);
  395. if (ferror(filep))
  396. return (NULL);
  397. *npidsp += nitems;
  398. } while (nitems == NPIDS);
  399. return (pidlist);
  400. }
  401. void
  402. free_pidlist(pid_t *pidlist)
  403. {
  404. free(pidlist);
  405. }
  406. long
  407. str2num(char *p, long min, long max)
  408. {
  409. long val;
  410. char *q;
  411. errno = 0;
  412. val = strtol(p, &q, 10);
  413. if (errno != 0 || q == p || *q != '\0' || val < min || val > max)
  414. errno = EINVAL;
  415. return (val);
  416. }
  417. /*
  418. * itoa() and reverse() taken almost verbatim from K & R Chapter 3.
  419. */
  420. static void reverse();
  421. /*
  422. * itoa(): Convert n to characters in s.
  423. */
  424. void
  425. itoa(n, s)
  426. long n;
  427. char *s;
  428. {
  429. long i, sign;
  430. if ((sign = n) < 0) /* record sign */
  431. n = -n; /* make sign positive */
  432. i = 0;
  433. do { /* generate digits in reverse order */
  434. s[i++] = n % 10 + '0'; /* get next digit */
  435. } while ((n /= 10) > 0); /* delete it */
  436. if (sign < 0)
  437. s[i++] = '-';
  438. s[i] = '\0';
  439. reverse(s);
  440. }
  441. /*
  442. * reverse(): Reverse string s in place.
  443. */
  444. static void
  445. reverse(s)
  446. char *s;
  447. {
  448. int c, i, j;
  449. for (i = 0, j = strlen(s) - 1; i < j; i++, j--) {
  450. c = s[i];
  451. s[i] = s[j];
  452. s[j] = (char)c;
  453. }
  454. }
  455. /*
  456. * The following routine was removed from libc (libc/port/gen/hrtnewres.c).
  457. * It has also been added to disadmin, so if you fix it here, you should
  458. * also probably fix it there. In the long term, this should be recoded to
  459. * not be hrt'ish.
  460. */
  461. /*
  462. * Convert interval expressed in htp->hrt_res to new_res.
  463. *
  464. * Calculate: (interval * new_res) / htp->hrt_res rounding off as
  465. * specified by round.
  466. *
  467. * Note: All args are assumed to be positive. If
  468. * the last divide results in something bigger than
  469. * a long, then -1 is returned instead.
  470. */
  471. int
  472. _hrtnewres(htp, new_res, round)
  473. register hrtimer_t *htp;
  474. register ulong_t new_res;
  475. long round;
  476. {
  477. register long interval;
  478. longlong_t dint;
  479. longlong_t dto_res;
  480. longlong_t drem;
  481. longlong_t dfrom_res;
  482. longlong_t prod;
  483. longlong_t quot;
  484. register long numerator;
  485. register long result;
  486. ulong_t modulus;
  487. ulong_t twomodulus;
  488. long temp;
  489. if (new_res > NANOSEC || htp->hrt_rem < 0)
  490. return (-1);
  491. if (htp->hrt_rem >= htp->hrt_res) {
  492. htp->hrt_secs += htp->hrt_rem / htp->hrt_res;
  493. htp->hrt_rem = htp->hrt_rem % htp->hrt_res;
  494. }
  495. interval = htp->hrt_rem;
  496. if (interval == 0) {
  497. htp->hrt_res = new_res;
  498. return (0);
  499. }
  500. /*
  501. * Try to do the calculations in single precision first
  502. * (for speed). If they overflow, use double precision.
  503. * What we want to compute is:
  504. *
  505. * (interval * new_res) / hrt->hrt_res
  506. */
  507. numerator = interval * new_res;
  508. if (numerator / new_res == interval) {
  509. /*
  510. * The above multiply didn't give overflow since
  511. * the division got back the original number. Go
  512. * ahead and compute the result.
  513. */
  514. result = numerator / htp->hrt_res;
  515. /*
  516. * For HRT_RND, compute the value of:
  517. *
  518. * (interval * new_res) % htp->hrt_res
  519. *
  520. * If it is greater than half of the htp->hrt_res,
  521. * then rounding increases the result by 1.
  522. *
  523. * For HRT_RNDUP, we increase the result by 1 if:
  524. *
  525. * result * htp->hrt_res != numerator
  526. *
  527. * because this tells us we truncated when calculating
  528. * result above.
  529. *
  530. * We also check for overflow when incrementing result
  531. * although this is extremely rare.
  532. */
  533. if (round == HRT_RND) {
  534. modulus = numerator - result * htp->hrt_res;
  535. if ((twomodulus = 2 * modulus) / 2 == modulus) {
  536. /*
  537. * No overflow (if we overflow in calculation
  538. * of twomodulus we fall through and use
  539. * double precision).
  540. */
  541. if (twomodulus >= htp->hrt_res) {
  542. temp = result + 1;
  543. if (temp - 1 == result)
  544. result++;
  545. else
  546. return (-1);
  547. }
  548. htp->hrt_res = new_res;
  549. htp->hrt_rem = result;
  550. return (0);
  551. }
  552. } else if (round == HRT_RNDUP) {
  553. if (result * htp->hrt_res != numerator) {
  554. temp = result + 1;
  555. if (temp - 1 == result)
  556. result++;
  557. else
  558. return (-1);
  559. }
  560. htp->hrt_res = new_res;
  561. htp->hrt_rem = result;
  562. return (0);
  563. } else { /* round == HRT_TRUNC */
  564. htp->hrt_res = new_res;
  565. htp->hrt_rem = result;
  566. return (0);
  567. }
  568. }
  569. /*
  570. * We would get overflow doing the calculation is
  571. * single precision so do it the slow but careful way.
  572. *
  573. * Compute the interval times the resolution we are
  574. * going to.
  575. */
  576. dint = interval;
  577. dto_res = new_res;
  578. prod = dint * dto_res;
  579. /*
  580. * For HRT_RND the result will be equal to:
  581. *
  582. * ((interval * new_res) + htp->hrt_res / 2) / htp->hrt_res
  583. *
  584. * and for HRT_RNDUP we use:
  585. *
  586. * ((interval * new_res) + htp->hrt_res - 1) / htp->hrt_res
  587. *
  588. * This is a different but equivalent way of rounding.
  589. */
  590. if (round == HRT_RND) {
  591. drem = htp->hrt_res / 2;
  592. prod = prod + drem;
  593. } else if (round == HRT_RNDUP) {
  594. drem = htp->hrt_res - 1;
  595. prod = prod + drem;
  596. }
  597. dfrom_res = htp->hrt_res;
  598. quot = prod / dfrom_res;
  599. /*
  600. * If the quotient won't fit in a long, then we have
  601. * overflow. Otherwise, return the result.
  602. */
  603. if (quot > UINT_MAX) {
  604. return (-1);
  605. } else {
  606. htp->hrt_res = new_res;
  607. htp->hrt_rem = (int)quot;
  608. return (0);
  609. }
  610. }