announce.c revision 1.2 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[] = "from: @(#)announce.c 5.9 (Berkeley) 2/26/91";*/
36 static char rcsid[] = "$Id: announce.c,v 1.2 1993/08/01 18:29:37 mycroft Exp $";
37 #endif /* not lint */
38
39 #include <sys/types.h>
40 #include <sys/stat.h>
41 #include <sys/time.h>
42 #include <sys/wait.h>
43 #include <sys/socket.h>
44 #include <protocols/talkd.h>
45 #include <sgtty.h>
46 #include <errno.h>
47 #include <syslog.h>
48 #include <unistd.h>
49 #include <stdio.h>
50 #include <string.h>
51 #include <paths.h>
52
53 extern char hostname[];
54
55 /*
56 * Announce an invitation to talk.
57 *
58 * Because the tty driver insists on attaching a terminal-less
59 * process to any terminal that it writes on, we must fork a child
60 * to protect ourselves
61 */
62 announce(request, remote_machine)
63 CTL_MSG *request;
64 char *remote_machine;
65 {
66 int pid, val, status;
67
68 if (pid = fork()) {
69 /* we are the parent, so wait for the child */
70 if (pid == -1) /* the fork failed */
71 return (FAILED);
72 do {
73 val = wait(&status);
74 if (val == -1) {
75 if (errno == EINTR)
76 continue;
77 /* shouldn't happen */
78 syslog(LOG_WARNING, "announce: wait: %m");
79 return (FAILED);
80 }
81 } while (val != pid);
82 if (status&0377 > 0) /* we were killed by some signal */
83 return (FAILED);
84 /* Get the second byte, this is the exit/return code */
85 return ((status >> 8) & 0377);
86 }
87 /* we are the child, go and do it */
88 _exit(announce_proc(request, remote_machine));
89 }
90
91 /*
92 * See if the user is accepting messages. If so, announce that
93 * a talk is requested.
94 */
95 announce_proc(request, remote_machine)
96 CTL_MSG *request;
97 char *remote_machine;
98 {
99 int pid, status;
100 char full_tty[32];
101 FILE *tf;
102 struct stat stbuf;
103
104 (void)sprintf(full_tty, "%s/%s", _PATH_DEV, request->r_tty);
105 if (access(full_tty, 0) != 0)
106 return (FAILED);
107 if ((tf = fopen(full_tty, "w")) == NULL)
108 return (PERMISSION_DENIED);
109 /*
110 * On first tty open, the server will have
111 * it's pgrp set, so disconnect us from the
112 * tty before we catch a signal.
113 */
114 ioctl(fileno(tf), TIOCNOTTY, (struct sgttyb *) 0);
115 if (fstat(fileno(tf), &stbuf) < 0)
116 return (PERMISSION_DENIED);
117 if ((stbuf.st_mode&020) == 0)
118 return (PERMISSION_DENIED);
119 print_mesg(tf, request, remote_machine);
120 fclose(tf);
121 return (SUCCESS);
122 }
123
124 #define max(a,b) ( (a) > (b) ? (a) : (b) )
125 #define N_LINES 5
126 #define N_CHARS 120
127
128 /*
129 * Build a block of characters containing the message.
130 * It is sent blank filled and in a single block to
131 * try to keep the message in one piece if the recipient
132 * in in vi at the time
133 */
134 print_mesg(tf, request, remote_machine)
135 FILE *tf;
136 CTL_MSG *request;
137 char *remote_machine;
138 {
139 struct timeval clock;
140 struct timezone zone;
141 struct tm *localtime();
142 struct tm *localclock;
143 char line_buf[N_LINES][N_CHARS];
144 int sizes[N_LINES];
145 char big_buf[N_LINES*N_CHARS];
146 char *bptr, *lptr;
147 int i, j, max_size;
148
149 i = 0;
150 max_size = 0;
151 gettimeofday(&clock, &zone);
152 localclock = localtime( &clock.tv_sec );
153 (void)sprintf(line_buf[i], " ");
154 sizes[i] = strlen(line_buf[i]);
155 max_size = max(max_size, sizes[i]);
156 i++;
157 (void)sprintf(line_buf[i], "Message from Talk_Daemon@%s at %d:%02d ...",
158 hostname, localclock->tm_hour , localclock->tm_min );
159 sizes[i] = strlen(line_buf[i]);
160 max_size = max(max_size, sizes[i]);
161 i++;
162 (void)sprintf(line_buf[i], "talk: connection requested by %s@%s.",
163 request->l_name, remote_machine);
164 sizes[i] = strlen(line_buf[i]);
165 max_size = max(max_size, sizes[i]);
166 i++;
167 (void)sprintf(line_buf[i], "talk: respond with: talk %s@%s",
168 request->l_name, remote_machine);
169 sizes[i] = strlen(line_buf[i]);
170 max_size = max(max_size, sizes[i]);
171 i++;
172 (void)sprintf(line_buf[i], " ");
173 sizes[i] = strlen(line_buf[i]);
174 max_size = max(max_size, sizes[i]);
175 i++;
176 bptr = big_buf;
177 *bptr++ = ''; /* send something to wake them up */
178 *bptr++ = '\r'; /* add a \r in case of raw mode */
179 *bptr++ = '\n';
180 for (i = 0; i < N_LINES; i++) {
181 /* copy the line into the big buffer */
182 lptr = line_buf[i];
183 while (*lptr != '\0')
184 *(bptr++) = *(lptr++);
185 /* pad out the rest of the lines with blanks */
186 for (j = sizes[i]; j < max_size + 2; j++)
187 *(bptr++) = ' ';
188 *(bptr++) = '\r'; /* add a \r in case of raw mode */
189 *(bptr++) = '\n';
190 }
191 *bptr = '\0';
192 fprintf(tf, big_buf);
193 fflush(tf);
194 ioctl(fileno(tf), TIOCNOTTY, (struct sgttyb *) 0);
195 }
196