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