logo

utils-std

Collection of commonly available Unix tools git clone https://anongit.hacktivis.me/git/utils-std.git

renice.c (3344B)


  1. // utils-std: Collection of commonly available Unix tools
  2. // SPDX-FileCopyrightText: 2017 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
  3. // SPDX-License-Identifier: MPL-2.0
  4. #define _POSIX_C_SOURCE 200809L
  5. #define _XOPEN_SOURCE 700 // getpriority, setpriority
  6. #include <assert.h>
  7. #include <errno.h>
  8. #include <stdio.h> // fprintf
  9. #include <stdlib.h> // abort
  10. #include <string.h> // strerror
  11. #include <sys/resource.h> // getpriority, setpriority
  12. #include <unistd.h> // getopt, nice
  13. static int
  14. renice(int which, id_t who, int adj)
  15. {
  16. const char *which_s = NULL;
  17. switch(which)
  18. {
  19. case PRIO_PROCESS:
  20. which_s = "PRIO_PROCESS";
  21. break;
  22. case PRIO_PGRP:
  23. which_s = "PRIO_PGRP";
  24. break;
  25. case PRIO_USER:
  26. which_s = "PRIO_USER";
  27. break;
  28. default:
  29. which_s = NULL;
  30. }
  31. errno = 0;
  32. int prio = getpriority(which, who);
  33. if(errno != 0)
  34. {
  35. fprintf(stderr, "renice: error: getpriority(%s, %d): %s\n", which_s, who, strerror(errno));
  36. return -1;
  37. }
  38. prio += adj;
  39. if(setpriority(which, who, prio) != 0)
  40. {
  41. fprintf(stderr,
  42. "renice: error: setpriority(%s, %d, %d): %s\n",
  43. which_s,
  44. who,
  45. prio,
  46. strerror(errno));
  47. return -1;
  48. }
  49. return 0;
  50. }
  51. static void
  52. usage(void)
  53. {
  54. fprintf(stderr, "\
  55. Usage: renice [-p] -n adj PID...\n\
  56. renice -g -n adj PGID...\n\
  57. renice -u -n adj UID...\n\
  58. ");
  59. }
  60. int
  61. main(int argc, char *argv[])
  62. {
  63. long adj = 0;
  64. int which = PRIO_PROCESS;
  65. int c = -1;
  66. while((c = getopt(argc, argv, ":gpun:")) != -1)
  67. {
  68. switch(c)
  69. {
  70. case 'g':
  71. which = PRIO_PGRP;
  72. break;
  73. case 'p':
  74. which = PRIO_PROCESS;
  75. break;
  76. case 'u':
  77. which = PRIO_USER;
  78. break;
  79. case 'n':
  80. assert(errno == 0);
  81. char *endptr = NULL;
  82. adj = strtol(optarg, &endptr, 10);
  83. if(endptr && *endptr != 0) errno = EINVAL;
  84. if(errno != 0)
  85. {
  86. fprintf(stderr,
  87. "renice: error: Failed parsing '%s' as a number: %s\n",
  88. optarg,
  89. strerror(errno));
  90. usage();
  91. return 1;
  92. }
  93. if(adj < PRIO_MIN)
  94. {
  95. fprintf(stderr, "renice: error: '-n %ld' is lower than PRIO_MIN(%d)\n", adj, PRIO_MIN);
  96. return 1;
  97. }
  98. if(adj > PRIO_MAX)
  99. {
  100. fprintf(stderr, "renice: error: '-n %ld' is greater than PRIO_MAX(%d)\n", adj, PRIO_MAX);
  101. return 1;
  102. }
  103. if(adj == 0)
  104. {
  105. fprintf(stderr, "renice: error: '-n 0' makes no sense\n");
  106. return 1;
  107. }
  108. break;
  109. case ':':
  110. fprintf(stderr, "renice: error: Missing operand for option: '-%c'\n", optopt);
  111. usage();
  112. return 1;
  113. case '?':
  114. fprintf(stderr, "renice: error: Unrecognised option: '-%c'\n", optopt);
  115. usage();
  116. return 1;
  117. default:
  118. abort();
  119. }
  120. }
  121. argc -= optind;
  122. argv += optind;
  123. if(argc == 0)
  124. {
  125. fprintf(stderr, "renice: error: No IDs passed\n");
  126. usage();
  127. return 1;
  128. }
  129. if(adj == 0)
  130. {
  131. fprintf(stderr, "renice: error: Mandatory option '-n adj' not passed\n");
  132. usage();
  133. return 1;
  134. }
  135. for(int i = 0; i < argc; i++)
  136. {
  137. char *endptr = NULL;
  138. char *arg = argv[i];
  139. long who = strtol(arg, &endptr, 0);
  140. if(endptr && *endptr != 0) errno = EINVAL;
  141. if(errno != 0)
  142. {
  143. fprintf(stderr,
  144. "renice: error: Failed parsing argument '%s' as a number: %s\n",
  145. arg,
  146. strerror(errno));
  147. usage();
  148. return 1;
  149. }
  150. if(renice(which, who, adj) != 0) return 1;
  151. }
  152. return 0;
  153. }