Commit | Line | Data |
---|---|---|
9319b3c3 C |
1 | /* vtd.c - VT responder */ |
2 | ||
3 | #ifndef lint | |
4 | static char *rcsid = "$Header: /f/osi/vt/RCS/vtd.c,v 7.3 91/02/22 09:48:28 mrose Interim $"; | |
5 | #endif | |
6 | ||
7 | /* | |
8 | * $Header: /f/osi/vt/RCS/vtd.c,v 7.3 91/02/22 09:48:28 mrose Interim $ | |
9 | * | |
10 | * | |
11 | * $Log: vtd.c,v $ | |
12 | * Revision 7.3 91/02/22 09:48:28 mrose | |
13 | * Interim 6.8 | |
14 | * | |
15 | * Revision 7.2 90/07/09 14:52:06 mrose | |
16 | * sync | |
17 | * | |
18 | * Revision 7.1 89/11/30 23:51:42 mrose | |
19 | * pa2str | |
20 | * | |
21 | * Revision 7.0 89/11/23 22:31:55 mrose | |
22 | * Release 6.0 | |
23 | * | |
24 | */ | |
25 | ||
26 | /* | |
27 | * NOTICE | |
28 | * | |
29 | * Acquisition, use, and distribution of this module and related | |
30 | * materials are subject to the restrictions of a license agreement. | |
31 | * Consult the Preface in the User's Manual for the full terms of | |
32 | * this agreement. | |
33 | * | |
34 | */ | |
35 | ||
36 | ||
37 | #undef MAP_BACKSPACE /*Map backspace character to VT ERASE CHAR*/ | |
38 | ||
39 | #include <signal.h> | |
40 | #include "vtpm.h" | |
41 | #include "sector1.h" | |
42 | #include "tailor.h" | |
43 | #include <sys/ioctl.h> | |
44 | #ifdef BSD44 | |
45 | #include <sys/termios.h> | |
46 | #include <sys/ttydefaults.h> | |
47 | #endif | |
48 | ||
49 | #ifndef _PATH_LOGIN | |
50 | #ifndef BSD44 | |
51 | #define _PATH_LOGIN "/bin/login" | |
52 | #else | |
53 | #define _PATH_LOGIN "/usr/bin/login" | |
54 | #endif | |
55 | #endif | |
56 | ||
57 | #include <arpa/telnet.h> | |
58 | ||
59 | #include <ctype.h> | |
60 | #include <setjmp.h> | |
61 | #include <pwd.h> | |
62 | #include <varargs.h> | |
63 | ||
64 | #define BELL '\07' | |
65 | #ifndef SUNOS4 | |
66 | #define BANNER "\r\n\r\n4.2 BSD UNIX (%s)\r\n\r\n\r%s" | |
67 | #else | |
68 | #define BANNER "\r\n\r\nSunOS UNIX (%s)\r\n\r\n\r%s" | |
69 | #endif | |
70 | ||
71 | int connected = FALSE; | |
72 | char command[256]; | |
73 | ||
74 | ||
75 | /* | |
76 | * I/O data buffers, pointers, and counters. | |
77 | */ | |
78 | char ptyobuf[BUFSIZ], *pfrontp = ptyobuf, *pbackp = ptyobuf; | |
79 | char netobuf[BUFSIZ], *nfrontp = netobuf, *nbackp = netobuf; | |
80 | int pcc; | |
81 | ||
82 | VT_PROFILE vtp_profile; | |
83 | int rflag = 0; | |
84 | char erase_char; | |
85 | char erase_line; | |
86 | char intr_char; | |
87 | char *crp = "\r"; | |
88 | char *my_displayobj = "D"; /*Acceptor's Display Object Name*/ | |
89 | char *my_echo_obj = "NA"; /*Acceptor's Negotiation Control Object Name*/ | |
90 | char *my_signal_obj = "DI"; /*Acceptor's Signal Control Object*/ | |
91 | char *his_echo_obj = "NI"; /*Initiator's Negotiation Control Object*/ | |
92 | char *his_signal_obj = "KB"; /*Initiator/s Signal control Object*/ | |
93 | int my_right = ACCEPTOR; | |
94 | char kb_image; /*KB Control Object image*/ | |
95 | char di_image; /*DI Control Object Image*/ | |
96 | char ni_image; /*NI Control Object image*/ | |
97 | char na_image; /*NA Control Object image*/ | |
98 | char nego_state; /*Current state of NA affected options*/ | |
99 | char sync_image; /*SY Control Object image*/ | |
100 | char ga_image; | |
101 | int transparent = 0; /*Flag for Transparent repertoire*/ | |
102 | int telnet_profile =1; | |
103 | int do_break = 1; /*If VT-BREAK agreed to*/ | |
104 | int showoptions = 0; | |
105 | int debug = 0; | |
106 | ||
107 | #ifdef BSD44 | |
108 | struct termios oterm; | |
109 | #else | |
110 | struct tchars otc; | |
111 | struct ltchars oltc; | |
112 | struct sgttyb ottyb; | |
113 | #endif | |
114 | char *myhostname; | |
115 | char peerhost[BUFSIZ]; | |
116 | struct PSAPaddr ts_bound; | |
117 | struct passwd *pwd; | |
118 | ||
119 | int pty, net; | |
120 | int inter; | |
121 | extern char **environ; | |
122 | extern int errno; | |
123 | char line[] = "/dev/ptyp0"; | |
124 | char *envinit[] = { "TERM=network", 0 }; | |
125 | SFD cleanup(); | |
126 | static int do_cleaning = 0; | |
127 | ||
128 | char *myname; | |
129 | LLog _vt_log = { | |
130 | "vt.log", NULLCP, NULLCP, | |
131 | LLOG_FATAL | LLOG_EXCEPTIONS | LLOG_NOTICE, LLOG_FATAL, -1, | |
132 | LLOGCLS | LLOGCRT | LLOGZER, NOTOK | |
133 | ||
134 | }; | |
135 | LLog *vt_log = &_vt_log; | |
136 | ||
137 | main(argc, argv) | |
138 | int argc; | |
139 | char *argv[]; | |
140 | { | |
141 | int f = 0; | |
142 | char *cp = line; | |
143 | char *logname = NULLCP; | |
144 | int i, p, t; | |
145 | char j; | |
146 | #ifndef BSD44 | |
147 | struct sgttyb b; | |
148 | #endif | |
149 | ||
150 | if (myname = rindex (*argv, '/')) | |
151 | myname++; | |
152 | if (myname == NULL || *myname == NULL) | |
153 | myname = *argv; | |
154 | ||
155 | isodetailor (myname, 0); | |
156 | if (debug = isatty (fileno (stderr))) | |
157 | ll_dbinit (vt_log, myname); | |
158 | else | |
159 | ll_hdinit (vt_log, myname); | |
160 | ||
161 | for(i=1; i<(argc - 2); i++) | |
162 | { | |
163 | if (!strcmp(argv[i], "-d")) | |
164 | { | |
165 | if (!isdigit(argv[++i][0]) | |
166 | || sscanf(argv[i], "%d", &debug) != 1) | |
167 | adios (NULLCP, "usage: %s -d 0-7", myname); | |
168 | advise(LLOG_DEBUG,NULLCP, "setting debug level to %d", debug); | |
169 | if (debug) | |
170 | ll_dbinit (vt_log, myname); | |
171 | } | |
172 | else if(!strcmp(argv[i], "-F")) | |
173 | { | |
174 | if ((logname = argv[++i]) == NULL || *logname == '-') | |
175 | adios (NULLCP, "usage: %s -F logfile", myname); | |
176 | vt_log -> ll_file = logname; | |
177 | (void) ll_close (vt_log); | |
178 | advise(LLOG_DEBUG,NULLCP, "logging to %s",logname); | |
179 | } | |
180 | else | |
181 | adios(NULLCP, "usage: %s [-F logfile] [-d N]", | |
182 | myname); | |
183 | } | |
184 | ||
185 | advise (LLOG_NOTICE,NULLCP, "starting"); | |
186 | ||
187 | acc = &accs; | |
188 | acr = &acrs; | |
189 | aci = &acis; | |
190 | acs = &acss; | |
191 | ||
192 | if (ass_ind(argc,argv) == OK) { | |
193 | connected = TRUE; | |
194 | if( !strcmp(vtp_profile.profile_name,"default") ) | |
195 | telnet_profile = 0; | |
196 | } | |
197 | else | |
198 | exit(1); | |
199 | #ifdef BSD44 | |
200 | na_image = 0; | |
201 | nego_state = 0; /*Start off in Local echo*/ | |
202 | i = forkpty(&p, line, NULL, NULL); | |
203 | if (i == -1) { | |
204 | perror("vtd -- forkpty"); | |
205 | vrelreq(); | |
206 | /*NOTREACHED*/ | |
207 | } | |
208 | if (i) { | |
209 | vtd(sd, p); | |
210 | /*NOTREACHED*/ | |
211 | } | |
212 | #else | |
213 | /* | |
214 | * Get a pty, scan input lines. | |
215 | */ | |
216 | for (j = 'p' ; j <= 't'; j++) { | |
217 | cp[strlen ("/dev/pty")] = j; | |
218 | for (i = 0; i < 16; i++) { | |
219 | cp[strlen("/dev/ptyp")] = "0123456789abcdef"[i]; | |
220 | p = open(cp, 2); | |
221 | if (p >= 0) | |
222 | goto gotpty; | |
223 | } | |
224 | } | |
225 | perror("All network ports in use"); | |
226 | vrelreq(); | |
227 | /*NOTREACHED*/ | |
228 | gotpty: | |
229 | ||
230 | cp[strlen("/dev/")] = 't'; | |
231 | t = open("/dev/tty", 2); | |
232 | if (t >= 0) { | |
233 | if (ioctl(t, TIOCNOTTY, 0) == -1) { | |
234 | perror("ioctl (TIOCNOTTY)"); | |
235 | } | |
236 | (void)close(t); | |
237 | } | |
238 | t = open(cp, 2); | |
239 | if (t < 0) | |
240 | fatalperror(f, cp, errno); | |
241 | if (ioctl(t, TIOCGETP, (char*)&b) == -1) { | |
242 | perror("ioctl (TIOCGETP)"); | |
243 | adios(NULLCP, "ioctl failed (TIOCGETP)"); | |
244 | } | |
245 | b.sg_flags = CRMOD|XTABS|ANYP; | |
246 | if (ioctl(t, TIOCSETP, (char*)&b) == -1) { | |
247 | perror("ioctl (TIOCSETP)"); | |
248 | adios(NULLCP, "ioctl failed (TIOCSETP)"); | |
249 | } | |
250 | if (ioctl(p, TIOCGETP, (char*)&b) == -1) { /* XXX why is this done on the controller */ | |
251 | perror("ioctl (TIOCGETP)"); | |
252 | adios(NULLCP, "ioctl failed (TIOCGETP)"); | |
253 | } | |
254 | if (telnet_profile) | |
255 | b.sg_flags &= ~ECHO; | |
256 | else | |
257 | b.sg_flags |= ECHO; /*Remote echo for Default*/ | |
258 | if (ioctl(p, TIOCSETP, (char*)&b) == -1) { | |
259 | perror("ioctl (TIOCSETP)"); | |
260 | adios(NULLCP, "ioctl failed (TIOCSETP)"); | |
261 | } | |
262 | na_image = 0; | |
263 | nego_state = 0; /*Start off in Local echo*/ | |
264 | ||
265 | if ((i = fork()) < 0) | |
266 | fatalperror(f, "fork", errno); | |
267 | if (i) | |
268 | vtd(sd, p); | |
269 | (void)close(sd); | |
270 | (void)close(p); | |
271 | if (dup2(t, 0) == -1) { | |
272 | perror("dup2"); | |
273 | adios(NULLCP, "dup2 failed"); | |
274 | } | |
275 | if (dup2(t, 1) == -1) { | |
276 | perror("dup2"); | |
277 | adios(NULLCP, "dup2 failed"); | |
278 | } | |
279 | if (dup2(t, 2) == -1) { | |
280 | perror("dup2"); | |
281 | adios(NULLCP, "dup2 failed"); | |
282 | } | |
283 | (void)close(t); | |
284 | #endif | |
285 | environ = envinit; | |
286 | ||
287 | execl(_PATH_LOGIN,"login","-h",peerhost,NULLCP); | |
288 | fatalperror(f, _PATH_LOGIN, errno); | |
289 | /*NOTREACHED*/ | |
290 | } | |
291 | ||
292 | fatal(f, msg) | |
293 | int f; | |
294 | char *msg; | |
295 | { | |
296 | char buf[BUFSIZ]; | |
297 | ||
298 | (void) sprintf(buf, "%s: %s.\n", myname, msg); | |
299 | (void) write(f, buf, strlen(buf)); | |
300 | adios (NULLCP, msg); | |
301 | } | |
302 | ||
303 | fatalperror(f, msg, errnum) | |
304 | int f; | |
305 | char *msg; | |
306 | int errnum; | |
307 | { | |
308 | char buf[BUFSIZ]; | |
309 | extern char *sys_errlist[]; | |
310 | ||
311 | (void) sprintf(buf, "%s: %s", msg, sys_errlist[errnum]); | |
312 | fatal(f, buf); | |
313 | } | |
314 | ||
315 | /* | |
316 | * Main loop. Select from pty and network. | |
317 | */ | |
318 | ||
319 | vtd(f, p) | |
320 | { | |
321 | int on = 1; | |
322 | int nfds, result; | |
323 | ||
324 | do_cleaning = 1; | |
325 | net = f, pty = p; | |
326 | nfds = (f > p ? f : p) + 1; | |
327 | ||
328 | if (ioctl(p, FIONBIO, (char*)&on) == -1) { | |
329 | perror("ioctl"); | |
330 | adios(NULLCP, "ioctl failed (FIONBIO)"); | |
331 | } | |
332 | #ifdef SIGTSTP | |
333 | (void) signal(SIGTSTP, SIG_IGN); | |
334 | #endif | |
335 | #ifdef SIGCHLD | |
336 | (void) signal(SIGCHLD, cleanup); | |
337 | #endif | |
338 | /* | |
339 | * Show banner that getty never gave. | |
340 | */ | |
341 | myhostname = PLocalHostName (); | |
342 | (void) sprintf(nfrontp, BANNER, myhostname, ""); | |
343 | nfrontp += strlen(nfrontp); | |
344 | ||
345 | #ifdef BSD44 | |
346 | if (tcgetattr(pty, &oterm) == -1) { | |
347 | perror("tcgetattr"); | |
348 | adios(NULLCP, "tcgetattr failed"); | |
349 | } | |
350 | if (telnet_profile) { | |
351 | oterm.c_lflag &= ~ECHO; | |
352 | if (tcsetattr(pty, TCSADRAIN, &oterm) == -1) { | |
353 | perror("tcgetattr"); | |
354 | adios(NULLCP, "tcgetattr failed"); | |
355 | } | |
356 | } | |
357 | erase_char = oterm.c_cc[VERASE]; | |
358 | erase_line = oterm.c_cc[VKILL]; | |
359 | intr_char = oterm.c_cc[VINTR]; | |
360 | #else | |
361 | if (ioctl(pty,TIOCGETP,(char*)&ottyb) == -1) { | |
362 | perror("ioctl"); | |
363 | adios(NULLCP, "ioctl failed (TIOCGETP)"); | |
364 | } | |
365 | if (ioctl(pty,TIOCGETC,(char*)&otc) == -1) { | |
366 | perror("ioctl"); | |
367 | adios(NULLCP, "ioctl failed (TIOCGETC)"); | |
368 | } | |
369 | if (ioctl(pty,TIOCGLTC,(char*)&oltc) == -1) { | |
370 | perror("ioctl"); | |
371 | adios(NULLCP, "ioctl failed (TIOCGLTC)"); | |
372 | } | |
373 | erase_char = ottyb.sg_erase; | |
374 | erase_line = ottyb.sg_kill; | |
375 | intr_char = otc.t_intrc; | |
376 | #endif | |
377 | ||
378 | ||
379 | for (;;) { | |
380 | fd_set ibits, obits; | |
381 | register int c; | |
382 | ||
383 | FD_ZERO (&ibits); | |
384 | FD_ZERO (&obits); | |
385 | /* | |
386 | * Never look for input if there's still | |
387 | * stuff in the corresponding output buffer | |
388 | */ | |
389 | if (nfrontp - nbackp) { | |
390 | FD_SET (f, &obits); | |
391 | } | |
392 | else { | |
393 | FD_SET (p, &ibits); | |
394 | } | |
395 | if (pfrontp - pbackp) { | |
396 | FD_SET (p, &obits); | |
397 | } | |
398 | else { | |
399 | FD_SET (f, &ibits); | |
400 | } | |
401 | if (FD_ISSET (f, &ibits) && data_pending()) { | |
402 | FD_CLR (f, &ibits); | |
403 | ||
404 | result = xselect(nfds, &ibits, &obits, | |
405 | (fd_set *)NULL, OK); | |
406 | ||
407 | if (result < 0) | |
408 | adios("failed", "xselect"); | |
409 | FD_SET (f, &ibits); | |
410 | } | |
411 | else { | |
412 | if (xselect(nfds, &ibits, &obits, (fd_set *)NULL, | |
413 | NOTOK) == -1) | |
414 | adios("failed", "xselect"); | |
415 | } | |
416 | if (!FD_ISSET (f, &ibits) | |
417 | && !FD_ISSET (p, &ibits) | |
418 | && !FD_ISSET (f, &obits) | |
419 | && !FD_ISSET (p, &obits)) { | |
420 | sleep(5); | |
421 | continue; | |
422 | } | |
423 | ||
424 | /* | |
425 | * Something to read from the network... | |
426 | */ | |
427 | if (FD_ISSET (f, &ibits)) { | |
428 | while ((c = getch()) > 0) | |
429 | *pfrontp++ = c; | |
430 | } | |
431 | if (c == E_EOF) { | |
432 | break; | |
433 | } | |
434 | ||
435 | /* | |
436 | * Something to read from the pty... | |
437 | */ | |
438 | if (FD_ISSET (p, &ibits)) { | |
439 | pcc = read(p, nfrontp, (&netobuf[BUFSIZ] - nfrontp)); | |
440 | ||
441 | if (pcc < 0 && errno == EWOULDBLOCK) | |
442 | pcc = 0; | |
443 | else { | |
444 | if (pcc <= 0) { | |
445 | if (debug) | |
446 | advise(LLOG_EXCEPTIONS,NULLCP, | |
447 | "problem reading from pty"); | |
448 | break; | |
449 | } | |
450 | } | |
451 | nfrontp += pcc; | |
452 | } | |
453 | ||
454 | if (FD_ISSET (f, &obits) && (nfrontp - nbackp) > 0) | |
455 | netflush(); | |
456 | ||
457 | if (FD_ISSET (p, &obits) && (pfrontp - pbackp) > 0) | |
458 | ptyflush(); | |
459 | } | |
460 | if (debug) | |
461 | advise(LLOG_DEBUG,NULLCP, "finished loop in vtp"); | |
462 | cleanup(); | |
463 | } | |
464 | ||
465 | /* | |
466 | * Send interrupt to process on other side of pty. | |
467 | * If it is in raw mode, just write NULL; | |
468 | * otherwise, write intr char. | |
469 | */ | |
470 | interrupt() | |
471 | { | |
472 | #ifdef BSD44 | |
473 | struct termios term; | |
474 | ||
475 | ptyflush(); | |
476 | if (tcgetattr(pty, &term) == -1) { | |
477 | perror("tcgetattr"); | |
478 | return; | |
479 | } | |
480 | if ((term.c_lflag&ISIG) && term.c_cc[VINTR] != _POSIX_VDISABLE) | |
481 | *pfrontp++ = term.c_cc[VINTR]; | |
482 | else | |
483 | *pfrontp++ = '\0'; | |
484 | #else | |
485 | struct sgttyb b; | |
486 | struct tchars tchars; | |
487 | ||
488 | ptyflush(); /* half-hearted */ | |
489 | if (ioctl(pty, TIOCGETP, (char*)&b) == -1) { | |
490 | perror("ioctl"); | |
491 | adios(NULLCP, "ioctl failed"); | |
492 | } | |
493 | if (b.sg_flags & RAW) { | |
494 | *pfrontp++ = '\0'; | |
495 | return; | |
496 | } | |
497 | *pfrontp++ = ioctl(pty, TIOCGETC, (char*)&tchars) < 0 ? | |
498 | '\177' : tchars.t_intrc; | |
499 | #endif | |
500 | } | |
501 | ||
502 | netflush() | |
503 | { | |
504 | register char *cp; | |
505 | int n; | |
506 | int i, j; | |
507 | int nl_flag; /*Records if Newline is included in current PDU to | |
508 | decide if Deliver Request should follow it. Should | |
509 | not be required but some implementations may wait | |
510 | for it before delivering NDQ to application*/ | |
511 | ||
512 | nl_flag = 0; | |
513 | if ((n = nfrontp - nbackp) > 0) { | |
514 | ||
515 | if (debug) { | |
516 | (void) ll_log (vt_log, LLOG_DEBUG, NULLCP, | |
517 | ("writing to the net")); | |
518 | (void) ll_printf (vt_log, "<<"); | |
519 | for(i=0; i<(nfrontp-nbackp); i++) | |
520 | (void)ll_printf (vt_log, "%02x ",*(nbackp+i)); | |
521 | (void)ll_printf (vt_log, ">>\n"); | |
522 | (void)ll_sync (vt_log); | |
523 | } | |
524 | if(transparent) | |
525 | { | |
526 | (void)vt_text(nbackp,n); | |
527 | vtsend(); | |
528 | cp = nbackp; | |
529 | for(i=0; i<n; i++) | |
530 | { | |
531 | if((*cp == '\r') || | |
532 | (*cp == '\n')) | |
533 | { | |
534 | vdelreq(FALSE); | |
535 | break; | |
536 | } | |
537 | ++cp; | |
538 | } | |
539 | nbackp += n; | |
540 | } | |
541 | else | |
542 | { | |
543 | cp = nbackp; | |
544 | for(i=0,j=0; i<n; i++) | |
545 | { | |
546 | if(*cp == '\r') | |
547 | { | |
548 | if(rflag) (void)vt_text(crp,1); | |
549 | /*Previous char was CR so put one in NDQ*/ | |
550 | if(j) | |
551 | (void)vt_text(nbackp,j); | |
552 | nbackp += (j+1); /*Skip over current CR*/ | |
553 | cp = nbackp; | |
554 | j = 0; | |
555 | if(i == (n-1) ) (void)vt_text(crp,1); | |
556 | /*If CR is last char in buffer, send it*/ | |
557 | else rflag = 1; | |
558 | /*If not last char in buffer, read next one*/ | |
559 | continue; | |
560 | } | |
561 | else if(rflag) /*If previous character was CR*/ | |
562 | { | |
563 | if(*cp == '\n') /*Got CR-LF -- map to Next X-Array*/ | |
564 | { | |
565 | nbackp += (j+1); | |
566 | cp = nbackp; | |
567 | rflag = 0; | |
568 | vt_newline(); | |
569 | ++nl_flag; | |
570 | continue; | |
571 | } | |
572 | else /*Preceeding char was CR but not followed by | |
573 | LF. Put CR in buffer*/ | |
574 | (void) vt_text(crp,1); | |
575 | rflag = 0; | |
576 | } | |
577 | if(telnet_profile) | |
578 | { | |
579 | rflag = 0; | |
580 | #ifdef MAP_BACKSPACE | |
581 | if(*cp == 0x08) /*If believed to be erase*/ | |
582 | { | |
583 | if(j) | |
584 | (void)vt_text(nbackp,j); | |
585 | nbackp += (j+1); | |
586 | cp = nbackp; | |
587 | j = 0; | |
588 | vt_char_erase(); | |
589 | continue; | |
590 | } | |
591 | #endif | |
592 | if(!vtp_profile.arg_val.tel_arg_list.full_ascii) | |
593 | /*If ASCII GO, dump ctrl chars*/ | |
594 | { | |
595 | if((*cp < 0x20) || (*cp > 0x7e)) | |
596 | { | |
597 | if(j) | |
598 | (void)vt_text(nbackp,j); | |
599 | nbackp += (j+1); | |
600 | cp = nbackp; | |
601 | j = 0; | |
602 | } | |
603 | else | |
604 | { | |
605 | ++j; ++cp; | |
606 | } | |
607 | } | |
608 | else | |
609 | { | |
610 | ++j; | |
611 | ++cp; | |
612 | } | |
613 | } | |
614 | else /*Else Default Profile*/ | |
615 | { | |
616 | if((*cp < 0x20) || (*cp > 0x7e)) | |
617 | { | |
618 | if(j) | |
619 | (void)vt_text(nbackp,j); | |
620 | nbackp += (j+1); | |
621 | cp = nbackp; | |
622 | j = 0; | |
623 | } | |
624 | else | |
625 | { | |
626 | ++j; | |
627 | ++cp; | |
628 | } | |
629 | } | |
630 | } /*End for loop*/ | |
631 | if(j) | |
632 | (void)vt_text(nbackp,j); /*Load anything left if CR or LF | |
633 | wasn't last char in buffer*/ | |
634 | nbackp += j; | |
635 | vtsend(); /*Send the whole NDQ*/ | |
636 | if(nl_flag && telnet_profile) vdelreq(FALSE); | |
637 | } | |
638 | } | |
639 | if (n < 0) { | |
640 | if (errno != ENOBUFS && errno != EWOULDBLOCK) { | |
641 | adios("closed", "association"); | |
642 | /*NOTREACHED*/ | |
643 | } | |
644 | n = 0; | |
645 | } | |
646 | if (nbackp == nfrontp) | |
647 | nbackp = nfrontp = netobuf; | |
648 | } | |
649 | ||
650 | SFD cleanup() | |
651 | { | |
652 | sleep(1); | |
653 | while(getch() > 0); /*Clean out unread VT-DATA PDU's still held | |
654 | in network. Kludge to overcome deficiency | |
655 | in Session Release. */ | |
656 | rmut(); | |
657 | #ifndef BSD44 | |
658 | vhangup(); | |
659 | #endif | |
660 | vrelreq(); | |
661 | (void)kill(0, SIGKILL); | |
662 | exit(1); | |
663 | } | |
664 | ||
665 | #include <utmp.h> | |
666 | ||
667 | struct utmp wtmp; | |
668 | char wtmpf[] = "/usr/adm/wtmp"; | |
669 | char utmp[] = "/etc/utmp"; | |
670 | #define SCPYN(a, b) strncpy(a, b, sizeof (a)) | |
671 | #define SCMPN(a, b) strncmp(a, b, sizeof (a)) | |
672 | ||
673 | long lseek (), time (); | |
674 | ||
675 | rmut() | |
676 | { | |
677 | register f; | |
678 | int found = 0; | |
679 | ||
680 | f = open(utmp, 2); | |
681 | if (f >= 0) { | |
682 | while(read(f, (char *)&wtmp, sizeof (wtmp)) == sizeof (wtmp)) { | |
683 | if (SCMPN(wtmp.ut_line, line+5) || wtmp.ut_name[0]==0) | |
684 | continue; | |
685 | (void)lseek(f, -(long)sizeof (wtmp), 1); | |
686 | (void)SCPYN(wtmp.ut_name, ""); | |
687 | #if !defined(SYS5) && !defined(bsd43_ut_host) | |
688 | (void)SCPYN(wtmp.ut_host, ""); | |
689 | #endif | |
690 | (void)time(&wtmp.ut_time); | |
691 | (void) write(f, (char *)&wtmp, sizeof (wtmp)); | |
692 | found++; | |
693 | } | |
694 | (void)close(f); | |
695 | } | |
696 | if (found) { | |
697 | f = open(wtmpf, 1); | |
698 | if (f >= 0) { | |
699 | (void)SCPYN(wtmp.ut_line, line+5); | |
700 | (void)SCPYN(wtmp.ut_name, ""); | |
701 | #if !defined(SYS5) && !defined(bsd43_ut_host) | |
702 | (void)SCPYN(wtmp.ut_host, ""); | |
703 | #endif | |
704 | (void)time(&wtmp.ut_time); | |
705 | (void)lseek(f, (long)0, 2); | |
706 | (void) write(f, (char *)&wtmp, sizeof (wtmp)); | |
707 | (void)close(f); | |
708 | } | |
709 | } | |
710 | (void)chmod(line, 0666); | |
711 | (void)chown(line, 0, 0); | |
712 | line[strlen("/dev/")] = 'p'; | |
713 | (void)chmod(line, 0666); | |
714 | (void)chown(line, 0, 0); | |
715 | } | |
716 | ||
717 | bye() | |
718 | { | |
719 | if(do_cleaning) { | |
720 | rmut(); | |
721 | (void)kill(0, SIGKILL); | |
722 | } | |
723 | exit(0); | |
724 | } | |
725 | ||
726 | flushbufs() | |
727 | { | |
728 | pcc = 0; | |
729 | pfrontp = pbackp = ptyobuf; | |
730 | nfrontp = nbackp = netobuf; | |
731 | while (getch() > 0) | |
732 | continue; | |
733 | } | |
734 | ||
735 | /* \f ERRORS */ | |
736 | ||
737 | void finalbye () | |
738 | { | |
739 | bye (); | |
740 | } | |
741 | ||
742 | ||
743 | #ifndef lint | |
744 | void adios (va_alist) | |
745 | va_dcl | |
746 | { | |
747 | va_list ap; | |
748 | ||
749 | va_start (ap); | |
750 | ||
751 | (void) _ll_log (vt_log, LLOG_FATAL, ap); | |
752 | ||
753 | va_end (ap); | |
754 | ||
755 | bye (); | |
756 | ||
757 | _exit (1); | |
758 | } | |
759 | #else | |
760 | /* VARARGS2 */ | |
761 | ||
762 | void adios (what, fmt) | |
763 | char *what, | |
764 | *fmt; | |
765 | { | |
766 | adios (what, fmt); | |
767 | } | |
768 | #endif | |
769 | ||
770 | ||
771 | #ifndef lint | |
772 | void advise (va_alist) | |
773 | va_dcl | |
774 | { | |
775 | int code; | |
776 | va_list ap; | |
777 | ||
778 | va_start (ap); | |
779 | ||
780 | code = va_arg (ap, int); | |
781 | ||
782 | (void) _ll_log (vt_log, code, ap); | |
783 | ||
784 | va_end (ap); | |
785 | } | |
786 | #else | |
787 | /* VARARGS3 */ | |
788 | ||
789 | void advise (code, what, fmt) | |
790 | int code; | |
791 | char *what, | |
792 | *fmt; | |
793 | { | |
794 | advise (code, what, fmt); | |
795 | } | |
796 | #endif | |
797 | ||
798 | ptyflush() | |
799 | { | |
800 | int n; | |
801 | ||
802 | if ((n = pfrontp - pbackp) > 0) | |
803 | { | |
804 | n = write(pty, pbackp, n); | |
805 | } | |
806 | if (n < 0) | |
807 | return; | |
808 | pbackp += n; | |
809 | if (pbackp == pfrontp) | |
810 | pbackp = pfrontp = ptyobuf; | |
811 | } | |
812 | ||
813 | #ifdef BSD44 | |
814 | ptyecho(on) | |
815 | { | |
816 | struct termios term; | |
817 | ||
818 | ptyflush(); | |
819 | if (tcgetattr(pty, &term) == -1) { | |
820 | perror("tcgetattr"); | |
821 | return; | |
822 | } | |
823 | if (on) | |
824 | term.c_lflag |= ECHO; | |
825 | else | |
826 | term.c_lflag &= ECHO; | |
827 | if (tcsetattr(pty, TCSAFLUSH, &term) == -1) { | |
828 | perror("tcsetattr"); | |
829 | return; | |
830 | } | |
831 | } | |
832 | #else | |
833 | setmode(on, off) | |
834 | int on, off; | |
835 | { | |
836 | struct sgttyb b; | |
837 | ||
838 | ptyflush(); | |
839 | if(ioctl(pty, TIOCGETP, (char*)&b) < 0) { | |
840 | perror("ioctl"); | |
841 | adios(NULLCP, "ioctl failed"); | |
842 | } | |
843 | b.sg_flags |= on; | |
844 | b.sg_flags &= ~off; | |
845 | if (ioctl(pty, TIOCSETP, (char*)&b) == -1) { | |
846 | perror("ioctl"); | |
847 | adios(NULLCP, "ioctl failed"); | |
848 | } | |
849 | } | |
850 | #endif |