├── LICENSE
├── README.md
├── bin
├── cat
├── cd
├── echo
├── false
├── head
├── nproc
├── printenv
├── pwd
├── sleep
├── tac
├── tail
├── time
├── touch
├── true
├── wc
└── yes
├── compile
└── src
├── cat.c
├── cd.c
├── echo.c
├── false.c
├── head.c
├── nproc.c
├── printenv.c
├── pwd.c
├── sleep.c
├── tac.c
├── tail.c
├── time.c
├── touch.c
├── true.c
├── wc.c
└── yes.c
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 X3ric
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ### **CoreUtils**
4 |
5 | This repository contains basic utility programs implemented in C, inspired by GNU coreutils.
6 |
7 | #### Repository Overview
8 |
9 | **src**: Contains the source code files for utility programs.
10 |
11 | **compile**: Compilation script.
12 |
13 | #### Usage
14 |
15 | **Clone the Repository:**
16 |
17 | git clone https://github.com/x3ric/coreutils
18 |
19 |
20 | **Compile the Utilities:**
21 | Use the provided `compile` script to compile the utilities.
22 |
23 | ./compile
24 |
25 |
26 | **Run the Utilities:**
27 |
28 | After compilation, execute the desired utility in the created folder `./bin/`.
29 |
30 |
31 | cat
32 | tac
33 | head
34 | tail
35 | cd
36 | echo
37 | touch
38 | false
39 | pwd
40 | sleep
41 | true
42 | nproc
43 | time
44 | wc
45 | yes
46 |
47 |
48 | **Compile and Run Shortcut:**
49 |
50 | Execute the following command in the root of the repository to compile and run a utility.
51 |
52 |
53 | ./compile <utility>
54 |
55 |
56 |
57 |

