announce.c revision 1.1 1 /*
2 * Copyright (c) 1983 Regents of the University of California.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #ifndef lint
35 static char sccsid[] = "@(#)announce.c 5.9 (Berkeley) 2/26/91";
36 #endif /* not lint */
37
38 #include <sys/types.h>
39 #include <sys/stat.h>
40 #include <sys/time.h>
41 #include <sys/wait.h>
42 #include <sys/socket.h>
43 #include <protocols/talkd.h>
44 #include <sgtty.h>
45 #include <errno.h>
46 #include <syslog.h>
47 #include <unistd.h>
48 #include <stdio.h>
49 #include <string.h>
50 #include <paths.h>
51
52 extern char hostname[];
53
54 /*
55 * Announce an invitation to talk.
56 *
57 * Because the tty driver insists on attaching a terminal-less
58 * process to any terminal that it writes on, we must fork a child
59 * to protect ourselves
60 */
61 announce(request, remote_machine)
62 CTL_MSG *request;
63 char *remote_machine;
64 {
65 int pid, val, status;
66
67 if (pid = fork()) {
68 /* we are the parent, so wait for the child */
69 if (pid == -1) /* the fork failed */
70 return (FAILED);
71 do {
72 val = wait(&status);
73 if (val == -1) {
74 if (errno == EINTR)
75 continue;
76 /* shouldn't happen */
77 syslog(LOG_WARNING, "announce: wait: %m");
78 return (FAILED);
79 }
80 } while (val != pid);
81 if (status&0377 > 0) /* we were killed by some signal */
82 return (FAILED);
83 /* Get the second byte, this is the exit/return code */
84 return ((status >> 8) & 0377);
85 }
86 /* we are the child, go and do it */
87 _exit(announce_proc(request, remote_machine));
88 }
89
90 /*
91 * See if the user is accepting messages. If so, announce that
92 * a talk is requested.
93 */
94 announce_proc(request, remote_machine)
95 CTL_MSG *request;
96 char *remote_machine;
97 {
98 int pid, status;
99 char full_tty[32];
100 FILE *tf;
101 struct stat stbuf;
102
103 (void)sprintf(full_tty, "%s/%s", _PATH_DEV, request->r_tty);
104 if (access(full_tty, 0) != 0)
105 return (FAILED);
106 if ((tf = fopen(full_tty, "w")) == NULL)
107 return (PERMISSION_DENIED);
108 /*
109 * On first tty open, the server will have
110 * it's pgrp set, so disconnect us from the
111 * tty before we catch a signal.
112 */
113 ioctl(fileno(tf), TIOCNOTTY, (struct sgttyb *) 0);
114 if (fstat(fileno(tf), &stbuf) < 0)
115 return (PERMISSION_DENIED);
116 if ((stbuf.st_mode&020) == 0)
117 return (PERMISSION_DENIED);
118 print_mesg(tf, request, remote_machine);
119 fclose(tf);
120 return (SUCCESS);
121 }
122
123 #define max(a,b) ( (a) > (b) ? (a) : (b) )
124 #define N_LINES 5
125 #define N_CHARS 120
126
127 /*
128 * Build a block of characters containing the message.
129 * It is sent blank filled and in a single block to
130 * try to keep the message in one piece if the recipient
131 * in in vi at the time
132 */
133 print_mesg(tf, request, remote_machine)
134 FILE *tf;
135 CTL_MSG *request;
136 char *remote_machine;
137 {
138 struct timeval clock;
139 struct timezone zone;
140 struct tm *localtime();
141 struct tm *localclock;
142 char line_buf[N_LINES][N_CHARS];
143 int sizes[N_LINES];
144 char big_buf[N_LINES*N_CHARS];
145 char *bptr, *lptr;
146 int i, j, max_size;
147
148 i = 0;
149 max_size = 0;
150 gettimeofday(&clock, &zone);
151 localclock = localtime( &clock.tv_sec );
152 (void)sprintf(line_buf[i], " ");
153 sizes[i] = strlen(line_buf[i]);
154 max_size = max(max_size, sizes[i]);
155 i++;
156 (void)sprintf(line_buf[i], "Message from Talk_Daemon@%s at %d:%02d ...",
157 hostname, localclock->tm_hour , localclock->tm_min );
158 sizes[i] = strlen(line_buf[i]);
159 max_size = max(max_size, sizes[i]);
160 i++;
161 (void)sprintf(line_buf[i], "talk: connection requested by %s@%s.",
162 request->l_name, remote_machine);
163 sizes[i] = strlen(line_buf[i]);
164 max_size = max(max_size, sizes[i]);
165 i++;
166 (void)sprintf(line_buf[i], "talk: respond with: talk %s@%s",
167 request->l_name, remote_machine);
168 sizes[i] = strlen(line_buf[i]);
169 max_size = max(max_size, sizes[i]);
170 i++;
171 (void)sprintf(line_buf[i], " ");
172 sizes[i] = strlen(line_buf[i]);
173 max_size = max(max_size, sizes[i]);
174 i++;
175 bptr = big_buf;
176 *bptr++ = ''; /* send something to wake them up */
177 *bptr++ = '\r'; /* add a \r in case of raw mode */
178 *bptr++ = '\n';
179 for (i = 0; i < N_LINES; i++) {
180 /* copy the line into the big buffer */
181 lptr = line_buf[i];
182 while (*lptr != '\0')
183 *(bptr++) = *(lptr++);
184 /* pad out the rest of the lines with blanks */
185 for (j = sizes[i]; j < max_size + 2; j++)
186 *(bptr++) = ' ';
187 *(bptr++) = '\r'; /* add a \r in case of raw mode */
188 *(bptr++) = '\n';
189 }
190 *bptr = '\0';
191 fprintf(tf, big_buf);
192 fflush(tf);
193 ioctl(fileno(tf), TIOCNOTTY, (struct sgttyb *) 0);
194 }
195