|
|
1.1 root 1: #include <stdio.h>
2: #include <signal.h>
3: #include <utmp.h>
4: #include <sys/types.h>
5: #include <sys/stat.h>
6: #include <utsname.h>
7:
8: #define MAXPPL 15 /* maximum number of people to whom we can write */
9: #define TTYSIZ 16 /* path-name size for ttys */
10: #define UDIRSIZ 8 /* size of fields in utmp */
11:
12: int num;
13: int fd[MAXPPL + 1];
14: char *logname, *mytty, *sysname;
15: struct utmp ut[MAXPPL + 1];
16:
17: main(argc, argv)
18: int argc;
19: char **argv;
20: {
21: int x;
22: int cleanup();
23: char inp[BUFSIZ], mesg[BUFSIZ], strm[MAXPPL + 1][TTYSIZ];
24: char *getlogin(), *ttyname();
25: struct utsname ourname;
26:
27: signal(SIGHUP, cleanup);
28: signal(SIGINT, cleanup);
29: signal(SIGQUIT, cleanup);
30:
31: logname = getlogin();
32: if ((mytty = ttyname(3)) != NULL) {
33: mytty += 5; /* strip "/dev/" off of tty */
34: cktty(logname, mytty, 1);
35: }
36: uname(&ourname);
37: sysname = ourname.nodename;
38:
39: if (argc > MAXPPL + 1 || argc < 2) {
40: sprintf(mesg, "usage: write person1 [... person%d]\n", MAXPPL);
41: error(mesg);
42: }
43: num = argc - 1;
44: if ((fd[0] = open("/etc/utmp", 0)) < 0)
45: error("write: Cannot open /etc/utmp.\n");
46: while (read(fd[0], &ut[0], sizeof(struct utmp)) == sizeof(struct utmp))
47: for (x = 1; x <= num; x++)
48: if (strncmp(ut[0].ut_name, argv[x], UDIRSIZ) == 0 ||
49: strncmp(ut[0].ut_line, argv[x], UDIRSIZ) == 0)
50: ut[x] = ut[0];
51:
52: for (x = 1; x <= num; x++) {
53: if(ut[x].ut_name[0] == 0){
54: sprintf(mesg, "write: %s is not on.\n", argv[x]);
55: error(mesg);
56: }
57: if (strcmp(ut[x].ut_line, argv[x]) == 0)
58: strcpy(ut[x].ut_name, ut[x].ut_line);
59: cktty(ut[x].ut_name, ut[x].ut_line, 0);
60: devoftty(strm[x], ut[x].ut_line);
61: if ((fd[x] = open(strm[x], 1)) < 0) {
62: sprintf(mesg, "write: Cannot open %s's tty.\n", argv[x]);
63: error(mesg);
64: }
65: }
66:
67: people(mesg);
68: for (x = 1; x <= num; x++) {
69: write(fd[x], "\007\007\007write: ", 10);
70: write(fd[x], sysname, strlen(sysname));
71: write(fd[x], "!", 1);
72: write(fd[x], logname, strlen(logname));
73: if (mytty) {
74: write(fd[x], " on ", 4);
75: write(fd[x], mytty, strlen(mytty));
76: }
77: write(fd[x], " to ", 4);
78: write(fd[x], mesg, strlen(mesg));
79: write(fd[x], ".\n", 2);
80: }
81: if (num > 1)
82: used();
83: while (fgets(inp, 512, stdin) != NULL)
84: if (inp[0] == '!')
85: shell(inp);
86: else if (inp[0] == ':')
87: colon(inp);
88: else
89: for (x = 1; x <= num; x++) {
90: if (num != 1) {
91: write(fd[x], logname, strlen(logname));
92: write(fd[x], ": ", 2);
93: }
94: write(fd[x], inp, strlen(inp));
95: }
96: cleanup();
97: }
98:
99: cleanup()
100: {
101: int x;
102:
103: for (x = 1; x <= num; x++) {
104: write(fd[x], "write: ", 7);
105: write(fd[x], logname, strlen(logname));
106: write(fd[x], ": EOF\n", 6);
107: close(fd[x]);
108: }
109: close(fd[0]);
110: exit(0);
111: }
112:
113: people(list)
114: char *list;
115: {
116: int x;
117:
118: strncpy(list, ut[1].ut_name, UDIRSIZ);
119: list[UDIRSIZ] = '\0';
120: if (num > 2) {
121: for (x = 2; x < num; x++) {
122: strcat(list, ", ");
123: strncat(list, ut[x].ut_name, UDIRSIZ);
124: }
125: strcat(list, ",");
126: }
127: if (num > 1) {
128: strcat(list, " and ");
129: strncat(list, ut[num].ut_name, UDIRSIZ);
130: }
131: }
132:
133: shell(str)
134: char *str;
135: {
136: int frkd;
137: int cleanup();
138:
139: signal(SIGINT, SIG_IGN);
140: signal(SIGQUIT, SIG_IGN);
141: if ((frkd = fork()) < 0)
142: printf("write: Cannot fork.\n");
143: if (frkd == 0) {
144: signal(SIGINT, SIG_DFL);
145: signal(SIGQUIT, SIG_DFL);
146: execl("/bin/sh", "sh", "-c", str + 1, 0);
147: exit(0);
148: }
149: if (frkd > 0)
150: wait(0);
151: signal(SIGINT, cleanup);
152: signal(SIGQUIT, cleanup);
153: printf("!\n");
154: }
155:
156: colon(arg)
157: char *arg;
158: {
159: char arg1[BUFSIZ], arg2[BUFSIZ];
160:
161: used();
162: strcpy(arg1, "\0");
163: strcpy(arg2, "\0");
164: sscanf(arg, ":%s %s\n", arg1, arg2);
165: if (strlen(arg1) <= 1) {
166: if (strcmp(arg2, "\0") == 0 && (strcmp(arg1, "a") == 0 ||
167: strcmp(arg1, "d") == 0))
168: printf("write: missing argument to colon escape.\n");
169: else
170: switch(arg1[0]) {
171: case 'a':
172: add(arg2);
173: break;
174: case 'd':
175: drop(arg2);
176: break;
177: case 'l':
178: plist();
179: break;
180: default:
181: printf("write: unknown colon escape.\n");
182: }
183: }
184: else
185: printf("write: unknown colon escape.\n");
186: }
187:
188: add(name)
189: char *name;
190: {
191: int x;
192: char dev[TTYSIZ], list[BUFSIZ];
193:
194: if (num + 1 > MAXPPL) {
195: printf("write: too many people.\n");
196: return;
197: }
198:
199: lseek(fd[0], 0L, 0);
200: while (read(fd[0], &ut[0], sizeof(struct utmp)) == sizeof(struct utmp))
201: if (strcmp(ut[0].ut_name, name) == 0 ||
202: strcmp(ut[0].ut_line, name) == 0)
203: ut[num + 1] = ut[0];
204:
205: if (strcmp(ut[num + 1].ut_name, "\0") == 0) {
206: printf("write: %s is not on.\n", name);
207: return;
208: }
209:
210: if (strcmp(ut[num + 1].ut_line, name) == 0)
211: strcpy(ut[num + 1].ut_name, ut[num + 1].ut_line);
212:
213: if (cktty(name, ut[num + 1].ut_line, 1))
214: return;
215: devoftty(dev, ut[num + 1].ut_line);
216: if ((fd[num + 1] = open(dev, 1)) < 0) {
217: printf("write: Cannot open %s's tty.\n", name);
218: return;
219: }
220:
221: num++;
222: people(list);
223: write(fd[num], "\007\007\007write: ", 10);
224: write(fd[num], sysname, strlen(sysname));
225: write(fd[num], "!", 1);
226: write(fd[num], logname, strlen(logname));
227: if (mytty) {
228: write(fd[num], " on ", 4);
229: write(fd[num], mytty, strlen(mytty));
230: }
231: write(fd[num], " to ", 4);
232: write(fd[num], list, strlen(list));
233: write(fd[num], ".\n", 2);
234: for (x = 1; x < num; x++) {
235: write(fd[x], "\007\007\007write: ", 10);
236: write(fd[x], logname, strlen(logname));
237: if (mytty) {
238: write(fd[x], " on ", 4);
239: write(fd[x], mytty, strlen(mytty));
240: }
241: write(fd[x], " added ", 7);
242: write(fd[x], name, strlen(name));
243: write(fd[x], ".\n", 2);
244: }
245: }
246:
247: drop(name)
248: char *name;
249: {
250: int x;
251: int place = 0;
252:
253: for (x = 1; x <= num; x++)
254: if (strcmp(ut[x].ut_name, name) == 0)
255: place = x;
256: if (place == 0)
257: printf("write: %s is not in the conversation.\n", name);
258: else {
259: write(fd[place], "\007\007\007write: ", 10);
260: write(fd[place], logname, strlen(logname));
261: if (mytty) {
262: write(fd[place], " on ", 4);
263: write(fd[place], mytty, strlen(mytty));
264: }
265: write(fd[place], " dropped you.\n", 14);
266: close(fd[place]);
267: for (x = place; x <= num; x++) {
268: fd[x] = fd[x + 1];
269: ut[x] = ut[x + 1];
270: }
271: num--;
272:
273: for (x = 1; x <= num; x++) {
274: write(fd[x], "\007\007\007write: ", 10);
275: write(fd[x], logname, strlen(logname));
276: if (mytty) {
277: write(fd[x], " on ", 4);
278: write(fd[x], mytty, strlen(mytty));
279: }
280: write(fd[x], " dropped ", 9);
281: write(fd[x], name, strlen(name));
282: write(fd[x], ".\n", 2);
283: }
284: }
285: }
286:
287: plist()
288: {
289: char list[BUFSIZ];
290:
291: people(list);
292: if (strlen(list) < 1)
293: printf("write: You're not talking to anyone.\n");
294: else
295: printf("write: You're talking to %s.\n", list);
296: }
297:
298: cktty(user, tty, flag)
299: int flag;
300: char *user, *tty;
301: {
302: char bfr[TTYSIZ], msg[BUFSIZ];
303: struct stat sbuf;
304:
305: devoftty(bfr, tty);
306: if (stat(bfr, &sbuf) < 0) {
307: sprintf(msg, "write: Cannot stat %s (%s's tty).\n", bfr, user);
308: if (flag) {
309: fprintf(stderr, msg);
310: return(1);
311: }
312: error(msg);
313: }
314: if (!(sbuf.st_mode & 02)) {
315: sprintf(msg, "write: %s's tty is protected.\n", user);
316: if (flag) {
317: fprintf(stderr, msg);
318: return(1);
319: }
320: error(msg);
321: }
322: }
323:
324: devoftty(buf, tty)
325: char *buf, *tty;
326: {
327: sprintf(buf, "/dev/%s", tty);
328: buf[13] = 0; /* strlen("/dev/")+8 */
329: }
330:
331: error(s)
332: char *s;
333: {
334: fprintf(stderr, s);
335: exit(1);
336: }
337:
338: used()
339: {
340: int fd;
341: char buf[20];
342:
343: if ((fd = open("/tmp/wacct", 2)) < 0)
344: return;
345: sprintf(buf, "%s\n", logname);
346: lseek(fd, 0L, 2);
347: write(fd, buf, strlen(buf));
348: close(fd);
349: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.