* Copyright (c) 1983 Regents of the University of California.
* All rights reserved. The Berkeley software License Agreement
* specifies the terms and conditions for redistribution.
"@(#) Copyright (c) 1983 Regents of the University of California.\n\
static char sccsid
[] = "@(#)rlogind.c 5.11 (Berkeley) %G%";
# define TIOCPKT_WINDOW 0x80
struct passwd
*getpwnam();
int on
= 1, options
= 0, fromlen
;
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
)
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
[strlen("/dev/ptyp")] = "0123456789abcdef"[i
];
(void) ioctl(p
, TIOCSWINSZ
, &win
);
line
[strlen("/dev/")] = 't';
{ int tt
= open("/dev/tty", 2);
fatalperror(f
, line
, errno
);
gtty(t
, &b
); b
.sg_flags
= RAW
|ANYP
; stty(t
, &b
);
fatalperror(f
, "", errno
);
dup2(t
, 0), dup2(t
, 1), dup2(t
, 2);
execl("/bin/login", "login", "-r", hp
->h_name
, 0);
fatalperror(2, "/bin/login", errno
);
signal(SIGTSTP
, SIG_IGN
);
signal(SIGCHLD
, cleanup
);
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", errno
);
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 */
buf
[0] = '\01'; /* error indicator */
(void) sprintf(buf
+ 1, "rlogind: %s.\r\n", msg
);
(void) write(f
, buf
, strlen(buf
));
fatalperror(f
, msg
, errno
)
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
);
char wtmpf
[] = "/usr/adm/wtmp";
char utmpf
[] = "/etc/utmp";
#define SCPYN(a, b) strncpy(a, b, sizeof(a))
#define SCMPN(a, b) strncmp(a, b, sizeof(a))
utmp
= (struct utmp
*)malloc(statbf
.st_size
);
syslog(LOG_ERR
, "utmp malloc failed");
if (statbf
.st_size
&& utmp
) {
nutmp
= read(f
, utmp
, statbf
.st_size
);
nutmp
/= sizeof(struct utmp
);
for (u
= utmp
; u
< &utmp
[nutmp
] ; u
++) {
if (SCMPN(u
->ut_line
, line
+5) ||
lseek(f
, ((long)u
)-((long)utmp
), L_SET
);
write(f
, (char *)u
, sizeof(wtmp
));
f
= open(wtmpf
, O_WRONLY
|O_APPEND
);
SCPYN(wtmp
.ut_line
, line
+5);
write(f
, (char *)&wtmp
, sizeof(wtmp
));
line
[strlen("/dev/")] = 'p';