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