1*73fe6daaSflorian /* $OpenBSD: announce.c,v 1.26 2024/04/28 16:42:53 florian Exp $ */
2ebad6d3cSmickey
3df930be7Sderaadt /*
4df930be7Sderaadt * Copyright (c) 1983 Regents of the University of California.
5df930be7Sderaadt * All rights reserved.
6df930be7Sderaadt *
7df930be7Sderaadt * Redistribution and use in source and binary forms, with or without
8df930be7Sderaadt * modification, are permitted provided that the following conditions
9df930be7Sderaadt * are met:
10df930be7Sderaadt * 1. Redistributions of source code must retain the above copyright
11df930be7Sderaadt * notice, this list of conditions and the following disclaimer.
12df930be7Sderaadt * 2. Redistributions in binary form must reproduce the above copyright
13df930be7Sderaadt * notice, this list of conditions and the following disclaimer in the
14df930be7Sderaadt * documentation and/or other materials provided with the distribution.
15e33d3bd3Smillert * 3. Neither the name of the University nor the names of its contributors
16df930be7Sderaadt * may be used to endorse or promote products derived from this software
17df930be7Sderaadt * without specific prior written permission.
18df930be7Sderaadt *
19df930be7Sderaadt * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20df930be7Sderaadt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21df930be7Sderaadt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22df930be7Sderaadt * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23df930be7Sderaadt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24df930be7Sderaadt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25df930be7Sderaadt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26df930be7Sderaadt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27df930be7Sderaadt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28df930be7Sderaadt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29df930be7Sderaadt * SUCH DAMAGE.
30df930be7Sderaadt */
31df930be7Sderaadt
32df930be7Sderaadt #include <sys/stat.h>
33df930be7Sderaadt #include <protocols/talkd.h>
34f652621fSmestre
35b9fc9a72Sderaadt #include <limits.h>
36df930be7Sderaadt #include <paths.h>
37f652621fSmestre #include <stdio.h>
38f652621fSmestre #include <string.h>
39f652621fSmestre #include <unistd.h>
40f652621fSmestre #include <vis.h>
41f652621fSmestre
42ebad6d3cSmickey #include "talkd.h"
43df930be7Sderaadt
44c72b5b24Smillert static void print_mesg(FILE *,CTL_MSG *,char *);
45df930be7Sderaadt
46df930be7Sderaadt /*
47a9920a05Smillert * Announce an invitation to talk. If the user is
48a9920a05Smillert * accepting messages, announce that a talk is requested.
49df930be7Sderaadt */
50ebad6d3cSmickey int
announce(CTL_MSG * request,char * remote_machine)516bcb9e83Sderaadt announce(CTL_MSG *request, char *remote_machine)
52df930be7Sderaadt {
53b9fc9a72Sderaadt char full_tty[PATH_MAX];
54df930be7Sderaadt FILE *tf;
55df930be7Sderaadt struct stat stbuf;
56df930be7Sderaadt
57b68d276fSitojun (void)snprintf(full_tty, sizeof(full_tty), "%s/%s", _PATH_DEV,
5899ee0920Sderaadt request->r_tty);
59df930be7Sderaadt if (access(full_tty, 0) != 0)
60df930be7Sderaadt return (FAILED);
61df930be7Sderaadt if ((tf = fopen(full_tty, "w")) == NULL)
62df930be7Sderaadt return (PERMISSION_DENIED);
63df69c215Sderaadt if (fstat(fileno(tf), &stbuf) == -1) {
64ec6c8ee6Stedu fclose(tf);
65df930be7Sderaadt return (PERMISSION_DENIED);
66ec6c8ee6Stedu }
67ec6c8ee6Stedu if ((stbuf.st_mode & S_IWGRP) == 0) {
68ec6c8ee6Stedu fclose(tf);
69df930be7Sderaadt return (PERMISSION_DENIED);
70ec6c8ee6Stedu }
71df930be7Sderaadt print_mesg(tf, request, remote_machine);
72df930be7Sderaadt fclose(tf);
73df930be7Sderaadt return (SUCCESS);
74df930be7Sderaadt }
75df930be7Sderaadt
76df930be7Sderaadt #define max(a,b) ( (a) > (b) ? (a) : (b) )
77df930be7Sderaadt #define N_LINES 5
78df930be7Sderaadt #define N_CHARS 120
79df930be7Sderaadt
80df930be7Sderaadt /*
81df930be7Sderaadt * Build a block of characters containing the message.
82df930be7Sderaadt * It is sent blank filled and in a single block to
83df930be7Sderaadt * try to keep the message in one piece if the recipient
845d5c76edSjufi * is in vi at the time
85df930be7Sderaadt */
86ebad6d3cSmickey static void
print_mesg(FILE * tf,CTL_MSG * request,char * remote_machine)876bcb9e83Sderaadt print_mesg(FILE *tf, CTL_MSG *request, char *remote_machine)
88df930be7Sderaadt {
89df930be7Sderaadt time_t clocktime;
90df930be7Sderaadt struct tm *localclock;
91df930be7Sderaadt char line_buf[N_LINES][N_CHARS];
92df930be7Sderaadt int sizes[N_LINES];
93d7e32e3eSitojun char big_buf[(N_LINES + 1) * N_CHARS];
9425f32b48Smillert char *bptr, *lptr, vis_user[sizeof(request->l_name) * 4];
95df930be7Sderaadt int i, j, max_size;
96df930be7Sderaadt
97df930be7Sderaadt i = 0;
98df930be7Sderaadt max_size = 0;
99c5f52c81Sderaadt time(&clocktime);
100df930be7Sderaadt localclock = localtime(&clocktime);
1014a7e372bSderaadt (void)snprintf(line_buf[i], N_CHARS, " ");
102df930be7Sderaadt sizes[i] = strlen(line_buf[i]);
103df930be7Sderaadt max_size = max(max_size, sizes[i]);
104df930be7Sderaadt i++;
105*73fe6daaSflorian if (localclock) {
1064a7e372bSderaadt (void)snprintf(line_buf[i], N_CHARS,
1074a7e372bSderaadt "Message from Talk_Daemon@%s at %d:%02d ...",
108df930be7Sderaadt hostname, localclock->tm_hour , localclock->tm_min );
109*73fe6daaSflorian } else {
110*73fe6daaSflorian (void)snprintf(line_buf[i], N_CHARS,
111*73fe6daaSflorian "Message from Talk_Daemon@%s ...", hostname);
112*73fe6daaSflorian }
113df930be7Sderaadt sizes[i] = strlen(line_buf[i]);
114df930be7Sderaadt max_size = max(max_size, sizes[i]);
115df930be7Sderaadt i++;
116df930be7Sderaadt strvis(vis_user, request->l_name, VIS_CSTYLE);
1174a7e372bSderaadt (void)snprintf(line_buf[i], N_CHARS,
1184a7e372bSderaadt "talk: connection requested by %s@%s.",
119df930be7Sderaadt vis_user, remote_machine);
120df930be7Sderaadt sizes[i] = strlen(line_buf[i]);
121df930be7Sderaadt max_size = max(max_size, sizes[i]);
122df930be7Sderaadt i++;
1234a7e372bSderaadt (void)snprintf(line_buf[i], N_CHARS, "talk: respond with: talk %s@%s",
124df930be7Sderaadt vis_user, remote_machine);
125df930be7Sderaadt sizes[i] = strlen(line_buf[i]);
126df930be7Sderaadt max_size = max(max_size, sizes[i]);
127df930be7Sderaadt i++;
1284a7e372bSderaadt (void)snprintf(line_buf[i], N_CHARS, " ");
129df930be7Sderaadt sizes[i] = strlen(line_buf[i]);
130df930be7Sderaadt max_size = max(max_size, sizes[i]);
131df930be7Sderaadt i++;
132df930be7Sderaadt bptr = big_buf;
1330f8c18e2Sderaadt *bptr++ = '\007'; /* send something to wake them up */
134df930be7Sderaadt *bptr++ = '\r'; /* add a \r in case of raw mode */
135df930be7Sderaadt *bptr++ = '\n';
136df930be7Sderaadt for (i = 0; i < N_LINES; i++) {
137df930be7Sderaadt /* copy the line into the big buffer */
138df930be7Sderaadt lptr = line_buf[i];
139df930be7Sderaadt while (*lptr != '\0')
140df930be7Sderaadt *(bptr++) = *(lptr++);
141df930be7Sderaadt /* pad out the rest of the lines with blanks */
142df930be7Sderaadt for (j = sizes[i]; j < max_size + 2; j++)
143df930be7Sderaadt *(bptr++) = ' ';
144df930be7Sderaadt *(bptr++) = '\r'; /* add a \r in case of raw mode */
145df930be7Sderaadt *(bptr++) = '\n';
146df930be7Sderaadt }
147df930be7Sderaadt *bptr = '\0';
148ff9e617fSderaadt fprintf(tf, "%s", big_buf);
149df930be7Sderaadt fflush(tf);
150df930be7Sderaadt }
151