diff options
Diffstat (limited to '')
| -rw-r--r-- | st.c | 60 |
1 files changed, 35 insertions, 25 deletions
| @@ -1,4 +1,4 @@ | |||
| 1 | /* See LICENSE for licence details. */ | 1 | /* See LICENSE for licence details. */ |
| 2 | #include "st.h" | 2 | #include "st.h" |
| 3 | 3 | ||
| 4 | /* Globals */ | 4 | /* Globals */ |
| @@ -7,6 +7,7 @@ XWindow xw; | |||
| 7 | Term term; | 7 | Term term; |
| 8 | Escseq escseq; | 8 | Escseq escseq; |
| 9 | int cmdfd; | 9 | int cmdfd; |
| 10 | pid_t pid; | ||
| 10 | int running; | 11 | int running; |
| 11 | 12 | ||
| 12 | void | 13 | void |
| @@ -27,34 +28,45 @@ execsh(void) { | |||
| 27 | } | 28 | } |
| 28 | 29 | ||
| 29 | void | 30 | void |
| 30 | xbell(void) { /* visual bell */ | 31 | xbell(void) { /* visual bell */ |
| 31 | XRectangle r = { 0, 0, xw.w, xw.h }; | 32 | XRectangle r = { 0, 0, xw.w, xw.h }; |
| 32 | XSetForeground(xw.dis, dc.gc, dc.col[BellCol]); | 33 | XSetForeground(xw.dis, dc.gc, dc.col[BellCol]); |
| 33 | XFillRectangles(xw.dis, xw.win, dc.gc, &r, 1); | 34 | XFillRectangles(xw.dis, xw.win, dc.gc, &r, 1); |
| 34 | usleep(30000); | 35 | /* usleep(30000); */ |
| 35 | draw(SCredraw); | 36 | draw(SCredraw); |
| 36 | } | 37 | } |
| 37 | 38 | ||
| 39 | void | ||
| 40 | sigchld(int a) { | ||
| 41 | int stat = 0; | ||
| 42 | if(waitpid(pid, &stat, 0) < 0) | ||
| 43 | die("Waiting for pid %hd failed: %s\n", pid, SERRNO); | ||
| 44 | if(WIFEXITED(stat)) | ||
| 45 | exit(WEXITSTATUS(stat)); | ||
| 46 | else | ||
| 47 | exit(EXIT_FAILURE); | ||
| 48 | } | ||
| 49 | |||
| 50 | |||
| 38 | void | 51 | void |
| 39 | ttynew(void) { | 52 | ttynew(void) { |
| 40 | int m, s; | 53 | int m, s; |
| 41 | pid_t pid; | ||
| 42 | char *pts; | 54 | char *pts; |
| 43 | 55 | ||
| 44 | if((m = posix_openpt(O_RDWR | O_NOCTTY)) < 0) | 56 | if((m = posix_openpt(O_RDWR | O_NOCTTY)) < 0) |
| 45 | die("openpt"); | 57 | die("openpt failed: %s\n", SERRNO); |
| 46 | if(grantpt(m) == -1) | 58 | if(grantpt(m) < 0) |
| 47 | die("grandpt"); | 59 | die("grandpt failed: %s\n", SERRNO); |
| 48 | if(unlockpt(m) == -1) | 60 | if(unlockpt(m) < 0) |
| 49 | die("unlockpt"); | 61 | die("unlockpt failed: %s\n", SERRNO); |
| 50 | if((pts = ptsname(m)) == NULL) | 62 | if(!(pts = ptsname(m))) |
| 51 | die("ptsname"); | 63 | die("ptsname failed: %s\n", SERRNO); |
| 52 | if((s = open(pts, O_RDWR | O_NOCTTY)) < 0) | 64 | if((s = open(pts, O_RDWR | O_NOCTTY)) < 0) |
| 53 | die("slave open"); | 65 | die("Couldn't open slave: %s\n", SERRNO); |
| 54 | fcntl(s, F_SETFL, O_NDELAY); | 66 | fcntl(s, F_SETFL, O_NDELAY); |
| 55 | switch(pid = fork()) { | 67 | switch(pid = fork()) { |
| 56 | case -1: | 68 | case -1: |
| 57 | die("fork"); | 69 | die("fork failed\n"); |
| 58 | break; | 70 | break; |
| 59 | case 0: | 71 | case 0: |
| 60 | setsid(); /* create a new process group */ | 72 | setsid(); /* create a new process group */ |
| @@ -62,12 +74,13 @@ ttynew(void) { | |||
| 62 | dup2(s, STDOUT_FILENO); | 74 | dup2(s, STDOUT_FILENO); |
| 63 | dup2(s, STDERR_FILENO); | 75 | dup2(s, STDERR_FILENO); |
| 64 | if(ioctl(s, TIOCSCTTY, NULL) < 0) | 76 | if(ioctl(s, TIOCSCTTY, NULL) < 0) |
| 65 | die("slave TTIOCSTTY"); | 77 | die("ioctl TTIOCSTTY failed: %s\n", SERRNO); |
| 66 | execsh(); | 78 | execsh(); |
| 67 | break; | 79 | break; |
| 68 | default: | 80 | default: |
| 69 | close(s); | 81 | close(s); |
| 70 | cmdfd = m; | 82 | cmdfd = m; |
| 83 | signal(SIGCHLD, sigchld); | ||
| 71 | } | 84 | } |
| 72 | } | 85 | } |
| 73 | 86 | ||
| @@ -85,9 +98,8 @@ ttyread(void) { | |||
| 85 | int ret; | 98 | int ret; |
| 86 | 99 | ||
| 87 | switch(ret = read(cmdfd, buf, BUFSIZ)) { | 100 | switch(ret = read(cmdfd, buf, BUFSIZ)) { |
| 88 | case -1: /* error or exit */ | 101 | case -1: |
| 89 | /* XXX: be more precise */ | 102 | die("Couldn't read from shell: %s\n", SERRNO); |
| 90 | running = 0; | ||
| 91 | break; | 103 | break; |
| 92 | default: | 104 | default: |
| 93 | tputs(buf, ret); | 105 | tputs(buf, ret); |
| @@ -97,7 +109,7 @@ ttyread(void) { | |||
| 97 | void | 109 | void |
| 98 | ttywrite(char *s, size_t n) { | 110 | ttywrite(char *s, size_t n) { |
| 99 | if(write(cmdfd, s, n) == -1) | 111 | if(write(cmdfd, s, n) == -1) |
| 100 | die("write error on tty."); | 112 | die("write error on tty: %s\n", SERRNO); |
| 101 | } | 113 | } |
| 102 | 114 | ||
| 103 | void | 115 | void |
| @@ -108,7 +120,7 @@ ttyresize(int x, int y) { | |||
| 108 | w.ws_col = term.col; | 120 | w.ws_col = term.col; |
| 109 | w.ws_xpixel = w.ws_ypixel = 0; | 121 | w.ws_xpixel = w.ws_ypixel = 0; |
| 110 | if(ioctl(cmdfd, TIOCSWINSZ, &w) < 0) | 122 | if(ioctl(cmdfd, TIOCSWINSZ, &w) < 0) |
| 111 | fprintf(stderr, "Couldn't set window size: %m\n"); | 123 | fprintf(stderr, "Couldn't set window size: %s\n", SERRNO); |
| 112 | } | 124 | } |
| 113 | 125 | ||
| 114 | int | 126 | int |
| @@ -889,7 +901,7 @@ run(void) { | |||
| 889 | 901 | ||
| 890 | running = 1; | 902 | running = 1; |
| 891 | XSelectInput(xw.dis, xw.win, ExposureMask | KeyPressMask | StructureNotifyMask); | 903 | XSelectInput(xw.dis, xw.win, ExposureMask | KeyPressMask | StructureNotifyMask); |
| 892 | XResizeWindow(xw.dis, xw.win, xw.w , xw.h); /* seems to fix the resize bug in wmii */ | 904 | XResizeWindow(xw.dis, xw.win, xw.w , xw.h); /* fix resize bug in wmii (?) */ |
| 893 | 905 | ||
| 894 | while(running) { | 906 | while(running) { |
| 895 | FD_ZERO(&rfd); | 907 | FD_ZERO(&rfd); |
| @@ -898,11 +910,9 @@ run(void) { | |||
| 898 | XFlush(xw.dis); | 910 | XFlush(xw.dis); |
| 899 | ret = select(MAX(xfd, cmdfd)+1, &rfd, NULL, NULL, NULL); | 911 | ret = select(MAX(xfd, cmdfd)+1, &rfd, NULL, NULL, NULL); |
| 900 | 912 | ||
| 901 | if(ret < 0) { | 913 | if(ret < 0) |
| 902 | fprintf(stderr, "select: %m\n"); | 914 | die("select failed: %s\n", SERRNO); |
| 903 | running = 0; | 915 | |
| 904 | } | ||
| 905 | |||
| 906 | if(FD_ISSET(xfd, &rfd)) { | 916 | if(FD_ISSET(xfd, &rfd)) { |
| 907 | while(XPending(xw.dis)) { | 917 | while(XPending(xw.dis)) { |
| 908 | XNextEvent(xw.dis, &ev); | 918 | XNextEvent(xw.dis, &ev); |
