Mercurial > hg > toybox
comparison toys/pending/openvt.c @ 1241:3c855d5a75be draft
openvt tries opening several devices to get an fd that points to the current console, without a need for read or write permissions. O_RDWR implies that both O_RDONLY and O_WRONLY would work, so skip it. Reindent.
author | Isaac Dunham <ibid.ag@gmail.com> |
---|---|
date | Thu, 03 Apr 2014 22:43:28 -0500 |
parents | a31d747b0017 |
children | 85f297591693 |
comparison
equal
deleted
inserted
replaced
1240:0d295a46f853 | 1241:3c855d5a75be |
---|---|
25 #include "toys.h" | 25 #include "toys.h" |
26 #include <linux/vt.h> | 26 #include <linux/vt.h> |
27 #include <linux/kd.h> | 27 #include <linux/kd.h> |
28 | 28 |
29 GLOBALS( | 29 GLOBALS( |
30 unsigned long vt_num; | 30 unsigned long vt_num; |
31 ) | 31 ) |
32 | 32 |
33 int find_console_fd(void) | 33 int find_console_fd(void) |
34 { | 34 { |
35 char *console_name[] = {"/dev/tty", "/dev/tty0", "/dev/console"}; | 35 char *console_name[] = {"/dev/tty", "/dev/tty0", "/dev/console"}; |
36 int i; | 36 int i; |
37 int fd; | 37 int fd; |
38 char arg; | 38 char arg; |
39 | 39 |
40 for (i = 0; i < 3; i++) { | 40 for (i = 0; i < 3; i++) { |
41 fd = open(console_name[i], O_RDWR); | 41 fd = open(console_name[i], O_RDONLY); |
42 if (fd < 0 && errno == EACCES) | 42 if (fd < 0 && errno == EACCES) |
43 fd = open(console_name[i], O_RDONLY); | 43 fd = open(console_name[i], O_WRONLY); |
44 | 44 |
45 if (fd < 0 && errno == EACCES) | 45 if (fd >= 0) { |
46 fd = open(console_name[i], O_WRONLY); | 46 arg = 0; |
47 if (0 == ioctl(fd, KDGKBTYPE, &arg)) | |
48 return fd; | |
49 else | |
50 close(fd); | |
51 } | |
52 } | |
47 | 53 |
48 if (fd >= 0) { | 54 /* check std fd 0, 1 and 2 */ |
49 arg = 0; | 55 for (fd = 0; fd < 3; fd++) { |
50 if (0 == ioctl(fd, KDGKBTYPE, &arg)) | 56 arg = 0; |
51 return fd; | 57 if (0 == ioctl(fd, KDGKBTYPE, &arg)) |
52 else | 58 return fd; |
53 close(fd); | 59 } |
54 } | |
55 } | |
56 | 60 |
57 /* check std fd 0, 1 and 2 */ | 61 return -1; |
58 for (fd = 0; fd < 3; fd++) { | |
59 arg = 0; | |
60 if (0 == ioctl(fd, KDGKBTYPE, &arg)) | |
61 return fd; | |
62 } | |
63 | |
64 return -1; | |
65 } | 62 } |
66 | 63 |
67 int xvtnum(int fd) | 64 int xvtnum(int fd) |
68 { | 65 { |
69 int ret; | 66 int ret; |
70 | 67 |
71 ret = ioctl(fd, VT_OPENQRY, (int *)&TT.vt_num); | 68 ret = ioctl(fd, VT_OPENQRY, (int *)&TT.vt_num); |
72 if (ret != 0 || TT.vt_num <= 0) perror_exit("can't find open VT"); | 69 if (ret != 0 || TT.vt_num <= 0) perror_exit("can't find open VT"); |
73 | 70 |
74 return TT.vt_num; | 71 return TT.vt_num; |
75 } | 72 } |
76 | 73 |
77 void openvt_main(void) | 74 void openvt_main(void) |
78 { | 75 { |
79 int fd = -1, vt_fd = -1, pid, ret = 0; | 76 int fd = -1, vt_fd = -1, pid, ret = 0; |
80 struct vt_stat vstate; | 77 struct vt_stat vstate; |
81 | 78 |
82 if (!(toys.optflags & FLAG_c)) { | 79 if (!(toys.optflags & FLAG_c)) { |
83 // check if fd 0,1 or 2 is already opened | 80 // check if fd 0,1 or 2 is already opened |
84 for (fd = 0; fd < 3; fd++) | 81 for (fd = 0; fd < 3; fd++) |
85 if (!ioctl(fd, VT_GETSTATE, &vstate)) { | 82 if (!ioctl(fd, VT_GETSTATE, &vstate)) { |
86 ret = xvtnum(fd); | 83 ret = xvtnum(fd); |
87 break; | 84 break; |
88 } | 85 } |
89 | 86 |
90 // find VT number using /dev/console | 87 // find VT number using /dev/console |
91 if (!ret) { | 88 if (!ret) { |
92 fd = xopen("/dev/console", O_RDONLY | O_NONBLOCK); | 89 fd = xopen("/dev/console", O_RDONLY | O_NONBLOCK); |
93 xioctl(fd, VT_GETSTATE, &vstate); | 90 xioctl(fd, VT_GETSTATE, &vstate); |
94 xvtnum(fd); | 91 xvtnum(fd); |
95 } | 92 } |
96 } | 93 } |
97 | 94 |
98 sprintf(toybuf, "/dev/tty%lu", TT.vt_num); | 95 sprintf(toybuf, "/dev/tty%lu", TT.vt_num); |
99 fd = find_console_fd(); | 96 fd = find_console_fd(); |
100 xioctl(fd, VT_GETSTATE, &vstate); | 97 xioctl(fd, VT_GETSTATE, &vstate); |
101 | 98 |
102 close(0); //new vt becomes stdin | 99 close(0); //new vt becomes stdin |
103 vt_fd = xopen(toybuf, O_RDWR); | 100 vt_fd = xopen(toybuf, O_RDWR); |
104 if (toys.optflags & FLAG_s) { | 101 if (toys.optflags & FLAG_s) { |
105 ioctl(vt_fd, VT_ACTIVATE, TT.vt_num); | 102 ioctl(vt_fd, VT_ACTIVATE, TT.vt_num); |
106 ioctl(vt_fd, VT_WAITACTIVE, TT.vt_num); | 103 ioctl(vt_fd, VT_WAITACTIVE, TT.vt_num); |
107 } | 104 } |
108 | 105 |
109 close(1); | 106 close(1); |
110 close(2); | 107 close(2); |
111 dup2(vt_fd, 1); | 108 dup2(vt_fd, 1); |
112 dup2(vt_fd, 2); | 109 dup2(vt_fd, 2); |
113 while (vt_fd > 2) | 110 while (vt_fd > 2) |
114 close(vt_fd--); | 111 close(vt_fd--); |
115 | 112 |
116 pid = vfork(); | 113 pid = vfork(); |
117 if (pid < 0) perror_exit("Fork failed"); | 114 if (pid < 0) perror_exit("Fork failed"); |
118 else if (!pid) { | 115 else if (!pid) { |
119 setsid(); | 116 setsid(); |
120 ioctl(vt_fd, TIOCSCTTY, 0); | 117 ioctl(vt_fd, TIOCSCTTY, 0); |
121 xexec(toys.optargs); | 118 xexec(toys.optargs); |
122 } | 119 } |
123 | 120 |
124 if (toys.optflags & FLAG_w) { | 121 if (toys.optflags & FLAG_w) { |
125 while (-1 == waitpid(pid, NULL, 0) && errno == EINTR) | 122 while (-1 == waitpid(pid, NULL, 0) && errno == EINTR) |
126 ; | 123 ; |
127 if (toys.optflags & FLAG_s) { | 124 if (toys.optflags & FLAG_s) { |
128 ioctl(fd, VT_ACTIVATE, vstate.v_active); | 125 ioctl(fd, VT_ACTIVATE, vstate.v_active); |
129 ioctl(fd, VT_WAITACTIVE, vstate.v_active); | 126 ioctl(fd, VT_WAITACTIVE, vstate.v_active); |
130 //check why deallocate isn't working here | 127 //check why deallocate isn't working here |
131 xioctl(fd, VT_DISALLOCATE, (void *)(ptrdiff_t)TT.vt_num); | 128 xioctl(fd, VT_DISALLOCATE, (void *)(ptrdiff_t)TT.vt_num); |
132 } | 129 } |
133 } | 130 } |
134 } | 131 } |