pty.c 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. /* Copyright (c) 1993-2002
  2. * Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
  3. * Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
  4. * Copyright (c) 1987 Oliver Laumann
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2, or (at your option)
  9. * any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program (see the file COPYING); if not, write to the
  18. * Free Software Foundation, Inc.,
  19. * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
  20. *
  21. ****************************************************************
  22. */
  23. #include "config.h"
  24. #include <sys/types.h>
  25. #include <sys/stat.h>
  26. #include <fcntl.h>
  27. #include <signal.h>
  28. #include <unistd.h>
  29. #include "screen.h"
  30. #ifndef sun
  31. # include <sys/ioctl.h>
  32. #endif
  33. /* for solaris 2.1, Unixware (SVR4.2) and possibly others */
  34. #if defined (HAVE_SVR4_PTYS) && defined (HAVE_SYS_STROPTS_H)
  35. # include <sys/stropts.h>
  36. #endif
  37. #if defined(sun) && defined(LOCKPTY) && !defined(TIOCEXCL)
  38. # include <sys/ttold.h>
  39. #endif
  40. #ifdef ISC
  41. # include <sys/tty.h>
  42. # include <sys/sioctl.h>
  43. # include <sys/pty.h>
  44. #endif
  45. #ifdef sgi
  46. # include <sys/sysmacros.h>
  47. #endif /* sgi */
  48. #include "extern.h"
  49. /*
  50. * if no PTYRANGE[01] is in the config file, we pick a default
  51. */
  52. #ifndef PTYRANGE0
  53. # define PTYRANGE0 "qpr"
  54. #endif
  55. #ifndef PTYRANGE1
  56. # define PTYRANGE1 "0123456789abcdef"
  57. #endif
  58. /* SVR4 pseudo ttys don't seem to work with SCO-5 */
  59. #ifdef M_UNIX
  60. # undef HAVE_SVR4_PTYS
  61. #endif
  62. extern int eff_uid;
  63. /* used for opening a new pty-pair: */
  64. static char PtyName[32], TtyName[32];
  65. #if !(defined(sequent) || defined(_SEQUENT_) || defined(HAVE_SVR4_PTYS))
  66. # ifdef hpux
  67. static char PtyProto[] = "/dev/ptym/ptyXY";
  68. static char TtyProto[] = "/dev/pty/ttyXY";
  69. # else
  70. # ifdef M_UNIX
  71. static char PtyProto[] = "/dev/ptypXY";
  72. static char TtyProto[] = "/dev/ttypXY";
  73. # else
  74. static char PtyProto[] = "/dev/ptyXY";
  75. static char TtyProto[] = "/dev/ttyXY";
  76. # endif
  77. # endif /* hpux */
  78. #endif
  79. static void initmaster __P((int));
  80. #if defined(sun)
  81. /* sun's utmp_update program opens the salve side, thus corrupting
  82. */
  83. int pty_preopen = 1;
  84. #else
  85. int pty_preopen = 0;
  86. #endif
  87. /*
  88. * Open all ptys with O_NOCTTY, just to be on the safe side
  89. * (RISCos mips breaks otherwise)
  90. */
  91. #ifndef O_NOCTTY
  92. # define O_NOCTTY 0
  93. #endif
  94. /***************************************************************/
  95. static void
  96. initmaster(f)
  97. int f;
  98. {
  99. #ifdef POSIX
  100. tcflush(f, TCIOFLUSH);
  101. #else
  102. # ifdef TIOCFLUSH
  103. (void) ioctl(f, TIOCFLUSH, (char *) 0);
  104. # endif
  105. #endif
  106. #ifdef LOCKPTY
  107. (void) ioctl(f, TIOCEXCL, (char *) 0);
  108. #endif
  109. }
  110. void
  111. InitPTY(f)
  112. int f;
  113. {
  114. if (f < 0)
  115. return;
  116. #if defined(I_PUSH) && defined(HAVE_SVR4_PTYS) && !defined(sgi) && !defined(linux) && !defined(__osf__) && !defined(M_UNIX)
  117. if (ioctl(f, I_PUSH, "ptem"))
  118. Panic(errno, "InitPTY: cannot I_PUSH ptem");
  119. if (ioctl(f, I_PUSH, "ldterm"))
  120. Panic(errno, "InitPTY: cannot I_PUSH ldterm");
  121. # ifdef sun
  122. if (ioctl(f, I_PUSH, "ttcompat"))
  123. Panic(errno, "InitPTY: cannot I_PUSH ttcompat");
  124. # endif
  125. #endif
  126. }
  127. /***************************************************************/
  128. #if defined(OSX) && !defined(PTY_DONE)
  129. #define PTY_DONE
  130. int
  131. OpenPTY(ttyn)
  132. char **ttyn;
  133. {
  134. register int f;
  135. if ((f = open_controlling_pty(TtyName)) < 0)
  136. return -1;
  137. initmaster(f);
  138. *ttyn = TtyName;
  139. return f;
  140. }
  141. #endif
  142. /***************************************************************/
  143. #if (defined(sequent) || defined(_SEQUENT_)) && !defined(PTY_DONE)
  144. #define PTY_DONE
  145. int
  146. OpenPTY(ttyn)
  147. char **ttyn;
  148. {
  149. char *m, *s;
  150. register int f;
  151. if ((f = getpseudotty(&s, &m)) < 0)
  152. return -1;
  153. #ifdef _SEQUENT_
  154. fvhangup(s);
  155. #endif
  156. strncpy(PtyName, m, sizeof(PtyName));
  157. strncpy(TtyName, s, sizeof(TtyName));
  158. initmaster(f);
  159. *ttyn = TtyName;
  160. return f;
  161. }
  162. #endif
  163. /***************************************************************/
  164. #if defined(__sgi) && !defined(PTY_DONE)
  165. #define PTY_DONE
  166. int
  167. OpenPTY(ttyn)
  168. char **ttyn;
  169. {
  170. int f;
  171. char *name, *_getpty();
  172. sigret_t (*sigcld)__P(SIGPROTOARG);
  173. /*
  174. * SIGCHLD set to SIG_DFL for _getpty() because it may fork() and
  175. * exec() /usr/adm/mkpts
  176. */
  177. sigcld = signal(SIGCHLD, SIG_DFL);
  178. name = _getpty(&f, O_RDWR | O_NONBLOCK, 0600, 0);
  179. signal(SIGCHLD, sigcld);
  180. if (name == 0)
  181. return -1;
  182. initmaster(f);
  183. *ttyn = name;
  184. return f;
  185. }
  186. #endif
  187. /***************************************************************/
  188. #if defined(MIPS) && defined(HAVE_DEV_PTC) && !defined(PTY_DONE)
  189. #define PTY_DONE
  190. int
  191. OpenPTY(ttyn)
  192. char **ttyn;
  193. {
  194. register int f;
  195. struct stat buf;
  196. strcpy(PtyName, "/dev/ptc");
  197. if ((f = open(PtyName, O_RDWR | O_NOCTTY | O_NONBLOCK)) < 0)
  198. return -1;
  199. if (fstat(f, &buf) < 0)
  200. {
  201. close(f);
  202. return -1;
  203. }
  204. sprintf(TtyName, "/dev/ttyq%d", minor(buf.st_rdev));
  205. initmaster(f);
  206. *ttyn = TtyName;
  207. return f;
  208. }
  209. #endif
  210. /***************************************************************/
  211. #if defined(HAVE_SVR4_PTYS) && !defined(PTY_DONE)
  212. #define PTY_DONE
  213. int
  214. OpenPTY(ttyn)
  215. char **ttyn;
  216. {
  217. register int f;
  218. char *m, *ptsname();
  219. int unlockpt __P((int)), grantpt __P((int));
  220. #if defined(HAVE_GETPT) && defined(linux)
  221. int getpt __P((void));
  222. #endif
  223. sigret_t (*sigcld)__P(SIGPROTOARG);
  224. strcpy(PtyName, "/dev/ptmx");
  225. #if defined(HAVE_GETPT) && defined(linux)
  226. if ((f = getpt()) == -1)
  227. #else
  228. if ((f = open(PtyName, O_RDWR | O_NOCTTY)) == -1)
  229. #endif
  230. return -1;
  231. /*
  232. * SIGCHLD set to SIG_DFL for grantpt() because it fork()s and
  233. * exec()s pt_chmod
  234. */
  235. sigcld = signal(SIGCHLD, SIG_DFL);
  236. if ((m = ptsname(f)) == NULL || grantpt(f) || unlockpt(f))
  237. {
  238. signal(SIGCHLD, sigcld);
  239. close(f);
  240. return -1;
  241. }
  242. signal(SIGCHLD, sigcld);
  243. strncpy(TtyName, m, sizeof(TtyName));
  244. initmaster(f);
  245. *ttyn = TtyName;
  246. return f;
  247. }
  248. #endif
  249. /***************************************************************/
  250. #if defined(_AIX) && defined(HAVE_DEV_PTC) && !defined(PTY_DONE)
  251. #define PTY_DONE
  252. int
  253. OpenPTY(ttyn)
  254. char **ttyn;
  255. {
  256. register int f;
  257. /* a dumb looking loop replaced by mycrofts code: */
  258. strcpy (PtyName, "/dev/ptc");
  259. if ((f = open (PtyName, O_RDWR | O_NOCTTY)) < 0)
  260. return -1;
  261. strncpy(TtyName, ttyname(f), sizeof(TtyName));
  262. if (eff_uid && access(TtyName, R_OK | W_OK))
  263. {
  264. close(f);
  265. return -1;
  266. }
  267. initmaster(f);
  268. # ifdef _IBMR2
  269. pty_preopen = 1;
  270. # endif
  271. *ttyn = TtyName;
  272. return f;
  273. }
  274. #endif
  275. /***************************************************************/
  276. #if defined(HAVE_OPENPTY) && !defined(PTY_DONE)
  277. #define PTY_DONE
  278. int
  279. OpenPTY(ttyn)
  280. char **ttyn;
  281. {
  282. int f, s;
  283. if (openpty(&f, &s, TtyName, NULL, NULL) != 0)
  284. return -1;
  285. close(s);
  286. initmaster(f);
  287. pty_preopen = 1;
  288. *ttyn = TtyName;
  289. return f;
  290. }
  291. #endif
  292. /***************************************************************/
  293. #ifndef PTY_DONE
  294. int
  295. OpenPTY(ttyn)
  296. char **ttyn;
  297. {
  298. register char *p, *q, *l, *d;
  299. register int f;
  300. debug("OpenPTY: Using BSD style ptys.\n");
  301. strcpy(PtyName, PtyProto);
  302. strcpy(TtyName, TtyProto);
  303. for (p = PtyName; *p != 'X'; p++)
  304. ;
  305. for (q = TtyName; *q != 'X'; q++)
  306. ;
  307. for (l = PTYRANGE0; (*p = *l) != '\0'; l++)
  308. {
  309. for (d = PTYRANGE1; (p[1] = *d) != '\0'; d++)
  310. {
  311. debug1("OpenPTY tries '%s'\n", PtyName);
  312. if ((f = open(PtyName, O_RDWR | O_NOCTTY)) == -1)
  313. continue;
  314. q[0] = *l;
  315. q[1] = *d;
  316. if (eff_uid && access(TtyName, R_OK | W_OK))
  317. {
  318. close(f);
  319. continue;
  320. }
  321. #if defined(sun) && defined(TIOCGPGRP) && !defined(SUNOS3)
  322. /* Hack to ensure that the slave side of the pty is
  323. * unused. May not work in anything other than SunOS4.1
  324. */
  325. {
  326. int pgrp;
  327. /* tcgetpgrp does not work (uses TIOCGETPGRP)! */
  328. if (ioctl(f, TIOCGPGRP, (char *)&pgrp) != -1 || errno != EIO)
  329. {
  330. close(f);
  331. continue;
  332. }
  333. }
  334. #endif
  335. initmaster(f);
  336. *ttyn = TtyName;
  337. return f;
  338. }
  339. }
  340. return -1;
  341. }
  342. #endif