~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Minix Cross Reference
Minix/Solaris/mlogin.c


  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 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.