58 |
--------------------------------------------------------------------------------
/bin/cat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/x3ric/coreutils/82660d8189a7cb1de6e5ae48f2e653217306ccbe/bin/cat
--------------------------------------------------------------------------------
/bin/cd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/x3ric/coreutils/82660d8189a7cb1de6e5ae48f2e653217306ccbe/bin/cd
--------------------------------------------------------------------------------
/bin/echo:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/x3ric/coreutils/82660d8189a7cb1de6e5ae48f2e653217306ccbe/bin/echo
--------------------------------------------------------------------------------
/bin/false:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/x3ric/coreutils/82660d8189a7cb1de6e5ae48f2e653217306ccbe/bin/false
--------------------------------------------------------------------------------
/bin/head:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/x3ric/coreutils/82660d8189a7cb1de6e5ae48f2e653217306ccbe/bin/head
--------------------------------------------------------------------------------
/bin/nproc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/x3ric/coreutils/82660d8189a7cb1de6e5ae48f2e653217306ccbe/bin/nproc
--------------------------------------------------------------------------------
/bin/printenv:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/x3ric/coreutils/82660d8189a7cb1de6e5ae48f2e653217306ccbe/bin/printenv
--------------------------------------------------------------------------------
/bin/pwd:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/x3ric/coreutils/82660d8189a7cb1de6e5ae48f2e653217306ccbe/bin/pwd
--------------------------------------------------------------------------------
/bin/sleep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/x3ric/coreutils/82660d8189a7cb1de6e5ae48f2e653217306ccbe/bin/sleep
--------------------------------------------------------------------------------
/bin/tac:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/x3ric/coreutils/82660d8189a7cb1de6e5ae48f2e653217306ccbe/bin/tac
--------------------------------------------------------------------------------
/bin/tail:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/x3ric/coreutils/82660d8189a7cb1de6e5ae48f2e653217306ccbe/bin/tail
--------------------------------------------------------------------------------
/bin/time:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/x3ric/coreutils/82660d8189a7cb1de6e5ae48f2e653217306ccbe/bin/time
--------------------------------------------------------------------------------
/bin/touch:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/x3ric/coreutils/82660d8189a7cb1de6e5ae48f2e653217306ccbe/bin/touch
--------------------------------------------------------------------------------
/bin/true:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/x3ric/coreutils/82660d8189a7cb1de6e5ae48f2e653217306ccbe/bin/true
--------------------------------------------------------------------------------
/bin/wc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/x3ric/coreutils/82660d8189a7cb1de6e5ae48f2e653217306ccbe/bin/wc
--------------------------------------------------------------------------------
/bin/yes:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/x3ric/coreutils/82660d8189a7cb1de6e5ae48f2e653217306ccbe/bin/yes
--------------------------------------------------------------------------------
/compile:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 | if [[ ! -d ./bin ]]; then mkdir ./bin; fi
3 | for file in ./src/*.c; do
4 | filename=$(basename -- "$file")
5 | filename_no_ext="./bin/${filename%.*}"
6 | gcc "$file" -o "$filename_no_ext"
7 | chmod +x "$filename_no_ext"
8 | done
9 | if [[ ! -z $1 ]]; then
10 | ./bin/"$1" "${@:2}"
11 | fi
12 |
--------------------------------------------------------------------------------
/src/cat.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | int main(int argc, char *argv[]) {
6 | if (argc == 1) {
7 | return 0;
8 | }
9 | if (argc > 1 && (strcmp(argv[1], "--help") == 0)) {
10 | printf("Concatenate Files\nUsage: cat [FILE]...\n");
11 | return 0;
12 | } else {
13 | for (int i = 1; i < argc; i++) {
14 | FILE *file = fopen(argv[i], "r");
15 | if (file == NULL) {
16 | perror(argv[i]);
17 | continue;
18 | }
19 | int c;
20 | while ((c = fgetc(file)) != EOF) {
21 | putchar(c);
22 | }
23 | putchar('\n');
24 | fclose(file);
25 | }
26 | }
27 | return 0;
28 | }
29 |
--------------------------------------------------------------------------------
/src/cd.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | int main(int argc, char *argv[]) {
7 | if (argc == 1) {
8 | chdir(getenv("HOME"));
9 | } else {
10 | chdir(argv[2]);
11 | }
12 | return 0;
13 | }
14 |
--------------------------------------------------------------------------------
/src/echo.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | void escape(char *str);
6 |
7 | int main(int argc, char *argv[]) {
8 | if (argc > 1 && (strcmp(argv[1], "--help") == 0)) {
9 | printf("Echo\nUsage: echo [ARG] [TEXT]\n"
10 | "args:\n"
11 | " -e enable interpretation of backslash escapes\n"
12 | " '\\a' alert (bell)\n"
13 | " '\\b' backspace\n"
14 | " '\\c' produce no further output\n"
15 | " '\\e' escape\n"
16 | " '\\f' form feed\n"
17 | " '\\n' newline\n"
18 | " '\\r' carriage return\n"
19 | " '\\t' horizontal tab\n"
20 | " '\\v' vertical tab\n"
21 | " '\\\\' backslash\n"
22 | " '\\0NNN' octal number NNN (zero to three digits), ninth bit ignored\n"
23 | " '\\NNN' octal number NNN (one to three digits), ninth bit ignored\n"
24 | " '\\xHH' hexadecimal number HH (one or two digits)\n");
25 | return 0;
26 | } else {
27 | int shift = 0;
28 | if (argc > 1 && strcmp(argv[1], "-e") == 0) {
29 | shift++;
30 | }
31 | for (int i = shift + 1; i < argc; i++) {
32 | if(shift == 0) {
33 | if (i == argc - 1) {
34 | printf("%s\n", argv[i]);
35 | } else {
36 | printf("%s ", argv[i]);
37 | }
38 | } else {
39 | if (i == argc - 1) {
40 | escape(argv[i]);
41 | putchar('\n');
42 | } else {
43 | escape(argv[i]);
44 | putchar(' ');
45 | }
46 | }
47 | }
48 | }
49 | return 0;
50 | }
51 |
52 | void escape(char *str) {
53 | char *p = str;
54 | while (*p != '\0') {
55 | if (*p == '\\') {
56 | switch (*(++p)) {
57 | case 'a':
58 | putchar('\a');
59 | break;
60 | case 'b':
61 | putchar('\b');
62 | break;
63 | case 'c':
64 | return;
65 | case 'e':
66 | putchar('\x1B');
67 | break;
68 | case 'f':
69 | putchar('\f');
70 | break;
71 | case 'n':
72 | putchar('\n');
73 | break;
74 | case 'r':
75 | putchar('\r');
76 | break;
77 | case 't':
78 | putchar('\t');
79 | break;
80 | case 'v':
81 | putchar('\v');
82 | break;
83 | case '\\':
84 | putchar('\\');
85 | break;
86 | case '0':
87 | case '1':
88 | case '2':
89 | case '3':
90 | case '4':
91 | case '5':
92 | case '6':
93 | case '7': {
94 | char *endptr;
95 | int value = strtol(p, &endptr, 8);
96 | putchar(value);
97 | p = endptr - 1;
98 | break;
99 | }
100 | case 'x': {
101 | char *endptr;
102 | int value = strtol(++p, &endptr, 16);
103 | putchar(value);
104 | p = endptr - 1;
105 | break;
106 | }
107 | default:
108 | putchar(*p);
109 | }
110 | } else {
111 | putchar(*p);
112 | }
113 | p++;
114 | }
115 | }
--------------------------------------------------------------------------------
/src/false.c:
--------------------------------------------------------------------------------
1 | int main() {
2 | return 1;
3 | }
4 |
--------------------------------------------------------------------------------
/src/head.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | int main(int argc, char *argv[]) {
7 | if (argc > 1 && (strcmp(argv[1], "--help") == 0)) {
8 | printf("Output First Part Of Files\nUsage: head [OPTIONS] [FILE]...\n"
9 | "Options:\n"
10 | " -h, --help Display this help and exit\n"
11 | " -n, --lines NUM Output the first NUM lines\n"
12 | " -c, --bytes NUM Output the first NUM bytes\n"
13 | " -q, --quiet, --silent Never print headers giving file names\n"
14 | " -v, --verbose Always print headers giving file names\n"
15 | " -z, --zero-terminated Line delimiter is NUL, not newline\n");
16 | return 0;
17 | } else {
18 | FILE *file;
19 |
20 | int nfiles = argc;
21 | int nbytes = 0;
22 | int mlines = 10;
23 | int mbytes = 0;
24 | bool skip = false;
25 | bool bytes = false;
26 | bool quiet = false;
27 | bool verbose = false;
28 | bool zterminated = false;
29 |
30 | for (int i = 1; i < argc; i++) {
31 | if (i == 1) {
32 | nbytes = 0;
33 | }
34 |
35 | if (skip) {
36 | nfiles--;
37 | skip = false;
38 | if (bytes) {
39 | mbytes = atoi(argv[i]);
40 | } else {
41 | mlines = atoi(argv[i]);
42 | }
43 | continue;
44 | }
45 |
46 | if (strcmp(argv[i], "-n") == 0 || strcmp(argv[i], "--lines") == 0) {
47 | nfiles--;
48 | skip = true;
49 | bytes = false;
50 | continue;
51 | }
52 |
53 | if (strcmp(argv[i], "-c") == 0 || strcmp(argv[i], "--bytes") == 0) {
54 | nfiles--;
55 | skip = true;
56 | bytes = true;
57 | continue;
58 | }
59 |
60 | if (strcmp(argv[i], "-z") == 0 || strcmp(argv[i], "--zero-terminated") == 0) {
61 | zterminated = true;
62 | continue;
63 | }
64 |
65 | if (strcmp(argv[i], "-q") == 0 || strcmp(argv[i], "--quiet") == 0 || strcmp(argv[i], "--silent") == 0) {
66 | quiet = true;
67 | continue;
68 | }
69 |
70 | if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) {
71 | verbose = true;
72 | continue;
73 | }
74 |
75 | file = fopen(argv[i], "r");
76 | if (file == NULL) {
77 | perror(argv[i]);
78 | continue;
79 | }
80 |
81 | if ( ((!quiet || verbose) && (nfiles > 2)) ) {
82 | if ( zterminated ) {
83 | printf("==> %s <==\0", argv[i]);
84 | } else {
85 | printf("==> %s <==\n", argv[i]);
86 | }
87 | }
88 |
89 | int c;
90 | int cline = 0;
91 | while (cline < mlines && (c = fgetc(file)) != EOF) {
92 | if (nbytes == mbytes && mbytes != 0) {
93 | if ( zterminated ) {
94 | putchar('\0');
95 | } else {
96 | putchar('\n');
97 | }
98 | break;
99 | }
100 | nbytes++;
101 | if (c == '\n' || c == '\r' || (zterminated && c == '\0')) cline++;
102 | putchar(c);
103 | }
104 |
105 | fclose(file);
106 | }
107 | }
108 | return 0;
109 | }
110 |
--------------------------------------------------------------------------------
/src/nproc.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | int main(int argc, char *argv[]) {
7 | int opt;
8 | int ignore = 0;
9 | int nproc = 0;
10 |
11 | struct option long_options[] = {
12 | {"all", no_argument, NULL, 'a'},
13 | {"ignore", required_argument, NULL, 'i'},
14 | {"help", no_argument, NULL, 'h'},
15 | {NULL, 0, NULL, 0}
16 | };
17 |
18 | while ((opt = getopt_long(argc, argv, "", long_options, NULL)) != -1) {
19 | switch (opt) {
20 | case 'a':
21 | goto exitnproc;
22 | break;
23 | case 'i':
24 | ignore = atoi(optarg);
25 | break;
26 | case 'h':
27 | printf("Usage: nproc [OPTION]...\n"
28 | "Print the number of processing units available to the current process,\n"
29 | "which may be less than the number of online processors\n\n"
30 | " --all print the number of installed processors\n"
31 | " --ignore=N if possible, exclude N processing units\n"
32 | " --help display this help and exit\n");
33 | exit(EXIT_SUCCESS);
34 | default:
35 | fprintf(stderr, "Usage: %s [--all] [--ignore=N] [--help]\n", argv[0]);
36 | exit(EXIT_FAILURE);
37 | }
38 | }
39 |
40 | if (ignore > 0) {
41 | nproc = sysconf(_SC_NPROCESSORS_CONF) - ignore;
42 | if(nproc<=0){nproc=1;}
43 | printf("%ld\n", nproc);
44 | } else {
45 | exitnproc:
46 | nproc = sysconf(_SC_NPROCESSORS_ONLN);
47 | printf("%ld\n", nproc);
48 | }
49 |
50 | return 0;
51 | }
52 |
--------------------------------------------------------------------------------
/src/printenv.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | extern char **environ;
6 |
7 | void print_help(char *program_name) {
8 | printf("Usage: %s [-0 | --null] [VARIABLE]\n", program_name);
9 | printf("Print the values of specified environment variable or all environment variables.\n\n");
10 | printf("Options:\n");
11 | printf(" -0, --null End each output line with NUL, not newline.\n");
12 | }
13 |
14 | int main(int argc, char *argv[]) {
15 | int use_null_terminator = 0;
16 | if (argc > 1 && (strcmp(argv[1], "-0") == 0 || strcmp(argv[1], "--null") == 0)) {
17 | use_null_terminator = 1;
18 | argc--;
19 | argv++;
20 | }
21 | if (argc > 2 || (argc == 2 && (strcmp(argv[1], "--help") == 0 || strcmp(argv[1], "-h") == 0))) {
22 | print_help(argv[0]);
23 | return 0;
24 | }
25 | if (argc == 2) {
26 | char *value = getenv(argv[1]);
27 | if (value == NULL) {
28 | fprintf(stderr, "%s: %s: No such environment variable\n", argv[0], argv[1]);
29 | return 1;
30 | }
31 | printf("%s", value);
32 | if (use_null_terminator) {
33 | putchar('\0');
34 | } else {
35 | putchar('\n');
36 | }
37 | } else {
38 | char **env = environ;
39 | while (*env != NULL) {
40 | printf("%s", *env);
41 | if (use_null_terminator) {
42 | putchar('\0');
43 | } else {
44 | putchar('\n');
45 | }
46 | env++;
47 | }
48 | }
49 |
50 | return 0;
51 | }
52 |
--------------------------------------------------------------------------------
/src/pwd.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | int main(int argc, char *argv[]) {
6 | printf("%s\n", getenv("PWD"));
7 | return 0;
8 | }
9 |
--------------------------------------------------------------------------------
/src/sleep.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | int main(int argc, char *argv[]) {
7 | if (argc > 1 && (strcmp(argv[1], "--help") == 0)) {
8 | printf("Sleep\nUsage: sleep [TIME]\ntime in seconds or milliseconds. \"int or float\"\n");
9 | return 0;
10 | } else {
11 | if (argc <= 1) {
12 | return 1;
13 | }
14 | if (strchr(argv[1], '.') != NULL) {
15 | float time = atof(argv[1]);
16 | usleep(time * 1000000);
17 | } else {
18 | int time = atoi(argv[1]);
19 | sleep(time);
20 | }
21 | }
22 | return 0;
23 | }
24 |
--------------------------------------------------------------------------------
/src/tac.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 |
5 | int main(int argc, char *argv[]) {
6 | if (argc == 1) {
7 | return 0;
8 | }
9 | if (argc > 1 && (strcmp(argv[1], "--help") == 0)) {
10 | printf("Concatenate Files In Reverse\nUsage: tac [FILE]...\n");
11 | return 0;
12 | } else {
13 | FILE *file;
14 | for (int i = 1; i < argc; i++) {
15 | file = fopen(argv[i], "r");
16 | if (file == NULL) {
17 | perror(argv[i]);
18 | continue;
19 | }
20 | int c, linec = 0;
21 | while ((c = fgetc(file)) != EOF) if (c == '\n') linec++;
22 | fseek(file, 0, SEEK_SET);
23 | char **lines = malloc(linec * sizeof(char *));
24 | for (int i = 0; i < linec; i++) {
25 | char *line = NULL;
26 | size_t len = 0;
27 | getline(&line, &len, file);
28 | lines[i] = line;
29 | }
30 | for (int i = linec - 1; i >= 0; i--) {
31 | printf("%s", lines[i]);
32 | free(lines[i]);
33 | }
34 | free(lines);
35 | putchar('\n');
36 | fclose(file);
37 | }
38 | }
39 | return 0;
40 | }
41 |
--------------------------------------------------------------------------------
/src/tail.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | int main(int argc, char *argv[]) {
7 | if (argc > 1 && (strcmp(argv[1], "--help") == 0)) {
8 | printf("Output Last Part Of Files\nUsage: tail [OPTIONS] [FILE]...\n"
9 | "Options:\n"
10 | " -h, --help Display this help and exit\n"
11 | " -n, --lines NUM Output the last NUM lines\n"
12 | " -c, --bytes NUM Output the last NUM bytes\n"
13 | " -q, --quiet, --silent Never print headers giving file names\n"
14 | " -v, --verbose Always print headers giving file names\n"
15 | " -z, --zero-terminated Line delimiter is NUL, not newline\n");
16 | return 0;
17 | } else {
18 | FILE *file;
19 |
20 | int nfiles = argc;
21 | int nbytes = 0;
22 | int mlines = 10;
23 | int mbytes = 0;
24 | bool skip = false;
25 | bool bytes = false;
26 | bool quiet = false;
27 | bool verbose = false;
28 | bool zterminated = false;
29 |
30 | for (int i = 1; i < argc; i++) {
31 | if (i == 1) {
32 | nbytes = 0;
33 | }
34 |
35 | if (skip) {
36 | nfiles--;
37 | skip = false;
38 | if (bytes) {
39 | mbytes = atoi(argv[i]);
40 | } else {
41 | mlines = atoi(argv[i]);
42 | }
43 | continue;
44 | }
45 |
46 | if (strcmp(argv[i], "-n") == 0 || strcmp(argv[i], "--lines") == 0) {
47 | nfiles--;
48 | skip = true;
49 | bytes = false;
50 | continue;
51 | }
52 |
53 | if (strcmp(argv[i], "-c") == 0 || strcmp(argv[i], "--bytes") == 0) {
54 | nfiles--;
55 | skip = true;
56 | bytes = true;
57 | continue;
58 | }
59 |
60 | if (strcmp(argv[i], "-z") == 0 || strcmp(argv[i], "--zero-terminated") == 0) {
61 | zterminated = true;
62 | continue;
63 | }
64 |
65 | if (strcmp(argv[i], "-q") == 0 || strcmp(argv[i], "--quiet") == 0 || strcmp(argv[i], "--silent") == 0) {
66 | quiet = true;
67 | continue;
68 | }
69 |
70 | if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) {
71 | verbose = true;
72 | continue;
73 | }
74 |
75 | file = fopen(argv[i], "r");
76 | if (file == NULL) {
77 | perror(argv[i]);
78 | continue;
79 | }
80 |
81 | if ((!quiet || verbose) && (nfiles > 2)) {
82 | if (zterminated) {
83 | printf("==> %s <==\0", argv[i]);
84 | } else {
85 | printf("==> %s <==\n", argv[i]);
86 | }
87 | }
88 |
89 | int c, linec = 0;
90 | while ((c = fgetc(file)) != EOF) {
91 | if (nbytes == mbytes && mbytes != 0) {
92 | if ( zterminated ) {
93 | putchar('\0');
94 | } else {
95 | putchar('\n');
96 | }
97 | break;
98 | }
99 | nbytes++;
100 | if (c == '\n' || c == '\r' || (zterminated && c == '\0')) linec++;
101 | }
102 | fseek(file, 0, SEEK_SET);
103 | char **lines = malloc(linec * sizeof(char *));
104 | for (int i = 0; i < linec; i++) {
105 | char *line = NULL;
106 | size_t len = 0;
107 | getline(&line, &len, file);
108 | lines[i] = line;
109 | }
110 | for (int i = linec - 1; i == (linec - mlines); i--) {
111 | printf("%s", lines[i]);
112 | free(lines[i]);
113 | }
114 | free(lines);
115 | fclose(file);
116 | }
117 | }
118 | return 0;
119 | }
120 |
--------------------------------------------------------------------------------
/src/time.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 |
7 | void print_usage(double user_time, double sys_time, double cpu_percentage, double elapsed_time) {
8 | printf("shell %.2fs user %.2fs system %.0f%% cpu %.3f total\n", user_time, sys_time, cpu_percentage, elapsed_time);
9 | printf("children %.2fs user %.2fs system %.0f%% cpu %.3f total\n", user_time * 1.5, sys_time * 1.5, cpu_percentage, elapsed_time);
10 | }
11 |
12 | int main(int argc, char *argv[]) {
13 | struct timeval start_time, end_time;
14 | struct rusage start_usage, end_usage;
15 | getrusage(RUSAGE_SELF, &start_usage);
16 | gettimeofday(&start_time, NULL);
17 | if (argc < 2) {
18 | int sum = 0;
19 | for (int i = 0; i < 1000000000; ++i) {
20 | sum += i;
21 | }
22 | gettimeofday(&end_time, NULL);
23 | getrusage(RUSAGE_SELF, &end_usage);
24 | double elapsed_time = (end_time.tv_sec - start_time.tv_sec) + (end_time.tv_usec - start_time.tv_usec) / 1000000.0;
25 | double user_time = (end_usage.ru_utime.tv_sec - start_usage.ru_utime.tv_sec) + (end_usage.ru_utime.tv_usec - start_usage.ru_utime.tv_usec) / 1000000.0;
26 | double sys_time = (end_usage.ru_stime.tv_sec - start_usage.ru_stime.tv_sec) + (end_usage.ru_stime.tv_usec - start_usage.ru_stime.tv_usec) / 1000000.0;
27 | double cpu_percentage = ((user_time + sys_time) / elapsed_time) * 100.0;
28 | print_usage(user_time, sys_time, cpu_percentage, elapsed_time);
29 | } else {
30 | if (system(argv[1]) == -1) {
31 | perror("Failed to execute command");
32 | return 1;
33 | }
34 | gettimeofday(&end_time, NULL);
35 | getrusage(RUSAGE_SELF, &end_usage);
36 | double elapsed_time = (end_time.tv_sec - start_time.tv_sec) + (end_time.tv_usec - start_time.tv_usec) / 1000000.0;
37 | double user_time = (end_usage.ru_utime.tv_sec - start_usage.ru_utime.tv_sec) + (end_usage.ru_utime.tv_usec - start_usage.ru_utime.tv_usec) / 1000000.0;
38 | double sys_time = (end_usage.ru_stime.tv_sec - start_usage.ru_stime.tv_sec) + (end_usage.ru_stime.tv_usec - start_usage.ru_stime.tv_usec) / 1000000.0;
39 | double cpu_percentage = ((user_time + sys_time) / elapsed_time) * 100.0;
40 | printf("%s %.2fs user %.2fs system %.0f%% cpu %.3f total\n", argv[1], user_time, sys_time, cpu_percentage, elapsed_time);
41 | }
42 | return 0;
43 | }
44 |
--------------------------------------------------------------------------------
/src/touch.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include
6 | #include
7 | #include
8 | #include
9 |
10 | time_t parse_time(const char *time_str) {
11 | struct tm time_info = {0};
12 | sscanf(time_str, "%4d%2d%2d%2d%2d%2d",
13 | &time_info.tm_year, &time_info.tm_mon, &time_info.tm_mday,
14 | &time_info.tm_hour, &time_info.tm_min, &time_info.tm_sec);
15 | time_info.tm_year -= 1900;
16 | time_info.tm_mon -= 1;
17 | return mktime(&time_info);
18 | }
19 |
20 | int main(int argc, char *argv[]) {
21 | if (argc > 1 && (strcmp(argv[1], "--help") == 0)) {
22 | printf("Set Timestamp\nUsage: touch [OPTION]... FILE...\n"
23 | "Options:\n"
24 | " -a change only the access time\n"
25 | " -c, --no-create do not create any files\n"
26 | " -h, --no-dereference affect each symbolic link instead of any referenced\n"
27 | " file (useful only on systems that can change the\n"
28 | " timestamps of a symlink)\n"
29 | " -m change only the modification time\n"
30 | " -r, --reference=FILE use this file's times instead of current time\n"
31 | " -t [[CC]YY]MMDDhhmm[.ss] use specified time instead of current time,\n"
32 | " with a date-time format that differs from -d's\n"
33 | " --time=WORD specify which time to change:\n"
34 | " access time (-a): 'access', 'atime', 'use';\n"
35 | " modification time (-m): 'modify', 'mtime'\n"
36 | " --help display this help and exit\n");
37 | return 0;
38 | }
39 |
40 | bool update_access = false, update_modification = false, create_files = true, no_dereference = false;
41 | time_t custom_time = 0;
42 | const char *reference_file = NULL;
43 |
44 | for (int i = 1; i < argc; i++) {
45 | if (argv[i][0] == '-') {
46 | if (strcmp(argv[i], "-a") == 0) {
47 | update_access = true;
48 | } else if (strcmp(argv[i], "-c") == 0 || strcmp(argv[i], "--no-create") == 0) {
49 | create_files = false;
50 | } else if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--no-dereference") == 0) {
51 | no_dereference = true;
52 | } else if (strcmp(argv[i], "-m") == 0) {
53 | update_modification = true;
54 | } else if (strcmp(argv[i], "-r") == 0 || strcmp(argv[i], "--reference") == 0) {
55 | if (i + 1 < argc) {
56 | reference_file = argv[++i];
57 | } else {
58 | printf("Option '%s' requires an argument.\n", argv[i]);
59 | return 1;
60 | }
61 | } else if (strcmp(argv[i], "-t") == 0 || strcmp(argv[i], "--time") == 0) {
62 | if (i + 1 < argc) {
63 | i++;
64 | custom_time = parse_time(argv[i]);
65 | } else {
66 | printf("Option '%s' requires an argument.\n", argv[i]);
67 | return 1;
68 | }
69 | } else {
70 | printf("Unknown option '%s'.\n", argv[i]);
71 | return 1;
72 | }
73 | }
74 | }
75 |
76 | struct stat st;
77 | for (int i = 1; i < argc; i++) {
78 | if (argv[i][0] != '-') {
79 | if (strcmp(argv[i], "-") == 0) {
80 | printf("Not implemented: update timestamps of standard output.\n");
81 | } else {
82 | if (no_dereference) {
83 | if (lstat(argv[i], &st) != 0) {
84 | perror("Error getting symbolic link information");
85 | return 1;
86 | }
87 | } else {
88 | if (stat(argv[i], &st) != 0) {
89 | perror("Error getting file information");
90 | return 1;
91 | }
92 | }
93 | struct utimbuf new_times;
94 | if (reference_file != NULL) {
95 | if (stat(reference_file, &st) == 0) {
96 | new_times.actime = st.st_atime;
97 | new_times.modtime = st.st_mtime;
98 | } else {
99 | perror("Error getting reference file information");
100 | return 1;
101 | }
102 | } else if (custom_time != 0) {
103 | new_times.actime = update_access ? custom_time : st.st_atime;
104 | new_times.modtime = update_modification ? custom_time : st.st_mtime;
105 | } else {
106 | new_times.actime = update_access ? time(NULL) : st.st_atime;
107 | new_times.modtime = update_modification ? time(NULL) : st.st_mtime;
108 | }
109 | if (utime(argv[i], &new_times) != 0) {
110 | perror("Error updating timestamp");
111 | return 1;
112 | }
113 | }
114 | }
115 | }
116 | return 0;
117 | }
118 |
--------------------------------------------------------------------------------
/src/true.c:
--------------------------------------------------------------------------------
1 | int main() {
2 | return 0;
3 | }
4 |
--------------------------------------------------------------------------------
/src/wc.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 |
6 | #define MAX_LINE_LENGTH 1024
7 |
8 | int main(int argc, char *argv[]) {
9 | if (argc > 1 && (strcmp(argv[1], "--help") == 0)) {
10 | printf("Usage: wc [OPTION]... [FILE]...\n"
11 | " or: w [OPTION]... --files0-from=F\n"
12 | "Print newline, word, and byte counts for each FILE, and a total line if\n"
13 | "more than one FILE is specified. A word is a nonempty sequence of non white\n"
14 | "space delimited by white space characters or by start or end of input.\n\n"
15 | "With no FILE, or when FILE is -, read standard input.\n\n"
16 | "Options:\n"
17 | " -c, --bytes print the byte counts\n"
18 | " -m, --chars print the character counts\n"
19 | " -l, --lines print the newline counts\n"
20 | " --files0-from=F read input from the files specified by\n"
21 | " NUL-terminated names in file F;\n"
22 | " If F is - then read names from standard input\n"
23 | " -L, --max-line-length print the maximum display width\n"
24 | " -w, --words print the word counts\n"
25 | " --total=WHEN when to print a line with total counts;\n"
26 | " WHEN can be: auto, always, only, never\n");
27 | return 0;
28 | } else {
29 | int print_lines = 0, print_words = 0, print_chars = 0, print_bytes = 0, print_max_line_length = 0;
30 | int print_total = 0;
31 | char *file_name = NULL;
32 | int opt;
33 | while ((opt = getopt(argc, argv, "clmLw")) != -1) {
34 | switch (opt) {
35 | case 'c': print_bytes = 1; break;
36 | case 'm': print_chars = 1; break;
37 | case 'l': print_lines = 1; break;
38 | case 'w': print_words = 1; break;
39 | case 'L': print_max_line_length = 1; break;
40 | default:
41 | fprintf(stderr, "Usage: %s [OPTION]... [FILE]...\n", argv[0]);
42 | fprintf(stderr, "Try '%s --help' for more information.\n", argv[0]);
43 | return 1;
44 | }
45 | }
46 | if (optind < argc) {
47 | file_name = argv[optind];
48 | } else {
49 | fprintf(stderr, "Usage: %s [OPTION]... [FILE]...\n", argv[0]);
50 | return 1;
51 | }
52 | FILE *file;
53 | if (file_name != NULL && strcmp(file_name, "-") != 0) {
54 | file = fopen(file_name, "r");
55 | if (file == NULL) {
56 | fprintf(stderr, "Error: Unable to open file %s\n", file_name);
57 | return 1;
58 | }
59 | } else {
60 | file = stdin;
61 | }
62 | int total_lines = 0, total_words = 0, total_chars = 0, total_bytes = 0, max_line_length = 0;
63 | char line[MAX_LINE_LENGTH];
64 | while (fgets(line, MAX_LINE_LENGTH, file) != NULL) {
65 | int line_length = strlen(line);
66 | total_lines++;
67 | total_chars += line_length;
68 | total_bytes += line_length;
69 | if (print_max_line_length && line_length > max_line_length) {
70 | max_line_length = line_length;
71 | }
72 | char *token = strtok(line, " \t\n\r\v\f");
73 | while (token != NULL) {
74 | total_words++;
75 | token = strtok(NULL, " \t\n\r\v\f");
76 | }
77 | }
78 | if (file != stdin) {
79 | fclose(file);
80 | }
81 | if (print_total) {
82 | printf("%d %d %d %s\n", total_lines, total_words, total_chars, file_name);
83 | } else {
84 | if (print_lines == 0 && print_words == 0 && print_chars == 0 && print_bytes == 0 && print_max_line_length == 0) {
85 | print_lines = print_words = print_chars = 1;
86 | }
87 | if (print_lines) printf("%d ", total_lines - 1);
88 | if (print_words) printf("%d ", total_words);
89 | if (print_chars) printf("%d ", total_chars);
90 | if (print_bytes) printf("%d ", total_bytes);
91 | if (print_max_line_length) printf("%d ", max_line_length - 1);
92 | printf("%s\n", file_name);
93 | }
94 | }
95 | return 0;
96 | }
97 |
--------------------------------------------------------------------------------
/src/yes.c:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | int main(int argc, char *argv[]) {
5 | if(argc >= 2 && (strcmp(argv[1], "--help") == 0)) {
6 | printf("Usage: yes [STRING]\n");
7 | return 0;
8 | } else {
9 | while (1) {
10 | if (argc < 2) {
11 | printf("y\n");
12 | } else {
13 | printf("%s\n", argv[1]);
14 | }
15 | }
16 | }
17 | return 0;
18 | }
19 |
--------------------------------------------------------------------------------