* Copyright (c) 1989 The Regents of the University of California.
* This code is derived from software contributed to Berkeley by
* Jef Poskanzer and Craig Leres of the Lawrence Berkeley Laboratory.
* 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 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
"@(#) Copyright (c) 1989 The Regents of the University of California.\n\
static char sccsid
[] = "@(#)write.c 4.20 (Berkeley) %G%";
char tty
[MAXPATHLEN
], *mytty
, *ttyname();
/* check that sender has write enabled */
if (isatty(fileno(stdin
)))
else if (isatty(fileno(stdout
)))
myttyfd
= fileno(stdout
);
else if (isatty(fileno(stderr
)))
myttyfd
= fileno(stderr
);
(void)fprintf(stderr
, "write: can't find your tty\n");
if (!(mytty
= ttyname(myttyfd
))) {
(void)fprintf(stderr
, "write: can't find your tty's name\n");
if (cp
= rindex(mytty
, '/'))
if (term_chk(mytty
, &msgsok
, &atime
, 1))
"write: you have write permission turned off.\n");
search_utmp(argv
[1], tty
, mytty
, myuid
);
do_write(tty
, mytty
, myuid
);
if (!strncmp(argv
[2], "/dev/", 5))
if (utmp_chk(argv
[1], argv
[2])) {
"write: %s is not logged in on %s.\n",
if (term_chk(argv
[2], &msgsok
, &atime
, 1))
"write: %s has messages disabled on %s\n",
do_write(argv
[2], mytty
, myuid
);
(void)fprintf(stderr
, "usage: write user [tty]\n");
* utmp_chk - checks that the given user is actually logged in on
if ((ufd
= open(_PATH_UTMP
, O_RDONLY
)) < 0)
return(0); /* ignore error, shouldn't happen anyway */
while (read(ufd
, (char *) &u
, sizeof(u
)) == sizeof(u
))
if (strncmp(user
, u
.ut_name
, sizeof(u
.ut_name
)) == 0 &&
strncmp(tty
, u
.ut_line
, sizeof(u
.ut_line
)) == 0) {
* search_utmp - search utmp for the "best" terminal to write to
* Ignores terminals with messages disabled, and of the rest, returns
* the one with the most recent access time. Returns as value the number
* of the user's terminals with messages enabled, or -1 if the user is
* Special case for writing to yourself - ignore the terminal you're
* writing from, unless that's the only terminal with messages enabled.
search_utmp(user
, tty
, mytty
, myuid
)
char *user
, *tty
, *mytty
;
int ufd
, nloggedttys
, nttys
, msgsok
, user_is_me
;
char atty
[UT_LINESIZE
+ 1];
if ((ufd
= open(_PATH_UTMP
, O_RDONLY
)) < 0) {
while (read(ufd
, (char *) &u
, sizeof(u
)) == sizeof(u
))
if (strncmp(user
, u
.ut_name
, sizeof(u
.ut_name
)) == 0) {
(void)strncpy(atty
, u
.ut_line
, UT_LINESIZE
);
atty
[UT_LINESIZE
] = '\0';
if (term_chk(atty
, &msgsok
, &atime
, 0))
continue; /* bad term? skip */
continue; /* skip ttys with msgs off */
if (strcmp(atty
, mytty
) == 0) {
continue; /* don't write to yourself */
(void)fprintf(stderr
, "write: %s is not logged in\n", user
);
if (user_is_me
) { /* ok, so write to yourself! */
(void)strcpy(tty
, mytty
);
"write: %s has messages disabled\n", user
);
"write: %s is logged in more than once; writing to %s\n",
* term_chk - check that a terminal exists, and get the message bit
term_chk(tty
, msgsokP
, atimeP
, showerror
)
(void)sprintf(path
, "/dev/%s", tty
);
if (stat(path
, &s
) < 0) {
"write: %s: %s\n", path
, strerror(errno
));
*msgsokP
= (s
.st_mode
& (S_IWRITE
>> 3)) != 0; /* group write bit */
* do_write - actually make the connection
do_write(tty
, mytty
, myuid
)
register char *login
, *nows
;
register struct passwd
*pwd
;
char *getlogin(), path
[MAXPATHLEN
], host
[MAXHOSTNAMELEN
], line
[512];
/* Determine our login name before the we reopen() stdout */
if ((login
= getlogin()) == NULL
)
if (pwd
= getpwuid(myuid
))
(void)sprintf(path
, "/dev/%s", tty
);
if ((freopen(path
, "w", stdout
)) == NULL
) {
(void)fprintf(stderr
, "write: %s: %s\n", path
, strerror(errno
));
(void)signal(SIGINT
, done
);
(void)signal(SIGHUP
, done
);
if (gethostname(host
, sizeof(host
)) < 0)
(void)strcpy(host
, "???");
now
= time((time_t *)NULL
);
(void)printf("\r\n\007\007\007Message from %s@%s on %s at %s ...\r\n",
login
, host
, mytty
, nows
+ 11);
while (fgets(line
, sizeof(line
), stdin
) != NULL
)
* done - cleanup and exit
* wr_fputs - like fputs(), but makes control characters visible and
#define PUTC(c) if (putchar(c) == EOF) goto err;
for (; *s
!= '\0'; ++s
) {
} else if (!isprint(c
) && !isspace(c
) && c
!= '\007') {
PUTC(c
^0x40); /* DEL to ?, others to alpha */
err
: (void)fprintf(stderr
, "write: %s\n", strerror(errno
));