|
1 // sys_term.c |
|
2 // |
|
3 // © Portions Copyright (c) Symbian Software Ltd 2007. All rights reserved. |
|
4 // |
|
5 /* |
|
6 * Copyright (c) 1989, 1993 |
|
7 * The Regents of the University of California. All rights reserved. |
|
8 * |
|
9 * Redistribution and use in source and binary forms, with or without |
|
10 * modification, are permitted provided that the following conditions |
|
11 * are met: |
|
12 * 1. Redistributions of source code must retain the above copyright |
|
13 * notice, this list of conditions and the following disclaimer. |
|
14 * 2. Redistributions in binary form must reproduce the above copyright |
|
15 * notice, this list of conditions and the following disclaimer in the |
|
16 * documentation and/or other materials provided with the distribution. |
|
17 * 3. Neither the name of the University nor the names of its contributors |
|
18 * may be used to endorse or promote products derived from this software |
|
19 * without specific prior written permission. |
|
20 * |
|
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
|
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
|
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
|
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
|
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
|
31 * SUCH DAMAGE. |
|
32 */ |
|
33 #include "telnetd.h" |
|
34 |
|
35 #ifdef __SYMBIAN32__ |
|
36 #include "dummy.h" |
|
37 #endif |
|
38 |
|
39 #ifndef __SYMBIAN32__ |
|
40 __RCSID("$Heimdal: sys_term.c,v 1.104 2001/09/17 02:09:04 assar Exp $" |
|
41 "$NetBSD: sys_term.c,v 1.2 2003/08/07 09:15:30 agc Exp $"); |
|
42 #endif |
|
43 |
|
44 #if defined(_CRAY) || (defined(__hpux) && !defined(HAVE_UTMPX_H)) |
|
45 # define PARENT_DOES_UTMP |
|
46 #endif |
|
47 |
|
48 #include <utmp.h> |
|
49 |
|
50 #ifdef HAVE_UTMPX_H |
|
51 #include <utmpx.h> |
|
52 #endif |
|
53 |
|
54 #ifdef __SYMBIAN32__ |
|
55 #ifdef __WINSCW__ |
|
56 #pragma warn_unusedarg off |
|
57 #endif//__WINSCW__ |
|
58 #endif//__SYMBIAN32__ |
|
59 |
|
60 #ifdef HAVE_UTMPX_H |
|
61 struct utmpx wtmp; |
|
62 #elif defined(HAVE_UTMP_H) |
|
63 struct utmp wtmp; |
|
64 #endif /* HAVE_UTMPX_H */ |
|
65 |
|
66 #ifdef HAVE_STRUCT_UTMP_UT_HOST |
|
67 int utmp_len = sizeof(wtmp.ut_host); |
|
68 #else |
|
69 int utmp_len = MAXHOSTNAMELEN; |
|
70 #endif |
|
71 |
|
72 #ifndef UTMP_FILE |
|
73 #ifdef _PATH_UTMP |
|
74 #define UTMP_FILE _PATH_UTMP |
|
75 #else |
|
76 #define UTMP_FILE "/etc/utmp" |
|
77 #endif |
|
78 #endif |
|
79 |
|
80 #if !defined(WTMP_FILE) && defined(_PATH_WTMP) |
|
81 #define WTMP_FILE _PATH_WTMP |
|
82 #endif |
|
83 |
|
84 #ifndef PARENT_DOES_UTMP |
|
85 #ifdef WTMP_FILE |
|
86 char wtmpf[] = WTMP_FILE; |
|
87 #else |
|
88 char wtmpf[] = "/usr/adm/wtmp"; |
|
89 #endif |
|
90 char utmpf[] = UTMP_FILE; |
|
91 #else /* PARENT_DOES_UTMP */ |
|
92 #ifdef WTMP_FILE |
|
93 char wtmpf[] = WTMP_FILE; |
|
94 #else |
|
95 char wtmpf[] = "/etc/wtmp"; |
|
96 #endif |
|
97 #endif /* PARENT_DOES_UTMP */ |
|
98 |
|
99 #ifdef HAVE_TMPDIR_H |
|
100 #include <tmpdir.h> |
|
101 #endif /* CRAY */ |
|
102 |
|
103 #ifdef STREAMSPTY |
|
104 |
|
105 #ifdef HAVE_SAC_H |
|
106 #include <sac.h> |
|
107 #endif |
|
108 |
|
109 #ifdef HAVE_SYS_STROPTS_H |
|
110 #include <sys/stropts.h> |
|
111 #endif |
|
112 |
|
113 #endif /* STREAMSPTY */ |
|
114 |
|
115 #undef NOERROR |
|
116 |
|
117 #ifdef HAVE_SYS_STREAM_H |
|
118 #ifdef HAVE_SYS_UIO_H |
|
119 #include <sys/uio.h> |
|
120 #endif |
|
121 #ifdef __hpux |
|
122 #undef SE |
|
123 #endif |
|
124 #include <sys/stream.h> |
|
125 #endif |
|
126 #if !(defined(__sgi) || defined(__linux) || defined(_AIX)) && defined(HAVE_SYS_TTY) |
|
127 #include <sys/tty.h> |
|
128 #endif |
|
129 #ifdef t_erase |
|
130 #undef t_erase |
|
131 #undef t_kill |
|
132 #undef t_intrc |
|
133 #undef t_quitc |
|
134 #undef t_startc |
|
135 #undef t_stopc |
|
136 #undef t_eofc |
|
137 #undef t_brkc |
|
138 #undef t_suspc |
|
139 #undef t_dsuspc |
|
140 #undef t_rprntc |
|
141 #undef t_flushc |
|
142 #undef t_werasc |
|
143 #undef t_lnextc |
|
144 #endif |
|
145 |
|
146 #ifdef HAVE_TERMIOS_H |
|
147 #include <termios.h> |
|
148 #else |
|
149 #ifdef HAVE_TERMIO_H |
|
150 #include <termio.h> |
|
151 #endif |
|
152 #endif |
|
153 |
|
154 #ifdef HAVE_UTIL_H |
|
155 #include <util.h> |
|
156 #endif |
|
157 #ifdef HAVE_LIBUTIL_H |
|
158 #include <libutil.h> |
|
159 #endif |
|
160 |
|
161 # ifndef TCSANOW |
|
162 # ifdef TCSETS |
|
163 # define TCSANOW TCSETS |
|
164 # define TCSADRAIN TCSETSW |
|
165 # define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t) |
|
166 # else |
|
167 # ifdef TCSETA |
|
168 # define TCSANOW TCSETA |
|
169 # define TCSADRAIN TCSETAW |
|
170 # define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t) |
|
171 # else |
|
172 # define TCSANOW TIOCSETA |
|
173 # define TCSADRAIN TIOCSETAW |
|
174 # define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t) |
|
175 # endif |
|
176 # endif |
|
177 # define tcsetattr(f, a, t) ioctl(f, a, t) |
|
178 # define cfsetospeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ |
|
179 (tp)->c_cflag |= (val) |
|
180 # define cfgetospeed(tp) ((tp)->c_cflag & CBAUD) |
|
181 # ifdef CIBAUD |
|
182 # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CIBAUD; \ |
|
183 (tp)->c_cflag |= ((val)<<IBSHIFT) |
|
184 # define cfgetispeed(tp) (((tp)->c_cflag & CIBAUD)>>IBSHIFT) |
|
185 # else |
|
186 # define cfsetispeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ |
|
187 (tp)->c_cflag |= (val) |
|
188 # define cfgetispeed(tp) ((tp)->c_cflag & CBAUD) |
|
189 # endif |
|
190 # endif /* TCSANOW */ |
|
191 struct termios termbuf, termbuf2; /* pty control structure */ |
|
192 # ifdef STREAMSPTY |
|
193 static int ttyfd = -1; |
|
194 int really_stream = 0; |
|
195 # endif |
|
196 |
|
197 const char *new_login = _PATH_LOGIN; |
|
198 |
|
199 /* |
|
200 * init_termbuf() |
|
201 * copy_termbuf(cp) |
|
202 * set_termbuf() |
|
203 * |
|
204 * These three routines are used to get and set the "termbuf" structure |
|
205 * to and from the kernel. init_termbuf() gets the current settings. |
|
206 * copy_termbuf() hands in a new "termbuf" to write to the kernel, and |
|
207 * set_termbuf() writes the structure into the kernel. |
|
208 */ |
|
209 |
|
210 void |
|
211 init_termbuf(void) |
|
212 { |
|
213 # ifdef STREAMSPTY |
|
214 if (really_stream) |
|
215 tcgetattr(ttyfd, &termbuf); |
|
216 else |
|
217 # endif |
|
218 tcgetattr(ourpty, &termbuf); |
|
219 termbuf2 = termbuf; |
|
220 } |
|
221 |
|
222 void |
|
223 set_termbuf(void) |
|
224 { |
|
225 /* |
|
226 * Only make the necessary changes. |
|
227 */ |
|
228 if (memcmp(&termbuf, &termbuf2, sizeof(termbuf))) |
|
229 # ifdef STREAMSPTY |
|
230 if (really_stream) |
|
231 tcsetattr(ttyfd, TCSANOW, &termbuf); |
|
232 else |
|
233 # endif |
|
234 tcsetattr(ourpty, TCSANOW, &termbuf); |
|
235 } |
|
236 |
|
237 |
|
238 /* |
|
239 * spcset(func, valp, valpp) |
|
240 * |
|
241 * This function takes various special characters (func), and |
|
242 * sets *valp to the current value of that character, and |
|
243 * *valpp to point to where in the "termbuf" structure that |
|
244 * value is kept. |
|
245 * |
|
246 * It returns the SLC_ level of support for this function. |
|
247 */ |
|
248 |
|
249 |
|
250 int |
|
251 spcset(int func, cc_t *valp, cc_t **valpp) |
|
252 { |
|
253 |
|
254 #define setval(a, b) *valp = termbuf.c_cc[a]; \ |
|
255 *valpp = &termbuf.c_cc[a]; \ |
|
256 return(b); |
|
257 #define defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT); |
|
258 |
|
259 switch(func) { |
|
260 case SLC_EOF: |
|
261 setval(VEOF, SLC_VARIABLE); |
|
262 case SLC_EC: |
|
263 setval(VERASE, SLC_VARIABLE); |
|
264 case SLC_EL: |
|
265 setval(VKILL, SLC_VARIABLE); |
|
266 case SLC_IP: |
|
267 setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); |
|
268 case SLC_ABORT: |
|
269 setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); |
|
270 case SLC_XON: |
|
271 #ifdef VSTART |
|
272 setval(VSTART, SLC_VARIABLE); |
|
273 #else |
|
274 defval(0x13); |
|
275 #endif |
|
276 case SLC_XOFF: |
|
277 #ifdef VSTOP |
|
278 setval(VSTOP, SLC_VARIABLE); |
|
279 #else |
|
280 defval(0x11); |
|
281 #endif |
|
282 case SLC_EW: |
|
283 #ifdef VWERASE |
|
284 setval(VWERASE, SLC_VARIABLE); |
|
285 #else |
|
286 defval(0); |
|
287 #endif |
|
288 case SLC_RP: |
|
289 #ifdef VREPRINT |
|
290 setval(VREPRINT, SLC_VARIABLE); |
|
291 #else |
|
292 defval(0); |
|
293 #endif |
|
294 case SLC_LNEXT: |
|
295 #ifdef VLNEXT |
|
296 setval(VLNEXT, SLC_VARIABLE); |
|
297 #else |
|
298 defval(0); |
|
299 #endif |
|
300 case SLC_AO: |
|
301 #if !defined(VDISCARD) && defined(VFLUSHO) |
|
302 # define VDISCARD VFLUSHO |
|
303 #endif |
|
304 #ifdef VDISCARD |
|
305 setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT); |
|
306 #else |
|
307 defval(0); |
|
308 #endif |
|
309 case SLC_SUSP: |
|
310 #ifdef VSUSP |
|
311 setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN); |
|
312 #else |
|
313 defval(0); |
|
314 #endif |
|
315 #ifdef VEOL |
|
316 case SLC_FORW1: |
|
317 setval(VEOL, SLC_VARIABLE); |
|
318 #endif |
|
319 #ifdef VEOL2 |
|
320 case SLC_FORW2: |
|
321 setval(VEOL2, SLC_VARIABLE); |
|
322 #endif |
|
323 case SLC_AYT: |
|
324 #ifdef VSTATUS |
|
325 setval(VSTATUS, SLC_VARIABLE); |
|
326 #else |
|
327 defval(0); |
|
328 #endif |
|
329 |
|
330 case SLC_BRK: |
|
331 case SLC_SYNCH: |
|
332 case SLC_EOR: |
|
333 defval(0); |
|
334 |
|
335 default: |
|
336 *valp = 0; |
|
337 *valpp = 0; |
|
338 return(SLC_NOSUPPORT); |
|
339 } |
|
340 } |
|
341 |
|
342 #ifdef _CRAY |
|
343 /* |
|
344 * getnpty() |
|
345 * |
|
346 * Return the number of pty's configured into the system. |
|
347 */ |
|
348 int |
|
349 getnpty() |
|
350 { |
|
351 #ifdef _SC_CRAY_NPTY |
|
352 int numptys; |
|
353 |
|
354 if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1) |
|
355 return numptys; |
|
356 else |
|
357 #endif /* _SC_CRAY_NPTY */ |
|
358 return 128; |
|
359 } |
|
360 #endif /* CRAY */ |
|
361 |
|
362 /* |
|
363 * getpty() |
|
364 * |
|
365 * Allocate a pty. As a side effect, the external character |
|
366 * array "line" contains the name of the slave side. |
|
367 * |
|
368 * Returns the file descriptor of the opened pty. |
|
369 */ |
|
370 |
|
371 static char Xline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; |
|
372 char *line = Xline; |
|
373 |
|
374 #ifdef _CRAY |
|
375 char myline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; |
|
376 #endif /* CRAY */ |
|
377 |
|
378 #if !defined(HAVE_PTSNAME) && defined(STREAMSPTY) |
|
379 static char *ptsname(int fd) |
|
380 { |
|
381 #ifdef HAVE_TTYNAME |
|
382 return ttyname(fd); |
|
383 #else |
|
384 return NULL; |
|
385 #endif |
|
386 } |
|
387 #endif |
|
388 |
|
389 int getpty(int *ptynum) |
|
390 { |
|
391 #ifdef __osf__ /* XXX */ |
|
392 int master; |
|
393 int slave; |
|
394 if(openpty(&master, &slave, line, 0, 0) == 0){ |
|
395 close(slave); |
|
396 return master; |
|
397 } |
|
398 return -1; |
|
399 #else |
|
400 #ifdef HAVE__GETPTY |
|
401 int master, slave; |
|
402 char *p; |
|
403 p = _getpty(&master, O_RDWR, 0600, 1); |
|
404 if(p == NULL) |
|
405 return -1; |
|
406 strlcpy(line, p, sizeof(Xline)); |
|
407 return master; |
|
408 #else |
|
409 |
|
410 int p; |
|
411 char *cp, *p1, *p2; |
|
412 int i; |
|
413 #if SunOS == 40 |
|
414 int dummy; |
|
415 #endif |
|
416 #if __linux |
|
417 int master; |
|
418 int slave; |
|
419 if(openpty(&master, &slave, line, 0, 0) == 0){ |
|
420 close(slave); |
|
421 return master; |
|
422 } |
|
423 #else |
|
424 #ifdef STREAMSPTY |
|
425 char *clone[] = { "/dev/ptc", "/dev/ptmx", "/dev/ptm", |
|
426 "/dev/ptym/clone", 0 }; |
|
427 |
|
428 char **q; |
|
429 for(q=clone; *q; q++){ |
|
430 p=open(*q, O_RDWR); |
|
431 if(p >= 0){ |
|
432 #ifdef HAVE_GRANTPT |
|
433 grantpt(p); |
|
434 #endif |
|
435 #ifdef HAVE_UNLOCKPT |
|
436 unlockpt(p); |
|
437 #endif |
|
438 strlcpy(line, ptsname(p), sizeof(Xline)); |
|
439 really_stream = 1; |
|
440 return p; |
|
441 } |
|
442 } |
|
443 #endif /* STREAMSPTY */ |
|
444 #ifndef _CRAY |
|
445 |
|
446 #ifndef __hpux |
|
447 snprintf(line, sizeof(Xline), "/dev/ptyXX"); |
|
448 p1 = &line[8]; |
|
449 p2 = &line[9]; |
|
450 #else |
|
451 snprintf(line, sizeof(Xline), "/dev/ptym/ptyXX"); |
|
452 p1 = &line[13]; |
|
453 p2 = &line[14]; |
|
454 #endif |
|
455 |
|
456 |
|
457 for (cp = "pqrstuvwxyzPQRST"; *cp; cp++) { |
|
458 struct stat stb; |
|
459 |
|
460 *p1 = *cp; |
|
461 *p2 = '0'; |
|
462 /* |
|
463 * This stat() check is just to keep us from |
|
464 * looping through all 256 combinations if there |
|
465 * aren't that many ptys available. |
|
466 */ |
|
467 if (stat(line, &stb) < 0) |
|
468 break; |
|
469 for (i = 0; i < 16; i++) { |
|
470 *p2 = "0123456789abcdef"[i]; |
|
471 p = open(line, O_RDWR); |
|
472 if (p > 0) { |
|
473 #ifndef __hpux |
|
474 line[5] = 't'; |
|
475 #else |
|
476 for (p1 = &line[8]; *p1; p1++) |
|
477 *p1 = *(p1+1); |
|
478 line[9] = 't'; |
|
479 #endif |
|
480 chown(line, 0, 0); |
|
481 chmod(line, 0600); |
|
482 #if SunOS == 40 |
|
483 if (ioctl(p, TIOCGPGRP, &dummy) == 0 |
|
484 || errno != EIO) { |
|
485 chmod(line, 0666); |
|
486 close(p); |
|
487 line[5] = 'p'; |
|
488 } else |
|
489 #endif /* SunOS == 40 */ |
|
490 return(p); |
|
491 } |
|
492 } |
|
493 } |
|
494 #else /* CRAY */ |
|
495 extern lowpty, highpty; |
|
496 struct stat sb; |
|
497 |
|
498 for (*ptynum = lowpty; *ptynum <= highpty; (*ptynum)++) { |
|
499 snprintf(myline, sizeof(myline), "/dev/pty/%03d", *ptynum); |
|
500 p = open(myline, 2); |
|
501 if (p < 0) |
|
502 continue; |
|
503 snprintf(line, sizeof(Xline), "/dev/ttyp%03d", *ptynum); |
|
504 /* |
|
505 * Here are some shenanigans to make sure that there |
|
506 * are no listeners lurking on the line. |
|
507 */ |
|
508 if(stat(line, &sb) < 0) { |
|
509 close(p); |
|
510 continue; |
|
511 } |
|
512 if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) { |
|
513 chown(line, 0, 0); |
|
514 chmod(line, 0600); |
|
515 close(p); |
|
516 p = open(myline, 2); |
|
517 if (p < 0) |
|
518 continue; |
|
519 } |
|
520 /* |
|
521 * Now it should be safe...check for accessability. |
|
522 */ |
|
523 if (access(line, 6) == 0) |
|
524 return(p); |
|
525 else { |
|
526 /* no tty side to pty so skip it */ |
|
527 close(p); |
|
528 } |
|
529 } |
|
530 #endif /* CRAY */ |
|
531 #endif /* STREAMSPTY */ |
|
532 #endif /* OPENPTY */ |
|
533 return(-1); |
|
534 #endif |
|
535 } |
|
536 |
|
537 |
|
538 int |
|
539 tty_isecho(void) |
|
540 { |
|
541 return (termbuf.c_lflag & ECHO); |
|
542 } |
|
543 |
|
544 int |
|
545 tty_flowmode(void) |
|
546 { |
|
547 return((termbuf.c_iflag & IXON) ? 1 : 0); |
|
548 } |
|
549 |
|
550 int |
|
551 tty_restartany(void) |
|
552 { |
|
553 return((termbuf.c_iflag & IXANY) ? 1 : 0); |
|
554 } |
|
555 |
|
556 void |
|
557 tty_setecho(int on) |
|
558 { |
|
559 if (on) |
|
560 termbuf.c_lflag |= ECHO; |
|
561 else |
|
562 termbuf.c_lflag &= ~ECHO; |
|
563 } |
|
564 |
|
565 int |
|
566 tty_israw(void) |
|
567 { |
|
568 return(!(termbuf.c_lflag & ICANON)); |
|
569 } |
|
570 |
|
571 void |
|
572 tty_binaryin(int on) |
|
573 { |
|
574 if (on) { |
|
575 termbuf.c_iflag &= ~ISTRIP; |
|
576 } else { |
|
577 termbuf.c_iflag |= ISTRIP; |
|
578 } |
|
579 } |
|
580 |
|
581 void |
|
582 tty_binaryout(int on) |
|
583 { |
|
584 if (on) { |
|
585 termbuf.c_cflag &= ~(CSIZE|PARENB); |
|
586 termbuf.c_cflag |= CS8; |
|
587 termbuf.c_oflag &= ~OPOST; |
|
588 } else { |
|
589 termbuf.c_cflag &= ~CSIZE; |
|
590 termbuf.c_cflag |= CS7|PARENB; |
|
591 termbuf.c_oflag |= OPOST; |
|
592 } |
|
593 } |
|
594 |
|
595 int |
|
596 tty_isbinaryin(void) |
|
597 { |
|
598 return(!(termbuf.c_iflag & ISTRIP)); |
|
599 } |
|
600 |
|
601 int |
|
602 tty_isbinaryout(void) |
|
603 { |
|
604 return(!(termbuf.c_oflag&OPOST)); |
|
605 } |
|
606 |
|
607 |
|
608 int |
|
609 tty_issofttab(void) |
|
610 { |
|
611 # ifdef OXTABS |
|
612 return (termbuf.c_oflag & OXTABS); |
|
613 # endif |
|
614 # ifdef TABDLY |
|
615 return ((termbuf.c_oflag & TABDLY) == TAB3); |
|
616 # endif |
|
617 } |
|
618 |
|
619 void |
|
620 tty_setsofttab(int on) |
|
621 { |
|
622 if (on) { |
|
623 # ifdef OXTABS |
|
624 termbuf.c_oflag |= OXTABS; |
|
625 # endif |
|
626 # ifdef TABDLY |
|
627 termbuf.c_oflag &= ~TABDLY; |
|
628 termbuf.c_oflag |= TAB3; |
|
629 # endif |
|
630 } else { |
|
631 # ifdef OXTABS |
|
632 termbuf.c_oflag &= ~OXTABS; |
|
633 # endif |
|
634 # ifdef TABDLY |
|
635 termbuf.c_oflag &= ~TABDLY; |
|
636 termbuf.c_oflag |= TAB0; |
|
637 # endif |
|
638 } |
|
639 } |
|
640 |
|
641 int |
|
642 tty_islitecho(void) |
|
643 { |
|
644 # ifdef ECHOCTL |
|
645 return (!(termbuf.c_lflag & ECHOCTL)); |
|
646 # endif |
|
647 # ifdef TCTLECH |
|
648 return (!(termbuf.c_lflag & TCTLECH)); |
|
649 # endif |
|
650 # if !defined(ECHOCTL) && !defined(TCTLECH) |
|
651 return (0); /* assumes ctl chars are echoed '^x' */ |
|
652 # endif |
|
653 } |
|
654 |
|
655 void |
|
656 tty_setlitecho(int on) |
|
657 { |
|
658 # ifdef ECHOCTL |
|
659 if (on) |
|
660 termbuf.c_lflag &= ~ECHOCTL; |
|
661 else |
|
662 termbuf.c_lflag |= ECHOCTL; |
|
663 # endif |
|
664 # ifdef TCTLECH |
|
665 if (on) |
|
666 termbuf.c_lflag &= ~TCTLECH; |
|
667 else |
|
668 termbuf.c_lflag |= TCTLECH; |
|
669 # endif |
|
670 } |
|
671 |
|
672 int |
|
673 tty_iscrnl(void) |
|
674 { |
|
675 return (termbuf.c_iflag & ICRNL); |
|
676 } |
|
677 |
|
678 /* |
|
679 * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD). |
|
680 */ |
|
681 #if B4800 != 4800 |
|
682 #define DECODE_BAUD |
|
683 #endif |
|
684 |
|
685 #ifdef DECODE_BAUD |
|
686 |
|
687 /* |
|
688 * A table of available terminal speeds |
|
689 */ |
|
690 struct termspeeds { |
|
691 int speed; |
|
692 int value; |
|
693 } termspeeds[] = { |
|
694 { 0, B0 }, { 50, B50 }, { 75, B75 }, |
|
695 { 110, B110 }, { 134, B134 }, { 150, B150 }, |
|
696 { 200, B200 }, { 300, B300 }, { 600, B600 }, |
|
697 { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, |
|
698 { 4800, B4800 }, |
|
699 #ifdef B7200 |
|
700 { 7200, B7200 }, |
|
701 #endif |
|
702 { 9600, B9600 }, |
|
703 #ifdef B14400 |
|
704 { 14400, B14400 }, |
|
705 #endif |
|
706 #ifdef B19200 |
|
707 { 19200, B19200 }, |
|
708 #endif |
|
709 #ifdef B28800 |
|
710 { 28800, B28800 }, |
|
711 #endif |
|
712 #ifdef B38400 |
|
713 { 38400, B38400 }, |
|
714 #endif |
|
715 #ifdef B57600 |
|
716 { 57600, B57600 }, |
|
717 #endif |
|
718 #ifdef B115200 |
|
719 { 115200, B115200 }, |
|
720 #endif |
|
721 #ifdef B230400 |
|
722 { 230400, B230400 }, |
|
723 #endif |
|
724 { -1, 0 } |
|
725 }; |
|
726 #endif /* DECODE_BUAD */ |
|
727 |
|
728 void |
|
729 tty_tspeed(int val) |
|
730 { |
|
731 #ifdef DECODE_BAUD |
|
732 struct termspeeds *tp; |
|
733 |
|
734 for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) |
|
735 ; |
|
736 if (tp->speed == -1) /* back up to last valid value */ |
|
737 --tp; |
|
738 cfsetospeed(&termbuf, tp->value); |
|
739 #else /* DECODE_BUAD */ |
|
740 cfsetospeed(&termbuf, val); |
|
741 #endif /* DECODE_BUAD */ |
|
742 } |
|
743 |
|
744 void |
|
745 tty_rspeed(int val) |
|
746 { |
|
747 #ifdef DECODE_BAUD |
|
748 struct termspeeds *tp; |
|
749 |
|
750 for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) |
|
751 ; |
|
752 if (tp->speed == -1) /* back up to last valid value */ |
|
753 --tp; |
|
754 cfsetispeed(&termbuf, tp->value); |
|
755 #else /* DECODE_BAUD */ |
|
756 cfsetispeed(&termbuf, val); |
|
757 #endif /* DECODE_BAUD */ |
|
758 } |
|
759 |
|
760 #ifdef PARENT_DOES_UTMP |
|
761 extern struct utmp wtmp; |
|
762 extern char wtmpf[]; |
|
763 |
|
764 extern void utmp_sig_init (void); |
|
765 extern void utmp_sig_reset (void); |
|
766 extern void utmp_sig_wait (void); |
|
767 extern void utmp_sig_notify (int); |
|
768 # endif /* PARENT_DOES_UTMP */ |
|
769 |
|
770 #ifdef STREAMSPTY |
|
771 |
|
772 /* I_FIND seems to live a life of its own */ |
|
773 static int my_find(int fd, char *module) |
|
774 { |
|
775 #if defined(I_FIND) && defined(I_LIST) |
|
776 static int flag; |
|
777 static struct str_list sl; |
|
778 int n; |
|
779 int i; |
|
780 |
|
781 if(!flag){ |
|
782 n = ioctl(fd, I_LIST, 0); |
|
783 if(n < 0){ |
|
784 perror("ioctl(fd, I_LIST, 0)"); |
|
785 return -1; |
|
786 } |
|
787 sl.sl_modlist=(struct str_mlist*)malloc(n * sizeof(struct str_mlist)); |
|
788 sl.sl_nmods = n; |
|
789 n = ioctl(fd, I_LIST, &sl); |
|
790 if(n < 0){ |
|
791 perror("ioctl(fd, I_LIST, n)"); |
|
792 return -1; |
|
793 } |
|
794 flag = 1; |
|
795 } |
|
796 |
|
797 for(i=0; i<sl.sl_nmods; i++) |
|
798 if(!strcmp(sl.sl_modlist[i].l_name, module)) |
|
799 return 1; |
|
800 #endif |
|
801 return 0; |
|
802 } |
|
803 |
|
804 static void maybe_push_modules(int fd, char **modules) |
|
805 { |
|
806 char **p; |
|
807 int err; |
|
808 |
|
809 for(p=modules; *p; p++){ |
|
810 err = my_find(fd, *p); |
|
811 if(err == 1) |
|
812 break; |
|
813 if(err < 0 && errno != EINVAL) |
|
814 fatalperror(net, "my_find()"); |
|
815 /* module not pushed or does not exist */ |
|
816 } |
|
817 /* p points to null or to an already pushed module, now push all |
|
818 modules before this one */ |
|
819 |
|
820 for(p--; p >= modules; p--){ |
|
821 err = ioctl(fd, I_PUSH, *p); |
|
822 if(err < 0 && errno != EINVAL) |
|
823 fatalperror(net, "I_PUSH"); |
|
824 } |
|
825 } |
|
826 #endif |
|
827 |
|
828 /* |
|
829 * getptyslave() |
|
830 * |
|
831 * Open the slave side of the pty, and do any initialization |
|
832 * that is necessary. The return value is a file descriptor |
|
833 * for the slave side. |
|
834 */ |
|
835 void getptyslave(void) |
|
836 { |
|
837 int t = -1; |
|
838 |
|
839 struct winsize ws; |
|
840 /* |
|
841 * Opening the slave side may cause initilization of the |
|
842 * kernel tty structure. We need remember the state of |
|
843 * if linemode was turned on |
|
844 * terminal window size |
|
845 * terminal speed |
|
846 * so that we can re-set them if we need to. |
|
847 */ |
|
848 |
|
849 |
|
850 /* |
|
851 * Make sure that we don't have a controlling tty, and |
|
852 * that we are the session (process group) leader. |
|
853 */ |
|
854 |
|
855 #ifdef HAVE_SETSID |
|
856 if(setsid()<0) |
|
857 fatalperror(net, "setsid()"); |
|
858 #else |
|
859 # ifdef TIOCNOTTY |
|
860 t = open(_PATH_TTY, O_RDWR); |
|
861 if (t >= 0) { |
|
862 ioctl(t, TIOCNOTTY, (char *)0); |
|
863 close(t); |
|
864 } |
|
865 # endif |
|
866 #endif |
|
867 |
|
868 # ifdef PARENT_DOES_UTMP |
|
869 /* |
|
870 * Wait for our parent to get the utmp stuff to get done. |
|
871 */ |
|
872 utmp_sig_wait(); |
|
873 # endif |
|
874 |
|
875 t = cleanopen(line); |
|
876 if (t < 0) |
|
877 fatalperror(net, line); |
|
878 |
|
879 #ifdef STREAMSPTY |
|
880 ttyfd = t; |
|
881 |
|
882 |
|
883 /* |
|
884 * Not all systems have (or need) modules ttcompat and pckt so |
|
885 * don't flag it as a fatal error if they don't exist. |
|
886 */ |
|
887 |
|
888 if (really_stream) |
|
889 { |
|
890 /* these are the streams modules that we want pushed. note |
|
891 that they are in reverse order, ptem will be pushed |
|
892 first. maybe_push_modules() will try to push all modules |
|
893 before the first one that isn't already pushed. i.e if |
|
894 ldterm is pushed, only ttcompat will be attempted. |
|
895 |
|
896 all this is because we don't know which modules are |
|
897 available, and we don't know which modules are already |
|
898 pushed (via autopush, for instance). |
|
899 |
|
900 */ |
|
901 |
|
902 char *ttymodules[] = { "ttcompat", "ldterm", "ptem", NULL }; |
|
903 char *ptymodules[] = { "pckt", NULL }; |
|
904 |
|
905 maybe_push_modules(t, ttymodules); |
|
906 maybe_push_modules(ourpty, ptymodules); |
|
907 } |
|
908 #endif |
|
909 /* |
|
910 * set up the tty modes as we like them to be. |
|
911 */ |
|
912 init_termbuf(); |
|
913 # ifdef TIOCSWINSZ |
|
914 if (def_row || def_col) { |
|
915 memset(&ws, 0, sizeof(ws)); |
|
916 ws.ws_col = def_col; |
|
917 ws.ws_row = def_row; |
|
918 ioctl(t, TIOCSWINSZ, (char *)&ws); |
|
919 } |
|
920 # endif |
|
921 |
|
922 /* |
|
923 * Settings for sgtty based systems |
|
924 */ |
|
925 |
|
926 /* |
|
927 * Settings for UNICOS (and HPUX) |
|
928 */ |
|
929 # if defined(_CRAY) || defined(__hpux) |
|
930 termbuf.c_oflag = OPOST|ONLCR|TAB3; |
|
931 termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON; |
|
932 termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK; |
|
933 termbuf.c_cflag = EXTB|HUPCL|CS8; |
|
934 # endif |
|
935 |
|
936 /* |
|
937 * Settings for all other termios/termio based |
|
938 * systems, other than 4.4BSD. In 4.4BSD the |
|
939 * kernel does the initial terminal setup. |
|
940 */ |
|
941 # if !(defined(_CRAY) || defined(__hpux)) && (BSD <= 43) |
|
942 # ifndef OXTABS |
|
943 # define OXTABS 0 |
|
944 # endif |
|
945 termbuf.c_lflag |= ECHO; |
|
946 termbuf.c_oflag |= ONLCR|OXTABS; |
|
947 termbuf.c_iflag |= ICRNL; |
|
948 termbuf.c_iflag &= ~IXOFF; |
|
949 # endif |
|
950 tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600); |
|
951 tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600); |
|
952 |
|
953 /* |
|
954 * Set the tty modes, and make this our controlling tty. |
|
955 */ |
|
956 set_termbuf(); |
|
957 if (login_tty(t) == -1) |
|
958 fatalperror(net, "login_tty"); |
|
959 if (net > 2) |
|
960 close(net); |
|
961 if (ourpty > 2) { |
|
962 close(ourpty); |
|
963 ourpty = -1; |
|
964 } |
|
965 } |
|
966 |
|
967 #ifndef O_NOCTTY |
|
968 #define O_NOCTTY 0 |
|
969 #endif |
|
970 /* |
|
971 * Open the specified slave side of the pty, |
|
972 * making sure that we have a clean tty. |
|
973 */ |
|
974 |
|
975 int cleanopen(char *line) |
|
976 { |
|
977 int t; |
|
978 |
|
979 #ifdef STREAMSPTY |
|
980 if (!really_stream) |
|
981 #endif |
|
982 { |
|
983 /* |
|
984 * Make sure that other people can't open the |
|
985 * slave side of the connection. |
|
986 */ |
|
987 chown(line, 0, 0); |
|
988 chmod(line, 0600); |
|
989 } |
|
990 |
|
991 #ifdef HAVE_REVOKE |
|
992 revoke(line); |
|
993 #endif |
|
994 |
|
995 t = open(line, O_RDWR|O_NOCTTY); |
|
996 |
|
997 if (t < 0) |
|
998 return(-1); |
|
999 |
|
1000 /* |
|
1001 * Hangup anybody else using this ttyp, then reopen it for |
|
1002 * ourselves. |
|
1003 */ |
|
1004 # if !(defined(_CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(STREAMSPTY) |
|
1005 signal(SIGHUP, SIG_IGN); |
|
1006 #ifdef HAVE_VHANGUP |
|
1007 vhangup(); |
|
1008 #else |
|
1009 #endif |
|
1010 signal(SIGHUP, SIG_DFL); |
|
1011 t = open(line, O_RDWR|O_NOCTTY); |
|
1012 if (t < 0) |
|
1013 return(-1); |
|
1014 # endif |
|
1015 # if defined(_CRAY) && defined(TCVHUP) |
|
1016 { |
|
1017 int i; |
|
1018 signal(SIGHUP, SIG_IGN); |
|
1019 ioctl(t, TCVHUP, (char *)0); |
|
1020 signal(SIGHUP, SIG_DFL); |
|
1021 |
|
1022 i = open(line, O_RDWR); |
|
1023 |
|
1024 if (i < 0) |
|
1025 return(-1); |
|
1026 close(t); |
|
1027 t = i; |
|
1028 } |
|
1029 # endif /* defined(CRAY) && defined(TCVHUP) */ |
|
1030 return(t); |
|
1031 } |
|
1032 |
|
1033 //#if !defined(BSD4_4) |
|
1034 |
|
1035 int login_tty(int t) |
|
1036 { |
|
1037 # if defined(TIOCSCTTY) && !defined(__hpux) |
|
1038 if (ioctl(t, TIOCSCTTY, (char *)0) < 0) |
|
1039 fatalperror(net, "ioctl(sctty)"); |
|
1040 # ifdef _CRAY |
|
1041 /* |
|
1042 * Close the hard fd to /dev/ttypXXX, and re-open through |
|
1043 * the indirect /dev/tty interface. |
|
1044 */ |
|
1045 close(t); |
|
1046 if ((t = open("/dev/tty", O_RDWR)) < 0) |
|
1047 fatalperror(net, "open(/dev/tty)"); |
|
1048 # endif |
|
1049 # else |
|
1050 /* |
|
1051 * We get our controlling tty assigned as a side-effect |
|
1052 * of opening up a tty device. But on BSD based systems, |
|
1053 * this only happens if our process group is zero. The |
|
1054 * setsid() call above may have set our pgrp, so clear |
|
1055 * it out before opening the tty... |
|
1056 */ |
|
1057 #ifdef HAVE_SETPGID |
|
1058 setpgid(0, 0); |
|
1059 #else |
|
1060 setpgrp(0, 0); /* if setpgid isn't available, setpgrp |
|
1061 probably takes arguments */ |
|
1062 #endif |
|
1063 close(open(line, O_RDWR)); |
|
1064 # endif |
|
1065 if (t != 0) |
|
1066 dup2(t, 0); |
|
1067 if (t != 1) |
|
1068 dup2(t, 1); |
|
1069 if (t != 2) |
|
1070 dup2(t, 2); |
|
1071 if (t > 2) |
|
1072 close(t); |
|
1073 return(0); |
|
1074 } |
|
1075 //#endif /* BSD <= 43 */ |
|
1076 |
|
1077 /* |
|
1078 * This comes from ../../bsd/tty.c and should not really be here. |
|
1079 */ |
|
1080 |
|
1081 /* |
|
1082 * Clean the tty name. Return a pointer to the cleaned version. |
|
1083 */ |
|
1084 #ifndef __SYMBIAN32__ |
|
1085 static char * |
|
1086 clean_ttyname (char *tty) |
|
1087 { |
|
1088 char *res = tty; |
|
1089 |
|
1090 if (strncmp (res, _PATH_DEV, strlen(_PATH_DEV)) == 0) |
|
1091 res += strlen(_PATH_DEV); |
|
1092 if (strncmp (res, "pty/", 4) == 0) |
|
1093 res += 4; |
|
1094 if (strncmp (res, "ptym/", 5) == 0) |
|
1095 res += 5; |
|
1096 return res; |
|
1097 } |
|
1098 #endif |
|
1099 /* |
|
1100 * Generate a name usable as an `ut_id', typically without `tty'. |
|
1101 */ |
|
1102 |
|
1103 #ifdef HAVE_STRUCT_UTMP_UT_ID |
|
1104 static char * |
|
1105 make_id (char *tty) |
|
1106 { |
|
1107 char *res = tty; |
|
1108 |
|
1109 if (strncmp (res, "pts/", 4) == 0) |
|
1110 res += 4; |
|
1111 if (strncmp (res, "tty", 3) == 0) |
|
1112 res += 3; |
|
1113 return res; |
|
1114 } |
|
1115 #endif |
|
1116 |
|
1117 |
|
1118 /* |
|
1119 * startslave(host) |
|
1120 * |
|
1121 * Given a hostname, do whatever |
|
1122 * is necessary to startup the login process on the slave side of the pty. |
|
1123 */ |
|
1124 |
|
1125 /* ARGSUSED */ |
|
1126 void |
|
1127 startslave(const char *host, const char *utmp_host, |
|
1128 int autologin, char *autoname) |
|
1129 { |
|
1130 #ifndef __SYMBIAN32__ |
|
1131 int i; |
|
1132 #else |
|
1133 int fds[3]; |
|
1134 int pid; |
|
1135 #endif |
|
1136 |
|
1137 #ifdef AUTHENTICATION |
|
1138 if (!autoname || !autoname[0]) |
|
1139 autologin = 0; |
|
1140 |
|
1141 if (autologin < auth_level) { |
|
1142 fatal(net, "Authorization failed"); |
|
1143 exit(1); |
|
1144 } |
|
1145 #endif |
|
1146 |
|
1147 { |
|
1148 char *tbuf = |
|
1149 "\r\n*** Connection not encrypted! " |
|
1150 "Communication may be eavesdropped. ***\r\n"; |
|
1151 #ifdef ENCRYPTION |
|
1152 if (!no_warn && (encrypt_output == 0 || decrypt_input == 0)) |
|
1153 #endif |
|
1154 writenet((unsigned char*)tbuf, strlen(tbuf)); |
|
1155 } |
|
1156 # ifdef PARENT_DOES_UTMP |
|
1157 utmp_sig_init(); |
|
1158 # endif /* PARENT_DOES_UTMP */ |
|
1159 |
|
1160 #ifdef __SYMBIAN32__ |
|
1161 pid=popen3("Z:\\sys\\bin\\zsh.exe", NULL, NULL, fds); |
|
1162 |
|
1163 if (pid==-1) |
|
1164 { |
|
1165 fatalperror(net, "popen3"); |
|
1166 } |
|
1167 #endif //__SYMBIAN32__ |
|
1168 |
|
1169 #ifndef __SYMBIAN32__ |
|
1170 if ((i = fork()) < 0) |
|
1171 fatalperror(net, "fork"); |
|
1172 if (i) { |
|
1173 # ifdef PARENT_DOES_UTMP |
|
1174 /* |
|
1175 * Cray parent will create utmp entry for child and send |
|
1176 * signal to child to tell when done. Child waits for signal |
|
1177 * before doing anything important. |
|
1178 */ |
|
1179 int pid = i; |
|
1180 void sigjob (int); |
|
1181 |
|
1182 setpgrp(); |
|
1183 utmp_sig_reset(); /* reset handler to default */ |
|
1184 /* |
|
1185 * Create utmp entry for child |
|
1186 */ |
|
1187 wtmp.ut_time = time(NULL); |
|
1188 wtmp.ut_type = LOGIN_PROCESS; |
|
1189 wtmp.ut_pid = pid; |
|
1190 strncpy(wtmp.ut_user, "LOGIN", sizeof(wtmp.ut_user)); |
|
1191 strncpy(wtmp.ut_host, utmp_host, sizeof(wtmp.ut_host)); |
|
1192 strncpy(wtmp.ut_line, clean_ttyname(line), sizeof(wtmp.ut_line)); |
|
1193 #ifdef HAVE_STRUCT_UTMP_UT_ID |
|
1194 strncpy(wtmp.ut_id, wtmp.ut_line + 3, sizeof(wtmp.ut_id)); |
|
1195 #endif |
|
1196 |
|
1197 pututline(&wtmp); |
|
1198 endutent(); |
|
1199 if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) { |
|
1200 write(i, &wtmp, sizeof(struct utmp)); |
|
1201 close(i); |
|
1202 } |
|
1203 #ifdef _CRAY |
|
1204 signal(WJSIGNAL, sigjob); |
|
1205 #endif |
|
1206 utmp_sig_notify(pid); |
|
1207 # endif /* PARENT_DOES_UTMP */ |
|
1208 } else { |
|
1209 getptyslave(); |
|
1210 #if defined(DCE) |
|
1211 /* if we authenticated via K5, try and join the PAG */ |
|
1212 kerberos5_dfspag(); |
|
1213 #endif |
|
1214 start_login(host, autologin, autoname); |
|
1215 /*NOTREACHED*/ |
|
1216 } |
|
1217 #endif//__SYMBIAN32__ |
|
1218 } |
|
1219 |
|
1220 |
|
1221 char *envinit[3]; |
|
1222 #ifndef __SYMBIAN32__ |
|
1223 extern char **environ; |
|
1224 #endif |
|
1225 |
|
1226 void |
|
1227 init_env(void) |
|
1228 { |
|
1229 char **envp; |
|
1230 |
|
1231 envp = envinit; |
|
1232 *envp = getenv("TZ"); |
|
1233 if (*envp) |
|
1234 *envp++ -= 3; |
|
1235 #if defined(_CRAY) || defined(__hpux) |
|
1236 else |
|
1237 *envp++ = "TZ=GMT0"; |
|
1238 #endif |
|
1239 *envp = 0; |
|
1240 environ = envinit; |
|
1241 } |
|
1242 |
|
1243 /* |
|
1244 * scrub_env() |
|
1245 * |
|
1246 * We only accept the environment variables listed below. |
|
1247 */ |
|
1248 #ifndef __SYMBIAN32__ |
|
1249 static void |
|
1250 scrub_env(void) |
|
1251 { |
|
1252 static const char *reject[] = { |
|
1253 "TERMCAP=/", |
|
1254 NULL |
|
1255 }; |
|
1256 |
|
1257 static const char *accept[] = { |
|
1258 "XAUTH=", "XAUTHORITY=", "DISPLAY=", |
|
1259 "TERM=", |
|
1260 "EDITOR=", |
|
1261 "PAGER=", |
|
1262 "PRINTER=", |
|
1263 "LOGNAME=", |
|
1264 "POSIXLY_CORRECT=", |
|
1265 "TERMCAP=", |
|
1266 NULL |
|
1267 }; |
|
1268 |
|
1269 char **cpp, **cpp2; |
|
1270 const char **p; |
|
1271 |
|
1272 for (cpp2 = cpp = environ; *cpp; cpp++) { |
|
1273 int reject_it = 0; |
|
1274 |
|
1275 for(p = reject; *p; p++) |
|
1276 if(strncmp(*cpp, *p, strlen(*p)) == 0) { |
|
1277 reject_it = 1; |
|
1278 break; |
|
1279 } |
|
1280 if (reject_it) |
|
1281 continue; |
|
1282 |
|
1283 for(p = accept; *p; p++) |
|
1284 if(strncmp(*cpp, *p, strlen(*p)) == 0) |
|
1285 break; |
|
1286 if(*p != NULL) |
|
1287 *cpp2++ = *cpp; |
|
1288 } |
|
1289 *cpp2 = NULL; |
|
1290 } |
|
1291 #endif |
|
1292 |
|
1293 struct arg_val { |
|
1294 int size; |
|
1295 int argc; |
|
1296 const char **argv; |
|
1297 }; |
|
1298 |
|
1299 #ifndef __SYMBIAN32__ |
|
1300 static void addarg(struct arg_val*, const char*); |
|
1301 /* |
|
1302 * start_login(host) |
|
1303 * |
|
1304 * Assuming that we are now running as a child processes, this |
|
1305 * function will turn us into the login process. |
|
1306 */ |
|
1307 |
|
1308 void |
|
1309 start_login(const char *host, int autologin, char *name) |
|
1310 { |
|
1311 struct arg_val argv; |
|
1312 char *user; |
|
1313 int save_errno; |
|
1314 |
|
1315 #ifdef HAVE_UTMPX_H |
|
1316 int pid = getpid(); |
|
1317 struct utmpx utmpx; |
|
1318 char *clean_tty; |
|
1319 |
|
1320 /* |
|
1321 * Create utmp entry for child |
|
1322 */ |
|
1323 |
|
1324 clean_tty = clean_ttyname(line); |
|
1325 memset(&utmpx, 0, sizeof(utmpx)); |
|
1326 strncpy(utmpx.ut_user, ".telnet", sizeof(utmpx.ut_user)); |
|
1327 strncpy(utmpx.ut_line, clean_tty, sizeof(utmpx.ut_line)); |
|
1328 #ifdef HAVE_STRUCT_UTMP_UT_ID |
|
1329 strncpy(utmpx.ut_id, make_id(clean_tty), sizeof(utmpx.ut_id)); |
|
1330 #endif |
|
1331 utmpx.ut_pid = pid; |
|
1332 |
|
1333 utmpx.ut_type = LOGIN_PROCESS; |
|
1334 |
|
1335 gettimeofday (&utmpx.ut_tv, NULL); |
|
1336 if (pututxline(&utmpx) == NULL) |
|
1337 fatal(net, "pututxline failed"); |
|
1338 #endif |
|
1339 |
|
1340 scrub_env(); |
|
1341 |
|
1342 /* |
|
1343 * -h : pass on name of host. |
|
1344 * WARNING: -h is accepted by login if and only if |
|
1345 * getuid() == 0. |
|
1346 * -p : don't clobber the environment (so terminal type stays set). |
|
1347 * |
|
1348 * -f : force this login, he has already been authenticated |
|
1349 */ |
|
1350 |
|
1351 /* init argv structure */ |
|
1352 argv.size=0; |
|
1353 argv.argc=0; |
|
1354 argv.argv=malloc(0); /*so we can call realloc later */ |
|
1355 addarg(&argv, "login"); |
|
1356 addarg(&argv, "-h"); |
|
1357 addarg(&argv, host); |
|
1358 addarg(&argv, "-p"); |
|
1359 if(name[0]) |
|
1360 user = name; |
|
1361 else |
|
1362 user = getenv("USER"); |
|
1363 #ifdef AUTHENTICATION |
|
1364 if (auth_level < 0 || autologin != AUTH_VALID) { |
|
1365 if(!no_warn) { |
|
1366 printf("User not authenticated. "); |
|
1367 if (require_otp) |
|
1368 printf("Using one-time password\r\n"); |
|
1369 else |
|
1370 printf("Using plaintext username and password\r\n"); |
|
1371 } |
|
1372 if (require_otp) { |
|
1373 addarg(&argv, "-a"); |
|
1374 addarg(&argv, "otp"); |
|
1375 } |
|
1376 if(log_unauth) |
|
1377 syslog(LOG_INFO, "unauthenticated access from %s (%s)", |
|
1378 host, user ? user : "unknown user"); |
|
1379 } |
|
1380 if (auth_level >= 0 && autologin == AUTH_VALID) |
|
1381 addarg(&argv, "-f"); |
|
1382 #endif |
|
1383 if(user){ |
|
1384 addarg(&argv, "--"); |
|
1385 addarg(&argv, strdup(user)); |
|
1386 } |
|
1387 if (getenv("USER")) { |
|
1388 /* |
|
1389 * Assume that login will set the USER variable |
|
1390 * correctly. For SysV systems, this means that |
|
1391 * USER will no longer be set, just LOGNAME by |
|
1392 * login. (The problem is that if the auto-login |
|
1393 * fails, and the user then specifies a different |
|
1394 * account name, he can get logged in with both |
|
1395 * LOGNAME and USER in his environment, but the |
|
1396 * USER value will be wrong. |
|
1397 */ |
|
1398 unsetenv("USER"); |
|
1399 } |
|
1400 closelog(); |
|
1401 /* |
|
1402 * This sleep(1) is in here so that telnetd can |
|
1403 * finish up with the tty. There's a race condition |
|
1404 * the login banner message gets lost... |
|
1405 */ |
|
1406 sleep(1); |
|
1407 |
|
1408 execv(new_login, argv.argv); |
|
1409 save_errno = errno; |
|
1410 #ifndef __SYMBIAN32__ |
|
1411 syslog(LOG_ERR, "%s: %m\n", new_login); |
|
1412 #endif |
|
1413 fatalperror_errno(net, new_login, save_errno); |
|
1414 /*NOTREACHED*/ |
|
1415 } |
|
1416 |
|
1417 static void |
|
1418 addarg(struct arg_val *argv, const char *val) |
|
1419 { |
|
1420 if(argv->size <= argv->argc+1) { |
|
1421 argv->argv = realloc(argv->argv, sizeof(char*) * (argv->size + 10)); |
|
1422 if (argv->argv == NULL) |
|
1423 fatal (net, "realloc: out of memory"); |
|
1424 argv->size+=10; |
|
1425 } |
|
1426 argv->argv[argv->argc++] = val; |
|
1427 argv->argv[argv->argc] = NULL; |
|
1428 } |
|
1429 #endif //__SYMBIAN32__ |
|
1430 |
|
1431 /* |
|
1432 * rmut() |
|
1433 * |
|
1434 * This is the function called by cleanup() to |
|
1435 * remove the utmp entry for this person. |
|
1436 */ |
|
1437 |
|
1438 #ifdef HAVE_UTMPX_H |
|
1439 static void |
|
1440 rmut(void) |
|
1441 { |
|
1442 struct utmpx utmpx, *non_save_utxp; |
|
1443 char *clean_tty = clean_ttyname(line); |
|
1444 |
|
1445 /* |
|
1446 * This updates the utmpx and utmp entries and make a wtmp/x entry |
|
1447 */ |
|
1448 |
|
1449 setutxent(); |
|
1450 memset(&utmpx, 0, sizeof(utmpx)); |
|
1451 strncpy(utmpx.ut_line, clean_tty, sizeof(utmpx.ut_line)); |
|
1452 utmpx.ut_type = LOGIN_PROCESS; |
|
1453 non_save_utxp = getutxline(&utmpx); |
|
1454 if (non_save_utxp) { |
|
1455 struct utmpx *utxp; |
|
1456 char user0; |
|
1457 |
|
1458 utxp = malloc(sizeof(struct utmpx)); |
|
1459 *utxp = *non_save_utxp; |
|
1460 user0 = utxp->ut_user[0]; |
|
1461 utxp->ut_user[0] = '\0'; |
|
1462 utxp->ut_type = DEAD_PROCESS; |
|
1463 #ifdef HAVE_STRUCT_UTMPX_UT_EXIT |
|
1464 #ifdef _STRUCT___EXIT_STATUS |
|
1465 utxp->ut_exit.__e_termination = 0; |
|
1466 utxp->ut_exit.__e_exit = 0; |
|
1467 #elif defined(__osf__) /* XXX */ |
|
1468 utxp->ut_exit.ut_termination = 0; |
|
1469 utxp->ut_exit.ut_exit = 0; |
|
1470 #else |
|
1471 utxp->ut_exit.e_termination = 0; |
|
1472 utxp->ut_exit.e_exit = 0; |
|
1473 #endif |
|
1474 #endif |
|
1475 gettimeofday(&utxp->ut_tv, NULL); |
|
1476 pututxline(utxp); |
|
1477 #ifdef WTMPX_FILE |
|
1478 utxp->ut_user[0] = user0; |
|
1479 updwtmpx(WTMPX_FILE, utxp); |
|
1480 #elif defined(WTMP_FILE) |
|
1481 /* This is a strange system with a utmpx and a wtmp! */ |
|
1482 { |
|
1483 int f = open(wtmpf, O_WRONLY|O_APPEND); |
|
1484 struct utmp wtmp; |
|
1485 if (f >= 0) { |
|
1486 strncpy(wtmp.ut_line, clean_tty, sizeof(wtmp.ut_line)); |
|
1487 strncpy(wtmp.ut_name, "", sizeof(wtmp.ut_name)); |
|
1488 #ifdef HAVE_STRUCT_UTMP_UT_HOST |
|
1489 strncpy(wtmp.ut_host, "", sizeof(wtmp.ut_host)); |
|
1490 #endif |
|
1491 wtmp.ut_time = time(NULL); |
|
1492 write(f, &wtmp, sizeof(wtmp)); |
|
1493 close(f); |
|
1494 } |
|
1495 } |
|
1496 #endif |
|
1497 free (utxp); |
|
1498 } |
|
1499 endutxent(); |
|
1500 } /* end of rmut */ |
|
1501 #endif |
|
1502 |
|
1503 #if !defined(HAVE_UTMPX_H) && !(defined(_CRAY) || defined(__hpux)) && BSD <= 43 |
|
1504 static void |
|
1505 rmut(void) |
|
1506 { |
|
1507 int f; |
|
1508 int found = 0; |
|
1509 struct utmp *u, *utmp; |
|
1510 int nutmp; |
|
1511 struct stat statbf; |
|
1512 char *clean_tty = clean_ttyname(line); |
|
1513 |
|
1514 f = open(utmpf, O_RDWR); |
|
1515 if (f >= 0) { |
|
1516 fstat(f, &statbf); |
|
1517 utmp = (struct utmp *)malloc((unsigned)statbf.st_size); |
|
1518 if (!utmp) |
|
1519 syslog(LOG_ERR, "utmp malloc failed"); |
|
1520 if (statbf.st_size && utmp) { |
|
1521 nutmp = read(f, utmp, (int)statbf.st_size); |
|
1522 nutmp /= sizeof(struct utmp); |
|
1523 |
|
1524 for (u = utmp ; u < &utmp[nutmp] ; u++) { |
|
1525 if (strncmp(u->ut_line, |
|
1526 clean_tty, |
|
1527 sizeof(u->ut_line)) || |
|
1528 u->ut_name[0]==0) |
|
1529 continue; |
|
1530 lseek(f, ((long)u)-((long)utmp), L_SET); |
|
1531 strncpy(u->ut_name, "", sizeof(u->ut_name)); |
|
1532 #ifdef HAVE_STRUCT_UTMP_UT_HOST |
|
1533 strncpy(u->ut_host, "", sizeof(u->ut_host)); |
|
1534 #endif |
|
1535 u->ut_time = time(NULL); |
|
1536 write(f, u, sizeof(wtmp)); |
|
1537 found++; |
|
1538 } |
|
1539 } |
|
1540 close(f); |
|
1541 } |
|
1542 if (found) { |
|
1543 f = open(wtmpf, O_WRONLY|O_APPEND); |
|
1544 if (f >= 0) { |
|
1545 strncpy(wtmp.ut_line, clean_tty, sizeof(wtmp.ut_line)); |
|
1546 strncpy(wtmp.ut_name, "", sizeof(wtmp.ut_name)); |
|
1547 #ifdef HAVE_STRUCT_UTMP_UT_HOST |
|
1548 strncpy(wtmp.ut_host, "", sizeof(wtmp.ut_host)); |
|
1549 #endif |
|
1550 wtmp.ut_time = time(NULL); |
|
1551 write(f, &wtmp, sizeof(wtmp)); |
|
1552 close(f); |
|
1553 } |
|
1554 } |
|
1555 chmod(line, 0666); |
|
1556 chown(line, 0, 0); |
|
1557 line[strlen("/dev/")] = 'p'; |
|
1558 chmod(line, 0666); |
|
1559 chown(line, 0, 0); |
|
1560 } /* end of rmut */ |
|
1561 #endif /* CRAY */ |
|
1562 |
|
1563 #if defined(__hpux) && !defined(HAVE_UTMPX_H) |
|
1564 static void |
|
1565 rmut (char *line) |
|
1566 { |
|
1567 struct utmp utmp; |
|
1568 struct utmp *utptr; |
|
1569 int fd; /* for /etc/wtmp */ |
|
1570 |
|
1571 utmp.ut_type = USER_PROCESS; |
|
1572 strncpy(utmp.ut_line, clean_ttyname(line), sizeof(utmp.ut_line)); |
|
1573 setutent(); |
|
1574 utptr = getutline(&utmp); |
|
1575 /* write it out only if it exists */ |
|
1576 if (utptr) { |
|
1577 utptr->ut_type = DEAD_PROCESS; |
|
1578 utptr->ut_time = time(NULL); |
|
1579 pututline(utptr); |
|
1580 /* set wtmp entry if wtmp file exists */ |
|
1581 if ((fd = open(wtmpf, O_WRONLY | O_APPEND)) >= 0) { |
|
1582 write(fd, utptr, sizeof(utmp)); |
|
1583 close(fd); |
|
1584 } |
|
1585 } |
|
1586 endutent(); |
|
1587 |
|
1588 chmod(line, 0666); |
|
1589 chown(line, 0, 0); |
|
1590 line[14] = line[13]; |
|
1591 line[13] = line[12]; |
|
1592 line[8] = 'm'; |
|
1593 line[9] = '/'; |
|
1594 line[10] = 'p'; |
|
1595 line[11] = 't'; |
|
1596 line[12] = 'y'; |
|
1597 chmod(line, 0666); |
|
1598 chown(line, 0, 0); |
|
1599 } |
|
1600 #endif |
|
1601 |
|
1602 /* |
|
1603 * cleanup() |
|
1604 * |
|
1605 * This is the routine to call when we are all through, to |
|
1606 * clean up anything that needs to be cleaned up. |
|
1607 */ |
|
1608 |
|
1609 #ifdef PARENT_DOES_UTMP |
|
1610 |
|
1611 void |
|
1612 cleanup(int sig) |
|
1613 { |
|
1614 #ifdef _CRAY |
|
1615 static int incleanup = 0; |
|
1616 int t; |
|
1617 int child_status; /* status of child process as returned by waitpid */ |
|
1618 int flags = WNOHANG|WUNTRACED; |
|
1619 |
|
1620 /* |
|
1621 * 1: Pick up the zombie, if we are being called |
|
1622 * as the signal handler. |
|
1623 * 2: If we are a nested cleanup(), return. |
|
1624 * 3: Try to clean up TMPDIR. |
|
1625 * 4: Fill in utmp with shutdown of process. |
|
1626 * 5: Close down the network and pty connections. |
|
1627 * 6: Finish up the TMPDIR cleanup, if needed. |
|
1628 */ |
|
1629 if (sig == SIGCHLD) { |
|
1630 while (waitpid(-1, &child_status, flags) > 0) |
|
1631 ; /* VOID */ |
|
1632 /* Check if the child process was stopped |
|
1633 * rather than exited. We want cleanup only if |
|
1634 * the child has died. |
|
1635 */ |
|
1636 if (WIFSTOPPED(child_status)) { |
|
1637 return; |
|
1638 } |
|
1639 } |
|
1640 t = sigblock(sigmask(SIGCHLD)); |
|
1641 if (incleanup) { |
|
1642 sigsetmask(t); |
|
1643 return; |
|
1644 } |
|
1645 incleanup = 1; |
|
1646 sigsetmask(t); |
|
1647 |
|
1648 t = cleantmp(&wtmp); |
|
1649 setutent(); /* just to make sure */ |
|
1650 #endif /* CRAY */ |
|
1651 rmut(line); |
|
1652 close(ourpty); |
|
1653 shutdown(net, 2); |
|
1654 #ifdef _CRAY |
|
1655 if (t == 0) |
|
1656 cleantmp(&wtmp); |
|
1657 #endif /* CRAY */ |
|
1658 exit(1); |
|
1659 } |
|
1660 |
|
1661 #else /* PARENT_DOES_UTMP */ |
|
1662 |
|
1663 void |
|
1664 cleanup(int sig) |
|
1665 { |
|
1666 #if defined(HAVE_UTMPX_H) || !defined(HAVE_LOGWTMP) |
|
1667 #ifndef __SYMBIAN32__ |
|
1668 rmut(); |
|
1669 #endif |
|
1670 #ifdef HAVE_VHANGUP |
|
1671 #ifndef __sgi |
|
1672 vhangup(); /* XXX */ |
|
1673 #endif |
|
1674 #endif |
|
1675 #else |
|
1676 char *p; |
|
1677 |
|
1678 p = line + sizeof("/dev/") - 1; |
|
1679 if (logout(p)) |
|
1680 logwtmp(p, "", ""); |
|
1681 chmod(line, 0666); |
|
1682 chown(line, 0, 0); |
|
1683 *p = 'p'; |
|
1684 chmod(line, 0666); |
|
1685 chown(line, 0, 0); |
|
1686 #endif |
|
1687 shutdown(net, 2); |
|
1688 exit(1); |
|
1689 } |
|
1690 |
|
1691 #endif /* PARENT_DOES_UTMP */ |
|
1692 |
|
1693 #ifdef PARENT_DOES_UTMP |
|
1694 /* |
|
1695 * _utmp_sig_rcv |
|
1696 * utmp_sig_init |
|
1697 * utmp_sig_wait |
|
1698 * These three functions are used to coordinate the handling of |
|
1699 * the utmp file between the server and the soon-to-be-login shell. |
|
1700 * The server actually creates the utmp structure, the child calls |
|
1701 * utmp_sig_wait(), until the server calls utmp_sig_notify() and |
|
1702 * signals the future-login shell to proceed. |
|
1703 */ |
|
1704 static int caught=0; /* NZ when signal intercepted */ |
|
1705 static void (*func)(); /* address of previous handler */ |
|
1706 |
|
1707 void |
|
1708 _utmp_sig_rcv(sig) |
|
1709 int sig; |
|
1710 { |
|
1711 caught = 1; |
|
1712 signal(SIGUSR1, func); |
|
1713 } |
|
1714 |
|
1715 void |
|
1716 utmp_sig_init() |
|
1717 { |
|
1718 /* |
|
1719 * register signal handler for UTMP creation |
|
1720 */ |
|
1721 if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1) |
|
1722 fatalperror(net, "telnetd/signal"); |
|
1723 } |
|
1724 |
|
1725 void |
|
1726 utmp_sig_reset() |
|
1727 { |
|
1728 signal(SIGUSR1, func); /* reset handler to default */ |
|
1729 } |
|
1730 |
|
1731 # ifdef __hpux |
|
1732 # define sigoff() /* do nothing */ |
|
1733 # define sigon() /* do nothing */ |
|
1734 # endif |
|
1735 |
|
1736 void |
|
1737 utmp_sig_wait() |
|
1738 { |
|
1739 /* |
|
1740 * Wait for parent to write our utmp entry. |
|
1741 */ |
|
1742 sigoff(); |
|
1743 while (caught == 0) { |
|
1744 pause(); /* wait until we get a signal (sigon) */ |
|
1745 sigoff(); /* turn off signals while we check caught */ |
|
1746 } |
|
1747 sigon(); /* turn on signals again */ |
|
1748 } |
|
1749 |
|
1750 void |
|
1751 utmp_sig_notify(pid) |
|
1752 { |
|
1753 kill(pid, SIGUSR1); |
|
1754 } |
|
1755 |
|
1756 #ifdef _CRAY |
|
1757 static int gotsigjob = 0; |
|
1758 |
|
1759 /*ARGSUSED*/ |
|
1760 void |
|
1761 sigjob(sig) |
|
1762 int sig; |
|
1763 { |
|
1764 int jid; |
|
1765 struct jobtemp *jp; |
|
1766 |
|
1767 while ((jid = waitjob(NULL)) != -1) { |
|
1768 if (jid == 0) { |
|
1769 return; |
|
1770 } |
|
1771 gotsigjob++; |
|
1772 jobend(jid, NULL, NULL); |
|
1773 } |
|
1774 } |
|
1775 |
|
1776 /* |
|
1777 * jid_getutid: |
|
1778 * called by jobend() before calling cleantmp() |
|
1779 * to find the correct $TMPDIR to cleanup. |
|
1780 */ |
|
1781 |
|
1782 struct utmp * |
|
1783 jid_getutid(jid) |
|
1784 int jid; |
|
1785 { |
|
1786 struct utmp *cur = NULL; |
|
1787 |
|
1788 setutent(); /* just to make sure */ |
|
1789 while (cur = getutent()) { |
|
1790 if ( (cur->ut_type != NULL) && (jid == cur->ut_jid) ) { |
|
1791 return(cur); |
|
1792 } |
|
1793 } |
|
1794 |
|
1795 return(0); |
|
1796 } |
|
1797 |
|
1798 /* |
|
1799 * Clean up the TMPDIR that login created. |
|
1800 * The first time this is called we pick up the info |
|
1801 * from the utmp. If the job has already gone away, |
|
1802 * then we'll clean up and be done. If not, then |
|
1803 * when this is called the second time it will wait |
|
1804 * for the signal that the job is done. |
|
1805 */ |
|
1806 int |
|
1807 cleantmp(wtp) |
|
1808 struct utmp *wtp; |
|
1809 { |
|
1810 struct utmp *utp; |
|
1811 static int first = 1; |
|
1812 int mask, omask, ret; |
|
1813 extern struct utmp *getutid (const struct utmp *_Id); |
|
1814 |
|
1815 |
|
1816 mask = sigmask(WJSIGNAL); |
|
1817 |
|
1818 if (first == 0) { |
|
1819 omask = sigblock(mask); |
|
1820 while (gotsigjob == 0) |
|
1821 sigpause(omask); |
|
1822 return(1); |
|
1823 } |
|
1824 first = 0; |
|
1825 setutent(); /* just to make sure */ |
|
1826 |
|
1827 utp = getutid(wtp); |
|
1828 if (utp == 0) { |
|
1829 syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR"); |
|
1830 return(-1); |
|
1831 } |
|
1832 /* |
|
1833 * Nothing to clean up if the user shell was never started. |
|
1834 */ |
|
1835 if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0) |
|
1836 return(1); |
|
1837 |
|
1838 /* |
|
1839 * Block the WJSIGNAL while we are in jobend(). |
|
1840 */ |
|
1841 omask = sigblock(mask); |
|
1842 ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user); |
|
1843 sigsetmask(omask); |
|
1844 return(ret); |
|
1845 } |
|
1846 |
|
1847 int |
|
1848 jobend(jid, path, user) |
|
1849 int jid; |
|
1850 char *path; |
|
1851 char *user; |
|
1852 { |
|
1853 static int saved_jid = 0; |
|
1854 static int pty_saved_jid = 0; |
|
1855 static char saved_path[sizeof(wtmp.ut_tpath)+1]; |
|
1856 static char saved_user[sizeof(wtmp.ut_user)+1]; |
|
1857 |
|
1858 /* |
|
1859 * this little piece of code comes into play |
|
1860 * only when ptyreconnect is used to reconnect |
|
1861 * to an previous session. |
|
1862 * |
|
1863 * this is the only time when the |
|
1864 * "saved_jid != jid" code is executed. |
|
1865 */ |
|
1866 |
|
1867 if ( saved_jid && saved_jid != jid ) { |
|
1868 if (!path) { /* called from signal handler */ |
|
1869 pty_saved_jid = jid; |
|
1870 } else { |
|
1871 pty_saved_jid = saved_jid; |
|
1872 } |
|
1873 } |
|
1874 |
|
1875 if (path) { |
|
1876 strncpy(saved_path, path, sizeof(wtmp.ut_tpath)); |
|
1877 strncpy(saved_user, user, sizeof(wtmp.ut_user)); |
|
1878 saved_path[sizeof(saved_path)] = '\0'; |
|
1879 saved_user[sizeof(saved_user)] = '\0'; |
|
1880 } |
|
1881 if (saved_jid == 0) { |
|
1882 saved_jid = jid; |
|
1883 return(0); |
|
1884 } |
|
1885 |
|
1886 /* if the jid has changed, get the correct entry from the utmp file */ |
|
1887 |
|
1888 if ( saved_jid != jid ) { |
|
1889 struct utmp *utp = NULL; |
|
1890 struct utmp *jid_getutid(); |
|
1891 |
|
1892 utp = jid_getutid(pty_saved_jid); |
|
1893 |
|
1894 if (utp == 0) { |
|
1895 syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR"); |
|
1896 return(-1); |
|
1897 } |
|
1898 |
|
1899 cleantmpdir(jid, utp->ut_tpath, utp->ut_user); |
|
1900 return(1); |
|
1901 } |
|
1902 |
|
1903 cleantmpdir(jid, saved_path, saved_user); |
|
1904 return(1); |
|
1905 } |
|
1906 |
|
1907 /* |
|
1908 * Fork a child process to clean up the TMPDIR |
|
1909 */ |
|
1910 cleantmpdir(jid, tpath, user) |
|
1911 int jid; |
|
1912 char *tpath; |
|
1913 char *user; |
|
1914 { |
|
1915 switch(fork()) { |
|
1916 case -1: |
|
1917 syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m\n", |
|
1918 tpath); |
|
1919 break; |
|
1920 case 0: |
|
1921 execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0); |
|
1922 syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m\n", |
|
1923 tpath, CLEANTMPCMD); |
|
1924 exit(1); |
|
1925 default: |
|
1926 /* |
|
1927 * Forget about child. We will exit, and |
|
1928 * /etc/init will pick it up. |
|
1929 */ |
|
1930 break; |
|
1931 } |
|
1932 } |
|
1933 #endif /* CRAY */ |
|
1934 #endif /* defined(PARENT_DOES_UTMP) */ |