ckupty.c 49 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989
  1. char *ckptyv = "Pseudoterminal support, 9.0.104, 18 Sep 2020";
  2. /* C K U P T Y -- C-Kermit pseudoterminal control functions for UNIX */
  3. /* Last update: Sat Sep 19 15:25:13 2020 */
  4. /*
  5. Copyright 1995 by the Massachusetts Institute of Technology.
  6. Permission to use, copy, modify, and distribute this software and its
  7. documentation for any purpose and without fee is hereby granted, provided
  8. that the above copyright notice appear in all copies and that both that
  9. copyright notice and this permission notice appear in supporting
  10. documentation, and that the name of M.I.T. not be used in advertising or
  11. publicity pertaining to distribution of the software without specific,
  12. written prior permission. Furthermore if you modify this software you must
  13. label your software as modified software and not distribute it in such a
  14. fashion that it might be confused with the original M.I.T. software.
  15. M.I.T. makes no representations about the suitability of this software for
  16. any purpose. It is provided "as is" without express or implied warranty.
  17. Modified for use in C-Kermit, and new material added, by:
  18. Jeffrey Altman <jaltman@secure-endpoints.com>
  19. Secure Endpoints Inc., New York City
  20. November 1999
  21. Parameterized for pty file descriptor and function code,
  22. Dec 2006 - Sep 2009, plus some minor "compliance" nits addressed in 2020.
  23. See "HAVE_OPENPTY" section of ckcdeb.h.
  24. Frank da Cruz, The Kermit Project, New York City
  25. */
  26. /*
  27. Built and tested successully on:
  28. . 4.4BSD, including BSDI/OS, NetBSD, FreeBSD, OpenBSD, Mac OS X
  29. . AIX 4.1 and later
  30. . DG/UX 5.4R4.11
  31. . Digital UNIX 3.2 and 4.0
  32. . HP-UX 9.00 and later
  33. . IRIX 6.0 and later
  34. . Linux
  35. . Mac OS X 10.4
  36. . NeXTSTEP 3.x
  37. . OpenBSD
  38. . QNX 4.25 (except PTY process termination not detected)
  39. . SCO OSR5.0.5
  40. . SCO Unixware 7
  41. . SINIX 5.42
  42. . Solaris 2.x and 7
  43. . SunOS 4.1.3
  44. Failures include:
  45. . SCO UNIX 3.2v4.2 (compile fails with syntax error in <memory.h>)
  46. . HP-UX 8.00 and earlier (no vhangup or ptsname routines)
  47. */
  48. #ifndef __FreeBSD__ /* bs 20151224 */
  49. #define _XOPEN_SOURCE 500 /* mdw 20140223 */
  50. #endif /* __FreeBSD__ */ /* bs 20151224 */
  51. #include <stdlib.h> /* mdw 20140223 */
  52. #include "ckcsym.h"
  53. #include "ckcdeb.h" /* To pick up NETPTY definition */
  54. #ifndef NETPTY /* Selector for PTY support */
  55. char * ptyver = "No PTY support";
  56. #else /* (rest of this module...) */
  57. char * ptyver = "PTY support 8.0.017, 18 Sep 2020";
  58. /* These will no doubt need adjustment... */
  59. #ifndef NEXT
  60. #define HAVE_SETSID
  61. #endif /* NEXT */
  62. #define HAVE_KILLPG
  63. #define HAVE_TTYNAME
  64. #define HAVE_WAITPID
  65. #ifdef SUNOS41
  66. #define BSD44ORPOSIX
  67. #endif /* SUNOS41 */
  68. #ifndef USE_TERMIO
  69. #ifdef LINUX
  70. #define USE_TERMIO
  71. #else
  72. #ifdef ATTSV
  73. #define USE_TERMIO
  74. #else
  75. #ifdef HPUX
  76. #define USE_TERMIO
  77. #else
  78. #ifdef AIX
  79. #define USE_TERMIO
  80. #else
  81. #ifdef BSD44ORPOSIX
  82. #define USE_TERMIO
  83. #else
  84. #ifdef IRIX60
  85. #define USE_TERMIO
  86. #else
  87. #ifdef QNX
  88. #define USE_TERMIO
  89. #endif /* QNX */
  90. #endif /* IRIX60 */
  91. #endif /* BSD44ORPOSIX */
  92. #endif /* AIX */
  93. #endif /* HPUX */
  94. #endif /* ATTSV */
  95. #endif /* LINUX */
  96. #endif /* USE_TERMIO */
  97. #ifdef QNX
  98. #include <fcntl.h>
  99. #endif /* QNX */
  100. #ifdef USE_TERMIO
  101. #define POSIX_TERMIOS /* Seems to be a misnomer */
  102. #endif /* USE_TERMIO */
  103. #ifdef NEXT
  104. #ifndef GETPGRP_ONEARG
  105. #define GETPGRP_ONEARG
  106. #endif /* GETPGRP_ONEARG */
  107. #endif /* NEXT */
  108. #ifdef WANT_UTMP /* See ckupty.h */
  109. /*
  110. WANT_UTMP is not defined because (a) the utmp/wtmp junk is the most
  111. nonportable part of this module, and (b) we're not logging anybody
  112. in, we're just running a process, and don't need to write utmp/wtmp records.
  113. */
  114. #ifndef HAVE_SETUTXENT /* Who has <utmpx.h> */
  115. #ifdef SOLARIS
  116. #define HAVE_SETUTXENT
  117. #else
  118. #ifdef IRIX60
  119. #define HAVE_SETUTXENT
  120. #else
  121. #ifdef CK_SCOV5
  122. #define HAVE_SETUTXENT
  123. #else
  124. #ifdef HPUX10
  125. #define HAVE_SETUTXENT
  126. #else
  127. #ifdef UNIXWARE
  128. #define HAVE_SETUTXENT
  129. #else
  130. #ifdef IRIX60
  131. #define HAVE_SETUTXENT
  132. #endif /* IRIX60 */
  133. #endif /* UNIXWARE */
  134. #endif /* HPUX10 */
  135. #endif /* CK_SCOV5 */
  136. #endif /* IRIX60 */
  137. #endif /* SOLARIS */
  138. #endif /* HAVE_SETUTXENT */
  139. #ifndef HAVE_UTHOST /* Does utmp include ut_host[]? */
  140. #ifdef HAVE_SETUTXENT /* utmpx always does */
  141. #define HAVE_UTHOST
  142. #else
  143. #ifdef LINUX /* Linux does */
  144. #define HAVE_UTHOST
  145. #else
  146. #ifdef SUNOS4 /* SunOS does */
  147. #define HAVE_UTHOST
  148. #else
  149. #ifdef AIX41 /* AIX 4.1 and later do */
  150. #define HAVE_UTHOST
  151. #endif /* AIX41 */
  152. #endif /* SUNOS4 */
  153. #endif /* LINUX */
  154. #endif /* HAVE_SETUTXENT */
  155. #endif /* HAVE_UTHOST */
  156. #ifndef HAVE_UT_HOST
  157. #ifndef NO_UT_HOST
  158. #define NO_UT_HOST
  159. #endif /* NO_UT_HOST */
  160. #endif /* HAVE_UT_HOST */
  161. #endif /* WANT_UTMP */
  162. #ifdef LINUX
  163. #define CK_VHANGUP
  164. #define HAVE_SYS_SELECT_H
  165. #define HAVE_GETUTENT
  166. #define HAVE_SETUTENT
  167. #define HAVE_UPDWTMP
  168. #endif /* LINUX */
  169. #ifdef HPUX10
  170. #define CK_VHANGUP
  171. #define VHANG_FIRST
  172. #define HAVE_PTSNAME
  173. #ifndef HAVE_PTYTRAP
  174. #define HAVE_PTYTRAP
  175. #endif /* HAVE_PTYTRAP */
  176. #else
  177. #ifdef HPUX9
  178. #define CK_VHANGUP
  179. #define VHANG_FIRST
  180. #define HAVE_PTSNAME
  181. #ifndef HAVE_PTYTRAP
  182. #define HAVE_PTYTRAP
  183. #endif /* HAVE_PTYTRAP */
  184. #endif /* HPUX9 */
  185. #endif /* HPUX10 */
  186. #ifdef SUNOS4
  187. #define CK_VHANGUP
  188. #define NO_UT_PID
  189. #define VHANG_FIRST
  190. #endif /* SUNOS4 */
  191. #ifdef IRIX60
  192. #define CK_VHANGUP
  193. #define HAVE__GETPTY
  194. #endif /* IRIX60 */
  195. #ifdef SINIX
  196. #define HAVE_STREAMS
  197. #define HAVE_GRANTPT
  198. #define HAVE_PTSNAME
  199. #define PUSH_PTEM
  200. #define PUSH_LDTERM
  201. #define PUSH_TTCOMPAT
  202. #endif /* SINIX */
  203. #ifdef ultrix
  204. #define MUST_SETPGRP
  205. #endif /* ultrix */
  206. #ifdef QNX
  207. #define MUST_SETPGRP
  208. #define NO_DEVTTY
  209. #define INIT_SPTY
  210. #endif /* QNX */
  211. #ifdef LINUX
  212. #ifdef HAVE_PTMX
  213. #define HAVE_GRANTPT
  214. #define HAVE_PTSNAME
  215. #endif /* HAVE_PTMX */
  216. #else
  217. #ifdef HAVE_STREAMS
  218. #define HAVE_PTMX
  219. #endif /* HAVE_STREAMS */
  220. #endif /* LINUX */
  221. #include "ckupty.h"
  222. #ifdef PTYNOBLOCK
  223. #ifndef O_NDELAY
  224. #ifdef O_NONBLOCK
  225. #define O_NDELAY O_NONBLOCK
  226. #endif /* O_NONBLOCK */
  227. #endif /* O_NDELAY */
  228. #else /* PTYNOBLOCK */
  229. #ifdef O_NDELAY
  230. #undef O_NDELAY
  231. #endif /* O_NDELAY */
  232. #define O_NDELAY 0
  233. #endif /* PTYNOBLOCK */
  234. #ifndef ONLCR
  235. #define ONLCR 0
  236. #endif /* ONLCR */
  237. #ifdef CK_WAIT_H
  238. #include <sys/wait.h>
  239. #endif /* CK_WAIT_H */
  240. #ifdef STREAMSPTY
  241. #ifndef INIT_SPTY
  242. #define INIT_SPTY
  243. #endif /* INIT_SPTY */
  244. #include <sys/stream.h>
  245. #include <stropts.h>
  246. #include <termio.h>
  247. /* Make sure we don't get the BSD version */
  248. #ifdef HAVE_SYS_TTY_H
  249. #include "/usr/include/sys/tty.h"
  250. #endif /* HAVE_SYS_TTY_H */
  251. #ifdef HAS_PTYVAR /* Where is this set? */
  252. #include <sys/ptyvar.h>
  253. #else /* HAS_PTYVAR */
  254. #ifndef TIOCPKT_FLUSHWRITE
  255. #define TIOCPKT_FLUSHWRITE 0x02
  256. #define TIOCPKT_NOSTOP 0x10
  257. #define TIOCPKT_DOSTOP 0x20
  258. #define TIOCPKT_IOCTL 0x40
  259. #endif /* TIOCPKT_FLUSHWRITE */
  260. #endif /* HAS_PTYVAR */
  261. #ifdef HAVE_TTY_H
  262. #include <tty.h>
  263. #endif /* HAVE_TTY_H */
  264. /*
  265. Because of the way ptyibuf is used with streams messages, we need
  266. ptyibuf+1 to be on a full-word boundary. The following weirdness
  267. is simply to make that happen.
  268. */
  269. long ptyibufbuf[BUFSIZ/sizeof(long)+1];
  270. char *ptyibuf = ((char *)&ptyibufbuf[1])-1;
  271. char *ptyip = ((char *)&ptyibufbuf[1])-1;
  272. char ptyibuf2[BUFSIZ];
  273. unsigned char ctlbuf[BUFSIZ];
  274. struct strbuf strbufc, strbufd;
  275. int readstream();
  276. #else /* ! STREAMSPTY */
  277. /* I/O data buffers, pointers, and counters. */
  278. char ptyibuf[BUFSIZ], *ptyip = ptyibuf;
  279. char ptyibuf2[BUFSIZ];
  280. #endif /* ! STREAMSPTY */
  281. #ifndef USE_TERMIO
  282. struct termbuf {
  283. struct sgttyb sg;
  284. struct tchars tc;
  285. struct ltchars ltc;
  286. int state;
  287. int lflags;
  288. } termbuf, termbuf2;
  289. #define cfsetospeed(tp,val) (tp)->sg.sg_ospeed = (val)
  290. #define cfsetispeed(tp,val) (tp)->sg.sg_ispeed = (val)
  291. #define cfgetospeed(tp) (tp)->sg.sg_ospeed
  292. #define cfgetispeed(tp) (tp)->sg.sg_ispeed
  293. #else /* USE_TERMIO */
  294. #ifdef SYSV_TERMIO
  295. #define termios termio
  296. #endif /* SYSV_TERMIO */
  297. #ifndef TCSANOW
  298. #ifdef TCSETS
  299. #define TCSANOW TCSETS
  300. #define TCSADRAIN TCSETSW
  301. #define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t)
  302. #else /* TCSETS */
  303. #ifdef TCSETA
  304. #define TCSANOW TCSETA
  305. #define TCSADRAIN TCSETAW
  306. #define tcgetattr(f,t) ioctl(f,TCGETA,(char *)t)
  307. #else /* TCSETA */
  308. #define TCSANOW TIOCSETA
  309. #define TCSADRAIN TIOCSETAW
  310. #define tcgetattr(f,t) ioctl(f,TIOCGETA,(char *)t)
  311. #endif /* TCSETA */
  312. #endif /* TCSETS */
  313. #define tcsetattr(f,a,t) ioctl(f,a,t)
  314. #define cfsetospeed(tp,val) (tp)->c_cflag &= ~CBAUD;(tp)->c_cflag|=(val)
  315. #define cfgetospeed(tp) ((tp)->c_cflag & CBAUD)
  316. #ifdef CIBAUD
  317. #define cfsetispeed(tp,val) \
  318. (tp)->c_cflag &= ~CIBAUD; (tp)->c_cflag |= ((val)<<IBSHIFT)
  319. #define cfgetispeed(tp) (((tp)->c_cflag & CIBAUD)>>IBSHIFT)
  320. #else /* CIBAUD */
  321. #define cfsetispeed(tp,val) (tp)->c_cflag &= ~CBAUD; (tp)->c_cflag|=(val)
  322. #define cfgetispeed(tp) ((tp)->c_cflag & CBAUD)
  323. #endif /* CIBAUD */
  324. #endif /* TCSANOW */
  325. struct termios termbuf, termbuf2; /* pty control structure */
  326. #ifdef INIT_SPTY
  327. static int spty = -1;
  328. #endif /* INIT_SPTY */
  329. #endif /* USE_TERMIO */
  330. #ifndef IXANY /* This was in #ifdef QNX.. */
  331. #define IXANY 0 /* but because of _XOPEN_SOURCE */
  332. #endif /* IXANY */ /* must be universal - does no harm */
  333. static int msg = 0;
  334. /* Variables available to other modules */
  335. int pty_fork_active = 0; /* pty fork is active */
  336. PID_T pty_fork_pid = -1; /* pty fork pid */
  337. int pty_slave_fd = -1; /* pty slave file descriptor */
  338. int pty_master_fd = -1; /* pty master file descriptor */
  339. /* termbuf routines (begin) */
  340. /*
  341. init_termbuf()
  342. copy_termbuf(cp)
  343. set_termbuf()
  344. These three routines are used to get and set the "termbuf" structure
  345. to and from the kernel. init_termbuf() gets the current settings.
  346. copy_termbuf() hands in a new "termbuf" to write to the kernel, and
  347. set_termbuf() writes the structure into the kernel.
  348. */
  349. VOID
  350. init_termbuf(fd) int fd; {
  351. int ttyfd;
  352. int rc = 0;
  353. ttyfd = fd;
  354. #ifdef HAVE_STREAMS
  355. debug(F100,"init_termbuf HAVE_STREAMS","",0);
  356. #else
  357. debug(F100,"init_termbuf HAVE_STREAMS NOT DEFINED","",0);
  358. #endif /* HAVE_STREAMS */
  359. #ifdef STREAMSPTY
  360. debug(F100,"init_termbuf STREAMSPTY","",0);
  361. #else
  362. debug(F100,"init_termbuf STREAMSPTY NOT DEFINED","",0);
  363. #endif /* STREAMSPTY */
  364. #ifdef INIT_SPTY
  365. debug(F100,"init_termbuf INIT_SPTY","",0);
  366. #else
  367. debug(F100,"init_termbuf INIT_SPTY NOT DEFINED","",0);
  368. #endif /* INIT_SPTY */
  369. debug(F101,"init_termbuf ttyfd","",ttyfd);
  370. #ifdef INIT_SPTY
  371. debug(F101,"init_termbuf spty","",spty);
  372. #endif /* INIT_SPTY */
  373. memset(&termbuf,0,sizeof(termbuf));
  374. memset(&termbuf2,0,sizeof(termbuf2));
  375. #ifndef USE_TERMIO
  376. rc = ioctl(ttyfd, TIOCGETP, (char *)&termbuf.sg);
  377. rc |= ioctl(ttyfd, TIOCGETC, (char *)&termbuf.tc);
  378. rc |= ioctl(ttyfd, TIOCGLTC, (char *)&termbuf.ltc);
  379. #ifdef TIOCGSTATE
  380. rc |= ioctl(ttyfd, TIOCGSTATE, (char *)&termbuf.state);
  381. #endif /* TIOCGSTATE */
  382. #else /* USE_TERMIO */
  383. errno = 0;
  384. #ifdef INIT_SPTY
  385. rc = tcgetattr(spty, &termbuf);
  386. debug(F111,"init_termbuf() tcgetattr(spty)",ckitoa(rc),errno);
  387. #else
  388. rc = tcgetattr(ttyfd, &termbuf);
  389. debug(F111,"init_termbuf() tcgetattr(ttyfd)",ckitoa(rc),errno);
  390. #endif /* INIT_SPTY */
  391. #endif /* USE_TERMIO */
  392. if (!rc)
  393. termbuf2 = termbuf;
  394. }
  395. #ifdef TIOCPKT_IOCTL
  396. VOID
  397. copy_termbuf(cp, len) char *cp; int len; {
  398. if (len > sizeof(termbuf))
  399. len = sizeof(termbuf);
  400. memcpy((char *)&termbuf, cp, len);
  401. termbuf2 = termbuf;
  402. }
  403. #endif /* TIOCPKT_IOCTL */
  404. VOID
  405. set_termbuf(fd) int fd; { /* Only make the necessary changes. */
  406. int x;
  407. int ttyfd;
  408. ttyfd = fd;
  409. debug(F101,"set_termbuf ttyfd","",ttyfd);
  410. #ifdef INIT_SPTY
  411. debug(F101,"set_termbuf spty","",spty);
  412. #endif /* INIT_SPTY */
  413. #ifndef USE_TERMIO
  414. debug(F100,"set_termbuf USE_TERMIO","",0);
  415. if (memcmp((char *)&termbuf.sg, (char *)&termbuf2.sg, sizeof(termbuf.sg)))
  416. ioctl(ttyfd, TIOCSETN, (char *)&termbuf.sg);
  417. if (memcmp((char *)&termbuf.tc, (char *)&termbuf2.tc, sizeof(termbuf.tc)))
  418. ioctl(ttyfd, TIOCSETC, (char *)&termbuf.tc);
  419. if (memcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc,
  420. sizeof(termbuf.ltc)))
  421. ioctl(ttyfd, TIOCSLTC, (char *)&termbuf.ltc);
  422. if (termbuf.lflags != termbuf2.lflags)
  423. ioctl(ttyfd, TIOCLSET, (char *)&termbuf.lflags);
  424. #else /* USE_TERMIO */
  425. x = memcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf));
  426. debug(F101,"set_termbuf !USE_TERMIO memcmp","",x);
  427. x = 1; /* Force this */
  428. if (x) {
  429. int x;
  430. errno = 0;
  431. #ifdef INIT_SPTY
  432. debug(F100,"set_termbuf INIT_SPTY","",0);
  433. x = tcsetattr(spty, TCSANOW, &termbuf);
  434. debug(F111,"set_termbuf tcsetattr(spty)",ckitoa(x),errno);
  435. #else
  436. debug(F100,"set_termbuf !INIT_SPTY","",0);
  437. x = tcsetattr(ttyfd, TCSANOW, &termbuf);
  438. debug(F111,"set_termbuf tcsetattr(ttyfd)",ckitoa(x),errno);
  439. #endif /* INIT_SPTY */
  440. }
  441. #endif /* USE_TERMIO */
  442. }
  443. /* termbuf routines (end) */
  444. VOID
  445. ptyint_vhangup() {
  446. #ifdef CK_VHANGUP
  447. _PROTOTYP( int vhangup, (void) );
  448. #ifdef CK_POSIX_SIG
  449. struct sigaction sa;
  450. /* Initialize "sa" structure. */
  451. sigemptyset(&sa.sa_mask);
  452. sa.sa_flags = 0;
  453. sa.sa_handler = SIG_IGN;
  454. sigaction(SIGHUP, &sa, (struct sigaction *)0);
  455. vhangup();
  456. sa.sa_handler = SIG_DFL;
  457. sigaction(SIGHUP, &sa, (struct sigaction *)0);
  458. #else /* CK_POSIX_SIG */
  459. signal(SIGHUP,SIG_IGN);
  460. vhangup();
  461. signal(SIGHUP,SIG_DFL);
  462. #endif /* CK_POSIX_SIG */
  463. #endif /* CK_VHANGUP */
  464. }
  465. /*
  466. This routine is called twice. It's not particularly important that the
  467. setsid() or TIOCSCTTY ioctls succeed (they may not the second time), but
  468. rather that we have a controlling terminal at the end. It is assumed that
  469. vhangup doesn't exist and confuse the process's notion of controlling
  470. terminal on any system without TIOCNOTTY. That is, either vhangup() leaves
  471. the controlling terminal in tact, breaks the association completely, or the
  472. system provides TIOCNOTTY to get things back into a reasonable state. In
  473. practice, vhangup() either breaks the association completely or doesn't
  474. effect controlling terminals, so this condition is met.
  475. */
  476. long
  477. ptyint_void_association() {
  478. int con_fd;
  479. #ifdef HAVE_SETSID
  480. debug(F110,
  481. "ptyint_void_association()",
  482. "setsid()",
  483. 0
  484. );
  485. setsid();
  486. #endif /* HAVE_SETSID */
  487. #ifndef NO_DEVTTY
  488. /* Void tty association first */
  489. #ifdef TIOCNOTTY
  490. con_fd = open("/dev/tty", O_RDWR);
  491. debug(F111,
  492. "ptyint_void_association() open(/dev/tty,O_RDWR)",
  493. "/dev/tty",
  494. con_fd);
  495. if (con_fd >= 0) {
  496. ioctl(con_fd, TIOCNOTTY, 0);
  497. close(con_fd);
  498. }
  499. #ifdef DEBUG
  500. else debug(F101, "ptyint_void_association() open() errno","",errno);
  501. #endif /* DEBUG */
  502. #endif /* TIOCNOTTY */
  503. #endif /* NO_DEVTTY */
  504. return(0);
  505. }
  506. /* PID may be zero for unknown.*/
  507. long
  508. pty_cleanup(slave, pid, update_utmp) char *slave; int pid; int update_utmp; {
  509. #ifdef VHANG_LAST
  510. int retval, fd;
  511. #endif /* VHANG_LAST */
  512. debug(F111,"pty_cleanup()",slave,pid);
  513. #ifdef WANT_UTMP
  514. if (update_utmp)
  515. pty_update_utmp(PTY_DEAD_PROCESS,
  516. 0,
  517. "",
  518. slave,
  519. (char *)0,
  520. PTY_UTMP_USERNAME_VALID
  521. );
  522. #endif /* WANT_UTMP */
  523. #ifdef SETUID
  524. chmod(slave, 0666);
  525. chown(slave, 0, 0);
  526. #endif /* SETUID */
  527. #ifdef HAVE_REVOKE
  528. revoke(slave);
  529. /*
  530. Revoke isn't guaranteed to send a SIGHUP to the processes it
  531. dissociates from the terminal. The best solution without a Posix
  532. mechanism for forcing a hangup is to killpg() the process group of the
  533. pty. This will at least kill the shell and hopefully, the child
  534. processes. This is not always the case, however. If the shell puts
  535. each job in a process group and doesn't pass along SIGHUP, all
  536. processes may not die.
  537. */
  538. if (pid > 0) {
  539. #ifdef HAVE_KILLPG
  540. killpg(pid, SIGHUP);
  541. #else
  542. kill(-(pid), SIGHUP);
  543. #endif /*HAVE_KILLPG*/
  544. }
  545. #else /* HAVE_REVOKE*/
  546. #ifdef VHANG_LAST
  547. {
  548. int status;
  549. #ifdef CK_POSIX_SIG
  550. sigset_t old, new;
  551. sigemptyset(&new);
  552. sigaddset(&new, SIGCHLD);
  553. sigprocmask(SIG_BLOCK, &new, &old);
  554. #else /*CK_POSIX_SIG*/
  555. int mask = sigblock(sigmask(SIGCHLD));
  556. #endif /*CK_POSIX_SIG*/
  557. switch (retval = fork()) {
  558. case -1:
  559. #ifdef CK_POSIX_SIG
  560. sigprocmask(SIG_SETMASK, &old, 0);
  561. #else /*CK_POSIX_SIG*/
  562. sigsetmask(mask);
  563. #endif /*CK_POSIX_SIG*/
  564. return errno;
  565. case 0:
  566. ptyint_void_association();
  567. if (retval = (pty_open_ctty(slave, &fd, -1)))
  568. exit(retval);
  569. ptyint_vhangup();
  570. exit(0);
  571. break;
  572. default:
  573. #ifdef HAVE_WAITPID
  574. waitpid(retval, &status, 0);
  575. #else /*HAVE_WAITPID*/
  576. wait(&status);
  577. #endif /* HAVE_WAITPID */
  578. #ifdef CK_POSIX_SIG
  579. sigprocmask(SIG_SETMASK, &old, 0);
  580. #else /*CK_POSIX_SIG*/
  581. sigsetmask(mask);
  582. #endif /*CK_POSIX_SIG*/
  583. break;
  584. }
  585. }
  586. #endif /*VHANG_LAST*/
  587. #endif /* HAVE_REVOKE*/
  588. #ifndef HAVE_STREAMS
  589. slave[strlen("/dev/")] = 'p';
  590. #ifdef SETUID
  591. chmod(slave, 0666);
  592. chown(slave, 0, 0);
  593. #endif /* SETUID */
  594. #endif /* HAVE_STREAMS */
  595. return(0);
  596. }
  597. #ifdef HAVE_OPENPTY
  598. #include <pty.h>
  599. #endif
  600. long
  601. pty_getpty(fd, slave, slavelength) int slavelength; int *fd; char *slave; {
  602. char *cp;
  603. char *p;
  604. int i, ptynum;
  605. struct stat stb;
  606. #ifndef HAVE_OPENPTY
  607. #ifndef HAVE__GETPTY
  608. char slavebuf[1024];
  609. #endif /* HAVE__GETPTY */
  610. #endif /* HAVE_OPENPTY */
  611. #ifdef HAVE__GETPTY
  612. char *slaveret; /* Temp to hold pointer to slave */
  613. #endif /*HAVE__GETPTY*/
  614. #ifdef HAVE_OPENPTY
  615. int slavefd;
  616. pty_master_fd = -1;
  617. debug(F100,"HAVE_OPENPTY","",0);
  618. if (openpty(fd,
  619. &slavefd,
  620. slave,
  621. (struct termios *)0,
  622. (struct winsize *)0
  623. )
  624. ) {
  625. pty_master_fd = *fd;
  626. return(1);
  627. }
  628. close(slavefd);
  629. return(0);
  630. #else /* HAVE_OPENPTY */
  631. #ifdef HAVE__GETPTY
  632. /*
  633. This code is included for Irix; as of version 5.3, Irix has /dev/ptmx, but
  634. it fails to work properly; even after calling unlockpt, root gets permission
  635. denied opening the pty. The code to support _getpty should be removed if
  636. Irix gets working streams ptys in favor of maintaining the least needed code
  637. paths.
  638. */
  639. debug(F100,"HAVE__GETPTY","",0);
  640. if ((slaveret = _getpty(fd, O_RDWR | O_NDELAY, 0600, 0)) == 0) {
  641. *fd = -1;
  642. return(PTY_GETPTY_NOPTY);
  643. }
  644. if (strlen(slaveret) > slavelength - 1) {
  645. close(*fd);
  646. *fd = -1;
  647. return(PTY_GETPTY_SLAVE_TOOLONG);
  648. } else {
  649. ckstrncpy(slave, slaveret, slavelength);
  650. }
  651. return(0);
  652. #else /* HAVE__GETPTY */
  653. *fd = open("/dev/ptym/clone", O_RDWR|O_NDELAY); /* HPUX */
  654. if (*fd >= 0) {
  655. debug(F110,"pty_getpty()","open(/dev/ptym/clone) success",0);
  656. goto have_fd;
  657. }
  658. #ifdef HAVE_PTMX
  659. debug(F100,"HAVE_PTMX","",0);
  660. *fd = open("/dev/ptmx",O_RDWR|O_NDELAY);
  661. if (*fd >= 0) {
  662. debug(F110,"pty_getpty()","open(/dev/ptmx) success",0);
  663. goto have_fd;
  664. }
  665. #endif /* HAVE_PTMX */
  666. *fd = open("/dev/ptc", O_RDWR|O_NDELAY); /* AIX */
  667. if (*fd >= 0) {
  668. debug(F110,"pty_getpty()","open(/dev/ptc) success",0);
  669. goto have_fd;
  670. }
  671. *fd = open("/dev/pty", O_RDWR|O_NDELAY); /* sysvimp */
  672. if (*fd >= 0)
  673. debug(F110,"pty_getpty()","open(/dev/pty) success",0);
  674. have_fd:
  675. /* This would be the pty master */
  676. debug(F101,"pty_getpty fd(A)","",*fd);
  677. if (*fd >= 0) {
  678. pty_master_fd = *fd;
  679. #ifdef HAVE_GRANTPT
  680. #ifdef HAVE_PTMX
  681. debug(F100,"HAVE_GRANTPT","",0);
  682. if (grantpt(*fd) || unlockpt(*fd))
  683. return(PTY_GETPTY_STREAMS);
  684. #endif /* HAVE_PTMX */
  685. #endif /* HAVE_GRANTPT */
  686. #ifdef HAVE_PTSNAME
  687. debug(F100,"HAVE_PTSNAME","",0);
  688. p = (char *)ptsname(*fd);
  689. debug(F110,"pty_getpty() ptsname()",p,0);
  690. #else
  691. #ifdef HAVE_TTYNAME
  692. debug(F100,"HAVE_TTYNAME","",0);
  693. p = ttyname(*fd);
  694. debug(F110,"pty_getpty() ttyname()",p,0);
  695. #else
  696. /* If we don't have either what do we do? */
  697. return(PTY_GETPTY_NOPTY); /* punt */
  698. #endif /* HAVE_TTYNAME */
  699. #endif /* HAVE_PTSNAME */
  700. if (p) {
  701. if (strlen(p) > slavelength - 1) {
  702. close (*fd);
  703. *fd = -1;
  704. return(PTY_GETPTY_SLAVE_TOOLONG);
  705. }
  706. ckstrncpy(slave, p, slavelength);
  707. return(0);
  708. }
  709. if (fstat(*fd, &stb) < 0) {
  710. close(*fd);
  711. return(PTY_GETPTY_FSTAT);
  712. }
  713. ptynum = (int)(stb.st_rdev&0xFF);
  714. sprintf(slavebuf, "/dev/ttyp%x", ptynum); /* safe */
  715. if (strlen(slavebuf) > slavelength - 1) {
  716. close(*fd);
  717. *fd = -1;
  718. return(PTY_GETPTY_SLAVE_TOOLONG);
  719. }
  720. debug(F110,"pty_getpty() slavebuf",slavebuf,0);
  721. ckstrncpy(slave, slavebuf, slavelength);
  722. return(0);
  723. } else {
  724. for (cp = "pqrstuvwxyzPQRST";*cp; cp++) {
  725. sprintf(slavebuf,"/dev/ptyXX"); /* safe */
  726. slavebuf[sizeof("/dev/pty") - 1] = *cp;
  727. slavebuf[sizeof("/dev/ptyp") - 1] = '0';
  728. if (stat(slavebuf, &stb) < 0)
  729. break;
  730. for (i = 0; i < 16; i++) {
  731. slavebuf[sizeof("/dev/ptyp") - 1] = "0123456789abcdef"[i];
  732. errno = 0;
  733. *fd = open(slavebuf, O_RDWR|O_NDELAY);
  734. if (*fd < 0) {
  735. debug(F111,"pty_getpty() pty master open error",
  736. slavebuf,errno);
  737. continue;
  738. }
  739. debug(F111,"pty_getpty() found pty master",slavebuf,*fd);
  740. slavebuf[sizeof("/dev/") - 1] = 't'; /* got pty */
  741. if (strlen(slavebuf) > slavelength -1) {
  742. close(*fd);
  743. *fd = -1;
  744. return(PTY_GETPTY_SLAVE_TOOLONG);
  745. }
  746. ckstrncpy(slave, slavebuf, slavelength);
  747. debug(F110,"pty_getpty slave name",slave,0);
  748. pty_master_fd = *fd;
  749. return(0);
  750. }
  751. }
  752. return(PTY_GETPTY_NOPTY);
  753. }
  754. #endif /*HAVE__GETPTY*/
  755. #endif /* HAVE_OPENPTY */
  756. }
  757. long
  758. pty_init() {
  759. #ifdef HAVE_PTYM
  760. static char dummy;
  761. debug(F100,"HAVE_PTYM","",0);
  762. tty_bank = &master_name[strlen("/dev/ptym/pty")];
  763. tty_num = &master_name[strlen("/dev/ptym/ptyX")];
  764. slave_bank = &slave_name[strlen("/dev/pty/tty")];
  765. slave_num = &slave_name[strlen("/dev/pty/ttyX")];
  766. #endif
  767. return(0L);
  768. }
  769. /*
  770. The following is an array of modules that should be pushed on the stream.
  771. See configure.in for caviats and notes about when this array is used and not
  772. used.
  773. */
  774. #ifdef HAVE_STREAMS
  775. #ifndef HAVE_LINE_PUSH
  776. static char *push_list[] = {
  777. #ifdef PUSH_PTEM
  778. "ptem",
  779. #endif
  780. #ifdef PUSH_LDTERM
  781. "ldterm",
  782. #endif
  783. #ifdef PUSH_TTCOMPAT
  784. "ttcompat",
  785. #endif
  786. 0
  787. };
  788. #endif /* HAVE_LINE_PUSH */
  789. #endif /* HAVE_STREAMS */
  790. long
  791. pty_initialize_slave (fd) int fd; {
  792. #ifdef POSIX_TERMIOS
  793. #ifndef ultrix
  794. struct termios new_termio;
  795. #else
  796. struct sgttyb b;
  797. #endif /* ultrix */
  798. #else
  799. struct sgttyb b;
  800. #endif /* POSIX_TERMIOS */
  801. int pid;
  802. #ifdef POSIX_TERMIOS
  803. #ifndef ultrix
  804. int rc;
  805. #endif /* ultrix */
  806. #endif /* POSIX_TERMIOS */
  807. debug(F111,"pty_initialize_slave()","fd",fd);
  808. #ifdef HAVE_STREAMS
  809. #ifdef HAVE_LINE_PUSH
  810. while (ioctl(fd,I_POP,0) == 0) ; /* Clear out any old lined's */
  811. if (line_push(fd) < 0) {
  812. debug(F110,"pty_initialize_slave()","line_push() failed",0);
  813. close(fd);
  814. fd = -1;
  815. return(PTY_OPEN_SLAVE_LINE_PUSHFAIL);
  816. }
  817. #else /*No line_push */
  818. {
  819. char **module = &push_list[0];
  820. while (*module) {
  821. if (ioctl(fd, I_PUSH, *(module++)) < 0) {
  822. debug(F110,"pty_initialize_slave()","ioctl(I_PUSH) failed",0);
  823. return(PTY_OPEN_SLAVE_PUSH_FAIL);
  824. }
  825. }
  826. }
  827. #endif /*LINE_PUSH*/
  828. #endif /*HAVE_STREAMS*/
  829. /*
  830. Under Ultrix 3.0, the pgrp of the slave pty terminal needs to be set
  831. explicitly. Why rlogind works at all without this on 4.3BSD is a mystery.
  832. */
  833. #ifdef GETPGRP_ONEARG
  834. pid = getpgrp(getpid());
  835. #else
  836. pid = getpgrp();
  837. #endif /* GETPGRP_ONEARG */
  838. debug(F111,"pty_initialize_slave()","pid",pid);
  839. #ifdef TIOCSPGRP
  840. ioctl(fd, TIOCSPGRP, &pid);
  841. #endif /* TIOCSPGRP */
  842. #ifdef POSIX_TERMIOS
  843. #ifndef ultrix
  844. tcsetpgrp(fd, pid);
  845. errno = 0;
  846. rc = tcgetattr(fd,&new_termio);
  847. debug(F111,"pty_initialize_slave tcgetattr(fd)",ckitoa(rc),errno);
  848. if (rc == 0) {
  849. new_termio.c_cc[VMIN] = 1;
  850. new_termio.c_cc[VTIME] = 0;
  851. rc = tcsetattr(fd,TCSANOW,&new_termio);
  852. debug(F111,"pty_initialize_slave tcsetattr(fd)",ckitoa(rc),errno);
  853. }
  854. #endif /* ultrix */
  855. #endif /* POSIX_TERMIOS */
  856. return(0L);
  857. }
  858. #ifdef WANT_UTMP
  859. long
  860. pty_logwtmp (tty, user, host) char *user, *tty, *host; {
  861. #ifdef HAVE_LOGWTMP
  862. logwtmp(tty,user,host);
  863. return(0);
  864. #else
  865. struct utmp ut;
  866. char *tmpx;
  867. char utmp_id[5];
  868. int loggingin = user[0]; /* Will be empty for logout */
  869. #ifndef NO_UT_HOST
  870. strncpy(ut.ut_host, host, sizeof(ut.ut_host));
  871. #endif /* NO_UT_HOST */
  872. strncpy(ut.ut_line, tty, sizeof(ut.ut_line));
  873. ut.ut_time = time(0);
  874. #ifndef NO_UT_PID
  875. ut.ut_pid = getpid();
  876. strncpy(ut.ut_user, user, sizeof(ut.ut_user));
  877. tmpx = tty + strlen(tty) - 2;
  878. ckmakmsg(utmp_id,5,"kr",tmpx,NULL,NULL);
  879. strncpy(ut.ut_id, utmp_id, sizeof(ut.ut_id));
  880. ut.ut_pid = (loggingin ? getpid() : 0);
  881. ut.ut_type = (loggingin ? USER_PROCESS : DEAD_PROCESS);
  882. #else
  883. strncpy(ut.ut_name, user, sizeof(ut.ut_name));
  884. #endif /* NO_UT_PID */
  885. return(ptyint_update_wtmp(&ut, host, user));
  886. #endif /* HAVE_LOGWTMP */
  887. }
  888. #endif /* WANT_UTMP */
  889. /*
  890. This routine is called twice. It's not particularly important that the
  891. setsid() or TIOCSCTTY ioctls succeed (they may not the second time), but
  892. rather that we have a controlling terminal at the end. It is assumed that
  893. vhangup doesn't exist and confuse the process's notion of controlling
  894. terminal on any system without TIOCNOTTY. That is, either vhangup() leaves
  895. the controlling terminal in tact, breaks the association completely, or the
  896. system provides TIOCNOTTY to get things back into a reasonable state. In
  897. practice, vhangup() either breaks the association completely or doesn't
  898. effect controlling terminals, so this condition is met.
  899. */
  900. long
  901. pty_open_ctty(slave, fd, fc) char * slave; int *fd; int fc; {
  902. int retval;
  903. debug(F110,"pty_open_ctty() slave",slave,0);
  904. /* First, dissociate from previous terminal */
  905. if ((retval = ptyint_void_association()) != 0) {
  906. debug(F111,
  907. "pty_open_ctty()",
  908. "ptyint_void_association() failed",
  909. retval
  910. );
  911. return(retval);
  912. }
  913. #ifdef MUST_SETPGRP
  914. /*
  915. The Ultrix (and other BSD tty drivers) require the process group
  916. to be zero in order to acquire the new tty as a controlling tty.
  917. */
  918. setpgrp(0,0);
  919. debug(F101,"pty_open_ctty MUST_SETPGRP setpgrp(0,0)","",errno);
  920. #endif /* MUST_SETPGRP */
  921. errno = 0;
  922. *fd = open(slave, O_RDWR);
  923. debug(F111,"pty_open_ctty open(slave) fd",slave,*fd);
  924. if (*fd < 0) {
  925. debug(F111,"pty_open_ctty() open failure", slave, errno);
  926. return(PTY_OPEN_SLAVE_OPENFAIL);
  927. }
  928. #ifdef SOLARIS
  929. /* This forces the job to have a controlling terminal. */
  930. close(*fd);
  931. *fd = open(slave, O_RDWR);
  932. debug(F111,"pty_open_ctty close/open(slave) fd",slave,*fd);
  933. #ifdef DEBUG
  934. /* This shows that /dev/tty exists */
  935. if (deblog) {
  936. int x;
  937. x = open("/dev/tty", O_RDWR);
  938. debug(F111,"pty_open_ctty open(/dev/tty) fd",slave,x);
  939. if (x < 0) debug(F111,"pty_open_ctty open(/dev/tty) errno","",errno);
  940. debug(F110,"pty_open_ctty ttyname(/dev/tty)",ttyname(x),0);
  941. if (x > -1) close(x);
  942. }
  943. #endif /* DEBUG */
  944. #endif /* SOLARIS */
  945. #ifdef MUST_SETPGRP
  946. setpgrp(0, getpid());
  947. #endif /* MUST_SETPGRP */
  948. #ifdef TIOCSCTTY
  949. if (
  950. #ifdef COMMENT
  951. fc == 0
  952. #else
  953. 1
  954. #endif /* COMMENT */
  955. ) {
  956. /* TIOCSCTTY = Make this the job's controlling terminal */
  957. errno = 0;
  958. retval = ioctl(*fd, TIOCSCTTY, 0); /* Don't check return.*/
  959. debug(F111,"pty_open_ctty() ioctl TIOCSCTTY",ckitoa(retval),errno);
  960. }
  961. #endif /* TIOCSCTTY */
  962. return(0L);
  963. }
  964. long
  965. pty_open_slave(slave, fd, fc) char *slave; int *fd; int fc; {
  966. int vfd, testfd;
  967. long retval;
  968. #ifdef CK_POSIX_SIG
  969. struct sigaction sa;
  970. sigemptyset(&sa.sa_mask); /* Initialize "sa" structure. */
  971. sa.sa_flags = 0;
  972. #endif /* CK_POSIX_SIG */
  973. /*
  974. First, chmod and chown the slave. If we have vhangup then we really need
  975. pty_open_ctty to make sure our controlling terminal is the pty we're
  976. opening. However, if we are using revoke or nothing then we just need a
  977. file descriiptor for the pty. Considering some OSes in this category break
  978. on the second call to open_ctty (currently OSF but others may), we simply
  979. use a descriptor if we can.
  980. */
  981. #ifdef VHANG_FIRST
  982. if ((retval = pty_open_ctty(slave, &vfd, fc)) != 0) {
  983. debug(F111,
  984. "pty_open_slave() VHANG_FIRST",
  985. "pty_open_ctty() failed",
  986. retval
  987. );
  988. return(retval);
  989. }
  990. if (vfd < 0) {
  991. debug(F111,
  992. "pty_open_slave() VHANG_FIRST",
  993. "PTY_OPEN_SLAVE_OPENFAIL",
  994. vfd
  995. );
  996. return(PTY_OPEN_SLAVE_OPENFAIL);
  997. }
  998. #endif /* VHANG_FIRST */
  999. if (slave == NULL || *slave == '\0') {
  1000. debug(F110,"pty_open_slave()","PTY_OPEN_SLAVE_TOOSHORT",0);
  1001. return(PTY_OPEN_SLAVE_TOOSHORT);
  1002. }
  1003. #ifdef SETUID
  1004. if (chmod(slave, 0)) {
  1005. debug(F110,"pty_open_slave()","PTY_OPEN_SLAVE_CHMODFAIL",0);
  1006. return(PTY_OPEN_SLAVE_CHMODFAIL);
  1007. }
  1008. if (chown(slave, 0, 0 ) == -1 ) {
  1009. debug(F110,"pty_open_slave()","PTY_OPEN_SLAVE_CHOWNFAIL",0);
  1010. return(PTY_OPEN_SLAVE_CHOWNFAIL);
  1011. }
  1012. #endif /* SETUID */
  1013. #ifdef VHANG_FIRST
  1014. ptyint_vhangup();
  1015. close(vfd);
  1016. #endif /* VHANG_FIRST */
  1017. if ((retval = ptyint_void_association()) != 0) {
  1018. debug(F111,
  1019. "pty_open_slave()",
  1020. "ptyint_void_association() failed",
  1021. retval
  1022. );
  1023. return(retval);
  1024. }
  1025. #ifdef HAVE_REVOKE
  1026. if (revoke (slave) < 0 ) {
  1027. debug(F110,"pty_open_slave()","PTY_OPEN_SLAVE_REVOKEFAIL",0);
  1028. return(PTY_OPEN_SLAVE_REVOKEFAIL);
  1029. }
  1030. #endif /* HAVE_REVOKE */
  1031. /* Open the pty for real. */
  1032. retval = pty_open_ctty(slave, fd, fc);
  1033. debug(F111,"pty_open_slave retval",slave,retval);
  1034. debug(F111,"pty_open_slave fd",slave,*fd);
  1035. if (retval != 0) {
  1036. debug(F111,"pty_open_slave()","pty_open_ctty() failed",retval);
  1037. return(PTY_OPEN_SLAVE_OPENFAIL);
  1038. }
  1039. pty_slave_fd = *fd; /* This is not visible to the upper fork */
  1040. debug(F111,"pty_open_slave fd ctty'd",slave,pty_slave_fd);
  1041. retval = pty_initialize_slave(*fd);
  1042. debug(F111,"pty_open_slave fd init'd",slave,pty_slave_fd);
  1043. if (retval) {
  1044. debug(F111,"pty_open_slave()","pty_initialize_slave() failed",retval);
  1045. return(retval);
  1046. }
  1047. /* (VOID)pty_make_raw(*fd); */
  1048. debug(F100,"pty_open_slave OK","",*fd);
  1049. return(0L);
  1050. }
  1051. #ifdef WANT_UTMP
  1052. #ifndef UTMP_FILE
  1053. #ifdef _PATH_UTMP
  1054. #define UTMP_FILE _PATH_UTMP
  1055. #endif /* _PATH_UTMP */
  1056. #endif /* UTMP_FILE */
  1057. /* If it is *still* missing, assume /etc/utmp */
  1058. #ifndef UTMP_FILE
  1059. #define UTMP_FILE "/etc/utmp"
  1060. #endif /* UTMP_FILE */
  1061. #ifndef NO_UT_PID
  1062. #define WTMP_REQUIRES_USERNAME
  1063. #endif /* NO_UT_PID */
  1064. long
  1065. pty_update_utmp(process_type, pid, username, line, host, flags)
  1066. int process_type;
  1067. int pid;
  1068. char *username, *line, *host;
  1069. int flags;
  1070. /* pty_update_utmp */ {
  1071. struct utmp ent, ut;
  1072. #ifndef HAVE_SETUTENT
  1073. struct stat statb;
  1074. int tty;
  1075. #endif /* HAVE_SETUTENT */
  1076. #ifdef HAVE_SETUTXENT
  1077. struct utmpx utx;
  1078. #endif /* HAVE_SETUTXENT */
  1079. #ifndef NO_UT_PID
  1080. char *tmpx;
  1081. char utmp_id[5];
  1082. #endif /* NO_UT_PID */
  1083. char userbuf[32];
  1084. int fd;
  1085. debug(F100,"pty_update_utmp()","",0);
  1086. strncpy(ent.ut_line, line+sizeof("/dev/")-1, sizeof(ent.ut_line));
  1087. ent.ut_time = time(0);
  1088. #ifdef NO_UT_PID
  1089. if (process_type == PTY_LOGIN_PROCESS)
  1090. return(0L);
  1091. #else /* NO_UT_PID */
  1092. ent.ut_pid = pid;
  1093. switch (process_type) {
  1094. case PTY_LOGIN_PROCESS:
  1095. ent.ut_type = LOGIN_PROCESS;
  1096. break;
  1097. case PTY_USER_PROCESS:
  1098. ent.ut_type = USER_PROCESS;
  1099. break;
  1100. case PTY_DEAD_PROCESS:
  1101. ent.ut_type = DEAD_PROCESS;
  1102. break;
  1103. default:
  1104. return(PTY_UPDATE_UTMP_PROCTYPE_INVALID);
  1105. }
  1106. #endif /*NO_UT_PID*/
  1107. #ifndef NO_UT_HOST
  1108. if (host)
  1109. strncpy(ent.ut_host, host, sizeof(ent.ut_host));
  1110. else
  1111. ent.ut_host[0] = '\0';
  1112. #endif /* NO_UT_HOST */
  1113. #ifndef NO_UT_PID
  1114. if (!strcmp (line, "/dev/console")) {
  1115. char * s = NULL;
  1116. #ifdef sun
  1117. #ifdef __SVR4
  1118. s = "co";
  1119. #else
  1120. s = "cons";
  1121. #endif /* __SVR4 */
  1122. #else
  1123. s = "cons";
  1124. #endif /* sun */
  1125. strncpy(ent.ut_id, s, 4);
  1126. } else {
  1127. tmpx = line + strlen(line)-1;
  1128. if (*(tmpx-1) != '/') tmpx--; /* last 2 chars unless it's a '/' */
  1129. #ifdef __hpux
  1130. ckstrncpy(utmp_id, tmpx, 5);
  1131. #else
  1132. ckmakmsg(utmp_id,5,"kl",tmpx,NULL,NULL);
  1133. #endif /* __hpux */
  1134. strncpy(ent.ut_id, utmp_id, sizeof(ent.ut_id));
  1135. }
  1136. strncpy(ent.ut_user, username, sizeof(ent.ut_user));
  1137. #else
  1138. strncpy(ent.ut_name, username, sizeof(ent.ut_name));
  1139. #endif /* NO_UT_PID */
  1140. if (username[0])
  1141. strncpy(userbuf, username, sizeof(userbuf));
  1142. else
  1143. userbuf[0] = '\0';
  1144. #ifdef HAVE_SETUTENT
  1145. utmpname(UTMP_FILE);
  1146. setutent();
  1147. /*
  1148. If we need to preserve the user name in the wtmp structure and Our flags
  1149. tell us we can obtain it from the utmp and we succeed in obtaining it, we
  1150. then save the utmp structure we obtain, write out the utmp structure and
  1151. change the username pointer so it is used by update_wtmp.
  1152. */
  1153. #ifdef WTMP_REQUIRES_USERNAME
  1154. if ((!username[0]) && (flags&PTY_UTMP_USERNAME_VALID) &&line) {
  1155. struct utmp *utptr;
  1156. strncpy(ut.ut_line, line, sizeof(ut.ut_line));
  1157. utptr = getutline(&ut);
  1158. if (utptr)
  1159. strncpy(userbuf,utptr->ut_user,sizeof(ut.ut_user));
  1160. }
  1161. #endif /* WTMP_REQUIRES_USERNAME */
  1162. pututline(&ent);
  1163. endutent();
  1164. #ifdef HAVE_SETUTXENT
  1165. setutxent();
  1166. #ifdef HAVE_GETUTMPX
  1167. getutmpx(&ent, &utx);
  1168. #else /* HAVE_GETUTMPX */
  1169. /* For platforms like HPUX and Dec Unix which don't have getutmpx */
  1170. strncpy(utx.ut_user, ent.ut_user, sizeof(ent.ut_user));
  1171. strncpy(utx.ut_id, ent.ut_id, sizeof(ent.ut_id));
  1172. strncpy(utx.ut_line, ent.ut_line, sizeof(ent.ut_line));
  1173. utx.ut_pid = pid; /* kludge for Irix, etc. to avoid trunc. */
  1174. utx.ut_type = ent.ut_type;
  1175. #ifdef UT_EXIT_STRUCTURE_DIFFER
  1176. utx.ut_exit.ut_exit = ent.ut_exit.e_exit;
  1177. #else /* UT_EXIT_STRUCTURE_DIFFER */
  1178. /* KLUDGE for now; eventually this will be a feature test... See PR#[40] */
  1179. #ifdef __hpux
  1180. utx.ut_exit.__e_termination = ent.ut_exit.e_termination;
  1181. utx.ut_exit.__e_exit = ent.ut_exit.e_exit;
  1182. #else /* __hpux */
  1183. /* XXX do nothing for now; we don't even know the struct member exists */
  1184. #endif /* __hpux */
  1185. #endif /* UT_EXIT_STRUCTURE_DIFFER */
  1186. utx.ut_tv.tv_sec = ent.ut_time;
  1187. utx.ut_tv.tv_usec = 0;
  1188. #endif /* HAVE_GETUTMPX */
  1189. if (host)
  1190. strncpy(utx.ut_host, host, sizeof(utx.ut_host));
  1191. else
  1192. utx.ut_host[0] = 0;
  1193. pututxline(&utx);
  1194. endutxent();
  1195. #endif /* HAVE_SETUTXENT */
  1196. #else /* HAVE_SETUTENT */
  1197. if (flags&PTY_TTYSLOT_USABLE) {
  1198. tty = ttyslot();
  1199. } else {
  1200. int lc;
  1201. tty = -1;
  1202. if ((fd = open(UTMP_FILE, O_RDWR)) < 0)
  1203. return(errno);
  1204. for (lc = 0;
  1205. lseek(fd, (off_t)(lc * sizeof(struct utmp)), SEEK_SET) != -1;
  1206. lc++
  1207. ) {
  1208. if (read(fd,
  1209. (char *)&ut,
  1210. sizeof(struct utmp)
  1211. ) != sizeof(struct utmp)
  1212. )
  1213. break;
  1214. if (strncmp(ut.ut_line, ent.ut_line, sizeof(ut.ut_line)) == 0) {
  1215. tty = lc;
  1216. #ifdef WTMP_REQUIRES_USERNAME
  1217. if (!username&&(flags&PTY_UTMP_USERNAME_VALID))
  1218. strncpy(userbuf, ut.ut_user, sizeof(ut.ut_user));
  1219. #endif /* WTMP_REQUIRES_USERNAME */
  1220. break;
  1221. }
  1222. }
  1223. close(fd);
  1224. }
  1225. if (tty > 0 && (fd = open(UTMP_FILE, O_WRONLY, 0)) >= 0) {
  1226. lseek(fd, (off_t)(tty * sizeof(struct utmp)), SEEK_SET);
  1227. write(fd, (char *)&ent, sizeof(struct utmp));
  1228. close(fd);
  1229. }
  1230. #endif /* HAVE_SETUTENT */
  1231. /* Don't record LOGIN_PROCESS entries. */
  1232. if (process_type == PTY_LOGIN_PROCESS)
  1233. return(0);
  1234. else
  1235. return(ptyint_update_wtmp(&ent, host, userbuf));
  1236. }
  1237. #ifndef WTMP_FILE
  1238. #ifdef _PATH_WTMP
  1239. #define WTMP_FILE _PATH_WTMP
  1240. #endif /* _PATH_WTMP */
  1241. #endif /* WTMP_FILE */
  1242. #ifndef WTMPX_FILE
  1243. #ifdef _PATH_WTMPX
  1244. #ifdef HAVE_UPDWTMPX
  1245. #define WTMPX_FILE _PATH_WTMPX
  1246. #endif /* HAVE_UPDWTMPX */
  1247. #endif /* _PATH_WTMPX */
  1248. #endif /* WTMPX_FILE */
  1249. /* If it is *still* missing, assume /usr/adm/wtmp */
  1250. #ifndef WTMP_FILE
  1251. #define WTMP_FILE "/usr/adm/wtmp"
  1252. #endif /* WTMP_FILE */
  1253. #ifdef COMMENT
  1254. /* The following test can not be made portably */
  1255. /* #if defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) */
  1256. /*
  1257. This is ugly, but the lack of standardization in the utmp/utmpx space, and
  1258. what glibc implements and doesn't make available, is even worse.
  1259. */
  1260. /* #undef HAVE_UPDWTMPX */ /* Don't use updwtmpx for glibc 2.1 */
  1261. /* #endif */ /* __GLIBC__ etc */
  1262. #else /* COMMENT */
  1263. #ifdef __GLIBC__
  1264. #undef HAVE_UPDWTMPX /* Don't use updwtmpx for glibc period */
  1265. #endif /* __GLIBC__ */
  1266. #endif /* COMMENT */
  1267. long
  1268. ptyint_update_wtmp(ent,host,user) struct utmp *ent; char *host; char *user; {
  1269. struct utmp ut;
  1270. struct stat statb;
  1271. int fd;
  1272. time_t uttime;
  1273. #ifdef HAVE_UPDWTMPX
  1274. struct utmpx utx;
  1275. getutmpx(ent, &utx);
  1276. if (host)
  1277. strncpy(utx.ut_host, host, sizeof(utx.ut_host) );
  1278. else
  1279. utx.ut_host[0] = 0;
  1280. if (user)
  1281. strncpy(utx.ut_user, user, sizeof(utx.ut_user));
  1282. updwtmpx(WTMPX_FILE, &utx);
  1283. #endif /* HAVE_UPDWTMPX */
  1284. #ifdef HAVE_UPDWTMP
  1285. #ifndef HAVE_UPDWTMPX
  1286. /* This is already performed byupdwtmpx if present.*/
  1287. updwtmp(WTMP_FILE, ent);
  1288. #endif /* HAVE_UPDWTMPX*/
  1289. #else /* HAVE_UPDWTMP */
  1290. if ((fd = open(WTMP_FILE, O_WRONLY|O_APPEND, 0)) >= 0) {
  1291. if (!fstat(fd, &statb)) {
  1292. memset((char *)&ut, 0, sizeof(ut));
  1293. #ifdef __hpux
  1294. strncpy(ut.ut_id, ent->ut_id, sizeof (ut.ut_id));
  1295. #endif /* __hpux */
  1296. strncpy(ut.ut_line, ent->ut_line, sizeof(ut.ut_line));
  1297. strncpy(ut.ut_name, ent->ut_name, sizeof(ut.ut_name));
  1298. #ifndef NO_UT_HOST
  1299. strncpy(ut.ut_host, ent->ut_host, sizeof(ut.ut_host));
  1300. #endif /* NO_UT_HOST */
  1301. time(&uttime);
  1302. ut.ut_time = uttime;
  1303. #ifdef HAVE_GETUTENT
  1304. #ifdef USER_PROCESS
  1305. if (ent->ut_name) {
  1306. if (!ut.ut_pid)
  1307. ut.ut_pid = getpid();
  1308. #ifndef __hpux
  1309. ut.ut_type = USER_PROCESS;
  1310. #else /* __hpux */
  1311. ut.ut_type = ent->ut_type;
  1312. #endif /* __hpux */
  1313. } else {
  1314. #ifdef EMPTY
  1315. ut.ut_type = EMPTY;
  1316. #else
  1317. ut.ut_type = DEAD_PROCESS; /* For Linux brokenness*/
  1318. #endif /* EMPTY */
  1319. }
  1320. #endif /* USER_PROCESS */
  1321. #endif /* HAVE_GETUTENT */
  1322. if (write(fd, (char *)&ut, sizeof(struct utmp)) !=
  1323. sizeof(struct utmp))
  1324. #ifndef COHERENT
  1325. ftruncate(fd, statb.st_size);
  1326. #else
  1327. chsize(fd, statb.st_size);
  1328. #endif /* COHERENT */
  1329. }
  1330. close(fd);
  1331. }
  1332. #endif /* HAVE_UPDWTMP */
  1333. return(0); /* no current failure cases; file not found is not failure! */
  1334. }
  1335. #endif /* WANT_UTMP */
  1336. /* This is for ancient Unixes that don't have these tty symbols defined. */
  1337. #ifndef PENDIN
  1338. #define PENDIN ICANON
  1339. #endif /* PENDIN */
  1340. #ifndef FLUSHO
  1341. #define FLUSHO ICANON
  1342. #endif /* FLUSHO */
  1343. #ifndef IMAXBEL
  1344. #define IMAXBEL ICANON
  1345. #endif /* IMAXBEL */
  1346. #ifndef EXTPROC
  1347. #define EXTPROC ICANON
  1348. #endif /* EXTPROC */
  1349. static char Xline[17] = { 0, 0 };
  1350. /*
  1351. getptyslave()
  1352. Open the slave side of the pty, and do any initialization that is necessary.
  1353. The return value fd is a file descriptor for the slave side.
  1354. fc = function code from do_pty() (q.v.)
  1355. */
  1356. int
  1357. getptyslave(fd, fc) int * fd, fc; {
  1358. int ttyfd;
  1359. int t = -1;
  1360. long retval;
  1361. #ifdef TIOCGWINSZ
  1362. struct winsize ws;
  1363. extern int cmd_rows, cmd_cols;
  1364. #endif /* TIOCGWINSZ */
  1365. ttyfd = *fd;
  1366. debug(F111,"getptyslave()","ttyfd",ttyfd);
  1367. /*
  1368. * Opening the slave side may cause initilization of the
  1369. * kernel tty structure. We need remember the state of:
  1370. * if linemode was turned on
  1371. * terminal window size
  1372. * terminal speed
  1373. * so that we can reset them if we need to.
  1374. */
  1375. if ((retval = pty_open_slave(Xline, &t, fc)) != 0) {
  1376. perror(Xline);
  1377. msg++;
  1378. debug(F111,"getptyslave()","Unable to open slave",retval);
  1379. return(-1);
  1380. }
  1381. debug(F111,"getptyslave","t",t);
  1382. #ifdef INIT_SPTY
  1383. spty = t;
  1384. debug(F111,"getptyslave","spty",spty);
  1385. #endif /* INIT_SPTY */
  1386. #ifdef STREAMSPTY
  1387. if (ioctl(t,I_PUSH,"pckt") < 0) {
  1388. debug(F111,"getptyslave()","ioctl(I_PUSH) failed",errno);
  1389. #ifndef _AIX
  1390. fatal("I_PUSH pckt");
  1391. #endif /* _AIX */
  1392. }
  1393. #endif /* STREAMSPTY */
  1394. /* Set up the tty modes as we like them to be. */
  1395. #ifdef COMMENT
  1396. /* Originally like this... But this is the master - we want the slave */
  1397. /* Anyway, this fails on Solaris and probably other System V OS's */
  1398. init_termbuf(ttyfd);
  1399. #else
  1400. init_termbuf(t);
  1401. #endif /* COMMENT */
  1402. #ifdef TIOCGWINSZ
  1403. if (cmd_rows || cmd_cols) {
  1404. memset((char *)&ws, 0, sizeof(ws));
  1405. ws.ws_col = cmd_cols;
  1406. ws.ws_row = cmd_rows;
  1407. debug(F101,"getptyslave() doing TIOCSWINSZ...","",t);
  1408. ioctl(t, TIOCSWINSZ, (char *)&ws);
  1409. }
  1410. #endif /* TIOCGWINSZ */
  1411. /* For external protocols, put the pty in no-echo mode */
  1412. if (fc == 1) {
  1413. debug(F100,"getptyslave() setting rawmode","",0);
  1414. /* iflags */
  1415. termbuf.c_iflag &= ~(PARMRK|ISTRIP|BRKINT|INLCR|IGNCR|ICRNL);
  1416. termbuf.c_iflag &= ~(INPCK|IGNPAR|IMAXBEL|IXANY|IXON|IXOFF);
  1417. termbuf.c_iflag |= IGNBRK;
  1418. #ifdef IUCLC
  1419. termbuf.c_iflag &= ~IUCLC;
  1420. #endif /* IUCLC */
  1421. /* oflags */
  1422. termbuf.c_oflag &= ~OPOST;
  1423. #ifdef OXTABS
  1424. termbuf.c_oflag &= ~OXTABS;
  1425. #endif /* OXTABS */
  1426. #ifdef ONOCR
  1427. termbuf.c_oflag &= ~ONOCR;
  1428. #endif /* ONOCR */
  1429. #ifdef ONLRET
  1430. termbuf.c_oflag &= ~ONLRET;
  1431. #endif /* ONLRET */
  1432. #ifdef ONLCR
  1433. termbuf.c_oflag &= ~ONLCR;
  1434. #endif /* ONLCR */
  1435. /* lflags */
  1436. termbuf.c_lflag &= ~ECHO;
  1437. #ifdef ECHOE
  1438. termbuf.c_lflag &= ~ECHOE;
  1439. #endif /* ECHOE */
  1440. #ifdef ECHONL
  1441. termbuf.c_lflag &= ~ECHONL;
  1442. #endif /* ECHONL */
  1443. #ifdef ECHOPRT
  1444. termbuf.c_lflag &= ~ECHOPRT;
  1445. #endif /* ECHOPRT */
  1446. #ifdef ECHOKE
  1447. termbuf.c_lflag &= ~ECHOKE;
  1448. #endif /* ECHOKE */
  1449. #ifdef ECHOCTL
  1450. termbuf.c_lflag &= ~ECHOCTL;
  1451. #endif /* ECHOCTL */
  1452. #ifdef ALTWERASE
  1453. termbuf.c_lflag &= ~ALTWERASE;
  1454. #endif /* ALTWERASE */
  1455. #ifdef EXTPROC
  1456. termbuf.c_lflag &= ~EXTPROC;
  1457. #endif /* EXTPROC */
  1458. termbuf.c_lflag &= ~(ICANON|ISIG|IEXTEN|TOSTOP|FLUSHO|PENDIN);
  1459. #ifdef NOKERNINFO
  1460. termbuf.c_lflag |= NOKERNINFO;
  1461. #endif /* NOKERNINFO */
  1462. /* termbuf.c_lflag |= NOFLSH; */
  1463. termbuf.c_lflag &= ~NOFLSH;
  1464. /* cflags */
  1465. termbuf.c_cflag &= ~(CSIZE|PARENB|PARODD);
  1466. termbuf.c_cflag |= CS8|CREAD;
  1467. #ifdef VMIN
  1468. termbuf.c_cc[VMIN] = 1;
  1469. #endif /* VMIN */
  1470. } else { /* Regular interactive use */
  1471. debug(F100,"getptyslave() setting cooked mode","",0);
  1472. /* Settings for sgtty based systems */
  1473. #ifndef USE_TERMIO
  1474. termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS;
  1475. #endif /* USE_TERMIO */
  1476. #ifndef OXTABS
  1477. #define OXTABS 0
  1478. #endif /* OXTABS */
  1479. /* Settings for UNICOS and HPUX */
  1480. #ifdef CRAY
  1481. termbuf.c_oflag = OPOST|ONLCR|TAB3;
  1482. termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
  1483. termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
  1484. termbuf.c_cflag = EXTB|HUPCL|CS8;
  1485. #else /* CRAY */
  1486. #ifdef HPUX
  1487. termbuf.c_oflag = OPOST|ONLCR|TAB3;
  1488. termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON;
  1489. termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK;
  1490. termbuf.c_cflag = EXTB|HUPCL|CS8;
  1491. #else /* HPUX */
  1492. #ifdef USE_TERMIO
  1493. /*
  1494. Settings for all other termios/termio based systems, other than
  1495. 4.4BSD. In 4.4BSD the kernel does the initial terminal setup.
  1496. */
  1497. #ifdef BSD42
  1498. #ifndef BSD44
  1499. termbuf.c_lflag |= ECHO|ICANON|IEXTEN|ISIG;
  1500. termbuf.c_oflag |= ONLCR|OXTABS|OPOST;
  1501. termbuf.c_iflag |= ICRNL|IGNPAR;
  1502. termbuf.c_cflag |= HUPCL;
  1503. termbuf.c_iflag &= ~IXOFF;
  1504. #endif /* BSD44 */
  1505. #else /* BSD42 */
  1506. termbuf.c_lflag |= ECHO|ICANON|IEXTEN|ISIG;
  1507. termbuf.c_oflag |= ONLCR|OXTABS|OPOST;
  1508. termbuf.c_iflag |= ICRNL|IGNPAR;
  1509. termbuf.c_cflag |= HUPCL;
  1510. termbuf.c_iflag &= ~IXOFF;
  1511. #endif /* BSD42 */
  1512. #endif /* USE_TERMIO */
  1513. #endif /* HPUX */
  1514. #endif /* CRAY */
  1515. }
  1516. /* Set the tty modes, and make this our controlling tty. */
  1517. #ifdef COMMENT
  1518. /* But this is the master - we want the slave */
  1519. set_termbuf(ttyfd);
  1520. #else
  1521. set_termbuf(t);
  1522. #endif /* COMMENT */
  1523. if (t != 0)
  1524. dup2(t, 0);
  1525. if (t != 1)
  1526. dup2(t, 1);
  1527. if (t != 2) {
  1528. if (fc == 0) {
  1529. dup2(t, 2);
  1530. } else if (fc == 1) {
  1531. /* For external protocols, send stderr to /dev/null */
  1532. #ifdef COMMENT
  1533. int xx;
  1534. #ifndef COMMENT
  1535. char * s = "/dev/null";
  1536. errno = 0;
  1537. xx = open(s, O_WRONLY);
  1538. #else
  1539. char * s = "pty.log";
  1540. errno = 0;
  1541. xx = open(s, O_CREAT, 0644);
  1542. #endif /* COMMENT */
  1543. debug(F111,"getptyslave redirect stderr",s,errno);
  1544. dup2(xx,2);
  1545. #endif /* COMMENT */
  1546. }
  1547. }
  1548. if (t > 2)
  1549. close(t);
  1550. if (ttyfd > 2) {
  1551. close(ttyfd);
  1552. ttyfd = -1;
  1553. *fd = ttyfd;
  1554. }
  1555. return(0);
  1556. }
  1557. #ifdef HAVE_PTYTRAP
  1558. /*
  1559. To be called to determine if a trap is pending on a pty
  1560. if and only if select() cannot be used.
  1561. */
  1562. int
  1563. pty_trap_pending(fd) int fd; {
  1564. int pending;
  1565. int rc;
  1566. rc = ioctl(fd, TIOCTRAPSTATUS, (char *)&pending, sizeof(pending));
  1567. if (rc == 0) {
  1568. debug(F101,"pty_trap_pending()","",pending);
  1569. return(pending);
  1570. } else {
  1571. debug(F111,"pty_trap_pending()","ioctl() failed",rc);
  1572. return(-1);
  1573. }
  1574. }
  1575. /*
  1576. To be called after select() has returned indicating that an exception is
  1577. waiting on a pty. It should be called with the file descriptor of the pty.
  1578. Returns -1 on error; 0 if pty is still open; 1 if pty has closed.
  1579. */
  1580. int
  1581. pty_trap_handler(fd) int fd; {
  1582. struct request_info ri;
  1583. memset(&ri,0,sizeof(ri));
  1584. if (ioctl(fd,TIOCREQCHECK,(char *)&ri, sizeof(ri)) != 0) {
  1585. debug(F111,"pty_trap_handler()","ioctl(TIOCREQCHECK) failed",errno);
  1586. return(-1);
  1587. }
  1588. switch (ri.request) {
  1589. case TIOCOPEN:
  1590. debug(F110,"pty_trap_handler()","an open() call",0);
  1591. break;
  1592. case TIOCCLOSE:
  1593. debug(F110,"pty_trap_handler()","a close() call",0);
  1594. break;
  1595. default:
  1596. debug(F110,"pty_trap_handler()","an ioctl() call",0);
  1597. ri.errno_error = EINVAL;
  1598. }
  1599. if (ioctl(fd, TIOCREQSET, (char *)&ri,sizeof(ri)) != 0) {
  1600. debug(F111,"pty_trap_handler()","ioctl(TIOCREQSET) failed",errno);
  1601. return(-1);
  1602. }
  1603. if (ri.request == TIOCCLOSE)
  1604. return(1);
  1605. else
  1606. return(0);
  1607. }
  1608. #endif /* HAVE_PTYTRAP */
  1609. VOID
  1610. exec_cmd(s) char * s; {
  1611. struct stringarray * q;
  1612. char ** args = NULL;
  1613. if (!s) return;
  1614. if (!*s) return;
  1615. q = cksplit(1,0,s,NULL,"\\%[]&$+-/=*^_@!{}/<>|.#~'`:;?",7,0,0,0);
  1616. if (!q) return;
  1617. args = q->a_head + 1;
  1618. #ifdef DEBUG
  1619. {
  1620. int i, n;
  1621. n = q->a_size;
  1622. for (i = 0; i <= n; i++) {
  1623. if (!args[i]) {
  1624. debug(F111,"exec_cmd arg","NULL",i);
  1625. break;
  1626. } else {
  1627. debug(F111,"exec_cmd arg",args[i],i);
  1628. if (i == n && args[i]) {
  1629. debug(F101,"exec_cmd SUBSTITUTING NULL","",i);
  1630. if (strlen(args[i]) == 0)
  1631. makestr(&(args[i]),NULL);
  1632. }
  1633. }
  1634. }
  1635. }
  1636. #endif /* DEBUG */
  1637. execvp(args[0],args);
  1638. }
  1639. /* Get a pty, scan input lines. */
  1640. /* fc = 0 for interactive access; fc = 1 for running external protocols */
  1641. static int pty_fc = -1; /* Global copy of fc */
  1642. int
  1643. do_pty(fd, cmd, fc) int * fd; char * cmd; int fc; {
  1644. long retval;
  1645. int syncpipe[2];
  1646. int i, ttyfd;
  1647. #ifdef HAVE_PTYTRAP
  1648. int x;
  1649. #endif /* HAVE_PTYTRAP */
  1650. int dummy;
  1651. debug(F101,"CKUPTY.C do_pty fc","",fc);
  1652. ttyfd = *fd;
  1653. pty_master_fd = -2;
  1654. pty_slave_fd = -2;
  1655. pty_fork_pid = -2;
  1656. msg = 0; /* Message counter */
  1657. pty_init(); /* Find an available pty to use. */
  1658. errno = 0;
  1659. if ((retval = pty_getpty(&ttyfd, Xline, 20)) != 0) {
  1660. if (msg++ == 0)
  1661. perror(Xline);
  1662. debug(F111,"do_pty()","pty_getpty() fails",retval);
  1663. *fd = ttyfd;
  1664. return(-1);
  1665. }
  1666. *fd = ttyfd;
  1667. debug(F111,"do_pty() Xline",Xline,ttyfd);
  1668. #ifdef SIGTTOU
  1669. /*
  1670. Ignoring SIGTTOU keeps the kernel from blocking us. we tweak the tty with
  1671. an ioctl() (in ttioct() in /sys/tty.c in a BSD kernel)
  1672. */
  1673. signal(SIGTTOU, SIG_IGN);
  1674. #endif /* SIGTTOU */
  1675. /* Start up the command on the slave side of the terminal */
  1676. if (pipe(syncpipe) < 0) {
  1677. debug(F110,"do_pty()","pipe() fails",0);
  1678. perror("pipe() failed");
  1679. msg++;
  1680. debug(F111,"do_pty()","pipe fails",errno);
  1681. return(-1);
  1682. }
  1683. if ((i = fork()) < 0) {
  1684. /* XXX - need to clean up the allocated pty */
  1685. perror("fork() failed");
  1686. msg++;
  1687. debug(F111,"do_pty()","fork fails",errno);
  1688. return(-1);
  1689. }
  1690. if (i) { /* Wait for child before writing to parent side of pty. */
  1691. char c;
  1692. #ifdef HAVE_PTYTRAP
  1693. int on = 1;
  1694. #endif /* HAVE_PTYTRAP */
  1695. close(syncpipe[1]);
  1696. errno = 0;
  1697. if (read(syncpipe[0], &c, 1) == 0) { /* Slave side died */
  1698. perror("Pipe read() failed");
  1699. msg++;
  1700. debug(F110,"do_pty()","Slave fails to initialize",0);
  1701. close(syncpipe[0]);
  1702. return(-1);
  1703. }
  1704. pty_fork_pid = i; /* So we can clean it up later */
  1705. pty_fork_active = 1;
  1706. debug(F101,"do_pty pty_fork_pid","",pty_fork_pid);
  1707. #ifdef HAVE_PTYTRAP
  1708. /* HPUX does not allow the master to read end of file. */
  1709. /* Therefore, we must determine that the slave has been */
  1710. /* closed by trapping the call to close(). */
  1711. errno = 0;
  1712. x = ioctl(ttyfd, TIOCTRAP, (char *)&on);
  1713. debug(F111,"do_pty ioctl(TIOCTRAP)",ckitoa(x),errno);
  1714. #endif /* HAVE_PTYTRAP */
  1715. debug(F111,"do_pty()","synchronized - pty_fork_pid",pty_fork_pid);
  1716. close(syncpipe[0]);
  1717. } else {
  1718. int x;
  1719. debug(F101,"do_pty getptyslave ttyfd A","",ttyfd);
  1720. debug(F110,"do_pty()","Slave starts",0);
  1721. x = getptyslave(&ttyfd,fc);
  1722. debug(F101,"do_pty getptyslave","",x);
  1723. if (x == 0) {
  1724. debug(F101,"do_pty getptyslave ttyfd B","",ttyfd);
  1725. #ifdef WANT_UTMP
  1726. pty_update_utmp(PTY_USER_PROCESS,
  1727. getpid(),
  1728. "KERMIT",
  1729. Xline,
  1730. cmd,
  1731. PTY_TTYSLOT_USABLE
  1732. );
  1733. #endif /* WANT_UTMP */
  1734. /* Notify our parent we're ready to continue.*/
  1735. debug(F110,"do_pty()","slave synchronizing",0);
  1736. dummy = write(syncpipe[1],"y",1);
  1737. close(syncpipe[0]);
  1738. close(syncpipe[1]);
  1739. debug(F110,"do_pty cmd",cmd,0);
  1740. exec_cmd(cmd);
  1741. debug(F111,"do_pty()","exec_cmd() returns - why?",errno);
  1742. }
  1743. *fd = ttyfd;
  1744. debug(F110,"do_pty()","getptyslave() fails - exiting",0);
  1745. exit(1);
  1746. }
  1747. *fd = ttyfd;
  1748. pty_fc = fc;
  1749. return(getpid());
  1750. } /* end of do_pty() */
  1751. VOID
  1752. end_pty() {
  1753. msg = 0; /* Message counter */
  1754. debug(F101,"end_pty pty_fork_pid","",pty_fork_pid);
  1755. if (Xline[0] && pty_fork_pid >= 0) {
  1756. pty_cleanup(Xline,pty_fork_pid,1);
  1757. Xline[0] = '\0';
  1758. pty_fork_pid = -1;
  1759. pty_fork_active = 0;
  1760. debug(F101,"end_pty pty_fork_active","",pty_fork_active);
  1761. }
  1762. pty_fc = -1;
  1763. }
  1764. #endif /* NETPTY */