logo

utils-std

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

nice.c (2370B)


  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 // nice() is in XSI
  6. #include "../config.h"
  7. #include "../libutils/getopt_nolong.h"
  8. #include <assert.h>
  9. #include <errno.h>
  10. #include <stdio.h> // fprintf
  11. #include <stdlib.h> // abort
  12. #include <string.h> // strerror
  13. #include <unistd.h> // getopt, nice
  14. #ifdef HAS_GETOPT_LONG
  15. #include <getopt.h>
  16. #endif
  17. const char *argv0 = "nice";
  18. static void
  19. usage(void)
  20. {
  21. fprintf(stderr, "Usage: nice [-n increment] command [argument ...]\n");
  22. }
  23. int
  24. main(int argc, char *argv[])
  25. {
  26. long incr = 0;
  27. #ifdef HAS_GETOPT_LONG
  28. // Strictly for GNUisms compatibility so no long-only options
  29. // clang-format off
  30. static struct option opts[] = {
  31. {"adjustment", required_argument, NULL, 'n'},
  32. {0, 0, 0, 0},
  33. };
  34. // clang-format on
  35. // Need + as first character to get POSIX-style option parsing
  36. for(int c = -1; (c = getopt_long(argc, argv, "+:n:", opts, NULL)) != -1;)
  37. #else
  38. for(int c = -1; (c = getopt_nolong(argc, argv, ":n:")) != -1;)
  39. #endif
  40. {
  41. char *endptr = NULL;
  42. switch(c)
  43. {
  44. case 'n':
  45. incr = strtol(optarg, &endptr, 10);
  46. if(endptr && *endptr != 0) errno = EINVAL;
  47. if(errno != 0)
  48. {
  49. fprintf(stderr,
  50. "%s: error: Failed parsing '%s' as a number: %s\n",
  51. argv0,
  52. optarg,
  53. strerror(errno));
  54. usage();
  55. return 125;
  56. }
  57. break;
  58. case ':':
  59. fprintf(stderr, "%s: error: Missing operand for option: '-%c'\n", argv0, optopt);
  60. usage();
  61. return 125;
  62. case '?':
  63. GETOPT_UNKNOWN_OPT
  64. usage();
  65. return 125;
  66. default:
  67. abort();
  68. }
  69. }
  70. argc -= optind;
  71. argv += optind;
  72. if(argc == 0) return 0;
  73. errno = 0;
  74. if(nice((int)incr) == -1)
  75. {
  76. switch(errno)
  77. {
  78. case 0:
  79. break;
  80. case EPERM:
  81. fprintf(
  82. stderr, "%s: warning: Failed setting nice to %ld: %s\n", argv0, incr, strerror(errno));
  83. errno = 0;
  84. break;
  85. default:
  86. fprintf(stderr, "%s: error: Failed setting nice to %ld: %s\n", argv0, incr, strerror(errno));
  87. return 125;
  88. }
  89. }
  90. assert(argv[0]);
  91. if(execvp(argv[0], argv) < 0)
  92. {
  93. fprintf(stderr, "%s: error: Failed executing '%s': %s\n", argv0, argv[0], strerror(errno));
  94. return (errno == ENOENT) ? 127 : 126;
  95. }
  96. abort();
  97. }