source: trunk/minix/commands/simple/write.c@ 11

Last change on this file since 11 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 5.8 KB
Line 
1/* write - write to a logged in user Authors: N. Andrew and F. van Kempen */
2
3/*
4 * Usage: write [-c] [-v] user [tty]
5 * -c Read & write one character at a time (cbreak mode)
6 * -v Verbose
7 *
8 * Version: 1.6 10/24/92
9 *
10 * NOTES: Write requires 1.4a (or higher) libraries,
11 * for getopt(), strchr().
12 *
13 * Authors: Nick Andrew (nick@nswitgould.oz) - Public Domain
14 * Fred van Kempen (minixug!waltje@kyber.uucp)
15 */
16
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 <minix/paths.h>
29
30static char *Version = "@(#) WRITE 1.6 (10/24/92)";
31
32int otty; /* file desc of callee's terminal */
33short int cbreak = 0; /* are we in CBREAK (-c) mode? */
34short int verbose = 0; /* are we in VERBOSE (-v) mode? */
35short int writing = 0; /* is there a connection? */
36char *user = NULL; /* callee's user name */
37char *tty = NULL; /* callee's terminal if given */
38char *ourtty = NULL; /* our terminal name */
39struct termios ttyold, ttynew; /* our tty controlling structs */
40
41extern int optind;
42
43_PROTOTYPE(int main, (int argc, char **argv));
44_PROTOTYPE(char *finduser, (void));
45_PROTOTYPE(void settty, (char *utty));
46_PROTOTYPE(void sayhello, (void));
47_PROTOTYPE(void escape, (char *cmd));
48_PROTOTYPE(void writetty, (void));
49_PROTOTYPE(void usage, (void));
50_PROTOTYPE(void intr, (int dummy));
51
52char *finduser()
53{
54/* Search the UTMP database for the user we want. */
55
56 static char utmptty[16];
57 struct utmp utmp;
58 struct passwd *userptr;
59 int utmpfd;
60
61 ourtty = ttyname(0);
62 if (ourtty == NULL) ourtty = "/dev/console";
63
64 if (user == NULL) exit(-1);
65 if ((userptr = getpwnam(user)) == NULL) {
66 fprintf(stderr, "No such user: %s\n", user);
67 return(NULL);
68 }
69 if (verbose) fprintf(stderr, "Trying to write to %s\n",
70 userptr->pw_gecos);
71
72 if ((utmpfd = open(_PATH_UTMP, O_RDONLY)) < 0) {
73 fprintf(stderr, "Cannot open utmp file\n");
74 return(NULL);
75 }
76 utmptty[0] = '\0';
77
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;
84
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;
89 }
90 }
91
92 if (utmptty[0] == '\0') {
93 fprintf(stderr, "%s is not logged on\n", user);
94 return( NULL);
95 }
96 if (tty != NULL && strcmp(utmptty, tty)) {
97 fprintf(stderr, "%s is logged onto %s, not %s\n", user, utmptty, tty);
98 return( NULL);
99 }
100 close(utmpfd);
101
102 if (verbose) fprintf(stderr, "Writing to %s on %s\n", user, utmptty);
103 return(utmptty);
104}
105
106
107void settty(utty)
108char *utty; /* name of terminal found in utmp */
109{
110/* Open other person's terminal and setup our own terminal. */
111
112 char buff[48];
113
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);
119 }
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);
125}
126
127
128void sayhello()
129{
130 struct passwd *pw;
131 char buff[128];
132 long now;
133 char *sp;
134
135 time(&now);
136
137 pw = getpwuid(getuid());
138 if (pw == NULL) {
139 fprintf(stderr, "unknown user\n");
140 exit(-1);
141 }
142 if ((sp = strrchr(ourtty, '/')) != NULL)
143 ++sp;
144 else
145 sp = ourtty;
146
147 sprintf(buff, "\nMessage from %s (%s) %-24.24s...\n",
148 pw->pw_name, sp, ctime(&now));
149
150 write(otty, buff, strlen(buff));
151 printf("\007\007");
152 fflush(stdout);
153}
154
155
156void escape(cmd)
157char *cmd;
158{
159/* Shell escape. */
160
161 register char *x;
162
163 write(1, "!\n", 2);
164 for (x = cmd; *x; ++x)
165 if (*x == '\n') *x = '\0';
166
167 system(cmd);
168 write(1, "!\n", 2);
169}
170
171
172void writetty()
173{
174/* The write loop. */
175
176 char line[80];
177 int n, cb_esc;
178
179 writing = 1;
180 cb_esc = 0;
181
182 while ((n = read(0, line, 79)) > 0) {
183 if (line[0] == '\004') break; /* EOT */
184
185 if (cbreak && line[0] == '\n') cb_esc = 1;
186
187 if (cbreak) write(1, line, n);
188
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;
201 }
202 write(otty, line, n);
203 }
204 write(1, "\nEOT\n", 5);
205 write(otty, "\nEOT\n", 5);
206}
207
208
209void usage()
210{
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);
214}
215
216
217int main(argc, argv)
218int argc;
219char *argv[];
220{
221 register int c;
222 char *sp;
223
224 setbuf(stdout, (char *) NULL);
225
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();
232 }
233
234 /* Parse user and tty arguments */
235 if (optind < argc) {
236 user = argv[optind++];
237
238 /* WTMP usernames are 1-8 chars */
239 if (strlen(user) > 8) *(user + 8) = '\0';
240
241 if (optind < argc) {
242 tty = argv[optind++];
243 if (optind < argc) usage();
244 }
245 } else
246 usage();
247
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);
255 }
256 return(-1);
257}
258
259void intr(dummy)
260int dummy; /* to satisfy the prototype */
261{
262/* The interrupt key has been hit. exit cleanly. */
263
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);
269}
Note: See TracBrowser for help on using the repository browser.