kernel: restore setting KTS_NONE
[minix.git] / commands / write / write.c
blob5988bae709c85809e0ea67abe88f450ae0ac0bcf
1 /* write - write to a logged in user Authors: N. Andrew and F. van Kempen */
3 /*
4 * Usage: write [-c] [-v] user [tty]
5 * -c Read & write one character at a time (cbreak mode)
6 * -v Verbose
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>
18 #include <fcntl.h>
19 #include <pwd.h>
20 #include <termios.h>
21 #include <signal.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <unistd.h>
25 #include <utmp.h>
26 #include <time.h>
27 #include <stdio.h>
28 #include <paths.h>
30 static char *Version = "@(#) WRITE 1.6 (10/24/92)";
32 int otty; /* file desc of callee's terminal */
33 short int cbreak = 0; /* are we in CBREAK (-c) mode? */
34 short int verbose = 0; /* are we in VERBOSE (-v) mode? */
35 short int writing = 0; /* is there a connection? */
36 char *user = NULL; /* callee's user name */
37 char *tty = NULL; /* callee's terminal if given */
38 char *ourtty = NULL; /* our terminal name */
39 struct termios ttyold, ttynew; /* our tty controlling structs */
41 extern int optind;
43 int main(int argc, char **argv);
44 char *finduser(void);
45 void settty(char *utty);
46 void sayhello(void);
47 void escape(char *cmd);
48 void writetty(void);
49 void usage(void);
50 void intr(int dummy);
52 char *finduser()
54 /* Search the UTMP database for the user we want. */
56 static char utmptty[16];
57 struct utmp utmp;
58 struct passwd *userptr;
59 int utmpfd;
61 ourtty = ttyname(0);
62 if (ourtty == NULL) ourtty = "/dev/console";
64 if (user == NULL) exit(-1);
65 if ((userptr = getpwnam(user)) == NULL) {
66 fprintf(stderr, "No such user: %s\n", user);
67 return(NULL);
69 if (verbose) fprintf(stderr, "Trying to write to %s\n",
70 userptr->pw_gecos);
72 if ((utmpfd = open(_PATH_UTMP, O_RDONLY)) < 0) {
73 fprintf(stderr, "Cannot open utmp file\n");
74 return(NULL);
76 utmptty[0] = '\0';
78 /* We want to find if 'user' is logged on, and return in utmptty[]
79 * 'user' `s terminal, and if 'user' is logged onto the tty the
80 * caller specified, return that tty name. */
81 while (read(utmpfd, (char *) &utmp, sizeof(utmp)) == sizeof(utmp)) {
82 /* is this the user we are looking for? */
83 if (strncmp(utmp.ut_name, user, sizeof(utmp.ut_name))) continue;
85 strcpy(utmptty, utmp.ut_line);
86 /* is he on the terminal we want to write to? */
87 if (tty == NULL || !strcmp(utmptty, tty)) {
88 break;
92 if (utmptty[0] == '\0') {
93 fprintf(stderr, "%s is not logged on\n", user);
94 return( NULL);
96 if (tty != NULL && strcmp(utmptty, tty)) {
97 fprintf(stderr, "%s is logged onto %s, not %s\n", user, utmptty, tty);
98 return( NULL);
100 close(utmpfd);
102 if (verbose) fprintf(stderr, "Writing to %s on %s\n", user, utmptty);
103 return(utmptty);
107 void settty(utty)
108 char *utty; /* name of terminal found in utmp */
110 /* Open other person's terminal and setup our own terminal. */
112 char buff[48];
114 sprintf(buff, "/dev/%s", utty);
115 if ((otty = open(buff, O_WRONLY)) < 0) {
116 fprintf(stderr, "Cannot open %s to write to %s\n", utty, user);
117 fprintf(stderr, "It may have write permission turned off\n");
118 exit(-1);
120 tcgetattr(0, &ttyold);
121 tcgetattr(0, &ttynew);
122 ttynew.c_lflag &= ~(ICANON|ECHO);
123 signal(SIGINT, intr);
124 if (cbreak) tcsetattr(0, TCSANOW, &ttynew);
128 void sayhello()
130 struct passwd *pw;
131 char buff[128];
132 long now;
133 char *sp;
135 time(&now);
137 pw = getpwuid(getuid());
138 if (pw == NULL) {
139 fprintf(stderr, "unknown user\n");
140 exit(-1);
142 if ((sp = strrchr(ourtty, '/')) != NULL)
143 ++sp;
144 else
145 sp = ourtty;
147 sprintf(buff, "\nMessage from %s (%s) %-24.24s...\n",
148 pw->pw_name, sp, ctime(&now));
150 write(otty, buff, strlen(buff));
151 printf("\007\007");
152 fflush(stdout);
156 void escape(cmd)
157 char *cmd;
159 /* Shell escape. */
161 register char *x;
163 write(1, "!\n", 2);
164 for (x = cmd; *x; ++x)
165 if (*x == '\n') *x = '\0';
167 system(cmd);
168 write(1, "!\n", 2);
172 void writetty()
174 /* The write loop. */
176 char line[80];
177 int n, cb_esc;
179 writing = 1;
180 cb_esc = 0;
182 while ((n = read(0, line, 79)) > 0) {
183 if (line[0] == '\004') break; /* EOT */
185 if (cbreak && line[0] == '\n') cb_esc = 1;
187 if (cbreak) write(1, line, n);
189 if (line[0] == '!') {
190 if (cbreak && cb_esc) {
191 cb_esc = 0;
192 tcsetattr(0, TCSANOW, &ttyold);
193 read(0, line, 79);
194 escape(line);
195 tcsetattr(0, TCSANOW, &ttynew);
196 } else if (cbreak)
197 write(otty, line, n);
198 else
199 escape(&line[1]);
200 continue;
202 write(otty, line, n);
204 write(1, "\nEOT\n", 5);
205 write(otty, "\nEOT\n", 5);
209 void usage()
211 fprintf(stderr, "usage: write [-c] [-v] user [tty]\n");
212 fprintf(stderr, "\t-c : cbreak mode\n\t-v : verbose\n");
213 exit(-1);
217 int main(argc, argv)
218 int argc;
219 char *argv[];
221 register int c;
222 char *sp;
224 setbuf(stdout, (char *) NULL);
226 /* Parse options. */
227 while ((c = getopt(argc, argv, "cv")) != EOF) switch (c) {
228 case 'c': cbreak = 1; break;
229 case 'v': verbose = 1; break;
230 default:
231 usage();
234 /* Parse user and tty arguments */
235 if (optind < argc) {
236 user = argv[optind++];
238 /* WTMP usernames are 1-8 chars */
239 if (strlen(user) > 8) *(user + 8) = '\0';
241 if (optind < argc) {
242 tty = argv[optind++];
243 if (optind < argc) usage();
245 } else
246 usage();
248 sp = finduser(); /* find which tty to write onto */
249 if (sp != NULL) { /* did we find one? */
250 settty(sp); /* setup our terminal */
251 sayhello(); /* print the initial message */
252 writetty(); /* the write loop */
253 tcsetattr(0, TCSANOW, &ttyold);
254 exit(0);
256 return(-1);
259 void intr(dummy)
260 int dummy; /* to satisfy the prototype */
262 /* The interrupt key has been hit. exit cleanly. */
264 signal(SIGINT, SIG_IGN);
265 fprintf(stderr, "\nInterrupt. Exiting write\n");
266 tcsetattr(0, TCSANOW, &ttyold);
267 if (writing) write(otty, "\nEOT\n", 5);
268 exit(0);