From 4aa9d65bfa76afd0d886ca410ae83428a490d4ea Mon Sep 17 00:00:00 2001 From: Sami Kerola Date: Sun, 12 Jun 2011 00:19:45 +0200 Subject: build-sys: move write to term-utils directory Signed-off-by: Sami Kerola --- misc-utils/.gitignore | 1 - misc-utils/Makefile.am | 15 --- misc-utils/write.1 | 102 -------------- misc-utils/write.c | 359 ------------------------------------------------- term-utils/.gitignore | 1 + term-utils/Makefile.am | 14 +- term-utils/write.1 | 102 ++++++++++++++ term-utils/write.c | 359 +++++++++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 473 insertions(+), 480 deletions(-) delete mode 100644 misc-utils/write.1 delete mode 100644 misc-utils/write.c create mode 100644 term-utils/write.1 create mode 100644 term-utils/write.c diff --git a/misc-utils/.gitignore b/misc-utils/.gitignore index d6536be03..897e6d123 100644 --- a/misc-utils/.gitignore +++ b/misc-utils/.gitignore @@ -10,7 +10,6 @@ rename script whereis kill -write uuidgen uuidd findfs diff --git a/misc-utils/Makefile.am b/misc-utils/Makefile.am index 8fd95b894..064437387 100644 --- a/misc-utils/Makefile.am +++ b/misc-utils/Makefile.am @@ -115,18 +115,3 @@ if BUILD_RENAME usrbin_exec_PROGRAMS += rename dist_man_MANS += rename.1 endif - -if BUILD_WRITE -usrbin_exec_PROGRAMS += write -dist_man_MANS += write.1 -write_CFLAGS = $(SUID_CFLAGS) $(AM_CFLAGS) -write_LDFLAGS = $(SUID_LDFLAGS) $(AM_LDFLAGS) - -if USE_TTY_GROUP -if MAKEINSTALL_DO_CHOWN -install-exec-hook:: - chgrp tty $(DESTDIR)$(usrbin_execdir)/write - chmod g+s $(DESTDIR)$(usrbin_execdir)/write -endif -endif -endif diff --git a/misc-utils/write.1 b/misc-utils/write.1 deleted file mode 100644 index 1c15f50c2..000000000 --- a/misc-utils/write.1 +++ /dev/null @@ -1,102 +0,0 @@ -.\" Copyright (c) 1989, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" 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, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)write.1 8.1 (Berkeley) 6/6/93 -.\" -.\" Modified for Linux, Sun Mar 12 10:21:01 1995, faith@cs.unc.edu -.\" -.TH WRITE 1 "12 March 1995" "" "Linux Programmer's Manual" -.SH NAME -write \- send a message to another user -.SH SYNOPSIS -.B write -.I user -.RI [ ttyname ] -.SH DESCRIPTION -.B Write -allows you to communicate with other users, by copying lines from -your terminal to theirs. -.PP -When you run the -.B write -command, the user you are writing to gets a message of the form: -.PP -.RS -Message from yourname@yourhost on yourtty at hh:mm ... -.RE -.PP -Any further lines you enter will be copied to the specified user's -terminal. If the other user wants to reply, they must run -.B write -as well. -.PP -When you are done, type an end-of-file or interrupt character. The other -user will see the message -.B EOF -indicating that the conversation is over. -.PP -You can prevent people (other than the super-user) from writing to you with -the -.BR mesg (1) -command. Some commands, for example -.BR nroff (1) -and -.BR pr (1), -may disallow writing automatically, so that your output isn't overwritten. -.PP -If the user you want to write to is logged in on more than one terminal, -you can specify which terminal to write to by specifying the terminal -name as the second operand to the -.B write -command. Alternatively, you can let -.B write -select one of the terminals \- it will pick the one with the shortest idle -time. This is so that if the user is logged in at work and also dialed up -from home, the message will go to the right place. -.PP -The traditional protocol for writing to someone is that the string `\-o', -either at the end of a line or on a line by itself, means that it's the -other person's turn to talk. The string `oo' means that the person -believes the conversation to be over. -.SH "SEE ALSO" -.BR mesg (1), -.BR talk (1), -.BR who (1) -.SH HISTORY -A -.B write -command appeared in Version 6 AT&T UNIX. -.SH AVAILABILITY -The write command is part of the util-linux package and is available from -ftp://ftp.kernel.org/pub/linux/utils/util-linux/. diff --git a/misc-utils/write.c b/misc-utils/write.c deleted file mode 100644 index c4f4ecc42..000000000 --- a/misc-utils/write.c +++ /dev/null @@ -1,359 +0,0 @@ -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * 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, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * Modified for Linux, Mon Mar 8 18:16:24 1993, faith@cs.unc.edu - * Wed Jun 22 21:41:56 1994, faith@cs.unc.edu: - * Added fix from Mike Grupenhoff (kashmir@umiacs.umd.edu) - * Mon Jul 1 17:01:39 MET DST 1996, janl@math.uio.no: - * - Added fix from David.Chapell@mail.trincoll.edu enabeling daemons - * to use write. - * - ANSIed it since I was working on it anyway. - * 1999-02-22 Arkadiusz Mi¶kiewicz - * - added Native Language Support - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "pathnames.h" -#include "carefulputc.h" -#include "nls.h" - -void search_utmp(char *, char *, char *, uid_t); -void do_write(char *, char *, uid_t); -void wr_fputs(char *); -static void done(int); -int term_chk(char *, int *, time_t *, int); -int utmp_chk(char *, char *); - -static gid_t myegid; - -int -main(int argc, char **argv) { - time_t atime; - uid_t myuid; - int msgsok, myttyfd; - char tty[MAXPATHLEN], *mytty; - - setlocale(LC_ALL, ""); - bindtextdomain(PACKAGE, LOCALEDIR); - textdomain(PACKAGE); - - myegid = getegid(); - - /* check that sender has write enabled */ - if (isatty(fileno(stdin))) - myttyfd = fileno(stdin); - else if (isatty(fileno(stdout))) - myttyfd = fileno(stdout); - else if (isatty(fileno(stderr))) - myttyfd = fileno(stderr); - else { - myttyfd = -1; - } - if (myttyfd != -1) { - if (!(mytty = ttyname(myttyfd))) { - (void)fprintf(stderr, _("write: can't find your tty's name\n")); - exit(1); - } - /* We may have /dev/ttyN but also /dev/pts/xx. - Below, term_chk() will put "/dev/" in front, so remove that part. */ - if (!strncmp(mytty, "/dev/", 5)) - mytty += 5; - if (term_chk(mytty, &msgsok, &atime, 1)) - exit(1); - if (!msgsok) { - (void)fprintf(stderr, - _("write: you have write permission turned off.\n")); - exit(1); - } - - } else { - mytty = ""; - } - - myuid = getuid(); - - /* check args */ - switch (argc) { - case 2: - search_utmp(argv[1], tty, mytty, myuid); - do_write(tty, mytty, myuid); - break; - case 3: - if (!strncmp(argv[2], "/dev/", 5)) - argv[2] += 5; - if (utmp_chk(argv[1], argv[2])) { - (void)fprintf(stderr, - _("write: %s is not logged in on %s.\n"), - argv[1], argv[2]); - exit(1); - } - if (term_chk(argv[2], &msgsok, &atime, 1)) - exit(1); - if (myuid && !msgsok) { - (void)fprintf(stderr, - _("write: %s has messages disabled on %s\n"), - argv[1], argv[2]); - exit(1); - } - do_write(argv[2], mytty, myuid); - break; - default: - (void)fprintf(stderr, _("usage: write user [tty]\n")); - exit(1); - } - done(0); - /* NOTREACHED */ - return 0; -} - - -/* - * utmp_chk - checks that the given user is actually logged in on - * the given tty - */ -int utmp_chk(char *user, char *tty) - -{ - struct utmp u; - struct utmp *uptr; - int res = 1; - - utmpname(_PATH_UTMP); - setutent(); - - while ((uptr = getutent())) { - memcpy(&u, uptr, sizeof(u)); - if (strncmp(user, u.ut_name, sizeof(u.ut_name)) == 0 && - strncmp(tty, u.ut_line, sizeof(u.ut_line)) == 0) { - res = 0; - break; - } - } - - endutent(); - return(res); -} - -/* - * 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 - * not logged in at all. - * - * 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) - -{ - struct utmp u; - struct utmp *uptr; - time_t bestatime, atime; - int nloggedttys, nttys, msgsok, user_is_me; - char atty[sizeof(u.ut_line) + 1]; - - utmpname(_PATH_UTMP); - setutent(); - - nloggedttys = nttys = 0; - bestatime = 0; - user_is_me = 0; - while ((uptr = getutent())) { - memcpy(&u, uptr, sizeof(u)); - if (strncmp(user, u.ut_name, sizeof(u.ut_name)) == 0) { - ++nloggedttys; - (void)strncpy(atty, u.ut_line, sizeof(u.ut_line)); - atty[sizeof(u.ut_line)] = '\0'; - if (term_chk(atty, &msgsok, &atime, 0)) - continue; /* bad term? skip */ - if (myuid && !msgsok) - continue; /* skip ttys with msgs off */ - if (strcmp(atty, mytty) == 0) { - user_is_me = 1; - continue; /* don't write to yourself */ - } - if (u.ut_type != USER_PROCESS) - continue; /* it's not a valid entry */ - ++nttys; - if (atime > bestatime) { - bestatime = atime; - (void)strcpy(tty, atty); - } - } - } - - endutent(); - if (nloggedttys == 0) { - (void)fprintf(stderr, _("write: %s is not logged in\n"), user); - exit(1); - } - if (nttys == 0) { - if (user_is_me) { /* ok, so write to yourself! */ - (void)strcpy(tty, mytty); - return; - } - (void)fprintf(stderr, - _("write: %s has messages disabled\n"), user); - exit(1); - } else if (nttys > 1) { - (void)fprintf(stderr, - _("write: %s is logged in more than once; writing to %s\n"), - user, tty); - } -} - -/* - * term_chk - check that a terminal exists, and get the message bit - * and the access time - */ -int term_chk(char *tty, int *msgsokP, time_t *atimeP, int showerror) - -{ - struct stat s; - char path[MAXPATHLEN]; - - if (strlen(tty) + 6 > sizeof(path)) - return(1); - (void)sprintf(path, "/dev/%s", tty); - if (stat(path, &s) < 0) { - if (showerror) - (void)fprintf(stderr, - "write: %s: %s\n", path, strerror(errno)); - return(1); - } - - /* group write bit and group ownership */ - *msgsokP = (s.st_mode & (S_IWRITE >> 3)) && myegid == s.st_gid; - *atimeP = s.st_atime; - return(0); -} - -/* - * do_write - actually make the connection - */ -void do_write(char *tty, char *mytty, uid_t myuid) { - char *login, *pwuid, *nows; - struct passwd *pwd; - time_t now; - char path[MAXPATHLEN], host[MAXHOSTNAMELEN], line[512]; - - /* Determine our login name(s) before the we reopen() stdout */ - if ((pwd = getpwuid(myuid)) != NULL) - pwuid = pwd->pw_name; - else - pwuid = "???"; - if ((login = getlogin()) == NULL) - login = pwuid; - - if (strlen(tty) + 6 > sizeof(path)) - exit(1); - (void)sprintf(path, "/dev/%s", tty); - if ((freopen(path, "w", stdout)) == NULL) { - (void)fprintf(stderr, "write: %s: %s\n", - path, strerror(errno)); - exit(1); - } - - (void)signal(SIGINT, done); - (void)signal(SIGHUP, done); - - /* print greeting */ - if (gethostname(host, sizeof(host)) < 0) - (void)strcpy(host, "???"); - now = time((time_t *)NULL); - nows = ctime(&now); - nows[16] = '\0'; - printf("\r\n\007\007\007"); - if (strcmp(login, pwuid)) - (void)printf(_("Message from %s@%s (as %s) on %s at %s ..."), - login, host, pwuid, mytty, nows + 11); - else - (void)printf(_("Message from %s@%s on %s at %s ..."), - login, host, mytty, nows + 11); - printf("\r\n"); - - while (fgets(line, sizeof(line), stdin) != NULL) - wr_fputs(line); -} - -/* - * done - cleanup and exit - */ -static void -done(int dummy) { - (void)printf("EOF\r\n"); - _exit(0); -} - -/* - * wr_fputs - like fputs(), but makes control characters visible and - * turns \n into \r\n. - */ -void -wr_fputs(char *s) { - char c; - -#define PUTC(c) if (carefulputc(c,stdout) == EOF) goto err; - - while(*s) { - c = *s++; - if (c == '\n') - PUTC('\r'); - PUTC(c); - } - return; - -err: - fprintf(stderr, "write: %s\n", strerror(errno)); - exit(1); -#undef PUTC -} diff --git a/term-utils/.gitignore b/term-utils/.gitignore index cbc5755c1..e6bb4591d 100644 --- a/term-utils/.gitignore +++ b/term-utils/.gitignore @@ -4,3 +4,4 @@ script scriptreplay setterm wall +write diff --git a/term-utils/Makefile.am b/term-utils/Makefile.am index c40d9db86..5e03560f1 100644 --- a/term-utils/Makefile.am +++ b/term-utils/Makefile.am @@ -55,12 +55,20 @@ if BUILD_WALL usrbin_exec_PROGRAMS += wall wall_SOURCES = wall.c ttymsg.c ttymsg.h $(top_srcdir)/lib/strutils.c dist_man_MANS += wall.1 +endif + +if BUILD_WRITE +usrbin_exec_PROGRAMS += write +dist_man_MANS += write.1 +write_CFLAGS = $(SUID_CFLAGS) $(AM_CFLAGS) +write_LDFLAGS = $(SUID_LDFLAGS) $(AM_LDFLAGS) +endif if USE_TTY_GROUP if MAKEINSTALL_DO_CHOWN install-exec-hook:: - chgrp tty $(DESTDIR)$(usrbin_execdir)/wall - chmod g+s $(DESTDIR)$(usrbin_execdir)/wall -endif + chgrp tty $(DESTDIR)$(usrbin_execdir)/wall $(DESTDIR)$(usrbin_execdir)/write + chmod g+s $(DESTDIR)$(usrbin_execdir)/wall $(DESTDIR)$(usrbin_execdir)/write + endif endif diff --git a/term-utils/write.1 b/term-utils/write.1 new file mode 100644 index 000000000..1c15f50c2 --- /dev/null +++ b/term-utils/write.1 @@ -0,0 +1,102 @@ +.\" Copyright (c) 1989, 1993 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" 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, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. All advertising materials mentioning features or use of this software +.\" must display the following acknowledgement: +.\" This product includes software developed by the University of +.\" California, Berkeley and its contributors. +.\" 4. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)write.1 8.1 (Berkeley) 6/6/93 +.\" +.\" Modified for Linux, Sun Mar 12 10:21:01 1995, faith@cs.unc.edu +.\" +.TH WRITE 1 "12 March 1995" "" "Linux Programmer's Manual" +.SH NAME +write \- send a message to another user +.SH SYNOPSIS +.B write +.I user +.RI [ ttyname ] +.SH DESCRIPTION +.B Write +allows you to communicate with other users, by copying lines from +your terminal to theirs. +.PP +When you run the +.B write +command, the user you are writing to gets a message of the form: +.PP +.RS +Message from yourname@yourhost on yourtty at hh:mm ... +.RE +.PP +Any further lines you enter will be copied to the specified user's +terminal. If the other user wants to reply, they must run +.B write +as well. +.PP +When you are done, type an end-of-file or interrupt character. The other +user will see the message +.B EOF +indicating that the conversation is over. +.PP +You can prevent people (other than the super-user) from writing to you with +the +.BR mesg (1) +command. Some commands, for example +.BR nroff (1) +and +.BR pr (1), +may disallow writing automatically, so that your output isn't overwritten. +.PP +If the user you want to write to is logged in on more than one terminal, +you can specify which terminal to write to by specifying the terminal +name as the second operand to the +.B write +command. Alternatively, you can let +.B write +select one of the terminals \- it will pick the one with the shortest idle +time. This is so that if the user is logged in at work and also dialed up +from home, the message will go to the right place. +.PP +The traditional protocol for writing to someone is that the string `\-o', +either at the end of a line or on a line by itself, means that it's the +other person's turn to talk. The string `oo' means that the person +believes the conversation to be over. +.SH "SEE ALSO" +.BR mesg (1), +.BR talk (1), +.BR who (1) +.SH HISTORY +A +.B write +command appeared in Version 6 AT&T UNIX. +.SH AVAILABILITY +The write command is part of the util-linux package and is available from +ftp://ftp.kernel.org/pub/linux/utils/util-linux/. diff --git a/term-utils/write.c b/term-utils/write.c new file mode 100644 index 000000000..c4f4ecc42 --- /dev/null +++ b/term-utils/write.c @@ -0,0 +1,359 @@ +/* + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * 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, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * Modified for Linux, Mon Mar 8 18:16:24 1993, faith@cs.unc.edu + * Wed Jun 22 21:41:56 1994, faith@cs.unc.edu: + * Added fix from Mike Grupenhoff (kashmir@umiacs.umd.edu) + * Mon Jul 1 17:01:39 MET DST 1996, janl@math.uio.no: + * - Added fix from David.Chapell@mail.trincoll.edu enabeling daemons + * to use write. + * - ANSIed it since I was working on it anyway. + * 1999-02-22 Arkadiusz Mi¶kiewicz + * - added Native Language Support + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pathnames.h" +#include "carefulputc.h" +#include "nls.h" + +void search_utmp(char *, char *, char *, uid_t); +void do_write(char *, char *, uid_t); +void wr_fputs(char *); +static void done(int); +int term_chk(char *, int *, time_t *, int); +int utmp_chk(char *, char *); + +static gid_t myegid; + +int +main(int argc, char **argv) { + time_t atime; + uid_t myuid; + int msgsok, myttyfd; + char tty[MAXPATHLEN], *mytty; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + myegid = getegid(); + + /* check that sender has write enabled */ + if (isatty(fileno(stdin))) + myttyfd = fileno(stdin); + else if (isatty(fileno(stdout))) + myttyfd = fileno(stdout); + else if (isatty(fileno(stderr))) + myttyfd = fileno(stderr); + else { + myttyfd = -1; + } + if (myttyfd != -1) { + if (!(mytty = ttyname(myttyfd))) { + (void)fprintf(stderr, _("write: can't find your tty's name\n")); + exit(1); + } + /* We may have /dev/ttyN but also /dev/pts/xx. + Below, term_chk() will put "/dev/" in front, so remove that part. */ + if (!strncmp(mytty, "/dev/", 5)) + mytty += 5; + if (term_chk(mytty, &msgsok, &atime, 1)) + exit(1); + if (!msgsok) { + (void)fprintf(stderr, + _("write: you have write permission turned off.\n")); + exit(1); + } + + } else { + mytty = ""; + } + + myuid = getuid(); + + /* check args */ + switch (argc) { + case 2: + search_utmp(argv[1], tty, mytty, myuid); + do_write(tty, mytty, myuid); + break; + case 3: + if (!strncmp(argv[2], "/dev/", 5)) + argv[2] += 5; + if (utmp_chk(argv[1], argv[2])) { + (void)fprintf(stderr, + _("write: %s is not logged in on %s.\n"), + argv[1], argv[2]); + exit(1); + } + if (term_chk(argv[2], &msgsok, &atime, 1)) + exit(1); + if (myuid && !msgsok) { + (void)fprintf(stderr, + _("write: %s has messages disabled on %s\n"), + argv[1], argv[2]); + exit(1); + } + do_write(argv[2], mytty, myuid); + break; + default: + (void)fprintf(stderr, _("usage: write user [tty]\n")); + exit(1); + } + done(0); + /* NOTREACHED */ + return 0; +} + + +/* + * utmp_chk - checks that the given user is actually logged in on + * the given tty + */ +int utmp_chk(char *user, char *tty) + +{ + struct utmp u; + struct utmp *uptr; + int res = 1; + + utmpname(_PATH_UTMP); + setutent(); + + while ((uptr = getutent())) { + memcpy(&u, uptr, sizeof(u)); + if (strncmp(user, u.ut_name, sizeof(u.ut_name)) == 0 && + strncmp(tty, u.ut_line, sizeof(u.ut_line)) == 0) { + res = 0; + break; + } + } + + endutent(); + return(res); +} + +/* + * 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 + * not logged in at all. + * + * 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) + +{ + struct utmp u; + struct utmp *uptr; + time_t bestatime, atime; + int nloggedttys, nttys, msgsok, user_is_me; + char atty[sizeof(u.ut_line) + 1]; + + utmpname(_PATH_UTMP); + setutent(); + + nloggedttys = nttys = 0; + bestatime = 0; + user_is_me = 0; + while ((uptr = getutent())) { + memcpy(&u, uptr, sizeof(u)); + if (strncmp(user, u.ut_name, sizeof(u.ut_name)) == 0) { + ++nloggedttys; + (void)strncpy(atty, u.ut_line, sizeof(u.ut_line)); + atty[sizeof(u.ut_line)] = '\0'; + if (term_chk(atty, &msgsok, &atime, 0)) + continue; /* bad term? skip */ + if (myuid && !msgsok) + continue; /* skip ttys with msgs off */ + if (strcmp(atty, mytty) == 0) { + user_is_me = 1; + continue; /* don't write to yourself */ + } + if (u.ut_type != USER_PROCESS) + continue; /* it's not a valid entry */ + ++nttys; + if (atime > bestatime) { + bestatime = atime; + (void)strcpy(tty, atty); + } + } + } + + endutent(); + if (nloggedttys == 0) { + (void)fprintf(stderr, _("write: %s is not logged in\n"), user); + exit(1); + } + if (nttys == 0) { + if (user_is_me) { /* ok, so write to yourself! */ + (void)strcpy(tty, mytty); + return; + } + (void)fprintf(stderr, + _("write: %s has messages disabled\n"), user); + exit(1); + } else if (nttys > 1) { + (void)fprintf(stderr, + _("write: %s is logged in more than once; writing to %s\n"), + user, tty); + } +} + +/* + * term_chk - check that a terminal exists, and get the message bit + * and the access time + */ +int term_chk(char *tty, int *msgsokP, time_t *atimeP, int showerror) + +{ + struct stat s; + char path[MAXPATHLEN]; + + if (strlen(tty) + 6 > sizeof(path)) + return(1); + (void)sprintf(path, "/dev/%s", tty); + if (stat(path, &s) < 0) { + if (showerror) + (void)fprintf(stderr, + "write: %s: %s\n", path, strerror(errno)); + return(1); + } + + /* group write bit and group ownership */ + *msgsokP = (s.st_mode & (S_IWRITE >> 3)) && myegid == s.st_gid; + *atimeP = s.st_atime; + return(0); +} + +/* + * do_write - actually make the connection + */ +void do_write(char *tty, char *mytty, uid_t myuid) { + char *login, *pwuid, *nows; + struct passwd *pwd; + time_t now; + char path[MAXPATHLEN], host[MAXHOSTNAMELEN], line[512]; + + /* Determine our login name(s) before the we reopen() stdout */ + if ((pwd = getpwuid(myuid)) != NULL) + pwuid = pwd->pw_name; + else + pwuid = "???"; + if ((login = getlogin()) == NULL) + login = pwuid; + + if (strlen(tty) + 6 > sizeof(path)) + exit(1); + (void)sprintf(path, "/dev/%s", tty); + if ((freopen(path, "w", stdout)) == NULL) { + (void)fprintf(stderr, "write: %s: %s\n", + path, strerror(errno)); + exit(1); + } + + (void)signal(SIGINT, done); + (void)signal(SIGHUP, done); + + /* print greeting */ + if (gethostname(host, sizeof(host)) < 0) + (void)strcpy(host, "???"); + now = time((time_t *)NULL); + nows = ctime(&now); + nows[16] = '\0'; + printf("\r\n\007\007\007"); + if (strcmp(login, pwuid)) + (void)printf(_("Message from %s@%s (as %s) on %s at %s ..."), + login, host, pwuid, mytty, nows + 11); + else + (void)printf(_("Message from %s@%s on %s at %s ..."), + login, host, mytty, nows + 11); + printf("\r\n"); + + while (fgets(line, sizeof(line), stdin) != NULL) + wr_fputs(line); +} + +/* + * done - cleanup and exit + */ +static void +done(int dummy) { + (void)printf("EOF\r\n"); + _exit(0); +} + +/* + * wr_fputs - like fputs(), but makes control characters visible and + * turns \n into \r\n. + */ +void +wr_fputs(char *s) { + char c; + +#define PUTC(c) if (carefulputc(c,stdout) == EOF) goto err; + + while(*s) { + c = *s++; + if (c == '\n') + PUTC('\r'); + PUTC(c); + } + return; + +err: + fprintf(stderr, "write: %s\n", strerror(errno)); + exit(1); +#undef PUTC +} -- cgit v1.2.3-55-g7522