time.c (2117B)
- // Collection of Unix tools, comparable to coreutils
- // SPDX-FileCopyrightText: 2017-2022 Haelwenn (lanodan) Monnier <contact+utils@hacktivis.me>
- // SPDX-License-Identifier: MPL-2.0
- #define _POSIX_C_SOURCE 200809L
- #include <errno.h> // errno
- #include <stdio.h> // perror, fprintf
- #include <stdlib.h> // abort
- #include <sys/times.h> // times
- #include <sys/wait.h> // waitpid
- #include <unistd.h> // sysconf, fork, execvp, getopt
- void
- usage()
- {
- fprintf(stderr, "Usage: time command [argument ...]\n");
- }
- int
- main(int argc, char *argv[])
- {
- struct tms tms;
- int ret = 0;
- if(argc <= 1)
- {
- usage();
- return 0;
- }
- int c = -1;
- while((c = getopt(argc, argv, ":p")) != -1)
- {
- switch(c)
- {
- case 'p': // POSIX format (default)
- break;
- case ':':
- fprintf(stderr, "time: Error: Missing operand for option: '-%c'\n", optopt);
- usage();
- return 1;
- case '?':
- fprintf(stderr, "time: Error: Unrecognised option: '-%c'\n", optopt);
- usage();
- return 1;
- }
- }
- argc -= optind;
- argv += optind;
- (void)argc;
- long ticks = sysconf(_SC_CLK_TCK);
- if(ticks <= 0)
- {
- perror("time: sysconf(_SC_CLK_TCK)");
- return 1;
- }
- clock_t t0 = times(&tms);
- if(t0 == (clock_t)-1)
- {
- perror("time: times");
- return 1;
- }
- // Note: posix_spawnp seems to lack enough error information
- pid_t pid = fork();
- switch(pid)
- {
- case -1:
- perror("time: fork");
- return 1;
- case 0:
- /* flawfinder: ignore. No restrictions on commands is intended */
- execvp(argv[0], argv);
- ret = 126 + (errno == ENOENT);
- perror("time: execvp");
- return ret;
- default:
- break;
- }
- int status = 0;
- waitpid(pid, &status, 0);
- int t1 = times(&tms);
- if(t1 == (clock_t)-1)
- {
- perror("time: times");
- return 1;
- }
- if(WIFSIGNALED(status))
- {
- fprintf(stderr, "time: Command terminated by signal %d\n", WTERMSIG(status));
- ret = 128 + WTERMSIG(status);
- }
- fprintf(stderr,
- "real %f\nuser %f\nsys %f\n",
- (t1 - t0) / (double)ticks,
- tms.tms_cutime / (double)ticks,
- tms.tms_cstime / (double)ticks);
- if(WIFEXITED(status))
- {
- ret = WEXITSTATUS(status);
- }
- return ret;
- }