1 /* write - write to a logged in user Authors: N. Andrew and F. van Kempen */
4 * Usage: write [-c] [-v] user [tty]
5 * -c Read & write one character at a time (cbreak mode)
8 * Version: 1.6 10/24/92
10 * NOTES: Write requires 1.4a (or higher) libraries,
11 * for getopt(), strchr().
13 * Authors: Nick Andrew (nick@nswitgould.oz) - Public Domain
14 * Fred van Kempen (minixug!waltje@kyber.uucp)
17 #include <sys/types.h>
31 static char *Version
= "@(#) WRITE 1.6 (10/24/92)";
34 int otty
; /* file desc of callee's terminal */
35 short int cbreak
= 0; /* are we in CBREAK (-c) mode? */
36 short int verbose
= 0; /* are we in VERBOSE (-v) mode? */
37 short int writing
= 0; /* is there a connection? */
38 char *user
= NULL
; /* callee's user name */
39 char *tty
= NULL
; /* callee's terminal if given */
40 char *ourtty
= NULL
; /* our terminal name */
41 struct termios ttyold
, ttynew
; /* our tty controlling structs */
45 int main(int argc
, char **argv
);
47 void settty(char *utty
);
49 void escape(char *cmd
);
56 /* Search the UTMP database for the user we want. */
58 static char utmptty
[16];
60 struct passwd
*userptr
;
64 if (ourtty
== NULL
) ourtty
= "/dev/console";
66 if (user
== NULL
) exit(-1);
67 if ((userptr
= getpwnam(user
)) == NULL
) {
68 fprintf(stderr
, "No such user: %s\n", user
);
71 if (verbose
) fprintf(stderr
, "Trying to write to %s\n",
74 if ((utmpfd
= open(_PATH_UTMP
, O_RDONLY
)) < 0) {
75 fprintf(stderr
, "Cannot open utmp file\n");
80 /* We want to find if 'user' is logged on, and return in utmptty[]
81 * 'user' `s terminal, and if 'user' is logged onto the tty the
82 * caller specified, return that tty name. */
83 while (read(utmpfd
, (char *) &utmp
, sizeof(utmp
)) == sizeof(utmp
)) {
84 /* is this the user we are looking for? */
85 if (strncmp(utmp
.ut_name
, user
, sizeof(utmp
.ut_name
))) continue;
87 strcpy(utmptty
, utmp
.ut_line
);
88 /* is he on the terminal we want to write to? */
89 if (tty
== NULL
|| !strcmp(utmptty
, tty
)) {
94 if (utmptty
[0] == '\0') {
95 fprintf(stderr
, "%s is not logged on\n", user
);
98 if (tty
!= NULL
&& strcmp(utmptty
, tty
)) {
99 fprintf(stderr
, "%s is logged onto %s, not %s\n", user
, utmptty
, tty
);
104 if (verbose
) fprintf(stderr
, "Writing to %s on %s\n", user
, utmptty
);
110 char *utty
; /* name of terminal found in utmp */
112 /* Open other person's terminal and setup our own terminal. */
116 sprintf(buff
, "/dev/%s", utty
);
117 if ((otty
= open(buff
, O_WRONLY
)) < 0) {
118 fprintf(stderr
, "Cannot open %s to write to %s\n", utty
, user
);
119 fprintf(stderr
, "It may have write permission turned off\n");
122 tcgetattr(0, &ttyold
);
123 tcgetattr(0, &ttynew
);
124 ttynew
.c_lflag
&= ~(ICANON
|ECHO
);
125 signal(SIGINT
, intr
);
126 if (cbreak
) tcsetattr(0, TCSANOW
, &ttynew
);
139 pw
= getpwuid(getuid());
141 fprintf(stderr
, "unknown user\n");
144 if ((sp
= strrchr(ourtty
, '/')) != NULL
)
149 sprintf(buff
, "\nMessage from %s (%s) %-24.24s...\n",
150 pw
->pw_name
, sp
, ctime(&now
));
152 write(otty
, buff
, strlen(buff
));
166 for (x
= cmd
; *x
; ++x
)
167 if (*x
== '\n') *x
= '\0';
176 /* The write loop. */
184 while ((n
= read(0, line
, 79)) > 0) {
185 if (line
[0] == '\004') break; /* EOT */
187 if (cbreak
&& line
[0] == '\n') cb_esc
= 1;
189 if (cbreak
) write(1, line
, n
);
191 if (line
[0] == '!') {
192 if (cbreak
&& cb_esc
) {
194 tcsetattr(0, TCSANOW
, &ttyold
);
197 tcsetattr(0, TCSANOW
, &ttynew
);
199 write(otty
, line
, n
);
204 write(otty
, line
, n
);
206 write(1, "\nEOT\n", 5);
207 write(otty
, "\nEOT\n", 5);
213 fprintf(stderr
, "usage: write [-c] [-v] user [tty]\n");
214 fprintf(stderr
, "\t-c : cbreak mode\n\t-v : verbose\n");
226 setbuf(stdout
, (char *) NULL
);
229 while ((c
= getopt(argc
, argv
, "cv")) != EOF
) switch (c
) {
230 case 'c': cbreak
= 1; break;
231 case 'v': verbose
= 1; break;
236 /* Parse user and tty arguments */
238 user
= argv
[optind
++];
240 /* WTMP usernames are 1-8 chars */
241 if (strlen(user
) > 8) *(user
+ 8) = '\0';
244 tty
= argv
[optind
++];
245 if (optind
< argc
) usage();
250 sp
= finduser(); /* find which tty to write onto */
251 if (sp
!= NULL
) { /* did we find one? */
252 settty(sp
); /* setup our terminal */
253 sayhello(); /* print the initial message */
254 writetty(); /* the write loop */
255 tcsetattr(0, TCSANOW
, &ttyold
);
262 int dummy
; /* to satisfy the prototype */
264 /* The interrupt key has been hit. exit cleanly. */
266 signal(SIGINT
, SIG_IGN
);
267 fprintf(stderr
, "\nInterrupt. Exiting write\n");
268 tcsetattr(0, TCSANOW
, &ttyold
);
269 if (writing
) write(otty
, "\nEOT\n", 5);