defend against malicious line in ut_line, which could cause unwanted
writes to anything under /dev. revoke setuid/gid privs earlier. From: xs@kittenz.org
This commit is contained in:
parent
39acbf03ed
commit
2abe377059
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: ttymsg.c,v 1.15 2000/07/05 11:46:42 ad Exp $ */
|
||||
/* $NetBSD: ttymsg.c,v 1.16 2002/08/16 20:21:48 itojun Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
@ -38,7 +38,7 @@
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)ttymsg.c 8.2 (Berkeley) 11/16/93";
|
||||
#else
|
||||
__RCSID("$NetBSD: ttymsg.c,v 1.15 2000/07/05 11:46:42 ad Exp $");
|
||||
__RCSID("$NetBSD: ttymsg.c,v 1.16 2002/08/16 20:21:48 itojun Exp $");
|
||||
#endif
|
||||
#endif /* LIBC_SCCS and not lint */
|
||||
|
||||
@ -67,8 +67,8 @@ __RCSID("$NetBSD: ttymsg.c,v 1.15 2000/07/05 11:46:42 ad Exp $");
|
||||
char *
|
||||
ttymsg(struct iovec *iov, int iovcnt, const char *line, int tmout)
|
||||
{
|
||||
static char device[MAXNAMLEN] = _PATH_DEV;
|
||||
static char errbuf[1024];
|
||||
char device[MAXNAMLEN];
|
||||
int cnt, fd, left, wret;
|
||||
struct iovec localiov[6];
|
||||
sigset_t nset;
|
||||
@ -81,12 +81,16 @@ ttymsg(struct iovec *iov, int iovcnt, const char *line, int tmout)
|
||||
if (iovcnt > sizeof(localiov) / sizeof(localiov[0]))
|
||||
return ("too many iov's (change code in libutil/ttymsg.c)");
|
||||
|
||||
(void)strncpy(device + sizeof(_PATH_DEV) - 1, line,
|
||||
sizeof(device) - sizeof(_PATH_DEV));
|
||||
if (strchr(device + sizeof(_PATH_DEV) - 1, '/')) {
|
||||
/* A slash is an attempt to break security... */
|
||||
(void) snprintf(errbuf, sizeof(errbuf), "'/' in \"%s\"",
|
||||
device);
|
||||
if (strlcpy(device, _PATH_DEV, sizeof(device)) >= sizeof(device) ||
|
||||
strlcat(device, line, sizeof(device)) >= sizeof(device)) {
|
||||
(void) snprintf(errbuf, sizeof(errbuf), "%s: path too long",
|
||||
line);
|
||||
return (errbuf);
|
||||
}
|
||||
if (strcspn(line, "./") != strlen(line)) {
|
||||
/* A slash or dot is an attempt to break security... */
|
||||
(void) snprintf(errbuf, sizeof(errbuf), "'/' or '.' in \"%s\"",
|
||||
line);
|
||||
return (errbuf);
|
||||
}
|
||||
|
||||
@ -101,6 +105,12 @@ ttymsg(struct iovec *iov, int iovcnt, const char *line, int tmout)
|
||||
"%s: %s", device, strerror(errno));
|
||||
return (errbuf);
|
||||
}
|
||||
if (!isatty(fd)) {
|
||||
(void) snprintf(errbuf, sizeof(errbuf),
|
||||
"%s: not a tty device", device);
|
||||
(void) close(fd);
|
||||
return (errbuf);
|
||||
}
|
||||
|
||||
for (cnt = left = 0; cnt < iovcnt; ++cnt)
|
||||
left += iov[cnt].iov_len;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: utmp_update.c,v 1.3 2002/08/09 10:01:53 soren Exp $ */
|
||||
/* $NetBSD: utmp_update.c,v 1.4 2002/08/16 20:21:48 itojun Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2002 The NetBSD Foundation, Inc.
|
||||
@ -41,6 +41,7 @@
|
||||
#include <stdio.h>
|
||||
#include <vis.h>
|
||||
#include <err.h>
|
||||
#include <fcntl.h>
|
||||
#include <pwd.h>
|
||||
#include <utmpx.h>
|
||||
#include <stdlib.h>
|
||||
@ -56,8 +57,14 @@ main(int argc, char *argv[])
|
||||
size_t len;
|
||||
struct passwd *pwd;
|
||||
struct stat st;
|
||||
int fd;
|
||||
uid_t euid;
|
||||
|
||||
if (argc != 1) {
|
||||
euid = geteuid();
|
||||
if (seteuid(getuid()) == -1)
|
||||
err(1, "seteuid");
|
||||
|
||||
if (argc != 2) {
|
||||
(void)fprintf(stderr, "Usage: %s <vis-utmpx-entry>\n",
|
||||
getprogname());
|
||||
exit(1);
|
||||
@ -90,18 +97,20 @@ main(int argc, char *argv[])
|
||||
errx(1, "Current user `%s' does not match `%s' in utmpx entry",
|
||||
pwd->pw_name, utx->ut_name);
|
||||
|
||||
if (stat(utx->ut_line, &st) == -1)
|
||||
fd = open(utx->ut_line, O_RDONLY, 0);
|
||||
if (fd == -1)
|
||||
err(1, "Cannot open `%s'", utx->ut_line);
|
||||
if (fstat(fd, &st) == -1)
|
||||
err(1, "Cannot stat `%s'", utx->ut_line);
|
||||
if (st.st_uid != getuid())
|
||||
errx(1, "%s: Is not owned by you", utx->ut_line);
|
||||
if (!isatty(fd))
|
||||
errx(1, "%s: Not a tty device", utx->ut_line);
|
||||
close(fd);
|
||||
if (access(utx->ut_line, W_OK|R_OK) == -1)
|
||||
err(1, "%s", utx->ut_line);
|
||||
|
||||
if (!S_ISCHR(st.st_mode))
|
||||
errx(1, "%s: Not a character device", utx->ut_line);
|
||||
|
||||
/*
|
||||
* to check if the tty is writable here is problematic. First we
|
||||
* don't even know if it is a tty, secondly we are setuid so it
|
||||
* is not trivial to use access
|
||||
*/
|
||||
|
||||
(void)seteuid(euid);
|
||||
pututxline(utx);
|
||||
|
||||
return 0;
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: optr.c,v 1.26 2002/08/02 02:07:09 christos Exp $ */
|
||||
/* $NetBSD: optr.c,v 1.27 2002/08/16 20:21:49 itojun Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1980, 1988, 1993
|
||||
@ -38,7 +38,7 @@
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)optr.c 8.2 (Berkeley) 1/6/94";
|
||||
#else
|
||||
__RCSID("$NetBSD: optr.c,v 1.26 2002/08/02 02:07:09 christos Exp $");
|
||||
__RCSID("$NetBSD: optr.c,v 1.27 2002/08/16 20:21:49 itojun Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
@ -272,11 +272,16 @@ sendmes(char *tty, char *message)
|
||||
int lmsg = 1;
|
||||
FILE *f_tty;
|
||||
|
||||
if (strcspn(tty, "./") != strlen(tty))
|
||||
return;
|
||||
|
||||
(void)strncpy(t, _PATH_DEV, sizeof(t) - 1);
|
||||
(void)strncat(t, tty, sizeof(t) - sizeof(_PATH_DEV) - 1);
|
||||
t[sizeof(t) - 1] = '\0';
|
||||
|
||||
if ((f_tty = fopen(t, "w")) != NULL) {
|
||||
if (!isatty(fileno(f_tty)))
|
||||
return;
|
||||
setbuf(f_tty, buf);
|
||||
(void) fprintf(f_tty,
|
||||
"\n\
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: wall.c,v 1.19 2002/08/02 01:52:13 christos Exp $ */
|
||||
/* $NetBSD: wall.c,v 1.20 2002/08/16 20:21:49 itojun Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1988, 1990, 1993
|
||||
@ -43,7 +43,7 @@ __COPYRIGHT("@(#) Copyright (c) 1988, 1990, 1993\n\
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)wall.c 8.2 (Berkeley) 11/16/93";
|
||||
#endif
|
||||
__RCSID("$NetBSD: wall.c,v 1.19 2002/08/02 01:52:13 christos Exp $");
|
||||
__RCSID("$NetBSD: wall.c,v 1.20 2002/08/16 20:21:49 itojun Exp $");
|
||||
#endif /* not lint */
|
||||
|
||||
/*
|
||||
@ -57,6 +57,7 @@ __RCSID("$NetBSD: wall.c,v 1.19 2002/08/02 01:52:13 christos Exp $");
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <paths.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
@ -71,7 +72,7 @@ void makemsg(const char *);
|
||||
int main(int, char **);
|
||||
|
||||
int nobanner;
|
||||
int mbufsize;
|
||||
size_t mbufsize;
|
||||
char *mbuf;
|
||||
|
||||
/* ARGSUSED */
|
||||
@ -81,8 +82,14 @@ main(int argc, char **argv)
|
||||
int ch;
|
||||
struct iovec iov;
|
||||
char *p;
|
||||
struct passwd *pep = getpwnam("nobody");
|
||||
struct passwd *pep;
|
||||
struct utmpentry *ep;
|
||||
gid_t egid;
|
||||
|
||||
egid = getegid();
|
||||
if (setegid(getgid()) == -1)
|
||||
err(1, "setegid");
|
||||
pep = getpwnam("nobody");
|
||||
|
||||
while ((ch = getopt(argc, argv, "n")) != -1)
|
||||
switch (ch) {
|
||||
@ -107,6 +114,7 @@ usage:
|
||||
iov.iov_base = mbuf;
|
||||
iov.iov_len = mbufsize;
|
||||
(void)getutentries(NULL, &ep);
|
||||
(void)setegid(egid);
|
||||
for (; ep; ep = ep->next)
|
||||
if ((p = ttymsg(&iov, 1, ep->line, 60*5)) != NULL)
|
||||
warnx("%s", p);
|
||||
@ -116,7 +124,7 @@ usage:
|
||||
void
|
||||
makemsg(const char *fname)
|
||||
{
|
||||
register int ch, cnt;
|
||||
int ch, cnt;
|
||||
struct tm *lt;
|
||||
struct passwd *pw;
|
||||
struct stat sbuf;
|
||||
@ -127,9 +135,11 @@ makemsg(const char *fname)
|
||||
char *p, *tty, tmpname[32], lbuf[100], hostname[MAXHOSTNAMELEN+1];
|
||||
|
||||
(void)snprintf(tmpname, sizeof tmpname, "%s/wall.XXXXXX", _PATH_TMP);
|
||||
if ((fd = mkstemp(tmpname)) == -1 || !(fp = fdopen(fd, "r+")))
|
||||
if ((fd = mkstemp(tmpname)) == -1)
|
||||
err(1, "can't open temporary file");
|
||||
(void)unlink(tmpname);
|
||||
if (!(fp = fdopen(fd, "r+")))
|
||||
err(1, "can't open temporary file");
|
||||
|
||||
if (!nobanner) {
|
||||
if (!(whom = getlogin()))
|
||||
@ -179,10 +189,12 @@ makemsg(const char *fname)
|
||||
|
||||
if (fstat(fd, &sbuf))
|
||||
err(1, "can't stat temporary file");
|
||||
if (sbuf.st_size > SIZE_T_MAX)
|
||||
errx(1, "file too big");
|
||||
mbufsize = sbuf.st_size;
|
||||
if (!(mbuf = malloc((u_int)mbufsize)))
|
||||
if (!(mbuf = malloc(mbufsize)))
|
||||
err(1, "malloc");
|
||||
if (fread(mbuf, sizeof(*mbuf), mbufsize, fp) != mbufsize)
|
||||
if (fread(mbuf, 1, mbufsize, fp) != mbufsize)
|
||||
err(1, "can't read temporary file");
|
||||
(void)close(fd);
|
||||
(void)fclose(fp);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* $NetBSD: write.c,v 1.20 2002/08/02 01:59:44 christos Exp $ */
|
||||
/* $NetBSD: write.c,v 1.21 2002/08/16 20:21:49 itojun Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
@ -46,7 +46,7 @@ __COPYRIGHT("@(#) Copyright (c) 1989, 1993\n\
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)write.c 8.2 (Berkeley) 4/27/95";
|
||||
#else
|
||||
__RCSID("$NetBSD: write.c,v 1.20 2002/08/02 01:59:44 christos Exp $");
|
||||
__RCSID("$NetBSD: write.c,v 1.21 2002/08/16 20:21:49 itojun Exp $");
|
||||
#endif
|
||||
#endif /* not lint */
|
||||
|
||||
@ -64,25 +64,34 @@ __RCSID("$NetBSD: write.c,v 1.20 2002/08/02 01:59:44 christos Exp $");
|
||||
#include <pwd.h>
|
||||
#include <unistd.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "utmpentry.h"
|
||||
|
||||
void done(int);
|
||||
void do_write(const char *, const char *, const uid_t);
|
||||
void do_write(int, const char *, const uid_t);
|
||||
void wr_fputs(char *);
|
||||
void search_utmp(char *, char *, char *, uid_t, int);
|
||||
int term_chk(const char *, int *, time_t *, int);
|
||||
int search_utmp(char *, char *, uid_t);
|
||||
int term_chk(uid_t, const char *, int *, time_t *, int);
|
||||
int utmp_chk(const char *, const char *);
|
||||
int main(int, char **);
|
||||
|
||||
static gid_t saved_egid;
|
||||
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
char *cp;
|
||||
time_t atime;
|
||||
uid_t myuid;
|
||||
int msgsok, myttyfd;
|
||||
char tty[MAXPATHLEN], *mytty;
|
||||
uid_t myuid, uid;
|
||||
int msgsok, myttyfd, ttyfd;
|
||||
char *mytty;
|
||||
|
||||
saved_egid = getegid();
|
||||
if (setegid(getgid()) == -1)
|
||||
err(1, "setegid");
|
||||
myuid = getuid();
|
||||
ttyfd = -1;
|
||||
|
||||
/* check that sender has write enabled */
|
||||
if (isatty(fileno(stdin)))
|
||||
@ -97,39 +106,41 @@ main(int argc, char **argv)
|
||||
errx(1, "can't find your tty's name");
|
||||
if ((cp = strrchr(mytty, '/')) != NULL)
|
||||
mytty = cp + 1;
|
||||
if (term_chk(mytty, &msgsok, &atime, 1))
|
||||
exit(1);
|
||||
if (term_chk(myuid, mytty, &msgsok, &atime, 1) == -1)
|
||||
err(1, "%s%s", _PATH_DEV, mytty);
|
||||
if (!msgsok) {
|
||||
(void)fprintf(stderr,
|
||||
"warning: you have write permission turned off; "
|
||||
"no reply possible\n");
|
||||
}
|
||||
|
||||
myuid = getuid();
|
||||
|
||||
/* check args */
|
||||
switch (argc) {
|
||||
case 2:
|
||||
search_utmp(argv[1], tty, mytty, myuid, sizeof tty);
|
||||
do_write(tty, mytty, myuid);
|
||||
ttyfd = search_utmp(argv[1], mytty, myuid);
|
||||
break;
|
||||
case 3:
|
||||
if (!strncmp(argv[2], _PATH_DEV, strlen(_PATH_DEV)))
|
||||
argv[2] += strlen(_PATH_DEV);
|
||||
if (uid_from_user(argv[1], &uid) == -1)
|
||||
errx(1, "%s: unknown user", argv[1]);
|
||||
if (utmp_chk(argv[1], argv[2]))
|
||||
errx(1, "%s is not logged in on %s",
|
||||
argv[1], argv[2]);
|
||||
if (term_chk(argv[2], &msgsok, &atime, 1))
|
||||
exit(1);
|
||||
ttyfd = term_chk(uid, argv[2], &msgsok, &atime, 0);
|
||||
if (ttyfd == -1)
|
||||
err(1, "%s%s", _PATH_DEV, argv[2]);
|
||||
if (myuid && !msgsok)
|
||||
errx(1, "%s has messages disabled on %s",
|
||||
argv[1], argv[2]);
|
||||
do_write(argv[2], mytty, myuid);
|
||||
break;
|
||||
default:
|
||||
(void)fprintf(stderr, "usage: write user [tty]\n");
|
||||
exit(1);
|
||||
}
|
||||
if (setgid(getgid()) == -1)
|
||||
err(1, "setgid");
|
||||
do_write(ttyfd, mytty, myuid);
|
||||
done(0);
|
||||
/* NOTREACHED */
|
||||
#ifdef __GNUC__
|
||||
@ -165,49 +176,63 @@ utmp_chk(const char *user, const char *tty)
|
||||
* Special case for writing to yourself - ignore the terminal you're
|
||||
* writing from, unless that's the only terminal with messages enabled.
|
||||
*/
|
||||
void
|
||||
search_utmp(char *user, char *tty, char *mytty, uid_t myuid, int ttylen)
|
||||
int
|
||||
search_utmp(char *user, char *mytty, uid_t myuid)
|
||||
{
|
||||
char tty[MAXPATHLEN];
|
||||
time_t bestatime, atime;
|
||||
int nloggedttys, nttys, msgsok, user_is_me;
|
||||
struct utmpentry *ep;
|
||||
int fd, nfd;
|
||||
uid_t uid;
|
||||
|
||||
if (uid_from_user(user, &uid) == -1)
|
||||
errx(1, "%s: unknown user", user);
|
||||
|
||||
(void)getutentries(NULL, &ep);
|
||||
|
||||
nloggedttys = nttys = 0;
|
||||
bestatime = 0;
|
||||
user_is_me = 0;
|
||||
fd = -1;
|
||||
for (; ep; ep = ep->next)
|
||||
if (strcmp(user, ep->name) == 0) {
|
||||
++nloggedttys;
|
||||
if (term_chk(ep->line, &msgsok, &atime, 0))
|
||||
nfd = term_chk(uid, ep->line, &msgsok, &atime, 0);
|
||||
if (nfd == -1)
|
||||
continue; /* bad term? skip */
|
||||
if (myuid && !msgsok)
|
||||
if (myuid && !msgsok) {
|
||||
close(nfd);
|
||||
continue; /* skip ttys with msgs off */
|
||||
}
|
||||
if (strcmp(ep->line, mytty) == 0) {
|
||||
user_is_me = 1;
|
||||
if (fd == -1)
|
||||
fd = nfd;
|
||||
else
|
||||
close(nfd);
|
||||
continue; /* don't write to yourself */
|
||||
}
|
||||
++nttys;
|
||||
if (atime > bestatime) {
|
||||
bestatime = atime;
|
||||
(void)strncpy(tty, ep->line, ttylen - 1);
|
||||
tty[ttylen - 1] = '\0';
|
||||
}
|
||||
(void)strlcpy(tty, ep->line, sizeof(tty));
|
||||
close(fd);
|
||||
fd = nfd;
|
||||
} else
|
||||
close(nfd);
|
||||
}
|
||||
|
||||
if (nloggedttys == 0)
|
||||
errx(1, "%s is not logged in", user);
|
||||
if (nttys == 0) {
|
||||
if (user_is_me) { /* ok, so write to yourself! */
|
||||
(void)strncpy(tty, mytty, ttylen - 1);
|
||||
tty[ttylen - 1] = '\0';
|
||||
return;
|
||||
}
|
||||
if (user_is_me) /* ok, so write to yourself! */
|
||||
return fd;
|
||||
errx(1, "%s has messages disabled", user);
|
||||
} else if (nttys > 1)
|
||||
warnx("%s is logged in more than once; writing to %s",
|
||||
user, tty);
|
||||
return fd;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -215,46 +240,71 @@ search_utmp(char *user, char *tty, char *mytty, uid_t myuid, int ttylen)
|
||||
* and the access time
|
||||
*/
|
||||
int
|
||||
term_chk(const char *tty, int *msgsokP, time_t *atimeP, int showerror)
|
||||
term_chk(uid_t uid, const char *tty, int *msgsokP, time_t *atimeP, int ismytty)
|
||||
{
|
||||
struct stat s;
|
||||
char path[MAXPATHLEN];
|
||||
struct stat s;
|
||||
int i, fd, serrno;
|
||||
|
||||
(void)snprintf(path, sizeof path, _PATH_DEV "%s", tty);
|
||||
if (stat(path, &s) < 0) {
|
||||
if (showerror)
|
||||
warn("%s", path);
|
||||
return(1);
|
||||
if (strcspn(tty, "./") != strlen(tty)) {
|
||||
errno = EINVAL; return(-1);
|
||||
}
|
||||
i = snprintf(path, sizeof path, _PATH_DEV "%s", tty);
|
||||
if (i < 0 || i >= sizeof(path)) {
|
||||
errno = ENOMEM; return(-1);
|
||||
}
|
||||
|
||||
(void)setegid(saved_egid);
|
||||
fd = open(path, O_WRONLY, 0);
|
||||
serrno = errno;
|
||||
(void)setegid(getgid());
|
||||
errno = serrno;
|
||||
|
||||
if (fd == -1)
|
||||
return(-1);
|
||||
if (fstat(fd, &s) == -1)
|
||||
goto error;
|
||||
if (!isatty(fd) || s.st_uid != uid)
|
||||
goto error;
|
||||
*msgsokP = (s.st_mode & S_IWGRP) != 0; /* group write bit */
|
||||
*atimeP = s.st_atime;
|
||||
return(0);
|
||||
if (ismytty)
|
||||
(void) close(fd);
|
||||
return(ismytty? 0: fd);
|
||||
error:
|
||||
if (fd != -1) {
|
||||
serrno = errno;
|
||||
close(fd);
|
||||
errno = serrno;
|
||||
}
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* do_write - actually make the connection
|
||||
*/
|
||||
void
|
||||
do_write(const char *tty, const char *mytty, const uid_t myuid)
|
||||
do_write(int ttyfd, const char *mytty, const uid_t myuid)
|
||||
{
|
||||
const char *login;
|
||||
char *nows;
|
||||
struct passwd *pwd;
|
||||
time_t now;
|
||||
char path[MAXPATHLEN], host[MAXHOSTNAMELEN + 1], line[512];
|
||||
char host[MAXHOSTNAMELEN + 1], line[512];
|
||||
|
||||
/* Determine our login name before the we reopen() stdout */
|
||||
/* Determine our login name before we re-open stdout */
|
||||
if ((login = getlogin()) == NULL) {
|
||||
if ((pwd = getpwuid(myuid)) != NULL)
|
||||
login = pwd->pw_name;
|
||||
else login = "???";
|
||||
}
|
||||
(void)snprintf(path, sizeof path, _PATH_DEV "%s", tty);
|
||||
if ((freopen(path, "w", stdout)) == NULL)
|
||||
err(1, "%s", path);
|
||||
|
||||
if (dup2(ttyfd, STDOUT_FILENO) == -1)
|
||||
err(1, "dup2");
|
||||
|
||||
(void)signal(SIGINT, done);
|
||||
(void)signal(SIGHUP, done);
|
||||
(void)close(ttyfd);
|
||||
|
||||
/* print greeting */
|
||||
if (gethostname(host, sizeof(host)) < 0)
|
||||
@ -264,7 +314,7 @@ do_write(const char *tty, const char *mytty, const uid_t myuid)
|
||||
now = time((time_t *)NULL);
|
||||
nows = ctime(&now);
|
||||
nows[16] = '\0';
|
||||
(void)printf("\r\n\007\007\007Message from %s@%s on %s at %s ...\r\n",
|
||||
(void)printf("\r\n\a\a\aMessage from %s@%s on %s at %s ...\r\n",
|
||||
login, host, mytty, nows + 11);
|
||||
|
||||
while (fgets(line, sizeof(line), stdin) != NULL)
|
||||
@ -275,11 +325,14 @@ do_write(const char *tty, const char *mytty, const uid_t myuid)
|
||||
* done - cleanup and exit
|
||||
*/
|
||||
void
|
||||
done(int dummy)
|
||||
done(int signo)
|
||||
{
|
||||
|
||||
(void)printf("EOF\r\n");
|
||||
exit(0);
|
||||
(void)write(STDOUT_FILENO, "EOF\r\n", sizeof("EOF\r\n") - 1);
|
||||
if (signo == 0)
|
||||
exit(0);
|
||||
else
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -289,7 +342,7 @@ done(int dummy)
|
||||
void
|
||||
wr_fputs(char *s)
|
||||
{
|
||||
char c;
|
||||
unsigned char c;
|
||||
|
||||
#define PUTC(c) if (putchar(c) == EOF) goto err;
|
||||
|
||||
@ -297,13 +350,11 @@ wr_fputs(char *s)
|
||||
c = toascii(*s);
|
||||
if (c == '\n') {
|
||||
PUTC('\r');
|
||||
PUTC('\n');
|
||||
} else if (!isprint((unsigned char)c) &&
|
||||
!isspace((unsigned char)c) && c != '\007') {
|
||||
} else if (!isprint(c) && !isspace(c) && c != '\a') {
|
||||
PUTC('^');
|
||||
PUTC(c^0x40); /* DEL to ?, others to alpha */
|
||||
} else
|
||||
PUTC(c);
|
||||
c ^= 0x40; /* DEL to ?, others to alpha */
|
||||
}
|
||||
PUTC(c);
|
||||
}
|
||||
return;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user