1 static char rcsid[] = "$Id: mlogin.c,v 1.2 1996/06/04 08:29:53 paul Exp $";
2
3 /*
4 * mlogin
5 *
6 * This is a Solaris utility for connecting with a running smx. It
7 * is similar to 'rlogin'. A "hostname" is given as the single command
8 * line argument. The directory /tmp/"hostname" contains a file called
9 * "lock" that gives details of the number of consoles, and their
10 * availability. Also in the directory are one pair of FIFOs per console.
11 * mlogin finds a "line" to use and opens the appropriate FIFOs. It then goes
12 * into a loop relaying characters between smx (i.e. the FIFIOs) and the
13 * controlling terminal. When the connection is severed (by either party)
14 * the lock file is updated to reflect that the line is now available,
15 */
16
17 #include <stdio.h>
18 #include <string.h>
19 #include <sys/types.h>
20 #include <sys/time.h>
21 #include <sys/socket.h>
22 #include <unistd.h>
23 #include <fcntl.h>
24 #include <termios.h>
25 #include <signal.h>
26 #include <stropts.h>
27
28 /*
29 * Need to get MLOGIN_HANGUP from ../kernel/const.h (need config.h first)
30 */
31 #include "../../include/minix/config.h"
32 #include "../kernel/const.h"
33 #undef printf /* defined to printk in kernel/const.h */
34
35 #define BUFSIZE 200 /* most characters read at one time */
36
37 static int termfd; /* /dev/tty fd */
38 static struct termios old_t; /* save area for terminal configuration */
39 static int ourline; /* number of the tty we are using */
40
41 static char lock_file[MAXPATHLEN]; /* name of the lock file */
42
43
44 /*
45 * Local functions
46 */
47 static void term(int pipeinfd, int pipeoutfd);
48 static int read_lock_file(int *nr_cons, int *cons_map);
49 static int write_lock_file(int fd, int cons_map);
50 static void exit_mlogin(const char *mess, int status);
51
52
53 /*
54 * Function: main
55 * Parameters: argc, argv - see usage
56 *
57 * We find a terminal line, open the FIFOs for that line, setup the
58 * controlling tty and signal settings, then call term to relay data
59 * to and from smx itself.
60 */
61 int main(int argc, char *argv[])
62 {
63 int pipeinfd; /* the smx connection */
64 int pipeoutfd;
65 struct termios t; /* terminal setup */
66 char host_name[MAXPATHLEN]; /* host we are connecting to */
67 int lockfd, cons_map, nr_cons;
68 int count;
69
70 /*
71 * find the directory relating to the desired host name
72 */
73 if (argc != 2) exit_mlogin("Usage: mlogin <host name>\n", 1);
74
75 /*
76 * Get the map of free terminal lines and allocate ourselves one
77 */
78 sprintf(lock_file, "/tmp/%s/lock", argv[1]);
79 if ((lockfd = read_lock_file(&nr_cons, &cons_map)) == -1) {
80 exit_mlogin("Can't read lock file\n", 1);
81 }
82 ourline = 0;
83 for (count = 0; count != nr_cons; count++) {
84 if ((cons_map & (1 << count)) != 0) {
85 ourline = count + 1; /* found a free terminal */
86 break;
87 }
88 }
89
90 if (ourline == 0) exit_mlogin("Out of terminal lines\n", 1);
91
92 cons_map &= ~(1 << count); /* mark it as used */
93 if (write_lock_file(lockfd, cons_map) == -1) {
94 exit_mlogin("Couldn't write to lock file\n", 1);
95 }
96
97 /*
98 * Open the two FIFOs, and set them to non-blocking IO.
99 */
100 sprintf(host_name, "/tmp/%s/out.%d", argv[1], ourline);
101 if ((pipeinfd = open(host_name, O_RDONLY)) == -1 ||
102 fcntl(pipeinfd, F_SETFL, O_NDELAY | O_RDWR) == -1) {
103 exit_mlogin("Can't setup from smx FIFO\n", 1);
104 }
105 sprintf(host_name, "/tmp/%s/in.%d", argv[1], ourline);
106 if ((pipeoutfd = open(host_name, O_RDWR)) == -1 ||
107 fcntl(pipeoutfd, F_SETFL, O_NDELAY | O_RDWR) == -1) {
108 exit_mlogin("Can't setup to smx FIFO\n", 0);
109 }
110
111 /*
112 * open the user's tty, and save its settings
113 */
114 termfd = open("/dev/tty", O_RDWR);
115 if (termfd < 0) {
116 exit_mlogin("Can't open /dev/tty\n", 1);
117 }
118 ioctl(termfd, TCGETS, &old_t);
119
120 /*
121 * setup the user terminal mode (no echo, no signals, non-blocking etc)
122 */
123 t = old_t;
124 t.c_lflag &= ~(ECHO | ICANON | ISIG );
125 t.c_iflag &= ~(IXON | IXOFF);
126 t.c_cc[VMIN] = 1;
127 t.c_cc[VTIME] = 0;
128 ioctl(termfd, TCSETS, &t);
129 fcntl(termfd, F_SETFL, O_NDELAY | O_RDWR);
130
131 /*
132 * ignore all signals
133 */
134 for (count = 1; count < _SIGRTMAX; count++) {
135 signal(count, SIG_IGN);
136 }
137
138 printf("Connected to host %s\n", argv[1]);
139
140 term(pipeinfd, pipeoutfd); /* Transfer the data */
141
142 /*NOTREACHED*/
143 return 0;
144 }
145
146
147 /*
148 * Function: term
149 * Parameters: pipeinfd - data from smx received on this descriptor
150 * pipeoutfd - data to smx sent on this descriptor
151 * Returns: never
152 *
153 * Loop forever, transfering data to and from smx. If the user types
154 * ^Q^U^I^T then we tear down the connection and exit.
155 */
156 static void term(int pipeinfd, int pipeoutfd)
157 {
158 char buffer[BUFSIZE]; /* where the characters are stored */
159 char quit = (char) MLOGIN_HANGUP; /* Minix's hangup character */
160 int length; /* how much was read? */
161 fd_set reads;
162 int max_fd;
163 int cnt;
164
165 /*
166 * terminal emulator escape sequence ^Q^U^I^T
167 */
168 char disco[] = {021, 025, 011, 024};
169 int discnt = 0; /* how far through this sequence? */
170
171 max_fd = termfd > pipeinfd ? termfd : pipeinfd;
172 discnt = 0;
173
174 /*
175 * forever until death do us part
176 */
177 while (1) {
178 FD_ZERO(&reads);
179 FD_SET(termfd, &reads);
180 FD_SET(pipeinfd, &reads);
181
182 /*
183 * wait until there is some data to transfer in one or both directions
184 */
185 select(max_fd + 1, &reads, 0, 0, 0);
186
187 if (FD_ISSET(termfd, &reads)) {
188 /*
189 * characters typed on the terminal
190 */
191 length = read(termfd, buffer, BUFSIZE);
192
193 /*
194 * part of escape sequence?
195 */
196 for (cnt = 0; cnt < length; cnt++) {
197 if (buffer[cnt] == disco[discnt]) {
198 discnt++;
199 if (discnt == sizeof(disco)) {
200 break; /* ^Q^U^I^T has been typed! */
201 }
202 } else {
203 discnt = 0; /* back to square one */
204 }
205 }
206
207 /*
208 * If the read failed or ^Q^U^I^T has been typed then time to
209 * exit. Tell smx by writing a quit_char to it.
210 */
211 if (length <= 0 || discnt == sizeof(disco)) {
212 write(pipeoutfd, &quit, 1);
213 exit_mlogin("\n\nExiting mlogin\n", 0);
214 }
215
216 /*
217 * Pass characters on to Minix
218 */
219 write(pipeoutfd, buffer, length);
220 }
221
222 if (FD_ISSET(pipeinfd, &reads)){
223 /*
224 * characters from smx to display on the terminal
225 */
226 length = read(pipeinfd, buffer, BUFSIZE);
227 if (length <= 0) {
228 write(pipeoutfd, &quit, 1);
229 exit_mlogin("\n\nExiting mlogin\n", 0);
230 }
231 write(termfd, buffer, length);
232 }
233 } /* Infinite while loop */
234 }
235
236
237 /*
238 * Function: read_lock_file
239 * Parameters: nr_cons - used to return the number of consoles
240 * cons_map - bit map of free consoles
241 * Returns: fd of open and locked "lock" file, -1 upon error
242 *
243 * Open and lock "lock" file and return its contents. A call
244 * to write_lock_file should be done soon after to unlock and
245 * close the "lock" file.
246 */
247 static int read_lock_file(int *nr_cons, int *cons_map)
248 {
249 int fd;
250
251 if ((fd = open(lock_file, O_RDWR)) == -1) {
252 return -1;
253 }
254
255 if (lockf(fd, F_LOCK, 0) != 0) {
256 return -1;
257 }
258
259 if (read(fd, nr_cons, sizeof(*nr_cons)) != sizeof(*nr_cons) ||
260 read(fd, cons_map, sizeof(*cons_map)) != sizeof(*cons_map)) {
261 return -1;
262 }
263 return fd;
264 }
265
266
267 /*
268 * Function: write_lock_file
269 * Parameters: fd - "lock" file is open and locked on this descriptor
270 * cons_map - map to write back to the log file.
271 * Returns: 0 on success, -1 on error
272 *
273 * Update "lock" file with new cons map, then unlock and close it.
274 */
275 static int write_lock_file(int fd, int cons_map)
276 {
277 if (lseek(fd, sizeof(int), SEEK_SET) == -1 ||
278 write(fd, &cons_map, sizeof(cons_map)) != sizeof(cons_map) ||
279 lockf(fd, F_ULOCK, 0) == -1 ||
280 close(fd) == -1) {
281 return -1;
282 }
283 return 0;
284 }
285
286
287 /*
288 * Function: exit_mlogin
289 * Parameters: mess - a parting message
290 * status - the status to call exit(2) with.
291 * Returns: doesn't
292 *
293 * mlogin is about to exit. Print the exit message, mark the terminal
294 * line as free, and restore the terminal to its former state.
295 */
296 static void exit_mlogin(const char *mess, int status)
297 {
298 int lockfd, cons_map, nr_cons;
299
300 fprintf(stderr, mess);
301
302 /*
303 * Mark this terminal line as free
304 */
305 if ((lockfd = read_lock_file(&nr_cons, &cons_map)) != -1) {
306 cons_map |= (1 << (ourline - 1));
307 (void) write_lock_file(lockfd, cons_map);
308 }
309
310 /*
311 * Reset the UNIX keyboard characteristics
312 */
313 ioctl(termfd, TCSETS, &old_t);
314
315 exit(status);
316 }
317
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.