diff options
Diffstat (limited to 'src/monkey/get_free_vt.c')
-rw-r--r-- | src/monkey/get_free_vt.c | 153 |
1 files changed, 153 insertions, 0 deletions
diff --git a/src/monkey/get_free_vt.c b/src/monkey/get_free_vt.c new file mode 100644 index 000000000..f5c980005 --- /dev/null +++ b/src/monkey/get_free_vt.c | |||
@@ -0,0 +1,153 @@ | |||
1 | /**[txh]******************************************************************** | ||
2 | |||
3 | Copyright (c) 2004 by Salvador E. Tropea. | ||
4 | Covered by the GPL license. | ||
5 | |||
6 | Module: Linux VT. | ||
7 | Comments: | ||
8 | Helper to find a free VT. That's 100% Linux specific.@p | ||
9 | The code comes from "lconsole.c" from Allegro project and was originally | ||
10 | created by Marek Habersack and then modified by George Foot. I addapted it | ||
11 | to my needs and changed license from giftware to GPL.@p | ||
12 | |||
13 | ***************************************************************************/ | ||
14 | |||
15 | #define _GNU_SOURCE | ||
16 | #include <string.h> | ||
17 | #include <stdio.h> | ||
18 | #include <unistd.h> | ||
19 | #include <fcntl.h> | ||
20 | #include <sys/ioctl.h> | ||
21 | #ifdef __APPLE__ | ||
22 | #include <util.h> | ||
23 | #endif /* __APPLE__ */ | ||
24 | |||
25 | #include "mi_gdb.h" | ||
26 | |||
27 | #if !defined(__linux__) | ||
28 | |||
29 | int mi_look_for_free_vt() | ||
30 | { | ||
31 | return -1; | ||
32 | } | ||
33 | |||
34 | mi_aux_term *gmi_look_for_free_vt() | ||
35 | { | ||
36 | return NULL; | ||
37 | } | ||
38 | |||
39 | #else | ||
40 | |||
41 | #include <linux/vt.h> | ||
42 | |||
43 | /**[txh]******************************************************************** | ||
44 | |||
45 | Description: | ||
46 | Look for a free and usable Linux VT. Low level, use | ||
47 | @x{gmi_look_for_free_vt}. | ||
48 | |||
49 | Return: The VT number or <0 on error. | ||
50 | |||
51 | ***************************************************************************/ | ||
52 | |||
53 | int mi_look_for_free_vt() | ||
54 | {/* Code from Allegro. */ | ||
55 | int tty, console_fd, fd; | ||
56 | unsigned short mask; | ||
57 | char tty_name[16]; | ||
58 | struct vt_stat vts; | ||
59 | |||
60 | /* Now we need to find a VT we can use. It must be readable and | ||
61 | * writable by us, if we're not setuid root. VT_OPENQRY itself | ||
62 | * isn't too useful because it'll only ever come up with one | ||
63 | * suggestion, with no guarrantee that we actually have access | ||
64 | * to it. | ||
65 | * | ||
66 | * At some stage I think this is a candidate for config | ||
67 | * file overriding, but for now we'll stat the first N consoles | ||
68 | * to see which ones we can write to (hopefully at least one!), | ||
69 | * so that we can use that one to do ioctls. We used to use | ||
70 | * /dev/console for that purpose but it looks like it's not | ||
71 | * always writable by enough people. | ||
72 | * | ||
73 | * Having found and opened a writable device, we query the state | ||
74 | * of the first sixteen (fifteen really) consoles, and try | ||
75 | * opening each unused one in turn. | ||
76 | */ | ||
77 | |||
78 | console_fd=open("/dev/console",O_WRONLY); | ||
79 | if (console_fd<0) | ||
80 | { | ||
81 | int n; | ||
82 | /* Try some ttys instead... */ | ||
83 | for (n=1; n<=24; n++) | ||
84 | { | ||
85 | snprintf(tty_name,sizeof(tty_name),"/dev/tty%d",n); | ||
86 | console_fd=open(tty_name,O_WRONLY); | ||
87 | if (console_fd>=0) | ||
88 | break; | ||
89 | } | ||
90 | if (n>24) | ||
91 | return -1; | ||
92 | } | ||
93 | |||
94 | /* Get the state of the console -- in particular, the free VT field */ | ||
95 | if (ioctl(console_fd,VT_GETSTATE,&vts)) | ||
96 | return -2; | ||
97 | close(console_fd); | ||
98 | |||
99 | /* We attempt to set our euid to 0; if we were run with euid 0 to | ||
100 | * start with, we'll be able to do this now. Otherwise, we'll just | ||
101 | * ignore the error returned since it might not be a problem if the | ||
102 | * ttys we look at are owned by the user running the program. */ | ||
103 | seteuid(0); | ||
104 | |||
105 | /* tty0 is not really a console, so start counting at 2. */ | ||
106 | fd=-1; | ||
107 | for (tty=1, mask=2; mask; tty++, mask<<=1) | ||
108 | if (!(vts.v_state & mask)) | ||
109 | { | ||
110 | snprintf(tty_name,sizeof(tty_name),"/dev/tty%d",tty); | ||
111 | fd=open(tty_name,O_RDWR); | ||
112 | if (fd!=-1) | ||
113 | { | ||
114 | close(fd); | ||
115 | break; | ||
116 | } | ||
117 | } | ||
118 | |||
119 | seteuid(getuid()); | ||
120 | |||
121 | if (!mask) | ||
122 | return -3; | ||
123 | |||
124 | return tty; | ||
125 | } | ||
126 | |||
127 | /**[txh]******************************************************************** | ||
128 | |||
129 | Description: | ||
130 | Look for a free and usable Linux VT to be used by the child. | ||
131 | |||
132 | Return: A new mi_aux_term structure, you can use @x{gmi_end_aux_term} to | ||
133 | release it. | ||
134 | |||
135 | ***************************************************************************/ | ||
136 | |||
137 | mi_aux_term *gmi_look_for_free_vt() | ||
138 | { | ||
139 | int vt=mi_look_for_free_vt(); | ||
140 | mi_aux_term *res; | ||
141 | |||
142 | if (vt<0) | ||
143 | return NULL; | ||
144 | res=(mi_aux_term *)malloc(sizeof(mi_aux_term)); | ||
145 | if (!res) | ||
146 | return NULL; | ||
147 | res->pid=-1; | ||
148 | asprintf(&res->tty,"/dev/tty%d",vt); | ||
149 | return res; | ||
150 | } | ||
151 | |||
152 | #endif | ||
153 | |||