45 |
# define PARENT_DOES_UTMP |
# define PARENT_DOES_UTMP |
46 |
#endif |
#endif |
47 |
|
|
|
#ifdef NEWINIT |
|
|
|
|
|
#include <initreq.h> |
|
|
int utmp_len = MAXHOSTNAMELEN; /* sizeof(init_request.host) */ |
|
|
#else /* !NEWINIT*/ |
|
|
# ifdef HAVE_UTMPX_H |
|
|
# define __USE_GNU |
|
|
# include <utmpx.h> |
|
|
struct utmpx wtmp; |
|
|
# ifdef HAVE_UTMPX_UT_TV |
|
|
# define HAVE_WTMP_UT_TV HAVE_UTMPX_UT_TV |
|
|
# endif |
|
|
# else /* !HAVE_UTMPX_H */ |
|
|
# include <utmp.h> |
|
|
struct utmp wtmp; |
|
|
# ifdef HAVE_UTMP_UT_TV |
|
|
# define HAVE_WTMP_UT_TV HAVE_UTMP_UT_TV |
|
|
# endif |
|
|
# endif /* HAVE_UTMPX_H */ |
|
|
|
|
|
#ifdef HAVE_UTMP_UT_HOST |
|
|
int utmp_len = sizeof(wtmp.ut_host); |
|
|
#endif |
|
|
# ifndef PARENT_DOES_UTMP |
|
|
char wtmpf[] = PATH_WTMP; |
|
|
char utmpf[] = PATH_UTMP; |
|
|
# else /* PARENT_DOES_UTMP */ |
|
|
char wtmpf[] = PATH_WTMP; |
|
|
# endif /* PARENT_DOES_UTMP */ |
|
|
|
|
|
# ifdef CRAY |
|
|
# include <tmpdir.h> |
|
|
# include <sys/wait.h> |
|
|
# if (UNICOS_LVL == '7.0') || (UNICOS_LVL == '7.1') |
|
|
# define UNICOS7x |
|
|
# endif |
|
|
|
|
|
# ifdef UNICOS7x |
|
|
# include <sys/sysv.h> |
|
|
# include <sys/secstat.h> |
|
|
extern int secflag; |
|
|
extern struct sysv sysv; |
|
|
# endif /* UNICOS7x */ |
|
|
# endif /* CRAY */ |
|
|
|
|
|
#endif /* NEWINIT */ |
|
|
|
|
|
#ifdef HAVE_STREAMSPTY |
|
|
#include <sac.h> |
|
|
#include <sys/stropts.h> |
|
|
#endif |
|
|
|
|
|
#define SCPYN(a, b) (void) strncpy(a, b, sizeof(a)) |
|
|
#define SCMPN(a, b) strncmp(a, b, sizeof(a)) |
|
|
|
|
48 |
#ifdef HAVE_SYS_STREAM_H |
#ifdef HAVE_SYS_STREAM_H |
49 |
#include <sys/stream.h> |
# include <sys/stream.h> |
|
#endif |
|
|
#ifdef __hpux |
|
|
#include <sys/resource.h> |
|
|
#include <sys/proc.h> |
|
50 |
#endif |
#endif |
51 |
|
|
52 |
#if defined(UNICOS5) && defined(CRAY2) && !defined(EXTPROC) |
#if defined(UNICOS5) && defined(CRAY2) && !defined(EXTPROC) |
119 |
*/ |
*/ |
120 |
|
|
121 |
void |
void |
122 |
init_termbuf() |
init_termbuf () |
123 |
{ |
{ |
124 |
#ifndef USE_TERMIO |
#ifndef USE_TERMIO |
125 |
(void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg); |
ioctl (pty, TIOCGETP, (char *)&termbuf.sg); |
126 |
(void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc); |
ioctl (pty, TIOCGETC, (char *)&termbuf.tc); |
127 |
(void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc); |
ioctl (pty, TIOCGLTC, (char *)&termbuf.ltc); |
128 |
# ifdef TIOCGSTATE |
# ifdef TIOCGSTATE |
129 |
(void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state); |
ioctl (pty, TIOCGSTATE, (char *)&termbuf.state); |
130 |
# endif |
# endif |
131 |
#else |
#else |
132 |
# ifdef HAVE_STREAMSPTY |
# ifdef HAVE_STREAMSPTY |
133 |
(void) tcgetattr(ttyfd, &termbuf); |
tcgetattr(ttyfd, &termbuf); |
134 |
# else |
# else |
135 |
(void) tcgetattr(pty, &termbuf); |
tcgetattr(pty, &termbuf); |
136 |
# endif |
# endif |
137 |
#endif |
#endif |
138 |
termbuf2 = termbuf; |
termbuf2 = termbuf; |
139 |
} |
} |
140 |
|
|
141 |
#if defined(LINEMODE) && defined(TIOCPKT_IOCTL) |
#if defined(LINEMODE) && defined(TIOCPKT_IOCTL) |
142 |
void |
void |
143 |
copy_termbuf(char *cp, int len) |
copy_termbuf (char *cp, int len) |
144 |
{ |
{ |
145 |
if (len > sizeof(termbuf)) |
if (len > sizeof (termbuf)) |
146 |
len = sizeof(termbuf); |
len = sizeof (termbuf); |
147 |
memmove((char *)&termbuf, cp, len); |
memmove ((char *)&termbuf, cp, len); |
148 |
termbuf2 = termbuf; |
termbuf2 = termbuf; |
149 |
} |
} |
150 |
#endif /* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */ |
#endif /* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */ |
151 |
|
|
152 |
void |
void |
153 |
set_termbuf() |
set_termbuf () |
154 |
{ |
{ |
155 |
/* |
/* |
156 |
* Only make the necessary changes. |
* Only make the necessary changes. |
157 |
*/ |
*/ |
158 |
#ifndef USE_TERMIO |
#ifndef USE_TERMIO |
159 |
if (memcmp((char *)&termbuf.sg, (char *)&termbuf2.sg, |
if (memcmp (&termbuf.sg, &termbuf2.sg, sizeof (termbuf.sg))) |
160 |
sizeof(termbuf.sg))) |
ioctl(pty, TIOCSETN, (char *)&termbuf.sg); |
161 |
(void) ioctl(pty, TIOCSETN, (char *)&termbuf.sg); |
if (memcmp (&termbuf.tc, &termbuf2.tc, sizeof (termbuf.tc))) |
162 |
if (memcmp((char *)&termbuf.tc, (char *)&termbuf2.tc, |
ioctl (pty, TIOCSETC, (char *)&termbuf.tc); |
163 |
sizeof(termbuf.tc))) |
if (memcmp (&termbuf.ltc, &termbuf2.ltc, sizeof (termbuf.ltc))) |
164 |
(void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc); |
ioctl (pty, TIOCSLTC, (char *)&termbuf.ltc); |
165 |
if (memcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc, |
if (termbuf.lflags != termbuf2.lflags) |
166 |
sizeof(termbuf.ltc))) |
ioctl (pty, TIOCLSET, &termbuf.lflags); |
|
(void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc); |
|
|
if (termbuf.lflags != termbuf2.lflags) |
|
|
(void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags); |
|
167 |
#else /* USE_TERMIO */ |
#else /* USE_TERMIO */ |
168 |
if (memcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf))) |
if (memcmp (&termbuf, &termbuf2, sizeof (termbuf))) |
169 |
|
{ |
170 |
# ifdef HAVE_STREAMSPTY |
# ifdef HAVE_STREAMSPTY |
171 |
(void) tcsetattr(ttyfd, TCSANOW, &termbuf); |
tcsetattr (ttyfd, TCSANOW, &termbuf); |
172 |
# else |
# else |
173 |
(void) tcsetattr(pty, TCSANOW, &termbuf); |
tcsetattr (pty, TCSANOW, &termbuf); |
174 |
# endif |
# endif |
175 |
# if defined(CRAY2) && defined(UNICOS5) |
} |
176 |
needtermstat = 1; |
# if defined(CRAY2) && defined(UNICOS5) |
177 |
|
needtermstat = 1; |
178 |
# endif |
# endif |
179 |
#endif /* USE_TERMIO */ |
#endif /* USE_TERMIO */ |
180 |
} |
} |
181 |
|
|
|
|
|
182 |
/* |
/* |
183 |
* spcset(func, valp, valpp) |
* spcset(func, valp, valpp) |
184 |
* |
* |
192 |
|
|
193 |
#ifndef USE_TERMIO |
#ifndef USE_TERMIO |
194 |
int |
int |
195 |
spcset(int func, cc_t *valp, cc_t **valpp) |
spcset (int func, cc_t *valp, cc_t **valpp) |
196 |
{ |
{ |
197 |
switch(func) { |
switch (func) |
198 |
case SLC_EOF: |
{ |
199 |
*valp = termbuf.tc.t_eofc; |
case SLC_EOF: |
200 |
*valpp = (cc_t *)&termbuf.tc.t_eofc; |
*valp = termbuf.tc.t_eofc; |
201 |
return(SLC_VARIABLE); |
*valpp = (cc_t *)&termbuf.tc.t_eofc; |
202 |
case SLC_EC: |
return SLC_VARIABLE; |
203 |
*valp = termbuf.sg.sg_erase; |
|
204 |
*valpp = (cc_t *)&termbuf.sg.sg_erase; |
case SLC_EC: |
205 |
return(SLC_VARIABLE); |
*valp = termbuf.sg.sg_erase; |
206 |
case SLC_EL: |
*valpp = (cc_t *)&termbuf.sg.sg_erase; |
207 |
*valp = termbuf.sg.sg_kill; |
return SLC_VARIABLE; |
208 |
*valpp = (cc_t *)&termbuf.sg.sg_kill; |
|
209 |
return(SLC_VARIABLE); |
case SLC_EL: |
210 |
case SLC_IP: |
*valp = termbuf.sg.sg_kill; |
211 |
*valp = termbuf.tc.t_intrc; |
*valpp = (cc_t *)&termbuf.sg.sg_kill; |
212 |
*valpp = (cc_t *)&termbuf.tc.t_intrc; |
return SLC_VARIABLE; |
213 |
return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); |
|
214 |
case SLC_ABORT: |
case SLC_IP: |
215 |
*valp = termbuf.tc.t_quitc; |
*valp = termbuf.tc.t_intrc; |
216 |
*valpp = (cc_t *)&termbuf.tc.t_quitc; |
*valpp = (cc_t *)&termbuf.tc.t_intrc; |
217 |
return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); |
return SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT; |
218 |
case SLC_XON: |
|
219 |
*valp = termbuf.tc.t_startc; |
case SLC_ABORT: |
220 |
*valpp = (cc_t *)&termbuf.tc.t_startc; |
*valp = termbuf.tc.t_quitc; |
221 |
return(SLC_VARIABLE); |
*valpp = (cc_t *)&termbuf.tc.t_quitc; |
222 |
case SLC_XOFF: |
return SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT; |
223 |
*valp = termbuf.tc.t_stopc; |
|
224 |
*valpp = (cc_t *)&termbuf.tc.t_stopc; |
case SLC_XON: |
225 |
return(SLC_VARIABLE); |
*valp = termbuf.tc.t_startc; |
226 |
case SLC_AO: |
*valpp = (cc_t *)&termbuf.tc.t_startc; |
227 |
*valp = termbuf.ltc.t_flushc; |
return SLC_VARIABLE; |
228 |
*valpp = (cc_t *)&termbuf.ltc.t_flushc; |
|
229 |
return(SLC_VARIABLE); |
case SLC_XOFF: |
230 |
case SLC_SUSP: |
*valp = termbuf.tc.t_stopc; |
231 |
*valp = termbuf.ltc.t_suspc; |
*valpp = (cc_t *)&termbuf.tc.t_stopc; |
232 |
*valpp = (cc_t *)&termbuf.ltc.t_suspc; |
return SLC_VARIABLE; |
233 |
return(SLC_VARIABLE); |
|
234 |
case SLC_EW: |
case SLC_AO: |
235 |
*valp = termbuf.ltc.t_werasc; |
*valp = termbuf.ltc.t_flushc; |
236 |
*valpp = (cc_t *)&termbuf.ltc.t_werasc; |
*valpp = (cc_t *)&termbuf.ltc.t_flushc; |
237 |
return(SLC_VARIABLE); |
return SLC_VARIABLE; |
238 |
case SLC_RP: |
|
239 |
*valp = termbuf.ltc.t_rprntc; |
case SLC_SUSP: |
240 |
*valpp = (cc_t *)&termbuf.ltc.t_rprntc; |
*valp = termbuf.ltc.t_suspc; |
241 |
return(SLC_VARIABLE); |
*valpp = (cc_t *)&termbuf.ltc.t_suspc; |
242 |
case SLC_LNEXT: |
return SLC_VARIABLE; |
243 |
*valp = termbuf.ltc.t_lnextc; |
|
244 |
*valpp = (cc_t *)&termbuf.ltc.t_lnextc; |
case SLC_EW: |
245 |
return(SLC_VARIABLE); |
*valp = termbuf.ltc.t_werasc; |
246 |
case SLC_FORW1: |
*valpp = (cc_t *)&termbuf.ltc.t_werasc; |
247 |
*valp = termbuf.tc.t_brkc; |
return SLC_VARIABLE; |
248 |
*valpp = (cc_t *)&termbuf.ltc.t_lnextc; |
|
249 |
return(SLC_VARIABLE); |
case SLC_RP: |
250 |
case SLC_BRK: |
*valp = termbuf.ltc.t_rprntc; |
251 |
case SLC_SYNCH: |
*valpp = (cc_t *)&termbuf.ltc.t_rprntc; |
252 |
case SLC_AYT: |
return SLC_VARIABLE; |
253 |
case SLC_EOR: |
|
254 |
*valp = (cc_t)0; |
case SLC_LNEXT: |
255 |
*valpp = (cc_t *)0; |
*valp = termbuf.ltc.t_lnextc; |
256 |
return(SLC_DEFAULT); |
*valpp = (cc_t *)&termbuf.ltc.t_lnextc; |
257 |
default: |
return SLC_VARIABLE; |
258 |
*valp = (cc_t)0; |
|
259 |
*valpp = (cc_t *)0; |
case SLC_FORW1: |
260 |
return(SLC_NOSUPPORT); |
*valp = termbuf.tc.t_brkc; |
261 |
} |
*valpp = (cc_t *)&termbuf.ltc.t_lnextc; |
262 |
|
return SLC_VARIABLE; |
263 |
|
|
264 |
|
case SLC_BRK: |
265 |
|
case SLC_SYNCH: |
266 |
|
case SLC_AYT: |
267 |
|
case SLC_EOR: |
268 |
|
*valp = (cc_t)0; |
269 |
|
*valpp = (cc_t *)0; |
270 |
|
return SLC_DEFAULT; |
271 |
|
|
272 |
|
default: |
273 |
|
*valp = (cc_t)0; |
274 |
|
*valpp = (cc_t *)0; |
275 |
|
return SLC_NOSUPPORT; |
276 |
|
} |
277 |
} |
} |
278 |
|
|
279 |
#else /* USE_TERMIO */ |
#else /* USE_TERMIO */ |
280 |
|
|
|
int |
|
|
spcset(int func, cc_t *valp, cc_t **valpp) |
|
|
{ |
|
|
|
|
281 |
#define setval(a, b) *valp = termbuf.c_cc[a]; \ |
#define setval(a, b) *valp = termbuf.c_cc[a]; \ |
282 |
*valpp = &termbuf.c_cc[a]; \ |
*valpp = &termbuf.c_cc[a]; \ |
283 |
return(b); |
return b; |
284 |
#define defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT); |
#define defval(a) *valp = ((cc_t)a); \ |
285 |
|
*valpp = (cc_t *)0; \ |
286 |
switch(func) { |
return SLC_DEFAULT; |
287 |
case SLC_EOF: |
|
288 |
setval(VEOF, SLC_VARIABLE); |
int |
289 |
case SLC_EC: |
spcset (int func, cc_t *valp, cc_t **valpp) |
290 |
setval(VERASE, SLC_VARIABLE); |
{ |
291 |
case SLC_EL: |
switch (func) |
292 |
setval(VKILL, SLC_VARIABLE); |
{ |
293 |
case SLC_IP: |
case SLC_EOF: |
294 |
setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); |
setval (VEOF, SLC_VARIABLE); |
295 |
case SLC_ABORT: |
|
296 |
setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); |
case SLC_EC: |
297 |
case SLC_XON: |
setval (VERASE, SLC_VARIABLE); |
298 |
|
|
299 |
|
case SLC_EL: |
300 |
|
setval (VKILL, SLC_VARIABLE); |
301 |
|
|
302 |
|
case SLC_IP: |
303 |
|
setval (VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); |
304 |
|
|
305 |
|
case SLC_ABORT: |
306 |
|
setval (VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); |
307 |
|
|
308 |
|
case SLC_XON: |
309 |
#ifdef VSTART |
#ifdef VSTART |
310 |
setval(VSTART, SLC_VARIABLE); |
setval (VSTART, SLC_VARIABLE); |
311 |
#else |
#else |
312 |
defval(0x13); |
defval (0x13); |
313 |
#endif |
#endif |
314 |
case SLC_XOFF: |
|
315 |
|
case SLC_XOFF: |
316 |
#ifdef VSTOP |
#ifdef VSTOP |
317 |
setval(VSTOP, SLC_VARIABLE); |
setval (VSTOP, SLC_VARIABLE); |
318 |
#else |
#else |
319 |
defval(0x11); |
defval (0x11); |
320 |
#endif |
#endif |
321 |
case SLC_EW: |
|
322 |
|
case SLC_EW: |
323 |
#ifdef VWERASE |
#ifdef VWERASE |
324 |
setval(VWERASE, SLC_VARIABLE); |
setval (VWERASE, SLC_VARIABLE); |
325 |
#else |
#else |
326 |
defval(0); |
defval (0); |
327 |
#endif |
#endif |
328 |
case SLC_RP: |
|
329 |
|
case SLC_RP: |
330 |
#ifdef VREPRINT |
#ifdef VREPRINT |
331 |
setval(VREPRINT, SLC_VARIABLE); |
setval (VREPRINT, SLC_VARIABLE); |
332 |
#else |
#else |
333 |
defval(0); |
defval(0); |
334 |
#endif |
#endif |
335 |
case SLC_LNEXT: |
|
336 |
|
case SLC_LNEXT: |
337 |
#ifdef VLNEXT |
#ifdef VLNEXT |
338 |
setval(VLNEXT, SLC_VARIABLE); |
setval (VLNEXT, SLC_VARIABLE); |
339 |
#else |
#else |
340 |
defval(0); |
defval (0); |
341 |
#endif |
#endif |
342 |
case SLC_AO: |
|
343 |
#if !defined(VDISCARD) && defined(VFLUSHO) |
case SLC_AO: |
344 |
|
#if !defined(VDISCARD) && defined(VFLUSHO) |
345 |
# define VDISCARD VFLUSHO |
# define VDISCARD VFLUSHO |
346 |
#endif |
#endif |
347 |
#ifdef VDISCARD |
#ifdef VDISCARD |
348 |
setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT); |
setval (VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT); |
349 |
#else |
#else |
350 |
defval(0); |
defval (0); |
351 |
#endif |
#endif |
352 |
case SLC_SUSP: |
|
353 |
|
case SLC_SUSP: |
354 |
#ifdef VSUSP |
#ifdef VSUSP |
355 |
setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN); |
setval (VSUSP, SLC_VARIABLE|SLC_FLUSHIN); |
356 |
#else |
#else |
357 |
defval(0); |
defval (0); |
358 |
#endif |
#endif |
359 |
|
|
360 |
#ifdef VEOL |
#ifdef VEOL |
361 |
case SLC_FORW1: |
case SLC_FORW1: |
362 |
setval(VEOL, SLC_VARIABLE); |
setval (VEOL, SLC_VARIABLE); |
363 |
#endif |
#endif |
364 |
|
|
365 |
#ifdef VEOL2 |
#ifdef VEOL2 |
366 |
case SLC_FORW2: |
case SLC_FORW2: |
367 |
setval(VEOL2, SLC_VARIABLE); |
setval (VEOL2, SLC_VARIABLE); |
368 |
#endif |
#endif |
369 |
case SLC_AYT: |
|
370 |
|
case SLC_AYT: |
371 |
#ifdef VSTATUS |
#ifdef VSTATUS |
372 |
setval(VSTATUS, SLC_VARIABLE); |
setval (VSTATUS, SLC_VARIABLE); |
373 |
#else |
#else |
374 |
defval(0); |
defval (0); |
375 |
#endif |
#endif |
376 |
|
|
377 |
case SLC_BRK: |
case SLC_BRK: |
378 |
case SLC_SYNCH: |
case SLC_SYNCH: |
379 |
case SLC_EOR: |
case SLC_EOR: |
380 |
defval(0); |
defval (0); |
381 |
|
|
382 |
default: |
default: |
383 |
*valp = 0; |
*valp = 0; |
384 |
*valpp = 0; |
*valpp = 0; |
385 |
return(SLC_NOSUPPORT); |
return SLC_NOSUPPORT; |
386 |
} |
} |
387 |
} |
} |
388 |
#endif /* USE_TERMIO */ |
#endif /* USE_TERMIO */ |
389 |
|
|
|
#ifdef CRAY |
|
|
/* |
|
|
* getnpty() |
|
|
* |
|
|
* Return the number of pty's configured into the system. |
|
|
*/ |
|
|
int |
|
|
getnpty() |
|
|
{ |
|
|
#ifdef _SC_CRAY_NPTY |
|
|
int numptys; |
|
|
|
|
|
if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1) |
|
|
return numptys; |
|
|
else |
|
|
#endif /* _SC_CRAY_NPTY */ |
|
|
return 128; |
|
|
} |
|
|
#endif /* CRAY */ |
|
|
|
|
|
#ifndef convex |
|
|
/* |
|
|
* getpty() |
|
|
* |
|
|
* Allocate a pty. As a side effect, the external character |
|
|
* array "line" contains the name of the slave side. |
|
|
* |
|
|
* Returns the file descriptor of the opened pty. |
|
|
*/ |
|
|
static char Xline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; |
|
|
char *line = Xline; |
|
|
|
|
|
#ifdef CRAY |
|
|
static char Xmyline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; |
|
|
char *myline = Xmyline; |
|
|
#endif /* CRAY */ |
|
|
|
|
|
int |
|
|
getpty(int *ptynum) |
|
|
{ |
|
|
register int p; |
|
|
#ifdef HAVE_STREAMSPTY |
|
|
int t; |
|
|
char *ptsname(); |
|
|
|
|
|
p = open("/dev/ptmx", O_RDWR); |
|
|
if (p > 0) { |
|
|
grantpt(p); |
|
|
unlockpt(p); |
|
|
strcpy(line, ptsname(p)); |
|
|
return(p); |
|
|
} |
|
|
|
|
|
#else /* ! HAVE_STREAMSPTY */ |
|
|
#ifndef CRAY |
|
|
register char *cp, *p1, *p2; |
|
|
register int i; |
|
|
#if defined(sun) && defined(TIOCGPGRP) && BSD < 199207 |
|
|
int dummy; |
|
|
#endif |
|
|
|
|
|
#ifndef __hpux |
|
|
(void) sprintf(line, "/dev/ptyXX"); |
|
|
p1 = &line[8]; |
|
|
p2 = &line[9]; |
|
|
#else |
|
|
(void) sprintf(line, "/dev/ptym/ptyXX"); |
|
|
p1 = &line[13]; |
|
|
p2 = &line[14]; |
|
|
#endif |
|
|
|
|
|
for (cp = "pqrstuvwxyzPQRST"; *cp; cp++) { |
|
|
struct stat stb; |
|
|
|
|
|
*p1 = *cp; |
|
|
*p2 = '0'; |
|
|
/* |
|
|
* This stat() check is just to keep us from |
|
|
* looping through all 256 combinations if there |
|
|
* aren't that many ptys available. |
|
|
*/ |
|
|
if (stat(line, &stb) < 0) |
|
|
break; |
|
|
for (i = 0; i < 16; i++) { |
|
|
*p2 = "0123456789abcdef"[i]; |
|
|
p = open(line, O_RDWR); |
|
|
if (p > 0) { |
|
|
#ifndef __hpux |
|
|
line[5] = 't'; |
|
|
#else |
|
|
for (p1 = &line[8]; *p1; p1++) |
|
|
*p1 = *(p1+1); |
|
|
line[9] = 't'; |
|
|
#endif |
|
|
chown(line, 0, 0); |
|
|
chmod(line, 0600); |
|
|
#if defined(sun) && defined(TIOCGPGRP) && BSD < 199207 |
|
|
if (ioctl(p, TIOCGPGRP, &dummy) == 0 |
|
|
|| errno != EIO) { |
|
|
chmod(line, 0666); |
|
|
close(p); |
|
|
line[5] = 'p'; |
|
|
} else |
|
|
#endif /* defined(sun) && defined(TIOCGPGRP) && BSD < 199207 */ |
|
|
return(p); |
|
|
} |
|
|
} |
|
|
} |
|
|
#else /* CRAY */ |
|
|
extern lowpty, highpty; |
|
|
struct stat sb; |
|
|
|
|
|
for (*ptynum = lowpty; *ptynum <= highpty; (*ptynum)++) { |
|
|
(void) sprintf(myline, "/dev/pty/%03d", *ptynum); |
|
|
p = open(myline, O_RDWR); |
|
|
if (p < 0) |
|
|
continue; |
|
|
(void) sprintf(line, "/dev/ttyp%03d", *ptynum); |
|
|
/* |
|
|
* Here are some shenanigans to make sure that there |
|
|
* are no listeners lurking on the line. |
|
|
*/ |
|
|
if(stat(line, &sb) < 0) { |
|
|
(void) close(p); |
|
|
continue; |
|
|
} |
|
|
if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) { |
|
|
chown(line, 0, 0); |
|
|
chmod(line, 0600); |
|
|
(void)close(p); |
|
|
p = open(myline, O_RDWR); |
|
|
if (p < 0) |
|
|
continue; |
|
|
} |
|
|
/* |
|
|
* Now it should be safe...check for accessability. |
|
|
*/ |
|
|
if (access(line, 6) == 0) |
|
|
return(p); |
|
|
else { |
|
|
/* no tty side to pty so skip it */ |
|
|
(void) close(p); |
|
|
} |
|
|
} |
|
|
#endif /* CRAY */ |
|
|
#endif /* HAVE_STREAMSPTY */ |
|
|
return(-1); |
|
|
} |
|
|
#endif /* convex */ |
|
|
|
|
390 |
#ifdef LINEMODE |
#ifdef LINEMODE |
391 |
/* |
/* |
392 |
* tty_flowmode() Find out if flow control is enabled or disabled. |
* tty_flowmode() Find out if flow control is enabled or disabled. |
419 |
#ifndef convex |
#ifndef convex |
420 |
#ifdef USE_TERMIO |
#ifdef USE_TERMIO |
421 |
#ifdef EXTPROC |
#ifdef EXTPROC |
422 |
return(termbuf.c_lflag & EXTPROC); |
return (termbuf.c_lflag & EXTPROC); |
423 |
#else |
#else |
424 |
return 0; /* Can't ever set it either. */ |
return 0; /* Can't ever set it either. */ |
425 |
#endif /* EXTPROC */ |
#endif /* EXTPROC */ |
426 |
#else /* !USE_TERMIO */ |
#else /* !USE_TERMIO */ |
427 |
return(termbuf.state & TS_EXTPROC); |
return termbuf.state & TS_EXTPROC; |
428 |
#endif /* USE_TERMIO */ |
#endif /* USE_TERMIO */ |
429 |
#else /* convex */ |
#else /* convex */ |
430 |
return(linestate); |
return linestate; |
431 |
#endif /* !convex */ |
#endif /* !convex */ |
432 |
} |
} |
433 |
|
|
434 |
void |
void |
435 |
tty_setlinemode(on) |
tty_setlinemode (int on) |
|
int on; |
|
436 |
{ |
{ |
437 |
#ifdef TIOCEXT |
#ifdef TIOCEXT |
438 |
# ifndef convex |
# ifndef convex |
439 |
set_termbuf(); |
set_termbuf (); |
440 |
# else |
# else |
441 |
linestate = on; |
linestate = on; |
442 |
# endif |
# endif |
443 |
(void) ioctl(pty, TIOCEXT, (char *)&on); |
ioctl (pty, TIOCEXT, (char *)&on); |
444 |
# ifndef convex |
# ifndef convex |
445 |
init_termbuf(); |
init_termbuf (); |
446 |
# endif |
# endif |
447 |
#else /* !TIOCEXT */ |
#else /* !TIOCEXT */ |
448 |
# ifdef EXTPROC |
# ifdef EXTPROC |
449 |
if (on) |
if (on) |
450 |
termbuf.c_lflag |= EXTPROC; |
termbuf.c_lflag |= EXTPROC; |
451 |
else |
else |
452 |
termbuf.c_lflag &= ~EXTPROC; |
termbuf.c_lflag &= ~EXTPROC; |
453 |
# endif |
# endif |
454 |
#endif /* TIOCEXT */ |
#endif /* TIOCEXT */ |
455 |
} |
} |
456 |
#endif /* LINEMODE */ |
#endif /* LINEMODE */ |
457 |
|
|
458 |
int |
int |
459 |
tty_isecho() |
tty_isecho () |
460 |
{ |
{ |
461 |
#ifndef USE_TERMIO |
#ifndef USE_TERMIO |
462 |
return (termbuf.sg.sg_flags & ECHO); |
return termbuf.sg.sg_flags & ECHO; |
463 |
#else |
#else |
464 |
return (termbuf.c_lflag & ECHO); |
return termbuf.c_lflag & ECHO; |
465 |
#endif |
#endif |
466 |
} |
} |
467 |
|
|
468 |
int |
int |
469 |
tty_flowmode() |
tty_flowmode () |
470 |
{ |
{ |
471 |
#ifndef USE_TERMIO |
#ifndef USE_TERMIO |
472 |
return(((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0) ? 1 : 0); |
return ((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0) ? 1 : 0; |
473 |
#else |
#else |
474 |
return((termbuf.c_iflag & IXON) ? 1 : 0); |
return (termbuf.c_iflag & IXON) ? 1 : 0; |
475 |
#endif |
#endif |
476 |
} |
} |
477 |
|
|
478 |
int |
int |
479 |
tty_restartany() |
tty_restartany () |
480 |
{ |
{ |
481 |
#ifndef USE_TERMIO |
#ifndef USE_TERMIO |
482 |
# ifdef DECCTQ |
# ifdef DECCTQ |
483 |
return((termbuf.lflags & DECCTQ) ? 0 : 1); |
return (termbuf.lflags & DECCTQ) ? 0 : 1; |
484 |
# else |
# else |
485 |
return(-1); |
return -1; |
486 |
# endif |
# endif |
487 |
#else |
#else |
488 |
return((termbuf.c_iflag & IXANY) ? 1 : 0); |
return (termbuf.c_iflag & IXANY) ? 1 : 0; |
489 |
#endif |
#endif |
490 |
} |
} |
491 |
|
|
492 |
void |
void |
493 |
tty_setecho(on) |
tty_setecho(int on) |
|
int on; |
|
494 |
{ |
{ |
495 |
#ifndef USE_TERMIO |
#ifndef USE_TERMIO |
496 |
if (on) |
if (on) |
497 |
termbuf.sg.sg_flags |= ECHO|CRMOD; |
termbuf.sg.sg_flags |= ECHO|CRMOD; |
498 |
else |
else |
499 |
termbuf.sg.sg_flags &= ~(ECHO|CRMOD); |
termbuf.sg.sg_flags &= ~(ECHO|CRMOD); |
500 |
#else |
#else |
501 |
if (on) |
if (on) |
502 |
termbuf.c_lflag |= ECHO; |
termbuf.c_lflag |= ECHO; |
503 |
else |
else |
504 |
termbuf.c_lflag &= ~ECHO; |
termbuf.c_lflag &= ~ECHO; |
505 |
#endif |
#endif |
506 |
} |
} |
507 |
|
|
508 |
int |
int |
509 |
tty_israw() |
tty_israw () |
510 |
{ |
{ |
511 |
#ifndef USE_TERMIO |
#ifndef USE_TERMIO |
512 |
return(termbuf.sg.sg_flags & RAW); |
return termbuf.sg.sg_flags & RAW; |
513 |
#else |
#else |
514 |
return(!(termbuf.c_lflag & ICANON)); |
return !(termbuf.c_lflag & ICANON); |
515 |
#endif |
#endif |
516 |
} |
} |
517 |
|
|
518 |
#if defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) |
#if defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) |
519 |
int |
int |
520 |
tty_setraw(int on) |
tty_setraw(int on) |
521 |
{ |
{ |
522 |
# ifndef USE_TERMIO |
# ifndef USE_TERMIO |
523 |
if (on) |
if (on) |
524 |
termbuf.sg.sg_flags |= RAW; |
termbuf.sg.sg_flags |= RAW; |
525 |
else |
else |
526 |
termbuf.sg.sg_flags &= ~RAW; |
termbuf.sg.sg_flags &= ~RAW; |
527 |
# else |
# else |
528 |
if (on) |
if (on) |
529 |
termbuf.c_lflag &= ~ICANON; |
termbuf.c_lflag &= ~ICANON; |
530 |
else |
else |
531 |
termbuf.c_lflag |= ICANON; |
termbuf.c_lflag |= ICANON; |
532 |
# endif |
# endif |
533 |
} |
} |
534 |
#endif |
#endif |
535 |
|
|
536 |
void |
void |
537 |
tty_binaryin(int on) |
tty_binaryin (int on) |
538 |
{ |
{ |
539 |
#ifndef USE_TERMIO |
#ifndef USE_TERMIO |
540 |
if (on) |
if (on) |
541 |
termbuf.lflags |= LPASS8; |
termbuf.lflags |= LPASS8; |
542 |
else |
else |
543 |
termbuf.lflags &= ~LPASS8; |
termbuf.lflags &= ~LPASS8; |
544 |
#else |
#else |
545 |
if (on) { |
if (on) |
546 |
termbuf.c_iflag &= ~ISTRIP; |
termbuf.c_iflag &= ~ISTRIP; |
547 |
} else { |
else |
548 |
termbuf.c_iflag |= ISTRIP; |
termbuf.c_iflag |= ISTRIP; |
|
} |
|
549 |
#endif |
#endif |
550 |
} |
} |
551 |
|
|
552 |
void |
void |
553 |
tty_binaryout(int on) |
tty_binaryout (int on) |
554 |
{ |
{ |
555 |
#ifndef USE_TERMIO |
#ifndef USE_TERMIO |
556 |
if (on) |
if (on) |
557 |
termbuf.lflags |= LLITOUT; |
termbuf.lflags |= LLITOUT; |
558 |
else |
else |
559 |
termbuf.lflags &= ~LLITOUT; |
termbuf.lflags &= ~LLITOUT; |
560 |
#else |
#else |
561 |
if (on) { |
if (on) |
562 |
termbuf.c_cflag &= ~(CSIZE|PARENB); |
{ |
563 |
termbuf.c_cflag |= CS8; |
termbuf.c_cflag &= ~(CSIZE|PARENB); |
564 |
termbuf.c_oflag &= ~OPOST; |
termbuf.c_cflag |= CS8; |
565 |
} else { |
termbuf.c_oflag &= ~OPOST; |
566 |
termbuf.c_cflag &= ~CSIZE; |
} |
567 |
termbuf.c_cflag |= CS7|PARENB; |
else |
568 |
termbuf.c_oflag |= OPOST; |
{ |
569 |
} |
termbuf.c_cflag &= ~CSIZE; |
570 |
|
termbuf.c_cflag |= CS7|PARENB; |
571 |
|
termbuf.c_oflag |= OPOST; |
572 |
|
} |
573 |
#endif |
#endif |
574 |
} |
} |
575 |
|
|
576 |
int |
int |
577 |
tty_isbinaryin() |
tty_isbinaryin () |
578 |
{ |
{ |
579 |
#ifndef USE_TERMIO |
#ifndef USE_TERMIO |
580 |
return(termbuf.lflags & LPASS8); |
return termbuf.lflags & LPASS8; |
581 |
#else |
#else |
582 |
return(!(termbuf.c_iflag & ISTRIP)); |
return !(termbuf.c_iflag & ISTRIP); |
583 |
#endif |
#endif |
584 |
} |
} |
585 |
|
|
586 |
int |
int |
587 |
tty_isbinaryout() |
tty_isbinaryout () |
588 |
{ |
{ |
589 |
#ifndef USE_TERMIO |
#ifndef USE_TERMIO |
590 |
return(termbuf.lflags & LLITOUT); |
return termbuf.lflags & LLITOUT; |
591 |
#else |
#else |
592 |
return(!(termbuf.c_oflag&OPOST)); |
return !(termbuf.c_oflag&OPOST); |
593 |
#endif |
#endif |
594 |
} |
} |
595 |
|
|
596 |
#ifdef LINEMODE |
#ifdef LINEMODE |
597 |
int |
int |
598 |
tty_isediting() |
tty_isediting () |
599 |
{ |
{ |
600 |
#ifndef USE_TERMIO |
#ifndef USE_TERMIO |
601 |
return(!(termbuf.sg.sg_flags & (CBREAK|RAW))); |
return !(termbuf.sg.sg_flags & (CBREAK|RAW)); |
602 |
#else |
#else |
603 |
return(termbuf.c_lflag & ICANON); |
return termbuf.c_lflag & ICANON; |
604 |
#endif |
#endif |
605 |
} |
} |
606 |
|
|
608 |
tty_istrapsig() |
tty_istrapsig() |
609 |
{ |
{ |
610 |
#ifndef USE_TERMIO |
#ifndef USE_TERMIO |
611 |
return(!(termbuf.sg.sg_flags&RAW)); |
return !(termbuf.sg.sg_flags&RAW); |
612 |
#else |
#else |
613 |
return(termbuf.c_lflag & ISIG); |
return termbuf.c_lflag & ISIG; |
614 |
#endif |
#endif |
615 |
} |
} |
616 |
|
|
617 |
void |
void |
618 |
tty_setedit(int on) |
tty_setedit (int on) |
619 |
{ |
{ |
620 |
#ifndef USE_TERMIO |
#ifndef USE_TERMIO |
621 |
if (on) |
if (on) |
622 |
termbuf.sg.sg_flags &= ~CBREAK; |
termbuf.sg.sg_flags &= ~CBREAK; |
623 |
else |
else |
624 |
termbuf.sg.sg_flags |= CBREAK; |
termbuf.sg.sg_flags |= CBREAK; |
625 |
#else |
#else |
626 |
if (on) |
if (on) |
627 |
termbuf.c_lflag |= ICANON; |
termbuf.c_lflag |= ICANON; |
628 |
else |
else |
629 |
termbuf.c_lflag &= ~ICANON; |
termbuf.c_lflag &= ~ICANON; |
630 |
#endif |
#endif |
631 |
} |
} |
632 |
|
|
633 |
void |
void |
634 |
tty_setsig(int on) |
tty_setsig (int on) |
635 |
{ |
{ |
636 |
#ifndef USE_TERMIO |
#ifdef USE_TERMIO |
637 |
if (on) |
if (on) |
638 |
; |
termbuf.c_lflag |= ISIG; |
639 |
#else |
else |
640 |
if (on) |
termbuf.c_lflag &= ~ISIG; |
|
termbuf.c_lflag |= ISIG; |
|
|
else |
|
|
termbuf.c_lflag &= ~ISIG; |
|
641 |
#endif |
#endif |
642 |
} |
} |
643 |
#endif /* LINEMODE */ |
#endif /* LINEMODE */ |
644 |
|
|
645 |
int |
int |
646 |
tty_issofttab() |
tty_issofttab () |
647 |
{ |
{ |
648 |
#ifndef USE_TERMIO |
#ifndef USE_TERMIO |
649 |
return (termbuf.sg.sg_flags & XTABS); |
return termbuf.sg.sg_flags & XTABS; |
650 |
#else |
#else |
651 |
# ifdef OXTABS |
# ifdef OXTABS |
652 |
return (termbuf.c_oflag & OXTABS); |
return termbuf.c_oflag & OXTABS; |
653 |
# endif |
# endif |
654 |
# ifdef TABDLY |
# ifdef TABDLY |
655 |
return ((termbuf.c_oflag & TABDLY) == TAB3); |
return (termbuf.c_oflag & TABDLY) == TAB3; |
656 |
# endif |
# endif |
657 |
#endif |
#endif |
658 |
} |
} |
659 |
|
|
660 |
void |
void |
661 |
tty_setsofttab(int on) |
tty_setsofttab (int on) |
662 |
{ |
{ |
663 |
#ifndef USE_TERMIO |
#ifndef USE_TERMIO |
664 |
if (on) |
if (on) |
665 |
termbuf.sg.sg_flags |= XTABS; |
termbuf.sg.sg_flags |= XTABS; |
666 |
else |
else |
667 |
termbuf.sg.sg_flags &= ~XTABS; |
termbuf.sg.sg_flags &= ~XTABS; |
668 |
#else |
#else |
669 |
if (on) { |
if (on) |
670 |
|
{ |
671 |
# ifdef OXTABS |
# ifdef OXTABS |
672 |
termbuf.c_oflag |= OXTABS; |
termbuf.c_oflag |= OXTABS; |
673 |
# endif |
# endif |
674 |
# ifdef TABDLY |
# ifdef TABDLY |
675 |
termbuf.c_oflag &= ~TABDLY; |
termbuf.c_oflag &= ~TABDLY; |
676 |
termbuf.c_oflag |= TAB3; |
termbuf.c_oflag |= TAB3; |
677 |
# endif |
# endif |
678 |
} else { |
} |
679 |
|
else |
680 |
|
{ |
681 |
# ifdef OXTABS |
# ifdef OXTABS |
682 |
termbuf.c_oflag &= ~OXTABS; |
termbuf.c_oflag &= ~OXTABS; |
683 |
# endif |
# endif |
684 |
# ifdef TABDLY |
# ifdef TABDLY |
685 |
termbuf.c_oflag &= ~TABDLY; |
termbuf.c_oflag &= ~TABDLY; |
686 |
termbuf.c_oflag |= TAB0; |
termbuf.c_oflag |= TAB0; |
687 |
# endif |
# endif |
688 |
} |
} |
689 |
#endif |
#endif |
690 |
} |
} |
691 |
|
|
692 |
int |
int |
693 |
tty_islitecho() |
tty_islitecho () |
694 |
{ |
{ |
695 |
#ifndef USE_TERMIO |
#ifndef USE_TERMIO |
696 |
return (!(termbuf.lflags & LCTLECH)); |
return !(termbuf.lflags & LCTLECH); |
697 |
#else |
#else |
698 |
# ifdef ECHOCTL |
# ifdef ECHOCTL |
699 |
return (!(termbuf.c_lflag & ECHOCTL)); |
return !(termbuf.c_lflag & ECHOCTL); |
700 |
# endif |
# endif |
701 |
# ifdef TCTLECH |
# ifdef TCTLECH |
702 |
return (!(termbuf.c_lflag & TCTLECH)); |
return !(termbuf.c_lflag & TCTLECH); |
703 |
# endif |
# endif |
704 |
# if !defined(ECHOCTL) && !defined(TCTLECH) |
# if!defined(ECHOCTL) && !defined(TCTLECH) |
705 |
return (0); /* assumes ctl chars are echoed '^x' */ |
return 0; /* assumes ctl chars are echoed '^x' */ |
706 |
# endif |
# endif |
707 |
#endif |
#endif |
708 |
} |
} |
709 |
|
|
710 |
void |
void |
711 |
tty_setlitecho(int on) |
tty_setlitecho (int on) |
712 |
{ |
{ |
713 |
#ifndef USE_TERMIO |
#ifndef USE_TERMIO |
714 |
if (on) |
if (on) |
715 |
termbuf.lflags &= ~LCTLECH; |
termbuf.lflags &= ~LCTLECH; |
716 |
else |
else |
717 |
termbuf.lflags |= LCTLECH; |
termbuf.lflags |= LCTLECH; |
718 |
#else |
#else |
719 |
# ifdef ECHOCTL |
# ifdef ECHOCTL |
720 |
if (on) |
if (on) |
721 |
termbuf.c_lflag &= ~ECHOCTL; |
termbuf.c_lflag &= ~ECHOCTL; |
722 |
else |
else |
723 |
termbuf.c_lflag |= ECHOCTL; |
termbuf.c_lflag |= ECHOCTL; |
724 |
# endif |
# endif |
725 |
# ifdef TCTLECH |
# ifdef TCTLECH |
726 |
if (on) |
if (on) |
727 |
termbuf.c_lflag &= ~TCTLECH; |
termbuf.c_lflag &= ~TCTLECH; |
728 |
else |
else |
729 |
termbuf.c_lflag |= TCTLECH; |
termbuf.c_lflag |= TCTLECH; |
730 |
# endif |
# endif |
731 |
#endif |
#endif |
732 |
} |
} |
733 |
|
|
734 |
int |
int |
735 |
tty_iscrnl() |
tty_iscrnl () |
736 |
{ |
{ |
737 |
#ifndef USE_TERMIO |
#ifndef USE_TERMIO |
738 |
return (termbuf.sg.sg_flags & CRMOD); |
return termbuf.sg.sg_flags & CRMOD; |
739 |
#else |
#else |
740 |
return (termbuf.c_iflag & ICRNL); |
return termbuf.c_iflag & ICRNL; |
741 |
#endif |
#endif |
742 |
} |
} |
743 |
|
|
754 |
* A table of available terminal speeds |
* A table of available terminal speeds |
755 |
*/ |
*/ |
756 |
struct termspeeds { |
struct termspeeds { |
757 |
int speed; |
int speed; |
758 |
int value; |
int value; |
759 |
} termspeeds[] = { |
} termspeeds[] = { |
760 |
{ 0, B0 }, { 50, B50 }, { 75, B75 }, |
{ 0, B0 }, { 50, B50 }, { 75, B75 }, |
761 |
{ 110, B110 }, { 134, B134 }, { 150, B150 }, |
{ 110, B110 }, { 134, B134 }, { 150, B150 }, |
762 |
{ 200, B200 }, { 300, B300 }, { 600, B600 }, |
{ 200, B200 }, { 300, B300 }, { 600, B600 }, |
763 |
{ 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, |
{ 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, |
764 |
{ 4800, B4800 }, |
{ 4800, B4800 }, |
765 |
#ifdef B7200 |
#ifdef B7200 |
766 |
{ 7200, B7200 }, |
{ 7200, B7200 }, |
767 |
#endif |
#endif |
768 |
{ 9600, B9600 }, |
{ 9600, B9600 }, |
769 |
#ifdef B14400 |
#ifdef B14400 |
770 |
{ 14400, B14400 }, |
{ 14400, B14400 }, |
771 |
#endif |
#endif |
772 |
#ifdef B19200 |
#ifdef B19200 |
773 |
{ 19200, B19200 }, |
{ 19200, B19200 }, |
774 |
#endif |
#endif |
775 |
#ifdef B28800 |
#ifdef B28800 |
776 |
{ 28800, B28800 }, |
{ 28800, B28800 }, |
777 |
#endif |
#endif |
778 |
#ifdef B38400 |
#ifdef B38400 |
779 |
{ 38400, B38400 }, |
{ 38400, B38400 }, |
780 |
#endif |
#endif |
781 |
#ifdef B57600 |
#ifdef B57600 |
782 |
{ 57600, B57600 }, |
{ 57600, B57600 }, |
783 |
#endif |
#endif |
784 |
#ifdef B115200 |
#ifdef B115200 |
785 |
{ 115200, B115200 }, |
{ 115200, B115200 }, |
786 |
#endif |
#endif |
787 |
#ifdef B230400 |
#ifdef B230400 |
788 |
{ 230400, B230400 }, |
{ 230400, B230400 }, |
789 |
#endif |
#endif |
790 |
{ -1, 0 } |
{ -1, 0 } |
791 |
}; |
}; |
792 |
#endif /* DECODE_BUAD */ |
#endif /* DECODE_BAUD */ |
793 |
|
|
794 |
void |
void |
795 |
tty_tspeed(int val) |
tty_tspeed (int val) |
796 |
{ |
{ |
797 |
#ifdef DECODE_BAUD |
#ifdef DECODE_BAUD |
798 |
register struct termspeeds *tp; |
register struct termspeeds *tp; |
799 |
|
|
800 |
for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) |
for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) |
801 |
; |
; |
802 |
if (tp->speed == -1) /* back up to last valid value */ |
if (tp->speed == -1) /* back up to last valid value */ |
803 |
--tp; |
--tp; |
804 |
cfsetospeed(&termbuf, tp->value); |
cfsetospeed (&termbuf, tp->value); |
805 |
#else /* DECODE_BUAD */ |
#else |
806 |
cfsetospeed(&termbuf, val); |
cfsetospeed (&termbuf, val); |
807 |
#endif /* DECODE_BUAD */ |
#endif /* DECODE_BAUD */ |
808 |
} |
} |
809 |
|
|
810 |
void |
void |
811 |
tty_rspeed(int val) |
tty_rspeed (int val) |
812 |
{ |
{ |
813 |
#ifdef DECODE_BAUD |
#ifdef DECODE_BAUD |
814 |
register struct termspeeds *tp; |
register struct termspeeds *tp; |
815 |
|
|
816 |
for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) |
for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) |
817 |
; |
; |
818 |
if (tp->speed == -1) /* back up to last valid value */ |
if (tp->speed == -1) /* back up to last valid value */ |
819 |
--tp; |
--tp; |
820 |
cfsetispeed(&termbuf, tp->value); |
cfsetispeed (&termbuf, tp->value); |
821 |
#else /* DECODE_BAUD */ |
#else /* DECODE_BAUD */ |
822 |
cfsetispeed(&termbuf, val); |
cfsetispeed (&termbuf, val); |
823 |
#endif /* DECODE_BAUD */ |
#endif /* DECODE_BAUD */ |
824 |
} |
} |
825 |
|
|
826 |
#if defined(CRAY2) && defined(UNICOS5) |
#if defined(CRAY2) && defined(UNICOS5) |
|
int |
|
|
tty_isnewmap() |
|
|
{ |
|
|
return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) && |
|
|
!(termbuf.c_oflag & ONLRET)); |
|
|
} |
|
|
#endif |
|
|
|
|
|
#ifdef PARENT_DOES_UTMP |
|
|
# ifndef NEWINIT |
|
|
extern struct utmp wtmp; |
|
|
extern char wtmpf[]; |
|
|
# else /* NEWINIT */ |
|
|
int gotalarm; |
|
|
|
|
|
/* ARGSUSED */ |
|
|
void |
|
|
nologinproc(int sig) |
|
|
{ |
|
|
gotalarm++; |
|
|
} |
|
|
# endif /* NEWINIT */ |
|
|
#endif /* PARENT_DOES_UTMP */ |
|
|
|
|
|
#ifndef NEWINIT |
|
|
# ifdef PARENT_DOES_UTMP |
|
|
extern void utmp_sig_init P((void)); |
|
|
extern void utmp_sig_reset P((void)); |
|
|
extern void utmp_sig_wait P((void)); |
|
|
extern void utmp_sig_notify P((int)); |
|
|
# endif /* PARENT_DOES_UTMP */ |
|
|
#endif |
|
|
|
|
|
/* |
|
|
* getptyslave() |
|
|
* |
|
|
* Open the slave side of the pty, and do any initialization |
|
|
* that is necessary. The return value is a file descriptor |
|
|
* for the slave side. |
|
|
*/ |
|
|
int |
|
|
getptyslave() |
|
|
{ |
|
|
register int t = -1; |
|
|
|
|
|
#if !defined(CRAY) || !defined(NEWINIT) |
|
|
# ifdef LINEMODE |
|
|
int waslm; |
|
|
# endif |
|
|
# ifdef TIOCGWINSZ |
|
|
struct winsize ws; |
|
|
extern int def_row, def_col; |
|
|
# endif |
|
|
extern int def_tspeed, def_rspeed; |
|
|
/* |
|
|
* Opening the slave side may cause initilization of the |
|
|
* kernel tty structure. We need remember the state of |
|
|
* if linemode was turned on |
|
|
* terminal window size |
|
|
* terminal speed |
|
|
* so that we can re-set them if we need to. |
|
|
*/ |
|
|
# ifdef LINEMODE |
|
|
waslm = tty_linemode(); |
|
|
# endif |
|
|
|
|
|
|
|
|
/* |
|
|
* Make sure that we don't have a controlling tty, and |
|
|
* that we are the session (process group) leader. |
|
|
*/ |
|
|
# ifdef TIOCNOTTY |
|
|
t = open(PATH_TTY, O_RDWR); |
|
|
if (t >= 0) { |
|
|
(void) ioctl(t, TIOCNOTTY, (char *)0); |
|
|
(void) close(t); |
|
|
} |
|
|
# endif |
|
|
|
|
|
|
|
|
# ifdef PARENT_DOES_UTMP |
|
|
/* |
|
|
* Wait for our parent to get the utmp stuff to get done. |
|
|
*/ |
|
|
utmp_sig_wait(); |
|
|
# endif |
|
|
|
|
|
t = cleanopen(line); |
|
|
if (t < 0) |
|
|
fatalperror(net, line); |
|
|
|
|
|
#ifdef HAVE_STREAMSPTY |
|
|
#ifdef USE_TERMIO |
|
|
ttyfd = t; |
|
|
#endif |
|
|
if (ioctl(t, I_PUSH, "ptem") < 0) |
|
|
fatal(net, "I_PUSH ptem"); |
|
|
if (ioctl(t, I_PUSH, "ldterm") < 0) |
|
|
fatal(net, "I_PUSH ldterm"); |
|
|
if (ioctl(t, I_PUSH, "ttcompat") < 0) |
|
|
fatal(net, "I_PUSH ttcompat"); |
|
|
if (ioctl(pty, I_PUSH, "pckt") < 0) |
|
|
fatal(net, "I_PUSH pckt"); |
|
|
#endif |
|
|
|
|
|
/* |
|
|
* set up the tty modes as we like them to be. |
|
|
*/ |
|
|
init_termbuf(); |
|
|
# ifdef TIOCGWINSZ |
|
|
if (def_row || def_col) { |
|
|
memset((char *)&ws, 0, sizeof(ws)); |
|
|
ws.ws_col = def_col; |
|
|
ws.ws_row = def_row; |
|
|
(void)ioctl(t, TIOCSWINSZ, (char *)&ws); |
|
|
} |
|
|
# endif |
|
|
|
|
|
/* |
|
|
* Settings for sgtty based systems |
|
|
*/ |
|
|
# ifndef USE_TERMIO |
|
|
termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS; |
|
|
# endif /* USE_TERMIO */ |
|
|
|
|
|
/* |
|
|
* Settings for UNICOS (and HPUX) |
|
|
*/ |
|
|
# if defined(CRAY) || defined(__hpux) |
|
|
termbuf.c_oflag = OPOST|ONLCR|TAB3; |
|
|
termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON; |
|
|
termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK; |
|
|
termbuf.c_cflag = EXTB|HUPCL|CS8; |
|
|
# endif |
|
|
|
|
|
/* |
|
|
* Settings for all other termios/termio based |
|
|
* systems, other than 4.4BSD. In 4.4BSD the |
|
|
* kernel does the initial terminal setup. |
|
|
*/ |
|
|
# if defined(USE_TERMIO) && !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) |
|
|
# ifndef OXTABS |
|
|
# define OXTABS 0 |
|
|
# endif |
|
|
termbuf.c_lflag |= ECHO; |
|
|
termbuf.c_oflag |= ONLCR|OXTABS; |
|
|
termbuf.c_iflag |= ICRNL; |
|
|
termbuf.c_iflag &= ~IXOFF; |
|
|
# endif /* defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43) */ |
|
|
tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600); |
|
|
tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600); |
|
|
# ifdef LINEMODE |
|
|
if (waslm) |
|
|
tty_setlinemode(1); |
|
|
# endif /* LINEMODE */ |
|
|
|
|
|
/* |
|
|
* Set the tty modes, and make this our controlling tty. |
|
|
*/ |
|
|
set_termbuf(); |
|
|
if (login_tty(t) == -1) |
|
|
fatalperror(net, "login_tty"); |
|
|
#endif /* !defined(CRAY) || !defined(NEWINIT) */ |
|
|
if (net > 2) |
|
|
(void) close(net); |
|
|
#if defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) |
|
|
/* |
|
|
* Leave the pty open so that we can write out the rlogin |
|
|
* protocol for /bin/login, if the authentication works. |
|
|
*/ |
|
|
#else |
|
|
if (pty > 2) { |
|
|
(void) close(pty); |
|
|
pty = -1; |
|
|
} |
|
|
#endif |
|
|
} |
|
|
|
|
|
#if !defined(CRAY) || !defined(NEWINIT) |
|
|
#ifndef O_NOCTTY |
|
|
#define O_NOCTTY 0 |
|
|
#endif |
|
|
/* |
|
|
* Open the specified slave side of the pty, |
|
|
* making sure that we have a clean tty. |
|
|
*/ |
|
|
int |
|
|
cleanopen(char *line) |
|
|
{ |
|
|
register int t; |
|
|
#ifdef UNICOS7x |
|
|
struct secstat secbuf; |
|
|
#endif /* UNICOS7x */ |
|
|
|
|
|
#ifndef HAVE_STREAMSPTY |
|
|
/* |
|
|
* Make sure that other people can't open the |
|
|
* slave side of the connection. |
|
|
*/ |
|
|
(void) chown(line, 0, 0); |
|
|
(void) chmod(line, 0600); |
|
|
#endif |
|
|
|
|
|
# if !defined(CRAY) && (BSD > 43) |
|
|
(void) revoke(line); |
|
|
# endif |
|
|
#ifdef UNICOS7x |
|
|
if (secflag) { |
|
|
if (secstat(line, &secbuf) < 0) |
|
|
return(-1); |
|
|
if (setulvl(secbuf.st_slevel) < 0) |
|
|
return(-1); |
|
|
if (setucmp(secbuf.st_compart) < 0) |
|
|
return(-1); |
|
|
} |
|
|
#endif /* UNICOS7x */ |
|
|
|
|
|
t = open(line, O_RDWR|O_NOCTTY); |
|
|
|
|
|
#ifdef UNICOS7x |
|
|
if (secflag) { |
|
|
if (setulvl(sysv.sy_minlvl) < 0) |
|
|
return(-1); |
|
|
if (setucmp(0) < 0) |
|
|
return(-1); |
|
|
} |
|
|
#endif /* UNICOS7x */ |
|
|
|
|
|
if (t < 0) |
|
|
return(-1); |
|
|
|
|
|
/* |
|
|
* Hangup anybody else using this ttyp, then reopen it for |
|
|
* ourselves. |
|
|
*/ |
|
|
# if !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(HAVE_STREAMSPTY) |
|
|
(void) signal(SIGHUP, SIG_IGN); |
|
|
vhangup(); |
|
|
(void) signal(SIGHUP, SIG_DFL); |
|
|
t = open(line, O_RDWR|O_NOCTTY); |
|
|
if (t < 0) |
|
|
return(-1); |
|
|
# endif |
|
|
# if defined(CRAY) && defined(TCVHUP) |
|
|
{ |
|
|
register int i; |
|
|
(void) signal(SIGHUP, SIG_IGN); |
|
|
(void) ioctl(t, TCVHUP, (char *)0); |
|
|
(void) signal(SIGHUP, SIG_DFL); |
|
|
|
|
|
#ifdef UNICOS7x |
|
|
if (secflag) { |
|
|
if (secstat(line, &secbuf) < 0) |
|
|
return(-1); |
|
|
if (setulvl(secbuf.st_slevel) < 0) |
|
|
return(-1); |
|
|
if (setucmp(secbuf.st_compart) < 0) |
|
|
return(-1); |
|
|
} |
|
|
#endif /* UNICOS7x */ |
|
|
|
|
|
i = open(line, O_RDWR); |
|
|
|
|
|
#ifdef UNICOS7x |
|
|
if (secflag) { |
|
|
if (setulvl(sysv.sy_minlvl) < 0) |
|
|
return(-1); |
|
|
if (setucmp(0) < 0) |
|
|
return(-1); |
|
|
} |
|
|
#endif /* UNICOS7x */ |
|
|
|
|
|
if (i < 0) |
|
|
return(-1); |
|
|
(void) close(t); |
|
|
t = i; |
|
|
} |
|
|
# endif /* defined(CRAY) && defined(TCVHUP) */ |
|
|
return(t); |
|
|
} |
|
|
#endif /* !defined(CRAY) || !defined(NEWINIT) */ |
|
|
|
|
|
#if BSD <= 43 |
|
|
|
|
827 |
int |
int |
828 |
login_tty(int t) |
tty_isnewmap () |
829 |
{ |
{ |
830 |
if (setsid() < 0) { |
return (termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) && |
831 |
#ifdef ultrix |
!(termbuf.c_oflag & ONLRET); |
|
/* |
|
|
* The setsid() may have failed because we |
|
|
* already have a pgrp == pid. Zero out |
|
|
* our pgrp and try again... |
|
|
*/ |
|
|
if ((setpgrp(0, 0) < 0) || (setsid() < 0)) |
|
|
#endif |
|
|
fatalperror(net, "setsid()"); |
|
|
} |
|
|
# ifdef TIOCSCTTY |
|
|
if (ioctl(t, TIOCSCTTY, (char *)0) < 0) |
|
|
fatalperror(net, "ioctl(sctty)"); |
|
|
# if defined(CRAY) |
|
|
/* |
|
|
* Close the hard fd to /dev/ttypXXX, and re-open through |
|
|
* the indirect /dev/tty interface. |
|
|
*/ |
|
|
close(t); |
|
|
if ((t = open("/dev/tty", O_RDWR)) < 0) |
|
|
fatalperror(net, "open(/dev/tty)"); |
|
|
# endif |
|
|
# else |
|
|
/* |
|
|
* We get our controlling tty assigned as a side-effect |
|
|
* of opening up a tty device. But on BSD based systems, |
|
|
* this only happens if our process group is zero. The |
|
|
* setsid() call above may have set our pgrp, so clear |
|
|
* it out before opening the tty... |
|
|
*/ |
|
|
setpgid (0, 0); |
|
|
|
|
|
close(open(line, O_RDWR)); |
|
|
# endif |
|
|
if (t != 0) |
|
|
(void) dup2(t, 0); |
|
|
if (t != 1) |
|
|
(void) dup2(t, 1); |
|
|
if (t != 2) |
|
|
(void) dup2(t, 2); |
|
|
if (t > 2) |
|
|
close(t); |
|
|
return(0); |
|
832 |
} |
} |
|
#endif /* BSD <= 43 */ |
|
|
|
|
|
#ifdef NEWINIT |
|
|
char *gen_id = "fe"; |
|
833 |
#endif |
#endif |
834 |
|
|
|
/* |
|
|
* startslave(host) |
|
|
* |
|
|
* Given a hostname, do whatever |
|
|
* is necessary to startup the login process on the slave side of the pty. |
|
|
*/ |
|
|
|
|
|
/* ARGSUSED */ |
|
|
void |
|
|
startslave(char *host, int autologin, char *autoname) |
|
|
{ |
|
|
register int i; |
|
|
char name[256]; |
|
|
#ifdef NEWINIT |
|
|
extern char *ptyip; |
|
|
struct init_request request; |
|
|
void nologinproc(); |
|
|
register int n; |
|
|
#endif /* NEWINIT */ |
|
|
|
|
|
#if defined(AUTHENTICATION) |
|
|
if (!autoname || !autoname[0]) |
|
|
autologin = 0; |
|
|
|
|
|
if (autologin < auth_level) { |
|
|
fatal(net, "Authorization failed"); |
|
|
exit(1); |
|
|
} |
|
|
#endif |
|
|
|
|
|
#ifndef NEWINIT |
|
|
# ifdef PARENT_DOES_UTMP |
|
|
utmp_sig_init(); |
|
|
# endif /* PARENT_DOES_UTMP */ |
|
|
|
|
|
if ((i = fork()) < 0) |
|
|
fatalperror(net, "fork"); |
|
|
if (i) { |
|
|
# ifdef PARENT_DOES_UTMP |
|
|
/* |
|
|
* Cray parent will create utmp entry for child and send |
|
|
* signal to child to tell when done. Child waits for signal |
|
|
* before doing anything important. |
|
|
*/ |
|
|
register int pid = i; |
|
|
void sigjob P((int)); |
|
|
|
|
|
setpgrp(); |
|
|
utmp_sig_reset(); /* reset handler to default */ |
|
|
/* |
|
|
* Create utmp entry for child |
|
|
*/ |
|
|
(void) time(&wtmp.ut_time); |
|
|
wtmp.ut_type = LOGIN_PROCESS; |
|
|
wtmp.ut_pid = pid; |
|
|
SCPYN(wtmp.ut_user, "LOGIN"); |
|
|
SCPYN(wtmp.ut_host, host); |
|
|
SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1); |
|
|
#ifndef __hpux |
|
|
SCPYN(wtmp.ut_id, wtmp.ut_line+3); |
|
|
#else |
|
|
SCPYN(wtmp.ut_id, wtmp.ut_line+7); |
|
|
#endif |
|
|
pututline(&wtmp); |
|
|
endutent(); |
|
|
if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) { |
|
|
(void) write(i, (char *)&wtmp, sizeof(struct utmp)); |
|
|
(void) close(i); |
|
|
} |
|
|
#ifdef CRAY |
|
|
(void) signal(WJSIGNAL, sigjob); |
|
|
#endif |
|
|
utmp_sig_notify(pid); |
|
|
# endif /* PARENT_DOES_UTMP */ |
|
|
} else { |
|
|
getptyslave(autologin); |
|
|
start_login(host, autologin, autoname); |
|
|
/*NOTREACHED*/ |
|
|
} |
|
|
#else /* NEWINIT */ |
|
|
|
|
|
/* |
|
|
* Init will start up login process if we ask nicely. We only wait |
|
|
* for it to start up and begin normal telnet operation. |
|
|
*/ |
|
|
if ((i = open(INIT_FIFO, O_WRONLY)) < 0) { |
|
|
char tbuf[128]; |
|
|
(void) sprintf(tbuf, "Can't open %s\n", INIT_FIFO); |
|
|
fatalperror(net, tbuf); |
|
|
} |
|
|
memset((char *)&request, 0, sizeof(request)); |
|
|
request.magic = INIT_MAGIC; |
|
|
SCPYN(request.gen_id, gen_id); |
|
|
SCPYN(request.tty_id, &line[8]); |
|
|
SCPYN(request.host, host); |
|
|
SCPYN(request.term_type, terminaltype ? terminaltype : "network"); |
|
|
#if !defined(UNICOS5) |
|
|
request.signal = SIGCLD; |
|
|
request.pid = getpid(); |
|
|
#endif |
|
|
#ifdef BFTPDAEMON |
|
|
/* |
|
|
* Are we working as the bftp daemon? |
|
|
*/ |
|
|
if (bftpd) { |
|
|
SCPYN(request.exec_name, BFTPPATH); |
|
|
} |
|
|
#endif /* BFTPDAEMON */ |
|
|
if (write(i, (char *)&request, sizeof(request)) < 0) { |
|
|
char tbuf[128]; |
|
|
(void) sprintf(tbuf, "Can't write to %s\n", INIT_FIFO); |
|
|
fatalperror(net, tbuf); |
|
|
} |
|
|
(void) close(i); |
|
|
(void) signal(SIGALRM, nologinproc); |
|
|
for (i = 0; ; i++) { |
|
|
char tbuf[128]; |
|
|
alarm(15); |
|
|
n = read(pty, ptyip, BUFSIZ); |
|
|
if (i == 3 || n >= 0 || !gotalarm) |
|
|
break; |
|
|
gotalarm = 0; |
|
|
snprintf (tbuf, sizeof tbuf, |
|
|
"telnetd: waiting for /etc/init to start login process on %s\r\n", |
|
|
line); |
|
|
(void) write(net, tbuf, strlen(tbuf)); |
|
|
} |
|
|
if (n < 0 && gotalarm) |
|
|
fatal(net, "/etc/init didn't start login process"); |
|
|
pcc += n; |
|
|
alarm(0); |
|
|
(void) signal(SIGALRM, SIG_DFL); |
|
|
|
|
|
return; |
|
|
#endif /* NEWINIT */ |
|
|
} |
|
|
|
|
835 |
char *envinit[3]; |
char *envinit[3]; |
836 |
extern char **environ; |
extern char **environ; |
837 |
|
|
852 |
environ = envinit; |
environ = envinit; |
853 |
} |
} |
854 |
|
|
|
#ifndef NEWINIT |
|
|
|
|
|
/* Security fix included in telnet-95.10.23.NE of David Borman <deb@cray.com>. |
|
|
*/ |
|
|
/* |
|
|
* scrub_env() |
|
|
* |
|
|
* Remove a few things from the environment that |
|
|
* don't need to be there. |
|
|
*/ |
|
|
static void |
|
|
scrub_env() |
|
|
{ |
|
|
register char **cpp, **cpp2; |
|
|
|
|
|
for (cpp2 = cpp = environ; *cpp; cpp++) { |
|
|
if (strncmp(*cpp, "LD_", 3) && |
|
|
strncmp(*cpp, "_RLD_", 5) && |
|
|
strncmp(*cpp, "LIBPATH=", 8) && |
|
|
strncmp(*cpp, "IFS=", 4)) |
|
|
*cpp2++ = *cpp; |
|
|
} |
|
|
*cpp2 = 0; |
|
|
} |
|
|
|
|
|
/* |
|
|
* start_login(host) |
|
|
* |
|
|
* Assuming that we are now running as a child processes, this |
|
|
* function will turn us into the login process. |
|
|
*/ |
|
|
|
|
|
void |
|
|
start_login(char *host, int autologin, char *name) |
|
|
{ |
|
|
register char *cp; |
|
|
register char **argv; |
|
|
char **addarg(); |
|
|
extern char *getenv(); |
|
|
#ifdef HAVE_UTMPX_H |
|
|
register int pid = getpid(); |
|
|
struct utmpx utmpx; |
|
|
#endif |
|
|
#ifdef SOLARIS |
|
|
char *term; |
|
|
char termbuf[64]; |
|
|
#endif |
|
|
|
|
|
#ifdef UTMPX |
|
|
/* |
|
|
* Create utmp entry for child |
|
|
*/ |
|
|
|
|
|
memset(&utmpx, 0, sizeof(utmpx)); |
|
|
SCPYN(utmpx.ut_user, ".telnet"); |
|
|
SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1); |
|
|
utmpx.ut_pid = pid; |
|
|
utmpx.ut_id[0] = 't'; |
|
|
utmpx.ut_id[1] = 'n'; |
|
|
#define SC_WILDC 'e' |
|
|
utmpx.ut_id[2] = SC_WILDC; |
|
|
utmpx.ut_id[3] = SC_WILDC; |
|
|
utmpx.ut_type = LOGIN_PROCESS; |
|
|
(void) time(&utmpx.ut_tv.tv_sec); |
|
|
if (pututxline(&utmpx) == NULL) |
|
|
fatal(net, "pututxline failed"); |
|
|
#endif |
|
|
|
|
|
scrub_env(); |
|
|
|
|
|
/* |
|
|
* -h : pass on name of host. |
|
|
* WARNING: -h is accepted by login if and only if |
|
|
* getuid() == 0. |
|
|
* -p : don't clobber the environment (so terminal type stays set). |
|
|
* |
|
|
* -f : force this login, he has already been authenticated |
|
|
*/ |
|
|
argv = addarg(0, "login"); |
|
|
|
|
|
#if !defined(NO_LOGIN_H) |
|
|
|
|
|
# if defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) |
|
|
/* |
|
|
* Don't add the "-h host" option if we are going |
|
|
* to be adding the "-r host" option down below... |
|
|
*/ |
|
|
if ((auth_level < 0) || (autologin != AUTH_VALID)) |
|
|
# endif |
|
|
{ |
|
|
argv = addarg(argv, "-h"); |
|
|
argv = addarg(argv, host); |
|
|
#ifdef SOLARIS |
|
|
/* |
|
|
* SVR4 version of -h takes TERM= as second arg, or - |
|
|
*/ |
|
|
term = getenv("TERM"); |
|
|
if (term == NULL || term[0] == 0) { |
|
|
term = "-"; |
|
|
} else { |
|
|
strcpy(termbuf, "TERM="); |
|
|
strncat(termbuf, term, sizeof(termbuf) - 6); |
|
|
term = termbuf; |
|
|
} |
|
|
argv = addarg(argv, term); |
|
|
#endif |
|
|
} |
|
|
#endif |
|
|
#if !defined(NO_LOGIN_P) |
|
|
argv = addarg(argv, "-p"); |
|
|
#endif |
|
|
#ifdef LINEMODE |
|
|
/* |
|
|
* Set the environment variable "LINEMODE" to either |
|
|
* "real" or "kludge" if we are operating in either |
|
|
* real or kludge linemode. |
|
|
*/ |
|
|
if (lmodetype == REAL_LINEMODE) |
|
|
setenv("LINEMODE", "real", 1); |
|
|
# ifdef KLUDGELINEMODE |
|
|
else if (lmodetype == KLUDGE_LINEMODE || lmodetype == KLUDGE_OK) |
|
|
setenv("LINEMODE", "kludge", 1); |
|
|
# endif |
|
|
#endif |
|
|
#ifdef BFTPDAEMON |
|
|
/* |
|
|
* Are we working as the bftp daemon? If so, then ask login |
|
|
* to start bftp instead of shell. |
|
|
*/ |
|
|
if (bftpd) { |
|
|
argv = addarg(argv, "-e"); |
|
|
argv = addarg(argv, BFTPPATH); |
|
|
} else |
|
|
#endif |
|
|
#if defined (SecurID) |
|
|
/* |
|
|
* don't worry about the -f that might get sent. |
|
|
* A -s is supposed to override it anyhow. |
|
|
*/ |
|
|
if (require_SecurID) |
|
|
argv = addarg(argv, "-s"); |
|
|
#endif |
|
|
#if defined (AUTHENTICATION) |
|
|
if (auth_level >= 0 && autologin == AUTH_VALID) { |
|
|
# if !defined(NO_LOGIN_F) |
|
|
argv = addarg(argv, "-f"); |
|
|
argv = addarg(argv, name); |
|
|
# else |
|
|
# if defined(LOGIN_R) |
|
|
/* |
|
|
* We don't have support for "login -f", but we |
|
|
* can fool /bin/login into thinking that we are |
|
|
* rlogind, and allow us to log in without a |
|
|
* password. The rlogin protocol expects |
|
|
* local-user\0remote-user\0term/speed\0 |
|
|
*/ |
|
|
|
|
|
if (pty > 2) { |
|
|
register char *cp; |
|
|
char speed[128]; |
|
|
int isecho, israw, xpty, len; |
|
|
extern int def_rspeed; |
|
|
# ifndef LOGIN_HOST |
|
|
/* |
|
|
* Tell login that we are coming from "localhost". |
|
|
* If we passed in the real host name, then the |
|
|
* user would have to allow .rhost access from |
|
|
* every machine that they want authenticated |
|
|
* access to work from, which sort of defeats |
|
|
* the purpose of an authenticated login... |
|
|
* So, we tell login that the session is coming |
|
|
* from "localhost", and the user will only have |
|
|
* to have "localhost" in their .rhost file. |
|
|
*/ |
|
|
# define LOGIN_HOST "localhost" |
|
|
# endif |
|
|
argv = addarg(argv, "-r"); |
|
|
argv = addarg(argv, LOGIN_HOST); |
|
|
|
|
|
xpty = pty; |
|
|
# ifndef HAVE_STREAMSPTY |
|
|
pty = 0; |
|
|
# else |
|
|
ttyfd = 0; |
|
|
# endif |
|
|
init_termbuf(); |
|
|
isecho = tty_isecho(); |
|
|
israw = tty_israw(); |
|
|
if (isecho || !israw) { |
|
|
tty_setecho(0); /* Turn off echo */ |
|
|
tty_setraw(1); /* Turn on raw */ |
|
|
set_termbuf(); |
|
|
} |
|
|
len = strlen(name)+1; |
|
|
write(xpty, name, len); |
|
|
write(xpty, name, len); |
|
|
snprintf (speed, sizeof speed, |
|
|
"%s/%d", (cp = getenv("TERM")) ? cp : "", |
|
|
(def_rspeed > 0) ? def_rspeed : 9600); |
|
|
len = strlen(speed)+1; |
|
|
write(xpty, speed, len); |
|
|
|
|
|
if (isecho || !israw) { |
|
|
init_termbuf(); |
|
|
tty_setecho(isecho); |
|
|
tty_setraw(israw); |
|
|
set_termbuf(); |
|
|
if (!israw) { |
|
|
/* |
|
|
* Write a newline to ensure |
|
|
* that login will be able to |
|
|
* read the line... |
|
|
*/ |
|
|
write(xpty, "\n", 1); |
|
|
} |
|
|
} |
|
|
pty = xpty; |
|
|
} |
|
|
# else |
|
|
argv = addarg(argv, name); |
|
|
# endif |
|
|
# endif |
|
|
} else |
|
|
#endif |
|
|
if (getenv("USER")) { |
|
|
argv = addarg(argv, getenv("USER")); |
|
|
#if defined(LOGIN_ARGS) && defined(NO_LOGIN_P) |
|
|
{ |
|
|
register char **cpp; |
|
|
for (cpp = environ; *cpp; cpp++) |
|
|
argv = addarg(argv, *cpp); |
|
|
} |
|
|
#endif |
|
|
/* |
|
|
* Assume that login will set the USER variable |
|
|
* correctly. For SysV systems, this means that |
|
|
* USER will no longer be set, just LOGNAME by |
|
|
* login. (The problem is that if the auto-login |
|
|
* fails, and the user then specifies a different |
|
|
* account name, he can get logged in with both |
|
|
* LOGNAME and USER in his environment, but the |
|
|
* USER value will be wrong. |
|
|
*/ |
|
|
unsetenv("USER"); |
|
|
} |
|
|
#ifdef SOLARIS |
|
|
else { |
|
|
char **p; |
|
|
|
|
|
argv = addarg(argv, ""); /* no login name */ |
|
|
for (p = environ; *p; p++) { |
|
|
argv = addarg(argv, *p); |
|
|
} |
|
|
} |
|
|
#endif /* SOLARIS */ |
|
|
#if defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) |
|
|
if (pty > 2) |
|
|
close(pty); |
|
|
#endif |
|
|
closelog(); |
|
|
/* |
|
|
* This sleep(1) is in here so that telnetd can |
|
|
* finish up with the tty. There's a race condition |
|
|
* the login banner message gets lost... |
|
|
*/ |
|
|
sleep(1); |
|
|
execv(PATH_LOGIN, argv); |
|
|
|
|
|
syslog(LOG_ERR, "%s: %m\n", PATH_LOGIN); |
|
|
fatalperror(net, PATH_LOGIN); |
|
|
/*NOTREACHED*/ |
|
|
} |
|
|
|
|
|
char ** |
|
|
addarg(register char **argv, register char *val) |
|
|
{ |
|
|
register char **cpp; |
|
|
|
|
|
if (argv == NULL) { |
|
|
/* |
|
|
* 10 entries, a leading length, and a null |
|
|
*/ |
|
|
argv = (char **)malloc(sizeof(*argv) * 12); |
|
|
if (argv == NULL) |
|
|
return(NULL); |
|
|
*argv++ = (char *)10; |
|
|
*argv = (char *)0; |
|
|
} |
|
|
for (cpp = argv; *cpp; cpp++) |
|
|
; |
|
|
if (cpp == &argv[(long)argv[-1]]) { |
|
|
--argv; |
|
|
*argv = (char *)((long)(*argv) + 10); |
|
|
argv = (char **)realloc(argv, sizeof(*argv)*((long)(*argv) + 2)); |
|
|
if (argv == NULL) |
|
|
return(NULL); |
|
|
argv++; |
|
|
cpp = &argv[(long)argv[-1] - 10]; |
|
|
} |
|
|
*cpp++ = val; |
|
|
*cpp = 0; |
|
|
return(argv); |
|
|
} |
|
|
#endif /* NEWINIT */ |
|
|
|
|
|
/* |
|
|
* cleanup() |
|
|
* |
|
|
* This is the routine to call when we are all through, to |
|
|
* clean up anything that needs to be cleaned up. |
|
|
*/ |
|
|
/* ARGSUSED */ |
|
|
void |
|
|
cleanup(int sig) |
|
|
{ |
|
|
#ifndef PARENT_DOES_UTMP |
|
|
# if (BSD > 43) || defined(convex) |
|
|
char *p; |
|
|
|
|
|
p = line + sizeof("/dev/") - 1; |
|
|
if (logout(p)) |
|
|
logwtmp(p, "", ""); |
|
|
(void)chmod(line, 0666); |
|
|
(void)chown(line, 0, 0); |
|
|
*p = 'p'; |
|
|
(void)chmod(line, 0666); |
|
|
(void)chown(line, 0, 0); |
|
|
(void) shutdown(net, 2); |
|
|
exit(1); |
|
|
# else |
|
|
void rmut(); |
|
|
|
|
|
rmut(); |
|
|
vhangup(); /* XXX */ |
|
|
(void) shutdown(net, 2); |
|
|
exit(1); |
|
|
# endif |
|
|
#else /* PARENT_DOES_UTMP */ |
|
|
# ifdef NEWINIT |
|
|
(void) shutdown(net, 2); |
|
|
exit(1); |
|
|
# else /* NEWINIT */ |
|
|
# ifdef CRAY |
|
|
static int incleanup = 0; |
|
|
register int t; |
|
|
int child_status; /* status of child process as returned by waitpid */ |
|
|
int flags = WNOHANG|WUNTRACED; |
|
|
|
|
|
/* |
|
|
* 1: Pick up the zombie, if we are being called |
|
|
* as the signal handler. |
|
|
* 2: If we are a nested cleanup(), return. |
|
|
* 3: Try to clean up TMPDIR. |
|
|
* 4: Fill in utmp with shutdown of process. |
|
|
* 5: Close down the network and pty connections. |
|
|
* 6: Finish up the TMPDIR cleanup, if needed. |
|
|
*/ |
|
|
if (sig == SIGCHLD) { |
|
|
while (waitpid(-1, &child_status, flags) > 0) |
|
|
; /* VOID */ |
|
|
/* Check if the child process was stopped |
|
|
* rather than exited. We want cleanup only if |
|
|
* the child has died. |
|
|
*/ |
|
|
if (WIFSTOPPED(child_status)) { |
|
|
return; |
|
|
} |
|
|
} |
|
|
t = sigblock(sigmask(SIGCHLD)); |
|
|
if (incleanup) { |
|
|
sigsetmask(t); |
|
|
return; |
|
|
} |
|
|
incleanup = 1; |
|
|
sigsetmask(t); |
|
|
#ifdef UNICOS7x |
|
|
if (secflag) { |
|
|
/* |
|
|
* We need to set ourselves back to a null |
|
|
* label to clean up. |
|
|
*/ |
|
|
|
|
|
setulvl(sysv.sy_minlvl); |
|
|
setucmp((long)0); |
|
|
} |
|
|
#endif /* UNICOS7x */ |
|
|
|
|
|
t = cleantmp(&wtmp); |
|
|
setutent(); /* just to make sure */ |
|
|
# endif /* CRAY */ |
|
|
rmut(line); |
|
|
close(pty); |
|
|
(void) shutdown(net, 2); |
|
|
# ifdef CRAY |
|
|
if (t == 0) |
|
|
cleantmp(&wtmp); |
|
|
# endif /* CRAY */ |
|
|
exit(1); |
|
|
# endif /* NEWINT */ |
|
|
#endif /* PARENT_DOES_UTMP */ |
|
|
} |
|
|
|
|
|
#if defined(PARENT_DOES_UTMP) && !defined(NEWINIT) |
|
|
/* |
|
|
* _utmp_sig_rcv |
|
|
* utmp_sig_init |
|
|
* utmp_sig_wait |
|
|
* These three functions are used to coordinate the handling of |
|
|
* the utmp file between the server and the soon-to-be-login shell. |
|
|
* The server actually creates the utmp structure, the child calls |
|
|
* utmp_sig_wait(), until the server calls utmp_sig_notify() and |
|
|
* signals the future-login shell to proceed. |
|
|
*/ |
|
|
static int caught=0; /* NZ when signal intercepted */ |
|
|
static void (*func)(); /* address of previous handler */ |
|
|
|
|
|
void |
|
|
_utmp_sig_rcv(int sig) |
|
|
{ |
|
|
caught = 1; |
|
|
(void) signal(SIGUSR1, func); |
|
|
} |
|
|
|
|
|
void |
|
|
utmp_sig_init() |
|
|
{ |
|
|
/* |
|
|
* register signal handler for UTMP creation |
|
|
*/ |
|
|
if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1) |
|
|
fatalperror(net, "telnetd/signal"); |
|
|
} |
|
|
|
|
|
void |
|
|
utmp_sig_reset() |
|
|
{ |
|
|
(void) signal(SIGUSR1, func); /* reset handler to default */ |
|
|
} |
|
855 |
|
|
|
# ifdef __hpux |
|
|
# define sigoff() /* do nothing */ |
|
|
# define sigon() /* do nothing */ |
|
|
# endif |
|
|
|
|
|
void |
|
|
utmp_sig_wait() |
|
|
{ |
|
|
/* |
|
|
* Wait for parent to write our utmp entry. |
|
|
*/ |
|
|
sigoff(); |
|
|
while (caught == 0) { |
|
|
pause(); /* wait until we get a signal (sigon) */ |
|
|
sigoff(); /* turn off signals while we check caught */ |
|
|
} |
|
|
sigon(); /* turn on signals again */ |
|
|
} |
|
|
|
|
|
void |
|
|
utmp_sig_notify(int pid) |
|
|
{ |
|
|
kill(pid, SIGUSR1); |
|
|
} |
|
|
|
|
|
# ifdef CRAY |
|
|
static int gotsigjob = 0; |
|
|
|
|
|
/*ARGSUSED*/ |
|
|
void |
|
|
sigjob(int sig) |
|
|
{ |
|
|
register int jid; |
|
|
register struct jobtemp *jp; |
|
|
|
|
|
while ((jid = waitjob(NULL)) != -1) { |
|
|
if (jid == 0) { |
|
|
return; |
|
|
} |
|
|
gotsigjob++; |
|
|
jobend(jid, NULL, NULL); |
|
|
} |
|
|
} |
|
|
|
|
|
/* |
|
|
* jid_getutid: |
|
|
* called by jobend() before calling cleantmp() |
|
|
* to find the correct $TMPDIR to cleanup. |
|
|
*/ |
|
|
|
|
|
struct utmp * |
|
|
jid_getutid(int jid) |
|
|
{ |
|
|
struct utmp *cur = NULL; |
|
|
|
|
|
setutent(); /* just to make sure */ |
|
|
while (cur = getutent()) { |
|
|
if ( (cur->ut_type != NULL) && (jid == cur->ut_jid) ) { |
|
|
return(cur); |
|
|
} |
|
|
} |
|
|
|
|
|
return(0); |
|
|
} |
|
|
|
|
|
/* |
|
|
* Clean up the TMPDIR that login created. |
|
|
* The first time this is called we pick up the info |
|
|
* from the utmp. If the job has already gone away, |
|
|
* then we'll clean up and be done. If not, then |
|
|
* when this is called the second time it will wait |
|
|
* for the signal that the job is done. |
|
|
*/ |
|
|
int |
|
|
cleantmp(register struct utmp *wtp) |
|
|
{ |
|
|
struct utmp *utp; |
|
|
static int first = 1; |
|
|
register int mask, omask, ret; |
|
|
extern struct utmp *getutid P((const struct utmp *_Id)); |
|
|
|
|
|
|
|
|
mask = sigmask(WJSIGNAL); |
|
|
|
|
|
if (first == 0) { |
|
|
omask = sigblock(mask); |
|
|
while (gotsigjob == 0) |
|
|
sigpause(omask); |
|
|
return(1); |
|
|
} |
|
|
first = 0; |
|
|
setutent(); /* just to make sure */ |
|
|
|
|
|
utp = getutid(wtp); |
|
|
if (utp == 0) { |
|
|
syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR"); |
|
|
return(-1); |
|
|
} |
|
|
/* |
|
|
* Nothing to clean up if the user shell was never started. |
|
|
*/ |
|
|
if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0) |
|
|
return(1); |
|
|
|
|
|
/* |
|
|
* Block the WJSIGNAL while we are in jobend(). |
|
|
*/ |
|
|
omask = sigblock(mask); |
|
|
ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user); |
|
|
sigsetmask(omask); |
|
|
return(ret); |
|
|
} |
|
|
|
|
|
int |
|
|
jobend(register int jid, register char *path, register char *user) |
|
|
{ |
|
|
static int saved_jid = 0; |
|
|
static int pty_saved_jid = 0; |
|
|
static char saved_path[sizeof(wtmp.ut_tpath)+1]; |
|
|
static char saved_user[sizeof(wtmp.ut_user)+1]; |
|
|
|
|
|
/* |
|
|
* this little piece of code comes into play |
|
|
* only when ptyreconnect is used to reconnect |
|
|
* to an previous session. |
|
|
* |
|
|
* this is the only time when the |
|
|
* "saved_jid != jid" code is executed. |
|
|
*/ |
|
|
|
|
|
if ( saved_jid && saved_jid != jid ) { |
|
|
if (!path) { /* called from signal handler */ |
|
|
pty_saved_jid = jid; |
|
|
} else { |
|
|
pty_saved_jid = saved_jid; |
|
|
} |
|
|
} |
|
|
|
|
|
if (path) { |
|
|
strncpy(saved_path, path, sizeof(wtmp.ut_tpath)); |
|
|
strncpy(saved_user, user, sizeof(wtmp.ut_user)); |
|
|
saved_path[sizeof(saved_path)] = '\0'; |
|
|
saved_user[sizeof(saved_user)] = '\0'; |
|
|
} |
|
|
if (saved_jid == 0) { |
|
|
saved_jid = jid; |
|
|
return(0); |
|
|
} |
|
|
|
|
|
/* if the jid has changed, get the correct entry from the utmp file */ |
|
|
|
|
|
if ( saved_jid != jid ) { |
|
|
struct utmp *utp = NULL; |
|
|
struct utmp *jid_getutid(); |
|
|
|
|
|
utp = jid_getutid(pty_saved_jid); |
|
|
|
|
|
if (utp == 0) { |
|
|
syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR"); |
|
|
return(-1); |
|
|
} |
|
|
|
|
|
cleantmpdir(jid, utp->ut_tpath, utp->ut_user); |
|
|
return(1); |
|
|
} |
|
|
|
|
|
cleantmpdir(jid, saved_path, saved_user); |
|
|
return(1); |
|
|
} |
|
|
|
|
|
/* |
|
|
* Fork a child process to clean up the TMPDIR |
|
|
*/ |
|
|
int |
|
|
cleantmpdir(register int jid, register char *tpath, register char *user) |
|
|
{ |
|
|
switch(fork()) { |
|
|
case -1: |
|
|
syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m\n", |
|
|
tpath); |
|
|
break; |
|
|
case 0: |
|
|
execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0); |
|
|
syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m\n", |
|
|
tpath, CLEANTMPCMD); |
|
|
exit(1); |
|
|
default: |
|
|
/* |
|
|
* Forget about child. We will exit, and |
|
|
* /etc/init will pick it up. |
|
|
*/ |
|
|
break; |
|
|
} |
|
|
} |
|
|
# endif /* CRAY */ |
|
|
#endif /* defined(PARENT_DOES_UTMP) && !defined(NEWINIT) */ |
|
|
|
|
|
/* |
|
|
* rmut() |
|
|
* |
|
|
* This is the function called by cleanup() to |
|
|
* remove the utmp entry for this person. |
|
|
*/ |
|
|
|
|
|
#ifdef HAVE_UTMPX_H |
|
|
void |
|
|
rmut() |
|
|
{ |
|
|
register f; |
|
|
int found = 0; |
|
|
//struct utmp *u, *utmp; |
|
|
int nutmp; |
|
|
struct stat statbf; |
|
|
|
|
|
struct utmpx *utxp, utmpx; |
|
|
|
|
|
/* |
|
|
* This updates the utmpx and utmp entries and make a wtmp/x entry |
|
|
*/ |
|
|
|
|
|
SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1); |
|
|
utxp = getutxline(&utmpx); |
|
|
if (utxp) { |
|
|
utxp->ut_type = DEAD_PROCESS; |
|
|
utxp->ut_exit.e_termination = 0; |
|
|
utxp->ut_exit.e_exit = 0; |
|
|
(void) time(&utmpx.ut_tv.tv_sec); |
|
|
utmpx.ut_tv.tv_usec = 0; |
|
|
//modutx(utxp); |
|
|
updwtmpx(PATH_UTMP, utxp); |
|
|
} |
|
|
endutxent(); |
|
|
} /* end of rmut */ |
|
|
#endif |
|
|
|
|
|
#if !defined(HAVE_UTMPX_H) && !(defined(CRAY) || defined(__hpux)) && BSD <= 43 |
|
|
void |
|
|
rmut() |
|
|
{ |
|
|
register f; |
|
|
int found = 0; |
|
|
struct utmp *u, *utmp; |
|
|
int nutmp; |
|
|
struct stat statbf; |
|
|
|
|
|
f = open(utmpf, O_RDWR); |
|
|
if (f >= 0) { |
|
|
(void) fstat(f, &statbf); |
|
|
utmp = (struct utmp *)malloc((unsigned)statbf.st_size); |
|
|
if (!utmp) |
|
|
syslog(LOG_ERR, "utmp malloc failed"); |
|
|
if (statbf.st_size && utmp) { |
|
|
nutmp = read(f, (char *)utmp, (int)statbf.st_size); |
|
|
nutmp /= sizeof(struct utmp); |
|
|
|
|
|
for (u = utmp ; u < &utmp[nutmp] ; u++) { |
|
|
if (SCMPN(u->ut_line, line+5) || |
|
|
u->ut_name[0]==0) |
|
|
continue; |
|
|
(void) lseek(f, ((long)u)-((long)utmp), SEEK_SET); |
|
|
SCPYN(u->ut_name, ""); |
|
|
#ifdef HAVE_UTMP_UT_HOST |
|
|
SCPYN(u->ut_host, ""); |
|
|
#endif |
|
|
(void) time(&u->ut_time); |
|
|
(void) write(f, (char *)u, sizeof(wtmp)); |
|
|
found++; |
|
|
} |
|
|
} |
|
|
(void) close(f); |
|
|
} |
|
|
if (found) { |
|
|
f = open(wtmpf, O_WRONLY|O_APPEND); |
|
|
if (f >= 0) { |
|
|
SCPYN(wtmp.ut_line, line+5); |
|
|
SCPYN(wtmp.ut_name, ""); |
|
|
#ifdef HAVE_UTMP_UT_HOST |
|
|
SCPYN(wtmp.ut_host, ""); |
|
|
#endif |
|
|
#ifdef HAVE_WTMP_UT_TV |
|
|
(void) time(&wtmp.ut_tv.tv_sec); |
|
|
#else |
|
|
(void) time(&wtmp.ut_time); |
|
|
#endif |
|
|
(void) write(f, (char *)&wtmp, sizeof(wtmp)); |
|
|
(void) close(f); |
|
|
} |
|
|
} |
|
|
(void) chmod(line, 0666); |
|
|
(void) chown(line, 0, 0); |
|
|
line[strlen("/dev/")] = 'p'; |
|
|
(void) chmod(line, 0666); |
|
|
(void) chown(line, 0, 0); |
|
|
} /* end of rmut */ |
|
|
#endif /* CRAY */ |
|
|
|
|
|
#ifdef __hpux |
|
|
int |
|
|
rmut (char *line) |
|
|
{ |
|
|
struct utmp utmp; |
|
|
struct utmp *utptr; |
|
|
int fd; /* for /etc/wtmp */ |
|
|
|
|
|
utmp.ut_type = USER_PROCESS; |
|
|
(void) strncpy(utmp.ut_id, line+12, sizeof(utmp.ut_id)); |
|
|
(void) setutent(); |
|
|
utptr = getutid(&utmp); |
|
|
/* write it out only if it exists */ |
|
|
if (utptr) { |
|
|
utptr->ut_type = DEAD_PROCESS; |
|
|
utptr->ut_time = time((long *) 0); |
|
|
(void) pututline(utptr); |
|
|
/* set wtmp entry if wtmp file exists */ |
|
|
if ((fd = open(wtmpf, O_WRONLY | O_APPEND)) >= 0) { |
|
|
(void) write(fd, utptr, sizeof(utmp)); |
|
|
(void) close(fd); |
|
|
} |
|
|
} |
|
|
(void) endutent(); |
|
|
|
|
|
(void) chmod(line, 0666); |
|
|
(void) chown(line, 0, 0); |
|
|
line[14] = line[13]; |
|
|
line[13] = line[12]; |
|
|
line[8] = 'm'; |
|
|
line[9] = '/'; |
|
|
line[10] = 'p'; |
|
|
line[11] = 't'; |
|
|
line[12] = 'y'; |
|
|
(void) chmod(line, 0666); |
|
|
(void) chown(line, 0, 0); |
|
|
} |
|
|
#endif |
|