├── Makefile ├── .clang-format ├── .vscode ├── launch.json ├── settings.json └── tasks.json ├── .gitignore ├── dbf-coreutils.c ├── system.h ├── dbf-yes.c ├── README.md ├── dbf-echo.c └── dbf-cat.c /Makefile: -------------------------------------------------------------------------------- 1 | PROGRAM = dbf-coreutils dbf-yes dbf-echo dbf-cat 2 | 3 | all: $(PROGRAM) 4 | 5 | %: %.c 6 | gcc -g -O0 $< -o bin/$@ 7 | 8 | test: 9 | ls bin 10 | 11 | clean: 12 | rm -rf bin/dbf* 13 | -------------------------------------------------------------------------------- /.clang-format: -------------------------------------------------------------------------------- 1 | BreakBeforeBraces: Custom 2 | BraceWrapping: 3 | AfterEnum: false 4 | AfterStruct: false 5 | SplitEmptyFunction: false 6 | AfterControlStatement: Never 7 | AllowShortCaseLabelsOnASingleLine: true 8 | SortIncludesOptions: Never 9 | TabWidth: 4 10 | IndentWidth: 4 11 | IndentCaseLabels: true -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.2.0", 3 | "configurations": [ 4 | { 5 | "type": "cppdbg", 6 | "request": "launch", 7 | "name": "GDB", 8 | "preLaunchTask": "make", 9 | "program": "${workspaceFolder}/bin/dbf-cat", 10 | "cwd": "${workspaceFolder}", 11 | "args": ["dbf-cat.c", "-n"] 12 | } 13 | ] 14 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "*.gmk": "makefile", 4 | "*.s": "nasm", 5 | "cstdlib": "c", 6 | "getopt.h": "c", 7 | "stdio.h": "c", 8 | "stdlib.h": "c", 9 | "system.h": "c", 10 | "unistd.h": "c", 11 | "ioctl.h": "c", 12 | "ioctls.h": "c", 13 | "ttydefaults.h": "c", 14 | "ioctl-types.h": "c", 15 | "fcntl.h": "c", 16 | "fcntl-linux.h": "c" 17 | } 18 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | bin 2 | # Prerequisites 3 | *.d 4 | 5 | # Object files 6 | *.o 7 | *.ko 8 | *.obj 9 | *.elf 10 | 11 | # Linker output 12 | *.ilk 13 | *.map 14 | *.exp 15 | 16 | # Precompiled Headers 17 | *.gch 18 | *.pch 19 | 20 | # Libraries 21 | *.lib 22 | *.a 23 | *.la 24 | *.lo 25 | 26 | # Shared objects (inc. Windows DLLs) 27 | *.dll 28 | *.so 29 | *.so.* 30 | *.dylib 31 | 32 | # Executables 33 | *.exe 34 | *.out 35 | *.app 36 | *.i*86 37 | *.x86_64 38 | *.hex 39 | 40 | # Debug files 41 | *.dSYM/ 42 | *.su 43 | *.idb 44 | *.pdb 45 | 46 | # Kernel Module Compile Results 47 | *.mod* 48 | *.cmd 49 | .tmp_versions/ 50 | modules.order 51 | Module.symvers 52 | Mkfile.old 53 | dkms.conf 54 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | "tasks": [ 3 | { 4 | "type": "cppbuild", 5 | "label": "C/C++: gcc build active file", 6 | "command": "/usr/bin/gcc", 7 | "args": [ 8 | "-fdiagnostics-color=always", 9 | "-g", 10 | "${file}", 11 | "-o", 12 | "${fileDirname}/${fileBasenameNoExtension}" 13 | ], 14 | "options": { 15 | "cwd": "${fileDirname}" 16 | }, 17 | "problemMatcher": [ 18 | "$gcc" 19 | ], 20 | "group": { 21 | "kind": "build", 22 | "isDefault": true 23 | }, 24 | "detail": "Task generated by Debugger." 25 | }, 26 | { 27 | "label": "make", 28 | "type": "shell", 29 | "command": "make", 30 | } 31 | ], 32 | "version": "2.0.0" 33 | } -------------------------------------------------------------------------------- /dbf-coreutils.c: -------------------------------------------------------------------------------- 1 | #include "system.h" 2 | #include 3 | 4 | #define PROGRAM_NAME "dbf-coreutils" 5 | 6 | void usage () { 7 | printf("Usage: %s\n", PROGRAM_NAME); 8 | puts("Template program only help or version."); 9 | puts(""); 10 | 11 | puts(HELP_OPTION_DESCRIPTION); 12 | puts(VERSION_OPTION_DESCRIPTION); 13 | print_more_info(PROGRAM_NAME); 14 | } 15 | 16 | static struct option long_options[] = {{GETOPT_HELP_OPTION_DECL}, 17 | {GETOPT_VERSION_OPTION_DECL}, 18 | {0, 0, 0, 0}}; 19 | 20 | int main(int argc, char **argv) { 21 | int optc; 22 | 23 | while ((optc = getopt_long(argc, argv, "", long_options, NULL)) != -1) { 24 | int a = optind; 25 | switch (optc) { 26 | case_GETOPT_HELP_CHAR; 27 | case_GETOPT_VERSION_CHAR(PROGRAM_NAME); 28 | default: print_try_help(PROGRAM_NAME); 29 | } 30 | } 31 | 32 | exit(EXIT_SUCCESS); 33 | } 34 | -------------------------------------------------------------------------------- /system.h: -------------------------------------------------------------------------------- 1 | #include /* for printf */ 2 | #include /* for exit */ 3 | #include /* for CHAR_MIN */ 4 | #include /* for bool */ 5 | #include /* for sleep */ 6 | #include /* for stpcpy */ 7 | 8 | #define min(h, i) ((h) < (i) ? (h) : (i)) 9 | #define max(h, i) ((h) > (i) ? (h) : (i)) 10 | 11 | enum { 12 | GETOPT_HELP_CHAR = (CHAR_MIN - 2), 13 | GETOPT_VERSION_CHAR = (CHAR_MIN - 3) 14 | }; 15 | 16 | #define case_GETOPT_HELP_CHAR \ 17 | case GETOPT_HELP_CHAR: usage(); break; 18 | 19 | #define case_GETOPT_VERSION_CHAR(Program_name) \ 20 | case GETOPT_VERSION_CHAR: \ 21 | printf("%s (dibingfa coreutils) 1.0\n", Program_name); \ 22 | puts("Thanks GNU coreutils Written by Joseph Arceneaux, David MacKenzie, and Michael Stone."); \ 23 | exit (EXIT_SUCCESS); 24 | 25 | #define HELP_OPTION_DESCRIPTION \ 26 | " --help display this help and exit" 27 | #define VERSION_OPTION_DESCRIPTION \ 28 | " --version output version information and exit" 29 | 30 | #define GETOPT_HELP_OPTION_DECL \ 31 | "help", no_argument, NULL, GETOPT_HELP_CHAR 32 | #define GETOPT_VERSION_OPTION_DECL \ 33 | "version", no_argument, NULL, GETOPT_VERSION_CHAR 34 | 35 | static inline void print_try_help(char * program_name) { 36 | fprintf (stderr, "Try '%s --help' for more information.\n", program_name); 37 | exit (EXIT_FAILURE); 38 | } 39 | 40 | static inline void print_more_info(char * program_name) { 41 | printf("\ncoreutils by dibingfa program:%s\n", program_name); 42 | puts("github: "); 43 | puts("wechat: dibingfa"); 44 | exit (EXIT_FAILURE); 45 | } 46 | -------------------------------------------------------------------------------- /dbf-yes.c: -------------------------------------------------------------------------------- 1 | #include "system.h" 2 | #include 3 | 4 | #define PROGRAM_NAME "dbf-yes" 5 | 6 | void usage() { 7 | printf("Usage: %s [SHORT-OPTION]... [STRING]...\n", PROGRAM_NAME); 8 | puts("Repeatedly output a line with all specified STRING(s), or 'y'."); 9 | puts(""); 10 | puts(" -n, --num show line number"); 11 | puts(" -s, --sleep=NUM sleep NUM microsecond between"); 12 | puts(HELP_OPTION_DESCRIPTION); 13 | puts(VERSION_OPTION_DESCRIPTION); 14 | print_more_info(PROGRAM_NAME); 15 | exit(EXIT_SUCCESS); 16 | } 17 | 18 | static struct option long_options[] = {{"num", no_argument, 0, 'n'}, 19 | {"sleep", required_argument, 0, 's'}, 20 | {GETOPT_HELP_OPTION_DECL}, 21 | {GETOPT_VERSION_OPTION_DECL}, 22 | {0, 0, 0, 0}}; 23 | 24 | int main(int argc, char **argv) { 25 | int optc; 26 | bool show_num = false; 27 | int sleep_microsecond = 0; 28 | 29 | while ((optc = getopt_long(argc, argv, "ns:", long_options, NULL)) != -1) { 30 | int a = optind; 31 | switch (optc) { 32 | case 'n': show_num = true; break; 33 | case 's': 34 | sleep_microsecond = atoi(optarg); 35 | break; 36 | case_GETOPT_HELP_CHAR; 37 | case_GETOPT_VERSION_CHAR(PROGRAM_NAME); 38 | default: print_try_help(PROGRAM_NAME); 39 | } 40 | } 41 | 42 | int num = 0; 43 | 44 | if (argc <= optind) { 45 | optind = argc; 46 | argv[argc++] = "y"; 47 | } 48 | 49 | while (1) { 50 | int i; 51 | for (i = optind; i < argc; i++) { 52 | if (show_num) { 53 | printf("%d ", num++); 54 | } 55 | fputs(argv[i], stdout); 56 | putchar(i == argc - 1 ? '\n' : ' '); 57 | } 58 | usleep(sleep_microsecond); 59 | } 60 | 61 | return EXIT_SUCCESS; 62 | } 63 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # dibingfa-coreutils 2 | coreutils by dibingfa 3 | 4 | gnu coreutils: https://github.com/coreutils/coreutils 5 | 6 | man 3 getopt: https://linux.die.net/man/3/getopt 7 | 8 | ## 进度表 9 | 10 | - [ ] basename 11 | - [ ] cat 12 | - [ ] chcon 13 | - [ ] chgrp 14 | - [ ] chmod 15 | - [ ] chown 16 | - [ ] chroot 17 | - [ ] cksum 18 | - [ ] comm 19 | - [ ] cp 20 | - [ ] csplit 21 | - [ ] cut 22 | - [ ] date 23 | - [ ] dd 24 | - [ ] df 25 | - [ ] dir 26 | - [ ] dircolors 27 | - [ ] dirname 28 | - [ ] du 29 | - [x] **echo**: -r -b -g etc for red blue green to print String 30 | - [ ] env 31 | - [ ] expand 32 | - [ ] expr 33 | - [ ] factor 34 | - [ ] false 35 | - [ ] fmt 36 | - [ ] fold 37 | - [ ] getlimits 38 | - [ ] ginstall 39 | - [ ] groups 40 | - [ ] head 41 | - [ ] hostid 42 | - [ ] id 43 | - [ ] join 44 | - [ ] kill 45 | - [ ] link 46 | - [ ] ln 47 | - [ ] local.mk 48 | - [ ] logname 49 | - [ ] ls 50 | - [ ] make-prime-list 51 | - [ ] md5sum 52 | - [ ] mkdir 53 | - [ ] mkfifo 54 | - [ ] mknod 55 | - [ ] mktemp 56 | - [ ] mv 57 | - [ ] nice 58 | - [ ] nl 59 | - [ ] nohup 60 | - [ ] nproc 61 | - [ ] numfmt 62 | - [ ] od 63 | - [ ] paste 64 | - [ ] pathchk 65 | - [ ] pinky 66 | - [ ] pr 67 | - [ ] printenv 68 | - [ ] printf 69 | - [ ] ptx 70 | - [ ] pwd 71 | - [ ] readlink 72 | - [ ] realpath 73 | - [ ] rm 74 | - [ ] rmdir 75 | - [ ] runcon 76 | - [ ] seq 77 | - [ ] sha1sum 78 | - [ ] sha224sum 79 | - [ ] sha256sum 80 | - [ ] sha384sum 81 | - [ ] sha512sum 82 | - [ ] shred 83 | - [ ] shuf 84 | - [ ] sleep 85 | - [ ] sort 86 | - [ ] split 87 | - [ ] stat 88 | - [ ] stdbuf 89 | - [ ] stty 90 | - [ ] sum 91 | - [ ] sync 92 | - [ ] tac 93 | - [ ] tail 94 | - [ ] tee 95 | - [ ] test 96 | - [ ] timeout 97 | - [ ] touch 98 | - [ ] tr 99 | - [ ] true 100 | - [ ] truncate 101 | - [ ] tsort 102 | - [ ] tty 103 | - [ ] uname 104 | - [ ] unexpand 105 | - [ ] uniq 106 | - [ ] unlink 107 | - [ ] uptime 108 | - [ ] users 109 | - [ ] vdir 110 | - [ ] wc 111 | - [ ] who 112 | - [ ] whoami 113 | - [x] **yes**: -n(show line number)-s(sleep NUM seconds between) 114 | 115 | ## coreutils 编译 116 | 117 | 第一步:ubuntu 16.04 118 | 119 | 第二步 120 | ``` 121 | ./bootstrap 122 | ./configure FORCE_UNSAFE_CONFIGURE=1 --disable-gcc-warnings 123 | ``` 124 | 125 | 第三步:修改 Makefile 126 | ``` 127 | CFLAGS = -g -O0 128 | ``` 129 | 130 | 第四步 131 | ``` 132 | make 133 | ``` 134 | 135 | 第五步:VS Code 配置 launcher.json 136 | ``` 137 | { 138 | "version": "0.2.0", 139 | "configurations": [ 140 | 141 | { 142 | "type": "cppdbg", 143 | "request": "launch", 144 | "name": "GDB", 145 | "program": "${workspaceFolder}/src/echo", 146 | "cwd": "${workspaceFolder}", 147 | "args": ["hello"] 148 | } 149 | ] 150 | } 151 | ``` 152 | 153 | 第六步:点击 debug 154 | 155 | ![image](https://user-images.githubusercontent.com/25787738/212536995-804b4534-6478-4e66-9965-ce147ddab552.png) 156 | -------------------------------------------------------------------------------- /dbf-echo.c: -------------------------------------------------------------------------------- 1 | #include "system.h" 2 | #include 3 | 4 | #define PROGRAM_NAME "dbf-echo" 5 | 6 | void usage() { 7 | printf("Usage: %s [SHORT-OPTION]... [STRING]...\n", PROGRAM_NAME); 8 | puts("Echo the STRING(s) to standard output."); 9 | puts(""); 10 | puts(" -r, --red print red STRING(s)"); 11 | puts(" -g, --greed print greed STRING(s)"); 12 | puts(" -y, --yellow print yellow STRING(s)"); 13 | puts(" -b, --blue print blue STRING(s)"); 14 | puts(" -w, --white print white STRING(s)"); 15 | puts(" -a, --all print all colors STRING(s)"); 16 | puts(HELP_OPTION_DESCRIPTION); 17 | puts(VERSION_OPTION_DESCRIPTION); 18 | print_more_info(PROGRAM_NAME); 19 | exit(EXIT_SUCCESS); 20 | } 21 | 22 | static struct option long_options[] = {{"red", no_argument, 0, 'r'}, 23 | {"greed", no_argument, 0, 'g'}, 24 | {"yellow", no_argument, 0, 'y'}, 25 | {"blue", no_argument, 0, 'b'}, 26 | {"white", no_argument, 0, 'w'}, 27 | {"all", no_argument, 0, 'a'}, 28 | {GETOPT_HELP_OPTION_DECL}, 29 | {GETOPT_VERSION_OPTION_DECL}, 30 | {0, 0, 0, 0}}; 31 | 32 | // Colors and formatting 33 | // https://misc.flogisoft.com/bash/tip_colors_and_formatting 34 | int main(int argc, char **argv) { 35 | int optc; 36 | char *str_template = "%s"; 37 | bool print_all = false; 38 | 39 | while ((optc = getopt_long(argc, argv, "rgybwa", long_options, NULL)) != -1) { 40 | int a = optind; 41 | switch (optc) { 42 | case 'r': str_template = "\033[1;31m%s\033[0m"; break; 43 | case 'g': str_template = "\033[1;32m%s\033[0m"; break; 44 | case 'y': str_template = "\033[1;33m%s\033[0m"; break; 45 | case 'b': str_template = "\033[1;34m%s\033[0m"; break; 46 | case 'w': str_template = "\033[1;35m%s\033[0m"; break; 47 | case 'a': print_all = true; break; 48 | case_GETOPT_HELP_CHAR; 49 | case_GETOPT_VERSION_CHAR(PROGRAM_NAME); 50 | default: print_try_help(PROGRAM_NAME); 51 | } 52 | } 53 | 54 | int i, j; 55 | 56 | if (print_all) { 57 | for (i = 0; i < 10; i++) { 58 | for (j = optind; j < argc; j++) { 59 | printf("3%d \033[1;3%dm%s\033[0m", i, i, argv[j]); 60 | if (argc > i) 61 | putchar(' '); 62 | } 63 | putchar('\n'); 64 | } 65 | return EXIT_SUCCESS; 66 | } 67 | 68 | 69 | for (i = optind; i < argc; i++) { 70 | printf(str_template, argv[i]); 71 | if (argc > i) 72 | putchar(' '); 73 | } 74 | putchar('\n'); 75 | 76 | return EXIT_SUCCESS; 77 | } 78 | -------------------------------------------------------------------------------- /dbf-cat.c: -------------------------------------------------------------------------------- 1 | #include "system.h" 2 | #include 3 | #include 4 | 5 | #define PROGRAM_NAME "dbf-cat" 6 | 7 | #define LINE_COUNTER_BUF_LEN 20 8 | static char line_buf[LINE_COUNTER_BUF_LEN] = { 9 | ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', 10 | ' ', ' ', ' ', ' ', ' ', ' ', ' ', '0', '\t', '\0'}; 11 | 12 | /* Position in `line_buf' where printing starts. This will not change 13 | unless the number of lines is larger than 999999. */ 14 | static char *line_num_print = line_buf + LINE_COUNTER_BUF_LEN - 8; 15 | 16 | /* Position of the first digit in `line_buf'. */ 17 | static char *line_num_start = line_buf + LINE_COUNTER_BUF_LEN - 3; 18 | 19 | /* Position of the last digit in `line_buf'. */ 20 | static char *line_num_end = line_buf + LINE_COUNTER_BUF_LEN - 3; 21 | 22 | static void next_line_num(void) { 23 | char *endp = line_num_end; 24 | do { 25 | if ((*endp)++ < '9') 26 | return; 27 | *endp-- = '0'; 28 | } while (endp >= line_num_start); 29 | if (line_num_start > line_buf) 30 | *--line_num_start = '1'; 31 | else 32 | *line_buf = '>'; 33 | if (line_num_start < line_num_print) 34 | line_num_print--; 35 | } 36 | 37 | static int insize = 1024; 38 | static int outsize = 1024; 39 | 40 | static struct option long_options[] = { 41 | {"number", no_argument, 0, 'n'}, 42 | {"remove-blanks", required_argument, 0, 'r'}, 43 | {GETOPT_HELP_OPTION_DECL}, 44 | {GETOPT_VERSION_OPTION_DECL}, 45 | {0, 0, 0, 0}}; 46 | 47 | void usage() { 48 | printf("Usage: %s [SHORT-OPTION]... [STRING]...\n", PROGRAM_NAME); 49 | puts("Repeatedly output a line with all specified STRING(s), or 'y'."); 50 | puts(""); 51 | puts(" -n, --number show line number"); 52 | puts(" -r, --remove-blanks remove all blank lines and chars"); 53 | puts(HELP_OPTION_DESCRIPTION); 54 | puts(VERSION_OPTION_DESCRIPTION); 55 | print_more_info(PROGRAM_NAME); 56 | exit(EXIT_SUCCESS); 57 | } 58 | 59 | static void simple_cat(int infd, char *inbuf) { 60 | while (true) { 61 | size_t n_read = read(infd, inbuf, insize); 62 | if (n_read == 0) { 63 | break; 64 | } 65 | write(STDOUT_FILENO, inbuf, n_read); 66 | } 67 | } 68 | 69 | static void cat(int infd, char *inbuf, char *outbuf, bool numbers, 70 | bool remove_blanks) { 71 | 72 | char *bpin; 73 | char *bpout = outbuf; 74 | size_t n_write = 0; 75 | unsigned char ch; 76 | int line_number = 0; 77 | char line_number_str[4] = {' ', ' ', ' ', ' '}; 78 | 79 | while (true) { 80 | // read insize 81 | size_t n_read = read(infd, inbuf, insize); 82 | if (n_read == 0) { 83 | break; 84 | } 85 | bpin = inbuf; 86 | while (true) { 87 | 88 | // write buf full 89 | if (n_write == outsize) { 90 | write(STDOUT_FILENO, outbuf, n_write); 91 | bpout = outbuf; 92 | n_write = 0; 93 | } 94 | 95 | // read finish 96 | if (n_read == 0) { 97 | break; 98 | } 99 | 100 | // char by char read 101 | ch = *bpin++; 102 | n_read--; 103 | 104 | // char by char handle 105 | if(remove_blanks && (ch == ' ' || ch == '\n')) { 106 | continue; 107 | } 108 | if (numbers && ch == '\n') { 109 | *bpout++ = ch; 110 | next_line_num(); 111 | bpout = stpcpy(bpout, line_num_print); 112 | continue; 113 | } 114 | 115 | // char by char write to outbuf 116 | *bpout++ = ch; 117 | n_write++; 118 | 119 | } 120 | 121 | } 122 | 123 | if (n_write != 0) { 124 | write(STDOUT_FILENO, outbuf, n_write); 125 | puts(""); 126 | } 127 | 128 | } 129 | 130 | int main(int argc, char **argv) { 131 | int optc; 132 | bool numbers = false; 133 | bool remove_blanks = false; 134 | 135 | while ((optc = getopt_long(argc, argv, "nr", long_options, NULL)) != -1) { 136 | int a = optind; 137 | switch (optc) { 138 | case 'n': numbers = true; break; 139 | case 'r': 140 | remove_blanks = true; 141 | break; 142 | case_GETOPT_HELP_CHAR; 143 | case_GETOPT_VERSION_CHAR(PROGRAM_NAME); 144 | default: print_try_help(PROGRAM_NAME); 145 | } 146 | } 147 | 148 | int argind = optind; 149 | 150 | while (argind < argc) { 151 | char *infile = argv[argind++]; 152 | int infd = open(infile, O_RDONLY); 153 | if (numbers || remove_blanks) { 154 | char *inbuf = malloc(insize); 155 | char *outbuf = malloc(outsize); 156 | cat(infd, inbuf, outbuf, numbers, remove_blanks); 157 | } else { 158 | char *inbuf = malloc(insize); 159 | simple_cat(infd, inbuf); 160 | } 161 | } 162 | 163 | return EXIT_SUCCESS; 164 | } 165 | --------------------------------------------------------------------------------