* Copyright (c) 1983 The Regents of the University of California.
* Redistribution and use in source and binary forms are permitted
* provided that the above copyright notice and this paragraph are
* duplicated in all such forms and that any documentation,
* advertising materials, and other materials related to such
* distribution and use acknowledge that the software was developed
* by the University of California, Berkeley. The name of the
* University may not be used to endorse or promote products derived
* from this software without specific prior written permission.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
"@(#) Copyright (c) 1983 The Regents of the University of California.\n\
static char sccsid
[] = "@(#)rlogind.c 5.17 (Berkeley) %G%";
# define TIOCPKT_WINDOW 0x80
struct passwd
*getpwnam();
openlog("rlogind", LOG_PID
| LOG_AUTH
, LOG_AUTH
);
if (getpeername(0, &from
, &fromlen
) < 0) {
fprintf(stderr
, "%s: ", argv
[0]);
if (setsockopt(0, SOL_SOCKET
, SO_KEEPALIVE
, &on
, sizeof (on
)) < 0) {
syslog(LOG_WARNING
, "setsockopt (SO_KEEPALIVE): %m");
extern char *inet_ntoa();
struct winsize win
= { 0, 0, 0, 0 };
struct sockaddr_in
*fromp
;
int i
, p
, t
, pid
, on
= 1;
register struct hostent
*hp
;
fromp
->sin_port
= ntohs((u_short
)fromp
->sin_port
);
hp
= gethostbyaddr(&fromp
->sin_addr
, sizeof (struct in_addr
),
* Only the name is used below.
hp
->h_name
= inet_ntoa(fromp
->sin_addr
);
if (fromp
->sin_family
!= AF_INET
||
fromp
->sin_port
>= IPPORT_RESERVED
||
fromp
->sin_port
< IPPORT_RESERVED
/2)
fatal(f
, "Permission denied");
for (c
= 'p'; c
<= 's'; c
++) {
line
[strlen("/dev/pty")] = c
;
line
[strlen("/dev/ptyp")] = '0';
if (stat(line
, &stb
) < 0)
for (i
= 0; i
< 16; i
++) {
line
[sizeof("/dev/ptyp") - 1] = "0123456789abcdef"[i
];
(void) ioctl(p
, TIOCSWINSZ
, &win
);
line
[strlen("/dev/")] = 't';
(void)signal(SIGHUP
, SIG_IGN
);
(void)signal(SIGHUP
, SIG_DFL
);
(void)ioctl(t
, TIOCGETP
, &b
);
(void)ioctl(t
, TIOCSETP
, &b
);
int tt
= open("/dev/tty", O_RDWR
);
(void)ioctl(tt
, TIOCNOTTY
, 0);
dup2(t
, 0), dup2(t
, 1), dup2(t
, 2);
execl("/bin/login", "login", "-r", hp
->h_name
, 0);
fatalperror(2, "/bin/login");
signal(SIGTSTP
, SIG_IGN
);
signal(SIGCHLD
, cleanup
);
signal(SIGCHLD
, SIG_IGN
);
char magic
[2] = { 0377, 0377 };
char oobdata
[] = {TIOCPKT_WINDOW
};
* Handle a "control" request (signaled by magic being present)
* in the data stream. For now, we are only willing to handle
if (n
< 4+sizeof (w
) || cp
[2] != 's' || cp
[3] != 's')
oobdata
[0] &= ~TIOCPKT_WINDOW
; /* we know he heard */
bcopy(cp
+4, (char *)&w
, sizeof(w
));
w
.ws_row
= ntohs(w
.ws_row
);
w
.ws_col
= ntohs(w
.ws_col
);
w
.ws_xpixel
= ntohs(w
.ws_xpixel
);
w
.ws_ypixel
= ntohs(w
.ws_ypixel
);
(void)ioctl(pty
, TIOCSWINSZ
, &w
);
* rlogin "protocol" machine.
char pibuf
[1024], fibuf
[1024], *pbp
, *fbp
;
register pcc
= 0, fcc
= 0;
* Must ignore SIGTTOU, otherwise we'll stop
* when we try and set slave pty's window shape
* (our controlling tty is the master pty).
(void) signal(SIGTTOU
, SIG_IGN
);
send(f
, oobdata
, 1, MSG_OOB
); /* indicate new rlogin */
if (select(16, &ibits
, &obits
, &ebits
, 0) < 0) {
fatalperror(f
, "select");
if (ibits
== 0 && obits
== 0 && ebits
== 0) {
/* shouldn't happen... */
#define pkcontrol(c) ((c)&(TIOCPKT_FLUSHWRITE|TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))
if (cc
== 1 && pkcontrol(cntl
)) {
send(f
, &cntl
, 1, MSG_OOB
);
if (cntl
& TIOCPKT_FLUSHWRITE
) {
fcc
= read(f
, fibuf
, sizeof (fibuf
));
if (fcc
< 0 && errno
== EWOULDBLOCK
)
for (cp
= fibuf
; cp
< fibuf
+fcc
-1; cp
++)
n
= control(p
, cp
, left
);
if ((obits
& (1<<p
)) && fcc
> 0) {
pcc
= read(p
, pibuf
, sizeof (pibuf
));
if (pcc
< 0 && errno
== EWOULDBLOCK
)
if (pkcontrol(pibuf
[0])) {
send(f
, &pibuf
[0], 1, MSG_OOB
);
if ((obits
& (1<<f
)) && pcc
> 0) {
if (cc
< 0 && errno
== EWOULDBLOCK
) {
/* also shouldn't happen */
p
= line
+ sizeof("/dev/") - 1;
buf
[0] = '\01'; /* error indicator */
(void) sprintf(buf
+ 1, "rlogind: %s.\r\n", msg
);
(void) write(f
, buf
, strlen(buf
));
extern char *sys_errlist
[];
if ((unsigned)errno
< sys_nerr
)
(void) sprintf(buf
, "%s: %s", msg
, sys_errlist
[errno
]);
(void) sprintf(buf
, "%s: Error %d", msg
, errno
);