|
17 | 17 | │ PERFORMANCE OF THIS SOFTWARE. │
|
18 | 18 | ╚─────────────────────────────────────────────────────────────────────────────*/
|
19 | 19 | #include "libc/calls/calls.h"
|
| 20 | +#include "libc/calls/syscall_support-nt.internal.h" |
| 21 | +#include "libc/dce.h" |
20 | 22 | #include "libc/intrin/safemacros.internal.h"
|
21 | 23 | #include "libc/limits.h"
|
| 24 | +#include "libc/mem/gc.h" |
22 | 25 | #include "libc/runtime/runtime.h"
|
23 | 26 | #include "libc/str/str.h"
|
| 27 | +#include "libc/sysv/consts/o.h" |
24 | 28 | #include "libc/temp.h"
|
| 29 | +#include "libc/x/x.h" |
| 30 | + |
| 31 | +static char *get_pagerpath(char *pathbuf, size_t pathbufsz) { |
| 32 | + char *pagerpath; |
| 33 | + if (strcmp(nulltoempty(getenv("TERM")), "dumb") && isatty(0) && isatty(1) && |
| 34 | + ((pagerpath = commandv("less", pathbuf, pathbufsz)) || |
| 35 | + (pagerpath = commandv("more", pathbuf, pathbufsz)) || |
| 36 | + (pagerpath = commandv("more.exe", pathbuf, pathbufsz)) || |
| 37 | + (pagerpath = commandv("more.com", pathbuf, pathbufsz)))) { |
| 38 | + return pagerpath; |
| 39 | + } |
| 40 | + return 0; |
| 41 | +} |
| 42 | + |
| 43 | +static bool run_pager(char *args[hasatleast 3]) { |
| 44 | + char16_t widepath[PATH_MAX]; |
| 45 | + int n, pid; |
| 46 | + if (IsWindows() && !strcasecmp(args[0], "/C/Windows/System32/more.com") && |
| 47 | + (((n = __mkntpath(args[1], widepath)) == -1) || |
| 48 | + !(args[1] = gc(utf16to8(widepath, n, 0))))) { |
| 49 | + return false; |
| 50 | + } |
| 51 | + if ((pid = fork()) != -1) { |
| 52 | + putenv("LC_ALL=C.UTF-8"); |
| 53 | + putenv("LESSCHARSET=utf-8"); |
| 54 | + putenv("LESS=-RS"); |
| 55 | + if (!pid) { |
| 56 | + execv(args[0], args); |
| 57 | + _Exit(127); |
| 58 | + } |
| 59 | + waitpid(pid, 0, 0); |
| 60 | + return true; |
| 61 | + } |
| 62 | + return false; |
| 63 | +} |
25 | 64 |
|
26 | 65 | /**
|
27 | 66 | * Displays wall of text in terminal with pagination.
|
28 | 67 | */
|
29 | 68 | void __paginate(int fd, const char *s) {
|
30 |
| - int tfd, pid; |
| 69 | + int tfd; |
31 | 70 | char *args[3] = {0};
|
32 | 71 | char tmppath[] = "/tmp/paginate.XXXXXX";
|
33 | 72 | char progpath[PATH_MAX];
|
34 |
| - if (strcmp(nulltoempty(getenv("TERM")), "dumb") && isatty(0) && isatty(1) && |
35 |
| - ((args[0] = commandv("less", progpath, sizeof(progpath))) || |
36 |
| - (args[0] = commandv("more", progpath, sizeof(progpath))) || |
37 |
| - (args[0] = commandv("more.exe", progpath, sizeof(progpath))))) { |
| 73 | + bool done; |
| 74 | + if ((args[0] = get_pagerpath(progpath, sizeof(progpath)))) { |
38 | 75 | if ((tfd = mkstemp(tmppath)) != -1) {
|
39 | 76 | write(tfd, s, strlen(s));
|
40 | 77 | close(tfd);
|
41 | 78 | args[1] = tmppath;
|
42 |
| - if ((pid = fork()) != -1) { |
43 |
| - putenv("LC_ALL=C.UTF-8"); |
44 |
| - putenv("LESSCHARSET=utf-8"); |
45 |
| - putenv("LESS=-RS"); |
46 |
| - if (!pid) { |
47 |
| - execv(args[0], args); |
48 |
| - _Exit(127); |
49 |
| - } |
50 |
| - waitpid(pid, 0, 0); |
51 |
| - unlink(tmppath); |
| 79 | + done = run_pager(args); |
| 80 | + unlink(tmppath); |
| 81 | + if (done) { |
52 | 82 | return;
|
53 | 83 | }
|
54 |
| - unlink(tmppath); |
55 | 84 | }
|
56 | 85 | }
|
57 | 86 | write(fd, s, strlen(s));
|
58 | 87 | }
|
| 88 | + |
| 89 | +/** |
| 90 | + * Displays a file in terminal with pagination |
| 91 | + */ |
| 92 | +void __paginate_file(int fd, const char *path) { |
| 93 | + char *args[3] = {0}; |
| 94 | + char progpath[PATH_MAX]; |
| 95 | + if ((args[0] = get_pagerpath(progpath, sizeof(progpath)))) { |
| 96 | + args[1] = (char *)path; |
| 97 | + if (run_pager(args)) { |
| 98 | + return; |
| 99 | + } |
| 100 | + } |
| 101 | + int sfd = open(path, O_RDONLY); |
| 102 | + if (sfd != -1) { |
| 103 | + ssize_t n; |
| 104 | + while ((n = read(sfd, progpath, sizeof(progpath)) > 0)) { |
| 105 | + write(fd, progpath, n); |
| 106 | + } |
| 107 | + } |
| 108 | + close(sfd); |
| 109 | +} |
0 commit comments