renice.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * renice implementation for busybox
  4. *
  5. * Copyright (C) 2005 Manuel Novoa III <mjn3@codepoet.org>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. *
  21. */
  22. /* Notes:
  23. * Setting an absolute priority was obsoleted in SUSv2 and removed
  24. * in SUSv3. However, the common linux version of renice does
  25. * absolute and not relative. So we'll continue supporting absolute,
  26. * although the stdout logging has been removed since both SUSv2 and
  27. * SUSv3 specify that stdout isn't used.
  28. *
  29. * This version is lenient in that it doesn't require any IDs. The
  30. * options -p, -g, and -u are treated as mode switches for the
  31. * following IDs (if any). Multiple switches are allowed.
  32. */
  33. #include <stdio.h>
  34. #include <stdlib.h>
  35. #include <string.h>
  36. #include <limits.h>
  37. #include <errno.h>
  38. #include <unistd.h>
  39. #include <sys/time.h>
  40. #include <sys/resource.h>
  41. #include "busybox.h"
  42. #if (PRIO_PROCESS < CHAR_MIN) || (PRIO_PROCESS > CHAR_MAX)
  43. #error Assumption violated : PRIO_PROCESS value
  44. #endif
  45. #if (PRIO_PGRP < CHAR_MIN) || (PRIO_PGRP > CHAR_MAX)
  46. #error Assumption violated : PRIO_PGRP value
  47. #endif
  48. #if (PRIO_USER < CHAR_MIN) || (PRIO_USER > CHAR_MAX)
  49. #error Assumption violated : PRIO_USER value
  50. #endif
  51. static inline int int_add_no_wrap(int a, int b)
  52. {
  53. int s = a + b;
  54. if (b < 0) {
  55. if (s > a) s = INT_MIN;
  56. } else {
  57. if (s < a) s = INT_MAX;
  58. }
  59. return s;
  60. }
  61. int renice_main(int argc, char **argv)
  62. {
  63. static const char Xetpriority_msg[] = "%d : %cetpriority";
  64. int retval = EXIT_SUCCESS;
  65. int which = PRIO_PROCESS; /* Default 'which' value. */
  66. int use_relative = 0;
  67. int adjustment, new_priority;
  68. id_t who;
  69. ++argv;
  70. /* Check if we are using a relative adjustment. */
  71. if (argv[0] && (argv[0][0] == '-') && (argv[0][1] == 'n') && !argv[0][2]) {
  72. use_relative = 1;
  73. ++argv;
  74. }
  75. if (!*argv) { /* No args? Then show usage. */
  76. bb_show_usage();
  77. }
  78. /* Get the priority adjustment (absolute or relative). */
  79. adjustment = bb_xgetlarg(*argv, 10, INT_MIN, INT_MAX);
  80. while (*++argv) {
  81. /* Check for a mode switch. */
  82. if ((argv[0][0] == '-') && argv[0][1] && !argv[0][2]) {
  83. static const char opts[]
  84. = { 'p', 'g', 'u', 0, PRIO_PROCESS, PRIO_PGRP, PRIO_USER };
  85. const char *p;
  86. if ((p = strchr(opts, argv[0][1]))) {
  87. which = p[4];
  88. continue;
  89. }
  90. }
  91. /* Process an ID arg. */
  92. if (which == PRIO_USER) {
  93. struct passwd *p;
  94. if (!(p = getpwnam(*argv))) {
  95. bb_error_msg("unknown user: %s", *argv);
  96. goto HAD_ERROR;
  97. }
  98. who = p->pw_uid;
  99. } else {
  100. char *e;
  101. errno = 0;
  102. who = strtoul(*argv, &e, 10);
  103. if (*e || (*argv == e) || errno) {
  104. bb_error_msg("bad value: %s", *argv);
  105. goto HAD_ERROR;
  106. }
  107. }
  108. /* Get priority to use, and set it. */
  109. if (use_relative) {
  110. int old_priority;
  111. errno = 0; /* Needed for getpriority error detection. */
  112. old_priority = getpriority(which, who);
  113. if (errno) {
  114. bb_perror_msg(Xetpriority_msg, who, 'g');
  115. goto HAD_ERROR;
  116. }
  117. new_priority = int_add_no_wrap(old_priority, adjustment);
  118. } else {
  119. new_priority = adjustment;
  120. }
  121. if (setpriority(which, who, new_priority) == 0) {
  122. continue;
  123. }
  124. bb_perror_msg(Xetpriority_msg, who, 's');
  125. HAD_ERROR:
  126. retval = EXIT_FAILURE;
  127. }
  128. /* No need to check for errors outputing to stderr since, if it
  129. * was used, the HAD_ERROR label was reached and retval was set. */
  130. return retval;
  131. }