tty.c
上传用户:minyiyu
上传日期:2018-12-24
资源大小:864k
文件大小:13k
源码类别:

Telnet服务器

开发平台:

Unix_Linux

  1. /* $Id: tty.c,v 1.1 2000/01/15 01:45:37 edwardc Exp $ */
  2. /*
  3.  * TTY.C ------ Routines for pseudo terminal allocation.
  4.  * Various platforms are supported.
  5.  *
  6.  * Copyright (C) 1992, 1993  Yongguang Zhang
  7.  * All right reserved. (ygz@cs.purdue.edu)
  8.  */
  9. #ifndef lint
  10. static char *rcs_id="$Id: tty.c,v 1.1 2000/01/15 01:45:37 edwardc Exp $";
  11. #endif /* lint */
  12. #include "config.h"
  13. /* 
  14.  * Functions get_pty() and pty_search() in this file are adopted from
  15.  * X11R5 xterm, copyrighted by DEC & MIT.
  16.  */ 
  17. #ifdef hpux
  18. # define PTYCHAR1 "zyxwvutsrqp"
  19. # define PTYCHAR2 "fedcba9876543210"
  20. # define PTYDEV "/dev/ptym/ptyxx"
  21. # define TTYDEV "/dev/pty/ttyxx"
  22. #else   /* !hpux */
  23. # define PTYCHAR1 "pqrstuvwxyzPQRSTUVWXYZ"
  24. # define PTYCHAR2 "0123456789abcdef"
  25. # define PTYDEV "/dev/ptyxx"
  26. # define TTYDEV "/dev/ttyxx"
  27. #endif  /* !hpux */
  28. #ifdef SYSV
  29. extern char *ptsname();
  30. #endif
  31. #ifdef hpux
  32. # include <sys/utsname.h>
  33. #endif
  34. static char ptydev[32];
  35. static char ttydev[32];
  36. static int pty_search();
  37. /* This function opens up a pty master and stuffs its value into pty.
  38.  * If it finds one, it returns a value of 0.  If it does not find one,
  39.  * it returns a value of !0.  This routine is designed to be re-entrant,
  40.  * so that if a pty master is found and later, we find that the slave
  41.  * has problems, we can re-enter this function and get another one.
  42.  */
  43. int get_pty (pty)
  44.     int *pty;
  45. {
  46. strcpy (ptydev, PTYDEV);
  47. strcpy (ttydev, TTYDEV);
  48. #if defined(SYSV) && defined(SYSV386)
  49.         if (pty_search(pty) == 0)
  50.     return 0;
  51. #endif /* SYSV && SYSV386 */
  52. #if (defined(att) || defined(ATT)) && (!defined(_SEQUENT_))
  53. {
  54.     if ((*pty = open ("/dev/ptmx", O_RDWR)) < 0)
  55. return 1;
  56. # if defined(SVR4) || defined(SYSV386)
  57.     strcpy(ttydev, ptsname(*pty));
  58. # endif
  59.     return 0;
  60. }
  61. # define GET_PTY_DONE
  62. #endif /* ATT */
  63. #if defined(AIXV3) || defined(_IBMR2)
  64. {
  65.     if ((*pty = open ("/dev/ptc", O_RDWR)) < 0) 
  66. return 1;
  67.     strcpy(ttydev, (char *)ttyname(*pty));
  68.     return 0;
  69. }
  70. # define GET_PTY_DONE
  71. #endif
  72. #if defined(sgi) && defined(IRIX4)
  73. {
  74.     char    *tty_name;
  75.     tty_name = _getpty (pty, O_RDWR, 0622, 0);
  76.     if (tty_name == 0)
  77. return 1;
  78.     strcpy (ttydev, tty_name);
  79.     return 0;
  80. }
  81. # define GET_PTY_DONE
  82. #endif
  83. #ifdef __convex__
  84.         {
  85.     char *pty_name, *getpty();
  86.     while ((pty_name = getpty()) != NULL) {
  87. if ((*pty = open (pty_name, O_RDWR)) >= 0) {
  88.     strcpy(ptydev, pty_name);
  89.     strcpy(ttydev, pty_name);
  90.     ttydev[5] = 't';
  91.     return 0;
  92. }
  93.     }
  94.     return 1;
  95. }
  96. # define GET_PTY_DONE
  97. #endif /* __convex__ */
  98. #if defined(sequent) || defined(_SEQUENT_)
  99. {
  100.     char *sl[2], *ms[2];
  101.     *pty = getpseudotty (sl, ms);
  102.     strcpy(ptydev, ms[0]);
  103.     strcpy(ttydev, sl[0]);
  104.     return (*pty >= 0 ? 0 : 1);
  105. }
  106. # define GET_PTY_DONE
  107. #endif /* sequent */
  108. #if (defined(sgi) && defined(IRIX3)) || (defined(umips) && defined (SYSTYPE_SYSV))
  109. {
  110.     struct stat fstat_buf;
  111.     int tty;
  112.     *pty = open ("/dev/ptc", O_RDWR);
  113.     if (*pty < 0 || (fstat (*pty, &fstat_buf)) < 0) {
  114.       return(1);
  115.     }
  116.     sprintf (ttydev, "/dev/ttyq%d", minor(fstat_buf.st_rdev));
  117. # ifndef sgi
  118.     sprintf (ptydev, "/dev/ptyq%d", minor(fstat_buf.st_rdev));
  119.     if ((*tty = open (ttydev, O_RDWR)) < 0) {
  120.       close (*pty);
  121.       return(1);
  122.     }
  123. # endif /* !sgi */
  124.     /* got one! */
  125.     return(0);
  126. }
  127. # define GET_PTY_DONE
  128. #endif /* sgi or umips */
  129. #ifndef GET_PTY_DONE
  130. return pty_search(pty);
  131. #endif
  132. }
  133. /*
  134.  * Called from get_pty to iterate over likely pseudo terminals
  135.  * we might allocate.  Used on those systems that do not have
  136.  * a functional interface for allocating a pty.
  137.  * Returns 0 if found a pty, 1 if fails.
  138.  */
  139. static int pty_search(pty)
  140.     int *pty;
  141. {
  142.     static int devindex, letter = 0;
  143. #ifdef O_NOCTTY
  144. # define O_RDWRPTY (O_RDWR | O_NOCTTY)
  145. #else
  146. # define O_RDWRPTY (O_RDWR)
  147. #endif
  148. #ifdef CRAY
  149.     for (; devindex < 256; devindex++) {
  150. sprintf (ttydev, "/dev/ttyp%03d", devindex);
  151. sprintf (ptydev, "/dev/pty/%03d", devindex);
  152. if ((*pty = open (ptydev, O_RDWRPTY)) >= 0) {
  153.     /* We need to set things up for our next entry
  154.      * into this function!
  155.      */
  156.     (void) devindex++;
  157. # ifdef TIOCEXCL
  158.     ioctl (*pty, TIOCEXCL, (char *)0);
  159. # endif
  160.     return 0;
  161. }
  162.     }
  163. #else /* CRAY */
  164.     while (PTYCHAR1[letter]) {
  165. ttydev [strlen(ttydev) - 2] = PTYCHAR1 [letter];
  166. ptydev [strlen(ptydev) - 2] = PTYCHAR1 [letter];
  167. while (PTYCHAR2[devindex]) {
  168.     ttydev [strlen(ttydev) - 1] = PTYCHAR2 [devindex];
  169.     ptydev [strlen(ptydev) - 1] = PTYCHAR2 [devindex];
  170.     if ((*pty = open (ptydev, O_RDWRPTY)) >= 0) {
  171. /* We need to set things up for our next entry
  172.  * into this function!
  173.  */
  174. # ifdef sun
  175. int dummy;
  176. ptydev[5] = 't';
  177. chown(ptydev, 0, 0);
  178. chmod(ptydev, 0600);
  179. ptydev[5] = 'p';
  180. if ((ioctl(*pty, TIOCGPGRP, &dummy) == -1) && errno == EIO) {
  181.     (void) devindex++;
  182.     return 0;
  183. }
  184. close(*pty);
  185. # else
  186. (void) devindex++;
  187. #  ifdef TIOCEXCL
  188. ioctl (*pty, TIOCEXCL, (char *)0);
  189. #  endif
  190. return 0;
  191. # endif
  192.     }
  193.     devindex++;
  194. }
  195. devindex = 0;
  196. letter++;
  197.     }
  198. #endif /* CRAY else */
  199.     /*
  200.      * We were unable to allocate a pty master!  Return an error
  201.      * condition and let our caller terminate cleanly.
  202.      */
  203.     return 1;
  204. }
  205. /* given master fildes, get the slave side tty */
  206. int get_tty (master, tty)
  207.     int master;
  208.     int *tty;
  209. {
  210.   int t;
  211. #if defined(POSIX) || defined(SVR4) || defined(__convex__)
  212.   int pgrp = setsid();
  213. #else
  214.   int pgrp = getpid();
  215. #endif
  216. #ifdef USE_PTYS
  217. setpgrp();
  218. grantpt (master);
  219. unlockpt (master);
  220. if ((*tty = open (ptsname(master), O_RDWR)) < 0)
  221. return 1; /* error */
  222. if (ioctl (*tty, I_PUSH, "ptem") < 0)
  223. return 1; /* error */
  224. # if !defined(SVR4) && !defined(SYSV386)
  225. if (!getenv("CONSEM") && ioctl (*tty, I_PUSH, "consem") < 0) {
  226. return 1;
  227. # endif
  228. if (ioctl (*tty, I_PUSH, "ldterm") < 0)
  229. return 1;
  230. # ifdef SVR4
  231. if (ioctl (*tty, I_PUSH, "ttcompat") < 0)
  232. return 1;
  233. # endif
  234. #else /* ! USE_PTYS */
  235. # ifdef TIOCNOTTY
  236. t = open ("/dev/tty", O_RDWR);
  237. if (t >= 0) {
  238. (void) ioctl(t, TIOCNOTTY, (char *)0);
  239. (void) close(t);
  240. }
  241. # endif
  242. *tty = open(ttydev, O_RDWR);
  243. if (*tty < 0) {
  244. perror(ttydev);
  245. return 1;
  246. }
  247. # ifdef SYSV
  248. setpgrp();
  249. # else
  250. #  ifdef TIOCSCTTY
  251. (void) setsid();
  252. (void) ioctl (*tty, TIOCSCTTY, 0);
  253. #  endif
  254. #  ifdef TIOCSPGRP
  255. (void) ioctl (*tty, TIOCSPGRP, (char *)&pgrp);
  256. #  endif
  257. setpgrp (0, 0);
  258. close (open (ttydev, O_WRONLY, 0));
  259. setpgrp (0, pgrp);
  260. # endif /* SYSV */
  261. #endif /* USE_PTYS */
  262. return 0; /* OK */
  263. }
  264. /**************************** TTY MODE stuffs ****************************/
  265. void get_term_mode(tty, termptr)
  266.      int tty;
  267.      struct term_mode *termptr;
  268. {
  269. #ifdef TIOCSLTC
  270. (void) ioctl (tty, TIOCGLTC, (char *)&(termptr->ltc));
  271. #endif
  272. #ifdef   TIOCLSET
  273. (void) ioctl (tty, TIOCLGET, (char *)&(termptr->lmode));
  274. #endif
  275. #ifdef USE_SYSV_TERMIO
  276. (void) ioctl (tty, TCGETA,   (char *)&(termptr->tio));
  277. #else /* USE_SYSV_TERMIO */
  278. (void) ioctl (tty, TIOCGETP, (char *)&(termptr->sb));
  279. (void) ioctl (tty, TIOCGETC, (char *)&(termptr->tc));
  280. (void) ioctl (tty, TIOCGETD, (char *)&(termptr->ldis));
  281. #endif /* USE_SYSV_TERMIO */
  282. }
  283. void set_term_mode(tty, termptr)
  284.      int tty;
  285.      struct term_mode *termptr;
  286. {
  287. #ifdef TIOCSLTC
  288. (void) ioctl (tty, TIOCSLTC, (char *)&(termptr->ltc));
  289. #endif
  290. #ifdef   TIOCLSET
  291. (void) ioctl (tty, TIOCLSET, (char *)&(termptr->lmode));
  292. #endif
  293. #ifdef USE_SYSV_TERMIO
  294. # ifdef POSIX
  295. (void) tcsetattr (fd, TCSAFLUSH, (char *)&(termptr->tio));
  296. # else
  297. (void) ioctl (tty, TCSETA,   (char *)&(termptr->tio));
  298. # endif
  299. #else /* USE_SYSV_TERMIO */
  300. (void) ioctl (tty, TIOCSETP, (char *)&(termptr->sb));
  301. (void) ioctl (tty, TIOCSETC, (char *)&(termptr->tc));
  302. (void) ioctl (tty, TIOCSETD, (char *)&(termptr->ldis));
  303. #endif /* USE_SYSV_TERMIO */
  304. }
  305. void make_raw(oldtermptr, newtermptr)
  306.      struct term_mode *oldtermptr, *newtermptr;
  307. {
  308. *newtermptr = *oldtermptr;
  309. #ifdef TIOCSLTC
  310. newtermptr->ltc.t_suspc = 0377;
  311. newtermptr->ltc.t_dsuspc = 0377;
  312. newtermptr->ltc.t_flushc = 0377;
  313. newtermptr->ltc.t_lnextc = 0377;
  314. #endif
  315. #if  defined(TIOCLSET) && defined(LPASS8)
  316. newtermptr->lmode |= LPASS8;
  317. #endif
  318. #ifdef USE_SYSV_TERMIO
  319. newtermptr->tio.c_iflag &= ~(ICRNL|IXON);
  320. # ifdef ISTRIP
  321. newtermptr->tio.c_iflag &= ~ISTRIP;
  322. # endif
  323. # ifdef ONLCR
  324. newtermptr->tio.c_oflag &= ~ONLCR;
  325. # endif
  326. newtermptr->tio.c_cflag |= CS8;
  327. newtermptr->tio.c_cflag &= ~(PARENB);
  328. newtermptr->tio.c_lflag &= ~(ICANON|ISIG|ECHO);
  329. newtermptr->tio.c_cc[VMIN] = 1;
  330. newtermptr->tio.c_cc[VTIME] = 0;
  331. newtermptr->tio.c_cc[VINTR] = 0377;
  332. newtermptr->tio.c_cc[VQUIT] = 0377;
  333. newtermptr->tio.c_cc[VINTR] = 0377;
  334. # ifdef VSTART
  335. newtermptr->tio.c_cc[VSTART] = 0377;
  336. # endif
  337. # ifdef VSTOP
  338. newtermptr->tio.c_cc[VSTOP] = 0377;
  339. # endif
  340. # ifdef VDISCARD
  341. newtermptr->tio.c_cc[VDISCARD] = 0377;
  342. # endif
  343. # ifdef VSUSP
  344.   newtermptr->tio.c_cc[VSUSP] = 0377;
  345. # endif
  346. # ifdef VDSUSP
  347. newtermptr->tio.c_cc[VDSUSP] = 0377;
  348. # endif
  349. #else /* USE_SYSV_TERMIO */
  350. newtermptr->sb.sg_flags &= ~(CRMOD | ECHO);
  351. newtermptr->sb.sg_flags |= CBREAK;
  352. newtermptr->tc.t_quitc = 0377;
  353. newtermptr->tc.t_intrc = 0377;
  354. newtermptr->tc.t_startc = 0377;
  355. newtermptr->tc.t_stopc = 0377;
  356. #endif /* USE_SYSV_TERMIO */
  357. }
  358. /******************************* UTMP stuffs *******************************/
  359. #include <utmp.h>
  360. #ifdef HAS_UTMPX
  361. # include <utmpx.h>
  362. # define USE_SYSV_UTMP
  363.   /* utmpx is very similar to utmp */
  364. # define utmp utmpx
  365. # define ut_time ut_xtime
  366. # define setutent setutxent
  367. # define endutent endutxent
  368. # define getutid getutxid
  369. # define pututline pututxline
  370. #endif
  371. #ifdef USE_SYSV_UTMP
  372. # ifndef SVR4 /* otherwise declared in utmp.h */
  373. extern struct utmp *getutid();
  374. extern void pututline();
  375. extern void setutent();
  376. extern void endutent();
  377. # endif /* !SVR4 */
  378. # ifndef SYSV386
  379. extern struct passwd *getpwuid();
  380. # endif
  381. extern time_t time();
  382. #else   /* not USE_SYSV_UTMP */
  383. # define UTMP_FILENAME "/etc/utmp"
  384. #endif
  385. #ifdef CRAY
  386. # define PTYCHLEN 4
  387. #else
  388. # define PTYCHLEN 2
  389. #endif
  390. /*
  391.  * addutmp() and rmutmp() will run in different processes --
  392.  * one in subsubprocess, and the other in subprocess.  There is no way to
  393.  * pass values or the status to each other by means of global variables.
  394.  */
  395. /* addutmp() -- add a record to the utmp file */
  396. void addutmp()
  397. {
  398.   struct utmp utmp;
  399.   struct passwd *pw;
  400. #ifndef USE_SYSV_UTMP
  401.   int utmpf;
  402.   int tslot;
  403. #endif
  404. pw = getpwuid(getuid());
  405. #ifdef USE_SYSV_UTMP
  406. (void) setutent ();
  407. /* set up entry to search for */
  408. (void) bzero ((char *)&utmp, sizeof(struct utmp));
  409. utmp.ut_type = DEAD_PROCESS;
  410. (void) strncpy ((char *)utmp.ut_id, ttydev + strlen(ttydev) - PTYCHLEN,
  411. sizeof (utmp.ut_id));
  412. /* position to entry in utmp file */
  413. (void) getutid(&utmp);
  414. /* set up the new entry */
  415. (void) bzero ((char *)&utmp, sizeof(struct utmp));
  416. utmp.ut_type = USER_PROCESS;
  417. # ifdef HAS_UTMPX
  418. utmpx.ut_exit.e_exit = 0;
  419. utmpx.ut_exit.e_termination = 0;
  420. # else
  421. utmp.ut_exit.e_exit = 2;
  422. # endif
  423. (void) strncpy ((char *)utmp.ut_user,
  424. (pw && pw->pw_name) ? pw->pw_name : "???",
  425. sizeof(utmp.ut_user));
  426. (void) strncpy ((char *)utmp.ut_id, ttydev + strlen(ttydev) - PTYCHLEN,
  427. sizeof(utmp.ut_id));
  428. utmp.ut_pid = getpid();
  429. # ifdef HAS_UTMPX
  430. utmpx.ut_syslen = 1;
  431. utmpx.ut_session = getsid(0);
  432. utmpx.ut_tv.tv_usec = 0;
  433. # endif
  434. #else /* USE_SYSV_UTMP */
  435. # ifndef apollo
  436. tslot = ttyslot();
  437. # else
  438. tslot = 1;
  439. # endif
  440. utmpf = open (UTMP_FILENAME, O_WRONLY);
  441. if (utmpf < 0)
  442. return;
  443. bzero((char *)&utmp, sizeof(struct utmp));
  444. #endif /* USE_SYSV_UTMP */
  445. /* common utmp fields */
  446. (void) strncpy (utmp.ut_line, ttydev + strlen("/dev/"),
  447. sizeof (utmp.ut_line));
  448. (void) strncpy (utmp.ut_name,
  449. (pw && pw->pw_name) ? pw->pw_name : "???",
  450. sizeof(utmp.ut_name));
  451. utmp.ut_time = time ((time_t *) 0);
  452. #ifdef USE_SYSV_UTMP
  453. (void) pututline(&utmp);
  454. (void) endutent();
  455. #else
  456. lseek (utmpf, (long)(tslot * sizeof(struct utmp)), 0);
  457. write (utmpf, (char *)&utmp, sizeof(struct utmp));
  458. close (utmpf);
  459. #endif
  460. }
  461. void rmutmp(child_pid)
  462.      int child_pid;
  463. {
  464.   struct utmp utmp;
  465. #ifdef USE_SYSV_UTMP
  466.   struct utmp *utptr;
  467. #else
  468.   int utmpf;
  469.   int tslot;
  470. #endif
  471. #ifdef USE_SYSV_UTMP
  472. (void) setutent();
  473. utmp.ut_type = USER_PROCESS;
  474. (void) bzero (utmp.ut_id, sizeof(utmp.ut_id));
  475. (void) strncpy ((char *)utmp.ut_id, ttydev + strlen(ttydev) - PTYCHLEN,
  476. sizeof(utmp.ut_id));
  477. utptr = getutid(&utmp);
  478. /* write it out only if it exists, and the pid's match */
  479. if (utptr && (utptr->ut_pid == child_pid)) {
  480. utptr->ut_type = DEAD_PROCESS;
  481. utptr->ut_time = time ((time_t *) 0);
  482. (void) pututline(utptr);
  483. }
  484. (void) endutent();
  485. #else /* USE_SYSV_UTMP */
  486. utmpf = open (UTMP_FILENAME, O_RDWR);
  487. if (utmpf < 0)
  488. return;
  489. tslot = 0;
  490. while (read(utmpf, (char *)&utmp, sizeof (utmp)) == sizeof (utmp)) {
  491. if (strncmp (utmp.ut_line, ttydev + strlen("/dev/"),
  492. sizeof (utmp.ut_line)) != 0) {
  493. tslot ++;
  494. continue;
  495. }
  496. /* find the right slot */
  497. utmp.ut_name[0] = '';
  498. utmp.ut_time = time ((time_t *) 0);
  499. lseek (utmpf, (long)(tslot * sizeof(struct utmp)), 0);
  500. write (utmpf, (char *)&utmp, sizeof(struct utmp));
  501. close (utmpf);
  502. break;
  503. }
  504. #endif /* USE_SYSV_UTMP */
  505. return;
  506. }