add opendir alias
[minix.git] / commands / write / write.c
blob335f49d682431712313df7f2aa0e6015050cd3f1
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 #if 0
31 static char *Version = "@(#) WRITE 1.6 (10/24/92)";
32 #endif
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 */
43 extern int optind;
45 int main(int argc, char **argv);
46 char *finduser(void);
47 void settty(char *utty);
48 void sayhello(void);
49 void escape(char *cmd);
50 void writetty(void);
51 void usage(void);
52 void intr(int dummy);
54 char *finduser()
56 /* Search the UTMP database for the user we want. */
58 static char utmptty[16];
59 struct utmp utmp;
60 struct passwd *userptr;
61 int utmpfd;
63 ourtty = ttyname(0);
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);
69 return(NULL);
71 if (verbose) fprintf(stderr, "Trying to write to %s\n",
72 userptr->pw_gecos);
74 if ((utmpfd = open(_PATH_UTMP, O_RDONLY)) < 0) {
75 fprintf(stderr, "Cannot open utmp file\n");
76 return(NULL);
78 utmptty[0] = '\0';
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)) {
90 break;
94 if (utmptty[0] == '\0') {
95 fprintf(stderr, "%s is not logged on\n", user);
96 return( NULL);
98 if (tty != NULL && strcmp(utmptty, tty)) {
99 fprintf(stderr, "%s is logged onto %s, not %s\n", user, utmptty, tty);
100 return( NULL);
102 close(utmpfd);
104 if (verbose) fprintf(stderr, "Writing to %s on %s\n", user, utmptty);
105 return(utmptty);
109 void settty(utty)
110 char *utty; /* name of terminal found in utmp */
112 /* Open other person's terminal and setup our own terminal. */
114 char buff[48];
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");
120 exit(-1);
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);
130 void sayhello()
132 struct passwd *pw;
133 char buff[128];
134 time_t now;
135 char *sp;
137 time(&now);
139 pw = getpwuid(getuid());
140 if (pw == NULL) {
141 fprintf(stderr, "unknown user\n");
142 exit(-1);
144 if ((sp = strrchr(ourtty, '/')) != NULL)
145 ++sp;
146 else
147 sp = ourtty;
149 sprintf(buff, "\nMessage from %s (%s) %-24.24s...\n",
150 pw->pw_name, sp, ctime(&now));
152 write(otty, buff, strlen(buff));
153 printf("\007\007");
154 fflush(stdout);
158 void escape(cmd)
159 char *cmd;
161 /* Shell escape. */
163 register char *x;
165 write(1, "!\n", 2);
166 for (x = cmd; *x; ++x)
167 if (*x == '\n') *x = '\0';
169 system(cmd);
170 write(1, "!\n", 2);
174 void writetty()
176 /* The write loop. */
178 char line[80];
179 int n, cb_esc;
181 writing = 1;
182 cb_esc = 0;
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) {
193 cb_esc = 0;
194 tcsetattr(0, TCSANOW, &ttyold);
195 read(0, line, 79);
196 escape(line);
197 tcsetattr(0, TCSANOW, &ttynew);
198 } else if (cbreak)
199 write(otty, line, n);
200 else
201 escape(&line[1]);
202 continue;
204 write(otty, line, n);
206 write(1, "\nEOT\n", 5);
207 write(otty, "\nEOT\n", 5);
211 void usage()
213 fprintf(stderr, "usage: write [-c] [-v] user [tty]\n");
214 fprintf(stderr, "\t-c : cbreak mode\n\t-v : verbose\n");
215 exit(-1);
219 int main(argc, argv)
220 int argc;
221 char *argv[];
223 register int c;
224 char *sp;
226 setbuf(stdout, (char *) NULL);
228 /* Parse options. */
229 while ((c = getopt(argc, argv, "cv")) != EOF) switch (c) {
230 case 'c': cbreak = 1; break;
231 case 'v': verbose = 1; break;
232 default:
233 usage();
236 /* Parse user and tty arguments */
237 if (optind < argc) {
238 user = argv[optind++];
240 /* WTMP usernames are 1-8 chars */
241 if (strlen(user) > 8) *(user + 8) = '\0';
243 if (optind < argc) {
244 tty = argv[optind++];
245 if (optind < argc) usage();
247 } else
248 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);
256 exit(0);
258 return(-1);
261 void intr(dummy)
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);
270 exit(0);