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