1 /*-
2 * Copyright (c) 1983, 1985
3 * The Regents of the University of California. All rights reserved.
4 *
5 * %sccs.include.redist.c%
6 */
7
8 #ifndef lint
9 static char sccsid[] = "@(#)announce.c 5.1 (Berkeley) 6/6/85";
10 #endif not lint
11
12 #include "ctl.h"
13
14 #include <sys/stat.h>
15 #include <sgtty.h>
16 #include <sys/ioctl.h>
17 #include <sys/time.h>
18 #include <stdio.h>
19 #include <sys/wait.h>
20 #include <errno.h>
21
22 extern int errno;
23 extern char hostname[];
24 int nofork = 0; /* to be set from the debugger */
25
26 /*
27 * Because the tty driver insists on attaching a terminal-less
28 * process to any terminal that it writes on, we must fork a child
29 * to protect ourselves
30 */
31
announce(request,remote_machine)32 announce(request, remote_machine)
33 CTL_MSG *request;
34 char *remote_machine;
35 {
36 int pid, val, status;
37
38 if (nofork)
39 return(announce_proc(request, remote_machine));
40 if (pid = fork()) {
41 /* we are the parent, so wait for the child */
42 if (pid == -1) /* the fork failed */
43 return(FAILED);
44 do {
45 val = wait(&status);
46 if (val == -1) {
47 if (errno == EINTR)
48 continue;
49 /* shouldn't happen */
50 perror("wait");
51 return (FAILED);
52 }
53 } while (val != pid);
54 if (status&0377 > 0) /* we were killed by some signal */
55 return (FAILED);
56 /* Get the second byte, this is the exit/return code */
57 return ((status >> 8) & 0377);
58 }
59 /* we are the child, go and do it */
60 _exit(announce_proc(request, remote_machine));
61 }
62
63 /*
64 * See if the user is accepting messages. If so, announce that
65 * a talk is requested.
66 */
announce_proc(request,remote_machine)67 announce_proc(request, remote_machine)
68 CTL_MSG *request;
69 char *remote_machine;
70 {
71 int pid, status;
72 char full_tty[32];
73 FILE *tf;
74 struct stat stbuf;
75
76 (void) sprintf(full_tty, "/dev/%s", request->r_tty);
77 if (access(full_tty, 0) != 0)
78 return (FAILED);
79 if ((tf = fopen(full_tty, "w")) == NULL)
80 return (PERMISSION_DENIED);
81 /*
82 * Open gratuitously attaches the talkd to
83 * any tty it opens, so disconnect us from the
84 * tty before we catch a signal
85 */
86 ioctl(fileno(tf), TIOCNOTTY, (struct sgttyb *) 0);
87 if (fstat(fileno(tf), &stbuf) < 0)
88 return (PERMISSION_DENIED);
89 if ((stbuf.st_mode&020) == 0)
90 return (PERMISSION_DENIED);
91 print_mesg(tf, request, remote_machine);
92 fclose(tf);
93 return (SUCCESS);
94 }
95
96 #define max(a,b) ( (a) > (b) ? (a) : (b) )
97 #define N_LINES 5
98 #define N_CHARS 120
99
100 /*
101 * Build a block of characters containing the message.
102 * It is sent blank filled and in a single block to
103 * try to keep the message in one piece if the recipient
104 * in in vi at the time
105 */
print_mesg(tf,request,remote_machine)106 print_mesg(tf, request, remote_machine)
107 FILE *tf;
108 CTL_MSG *request;
109 char *remote_machine;
110 {
111 struct timeval clock;
112 struct timezone zone;
113 struct tm *localtime();
114 struct tm *localclock;
115 char line_buf[N_LINES][N_CHARS];
116 int sizes[N_LINES];
117 char big_buf[N_LINES*N_CHARS];
118 char *bptr, *lptr;
119 int i, j, max_size;
120
121 i = 0;
122 max_size = 0;
123 gettimeofday(&clock, &zone);
124 localclock = localtime( &clock.tv_sec );
125 sprintf(line_buf[i], " ");
126 sizes[i] = strlen(line_buf[i]);
127 max_size = max(max_size, sizes[i]);
128 i++;
129 sprintf(line_buf[i], "Message from Talk_Daemon@%s at %d:%02d ...",
130 hostname, localclock->tm_hour , localclock->tm_min );
131 sizes[i] = strlen(line_buf[i]);
132 max_size = max(max_size, sizes[i]);
133 i++;
134 sprintf(line_buf[i], "talk: connection requested by %s@%s.",
135 request->l_name, remote_machine);
136 sizes[i] = strlen(line_buf[i]);
137 max_size = max(max_size, sizes[i]);
138 i++;
139 sprintf(line_buf[i], "talk: respond with: /usr/old/talk %s@%s",
140 request->l_name, remote_machine);
141 sizes[i] = strlen(line_buf[i]);
142 max_size = max(max_size, sizes[i]);
143 i++;
144 sprintf(line_buf[i], " ");
145 sizes[i] = strlen(line_buf[i]);
146 max_size = max(max_size, sizes[i]);
147 i++;
148 bptr = big_buf;
149 *(bptr++) = ''; /* send something to wake them up */
150 *(bptr++) = '\r'; /* add a \r in case of raw mode */
151 *(bptr++) = '\n';
152 for (i = 0; i < N_LINES; i++) {
153 /* copy the line into the big buffer */
154 lptr = line_buf[i];
155 while (*lptr != '\0')
156 *(bptr++) = *(lptr++);
157 /* pad out the rest of the lines with blanks */
158 for (j = sizes[i]; j < max_size + 2; j++)
159 *(bptr++) = ' ';
160 *(bptr++) = '\r'; /* add a \r in case of raw mode */
161 *(bptr++) = '\n';
162 }
163 *bptr = '\0';
164 fprintf(tf, big_buf);
165 fflush(tf);
166 ioctl(fileno(tf), TIOCNOTTY, (struct sgttyb *) 0);
167 }
168