Commit | Line | Data |
---|---|---|
31b42ab1 | 1 | #ifndef lint |
ba634270 | 2 | static char *sccsid = "@(#)write.c 4.14 %G%"; |
31b42ab1 | 3 | #endif |
cd784246 BJ |
4 | /* |
5 | * write to another user | |
6 | */ | |
7 | ||
8 | #include <stdio.h> | |
31b42ab1 | 9 | #include <ctype.h> |
cd784246 BJ |
10 | #include <sys/types.h> |
11 | #include <sys/stat.h> | |
12 | #include <signal.h> | |
13 | #include <utmp.h> | |
72cf2549 | 14 | #include <sys/time.h> |
ba634270 | 15 | #include "pathnames.h" |
cd784246 | 16 | |
cf288731 BJ |
17 | #define NMAX sizeof(ubuf.ut_name) |
18 | #define LMAX sizeof(ubuf.ut_line) | |
cd784246 BJ |
19 | |
20 | char *strcat(); | |
21 | char *strcpy(); | |
22 | struct utmp ubuf; | |
23 | int signum[] = {SIGHUP, SIGINT, SIGQUIT, 0}; | |
31b42ab1 | 24 | char me[NMAX + 1] = "???"; |
cd784246 BJ |
25 | char *him; |
26 | char *mytty; | |
27 | char histty[32]; | |
14c6ba7a | 28 | char ttybuf[32]; |
cd784246 BJ |
29 | char *histtya; |
30 | char *ttyname(); | |
31 | char *rindex(); | |
32 | int logcnt; | |
33 | int eof(); | |
34 | int timout(); | |
35 | FILE *tf; | |
36 | char *getenv(); | |
37 | ||
38 | main(argc, argv) | |
cf288731 BJ |
39 | int argc; |
40 | char *argv[]; | |
cd784246 BJ |
41 | { |
42 | struct stat stbuf; | |
43 | register i; | |
44 | register FILE *uf; | |
45 | int c1, c2; | |
cf288731 | 46 | long clock = time(0); |
25a06dbc | 47 | int suser = getuid() == 0; |
14c6ba7a | 48 | int nomesg = 0; |
cd784246 BJ |
49 | struct tm *localtime(); |
50 | struct tm *localclock = localtime( &clock ); | |
51 | ||
cf288731 | 52 | if (argc < 2) { |
31b42ab1 | 53 | fprintf(stderr, "Usage: write user [ttyname]\n"); |
cd784246 BJ |
54 | exit(1); |
55 | } | |
56 | him = argv[1]; | |
cf288731 | 57 | if (argc > 2) |
cd784246 | 58 | histtya = argv[2]; |
ba634270 KB |
59 | if ((uf = fopen(_PATH_UTMP, "r")) == NULL) { |
60 | fprintf(stderr, "write: can't read %s\n", _PATH_UTMP); | |
c7616a71 MK |
61 | if (histtya == 0) |
62 | exit(10); | |
cd784246 BJ |
63 | goto cont; |
64 | } | |
65 | mytty = ttyname(2); | |
66 | if (mytty == NULL) { | |
31b42ab1 | 67 | fprintf(stderr, "write: Can't find your tty\n"); |
cd784246 BJ |
68 | exit(1); |
69 | } | |
cf288731 | 70 | if (stat(mytty, &stbuf) < 0) { |
31b42ab1 | 71 | perror("write: Can't stat your tty"); |
cf288731 | 72 | exit(1); |
b40712b7 | 73 | } |
10e7537d | 74 | if ((stbuf.st_mode&020) == 0) { |
31b42ab1 S |
75 | fprintf(stderr, |
76 | "write: You have write permission turned off\n"); | |
14c6ba7a MK |
77 | if (!suser) |
78 | exit(1); | |
b40712b7 | 79 | } |
cd784246 BJ |
80 | mytty = rindex(mytty, '/') + 1; |
81 | if (histtya) { | |
ba634270 | 82 | strcpy(histty, _PATH_DEV); |
cd784246 BJ |
83 | strcat(histty, histtya); |
84 | } | |
85 | while (fread((char *)&ubuf, sizeof(ubuf), 1, uf) == 1) { | |
b85a75a1 EA |
86 | if (ubuf.ut_name[0] == '\0') |
87 | continue; | |
cd784246 | 88 | if (strcmp(ubuf.ut_line, mytty)==0) { |
cf288731 | 89 | for (i=0; i<NMAX; i++) { |
cd784246 | 90 | c1 = ubuf.ut_name[i]; |
cf288731 | 91 | if (c1 == ' ') |
cd784246 BJ |
92 | c1 = 0; |
93 | me[i] = c1; | |
cf288731 | 94 | if (c1 == 0) |
cd784246 BJ |
95 | break; |
96 | } | |
97 | } | |
31b42ab1 S |
98 | if (him[0] == '-' && him[1] == 0) |
99 | goto nomat; | |
cf288731 | 100 | for (i=0; i<NMAX; i++) { |
cd784246 BJ |
101 | c1 = him[i]; |
102 | c2 = ubuf.ut_name[i]; | |
cf288731 BJ |
103 | if (c1 == 0) |
104 | if (c2 == 0 || c2 == ' ') | |
cd784246 | 105 | break; |
cf288731 | 106 | if (c1 != c2) |
cd784246 BJ |
107 | goto nomat; |
108 | } | |
14c6ba7a MK |
109 | if (histtya && strncmp(histtya, ubuf.ut_line, |
110 | sizeof(ubuf.ut_line))) | |
111 | continue; | |
cd784246 | 112 | logcnt++; |
14c6ba7a | 113 | if (histty[0]==0 || nomesg && histtya == 0) { |
ba634270 | 114 | strcpy(ttybuf, _PATH_DEV); |
14c6ba7a MK |
115 | strcat(ttybuf, ubuf.ut_line); |
116 | if (histty[0]==0) | |
117 | strcpy(histty, ttybuf); | |
118 | if (access(ttybuf, 0) < 0 || stat(ttybuf, &stbuf) < 0 || | |
10e7537d | 119 | (stbuf.st_mode&020) == 0) |
14c6ba7a MK |
120 | nomesg++; |
121 | else { | |
122 | strcpy(histty, ttybuf); | |
123 | nomesg = 0; | |
124 | } | |
cd784246 BJ |
125 | } |
126 | nomat: | |
127 | ; | |
128 | } | |
c7616a71 | 129 | fclose(uf); |
14c6ba7a | 130 | if (logcnt==0) { |
c7616a71 MK |
131 | fprintf(stderr, "write: %s not logged in%s\n", him, |
132 | histtya ? " on that tty" : ""); | |
cd784246 BJ |
133 | exit(1); |
134 | } | |
cd784246 | 135 | if (histtya==0 && logcnt > 1) { |
31b42ab1 S |
136 | fprintf(stderr, |
137 | "write: %s logged in more than once ... writing to %s\n", | |
138 | him, histty+5); | |
cd784246 | 139 | } |
c7616a71 | 140 | cont: |
cd784246 | 141 | if (access(histty, 0) < 0) { |
31b42ab1 | 142 | fprintf(stderr, "write: No such tty\n"); |
cd784246 BJ |
143 | exit(1); |
144 | } | |
145 | signal(SIGALRM, timout); | |
146 | alarm(5); | |
14c6ba7a MK |
147 | if ((tf = fopen(histty, "w")) == NULL) { |
148 | fprintf(stderr, "write: Permission denied\n"); | |
149 | exit(1); | |
150 | } | |
cd784246 | 151 | alarm(0); |
cd784246 | 152 | sigs(eof); |
cf288731 BJ |
153 | { char hostname[32]; |
154 | gethostname(hostname, sizeof (hostname)); | |
31b42ab1 S |
155 | fprintf(tf, |
156 | "\r\nMessage from %s@%s on %s at %d:%02d ...\r\n\007\007\007", | |
157 | me, hostname, mytty, localclock->tm_hour, localclock->tm_min); | |
cd784246 | 158 | fflush(tf); |
31b42ab1 | 159 | } |
cf288731 | 160 | for (;;) { |
31b42ab1 S |
161 | char buf[BUFSIZ]; |
162 | register char *bp; | |
163 | i = read(0, buf, sizeof buf); | |
cf288731 | 164 | if (i <= 0) |
cd784246 | 165 | eof(); |
cf288731 | 166 | if (buf[0] == '!') { |
cd784246 BJ |
167 | buf[i] = 0; |
168 | ex(buf); | |
169 | continue; | |
170 | } | |
31b42ab1 S |
171 | for (bp = buf; --i >= 0; bp++) { |
172 | if (*bp == '\n') | |
173 | putc('\r', tf); | |
174 | ||
175 | if (!isascii(*bp)) { | |
176 | putc('M', tf); | |
177 | putc('-', tf); | |
178 | *bp = toascii(*bp); | |
179 | } | |
180 | ||
181 | if (isprint(*bp) || | |
182 | *bp == ' ' || *bp == '\t' || *bp == '\n') { | |
183 | putc(*bp, tf); | |
184 | } else { | |
185 | putc('^', tf); | |
186 | putc(*bp ^ 0100, tf); | |
187 | } | |
188 | ||
189 | if (*bp == '\n') | |
190 | fflush(tf); | |
191 | ||
192 | if (ferror(tf) || feof(tf)) { | |
193 | printf("\n\007Write failed (%s logged out?)\n", | |
194 | him); | |
195 | exit(1); | |
196 | } | |
93665ffd | 197 | } |
cd784246 | 198 | } |
cd784246 BJ |
199 | } |
200 | ||
201 | timout() | |
202 | { | |
203 | ||
31b42ab1 | 204 | fprintf(stderr, "write: Timeout opening their tty\n"); |
cd784246 BJ |
205 | exit(1); |
206 | } | |
207 | ||
208 | eof() | |
209 | { | |
210 | ||
211 | fprintf(tf, "EOF\r\n"); | |
212 | exit(0); | |
213 | } | |
214 | ||
215 | ex(bp) | |
cf288731 | 216 | char *bp; |
cd784246 BJ |
217 | { |
218 | register i; | |
219 | ||
220 | sigs(SIG_IGN); | |
221 | i = fork(); | |
cf288731 | 222 | if (i < 0) { |
cd784246 BJ |
223 | printf("Try again\n"); |
224 | goto out; | |
225 | } | |
cf288731 | 226 | if (i == 0) { |
10e7537d KM |
227 | fclose(tf); /* Close his terminal */ |
228 | setgid(getgid()); /* Give up effective group privs */ | |
cd784246 | 229 | sigs((int (*)())0); |
cf288731 | 230 | execl(getenv("SHELL") ? |
ba634270 | 231 | getenv("SHELL") : _PATH_BSHELL, "sh", "-c", bp+1, 0); |
cd784246 BJ |
232 | exit(0); |
233 | } | |
cf288731 | 234 | while (wait((int *)NULL) != i) |
cd784246 BJ |
235 | ; |
236 | printf("!\n"); | |
237 | out: | |
238 | sigs(eof); | |
239 | } | |
240 | ||
241 | sigs(sig) | |
cf288731 | 242 | int (*sig)(); |
cd784246 BJ |
243 | { |
244 | register i; | |
245 | ||
cf288731 BJ |
246 | for (i=0; signum[i]; i++) |
247 | signal(signum[i], sig); | |
cd784246 | 248 | } |