logo

utils

~/.local/bin tools and git-hooks git clone https://hacktivis.me/git/utils.git

time.c (2117B)


  1. // Collection of Unix tools, comparable to coreutils
  2. // SPDX-FileCopyrightText: 2017-2022 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
  3. // SPDX-License-Identifier: MPL-2.0
  4. #define _POSIX_C_SOURCE 200809L
  5. #include <errno.h> // errno
  6. #include <stdio.h> // perror, fprintf
  7. #include <stdlib.h> // abort
  8. #include <sys/times.h> // times
  9. #include <sys/wait.h> // waitpid
  10. #include <unistd.h> // sysconf, fork, execvp, getopt
  11. void
  12. usage()
  13. {
  14. fprintf(stderr, "Usage: time command [argument ...]\n");
  15. }
  16. int
  17. main(int argc, char *argv[])
  18. {
  19. struct tms tms;
  20. int ret = 0;
  21. if(argc <= 1)
  22. {
  23. usage();
  24. return 0;
  25. }
  26. int c = -1;
  27. while((c = getopt(argc, argv, ":p")) != -1)
  28. {
  29. switch(c)
  30. {
  31. case 'p': // POSIX format (default)
  32. break;
  33. case ':':
  34. fprintf(stderr, "time: Error: Missing operand for option: '-%c'\n", optopt);
  35. usage();
  36. return 1;
  37. case '?':
  38. fprintf(stderr, "time: Error: Unrecognised option: '-%c'\n", optopt);
  39. usage();
  40. return 1;
  41. }
  42. }
  43. argc -= optind;
  44. argv += optind;
  45. (void)argc;
  46. long ticks = sysconf(_SC_CLK_TCK);
  47. if(ticks <= 0)
  48. {
  49. perror("time: sysconf(_SC_CLK_TCK)");
  50. return 1;
  51. }
  52. clock_t t0 = times(&tms);
  53. if(t0 == (clock_t)-1)
  54. {
  55. perror("time: times");
  56. return 1;
  57. }
  58. // Note: posix_spawnp seems to lack enough error information
  59. pid_t pid = fork();
  60. switch(pid)
  61. {
  62. case -1:
  63. perror("time: fork");
  64. return 1;
  65. case 0:
  66. /* flawfinder: ignore. No restrictions on commands is intended */
  67. execvp(argv[0], argv);
  68. ret = 126 + (errno == ENOENT);
  69. perror("time: execvp");
  70. return ret;
  71. default:
  72. break;
  73. }
  74. int status = 0;
  75. waitpid(pid, &status, 0);
  76. int t1 = times(&tms);
  77. if(t1 == (clock_t)-1)
  78. {
  79. perror("time: times");
  80. return 1;
  81. }
  82. if(WIFSIGNALED(status))
  83. {
  84. fprintf(stderr, "time: Command terminated by signal %d\n", WTERMSIG(status));
  85. ret = 128 + WTERMSIG(status);
  86. }
  87. fprintf(stderr,
  88. "real %f\nuser %f\nsys %f\n",
  89. (t1 - t0) / (double)ticks,
  90. tms.tms_cutime / (double)ticks,
  91. tms.tms_cstime / (double)ticks);
  92. if(WIFEXITED(status))
  93. {
  94. ret = WEXITSTATUS(status);
  95. }
  96. return ret;
  97. }