xref: /csrg-svn/libexec/talkd/announce.c (revision 16362)
1*16362Skarels #ifndef lint
2*16362Skarels static char sccsid[] = "@(#)announce.c	1.2 (Berkeley) 04/11/84";
3*16362Skarels #endif
416341Skarels 
516341Skarels #include "ctl.h"
616341Skarels 
716341Skarels #include <sys/stat.h>
816341Skarels #include <sgtty.h>
916341Skarels #include <sys/ioctl.h>
1016341Skarels #include <sys/time.h>
1116341Skarels #include <stdio.h>
1216341Skarels #include <sys/wait.h>
1316341Skarels #include <errno.h>
1416341Skarels 
1516341Skarels char *sprintf();
1616341Skarels 
1716341Skarels extern int errno;
1816341Skarels extern char hostname[];
1916341Skarels int nofork = 0;		/* to be set from the debugger */
2016341Skarels 
2116341Skarels /*
2216341Skarels  * Because the tty driver insists on attaching a terminal-less
2316341Skarels  * process to any terminal that it writes on, we must fork a child
2416341Skarels  * to protect ourselves
2516341Skarels  */
2616341Skarels 
2716341Skarels announce(request, remote_machine)
28*16362Skarels 	CTL_MSG *request;
29*16362Skarels 	char *remote_machine;
3016341Skarels {
31*16362Skarels 	int pid, val, status;
3216341Skarels 
33*16362Skarels 	if (nofork)
34*16362Skarels 		return(announce_proc(request, remote_machine));
35*16362Skarels 	if (pid = fork()) {
36*16362Skarels 		/* we are the parent, so wait for the child */
37*16362Skarels 		if (pid == -1)		/* the fork failed */
38*16362Skarels 			return(FAILED);
39*16362Skarels 		do {
40*16362Skarels 			val = wait(&status);
41*16362Skarels 			if (val == -1) {
42*16362Skarels 				if (errno == EINTR)
43*16362Skarels 					continue;
44*16362Skarels 				/* shouldn't happen */
45*16362Skarels 				perror("wait");
46*16362Skarels 				return (FAILED);
47*16362Skarels 			}
48*16362Skarels 		} while (val != pid);
49*16362Skarels 		if (status&0377 > 0)	/* we were killed by some signal */
50*16362Skarels 			return (FAILED);
51*16362Skarels 		/* Get the second byte, this is the exit/return code */
52*16362Skarels 		return ((status >> 8) & 0377);
5316341Skarels 	}
54*16362Skarels 	/* we are the child, go and do it */
5516341Skarels 	_exit(announce_proc(request, remote_machine));
5616341Skarels }
5716341Skarels 
58*16362Skarels /*
59*16362Skarels  * See if the user is accepting messages. If so, announce that
60*16362Skarels  * a talk is requested.
61*16362Skarels  */
6216341Skarels announce_proc(request, remote_machine)
63*16362Skarels 	CTL_MSG *request;
64*16362Skarels 	char *remote_machine;
6516341Skarels {
66*16362Skarels 	int pid, status;
67*16362Skarels 	char full_tty[32];
68*16362Skarels 	FILE *tf;
69*16362Skarels 	struct stat stbuf;
7016341Skarels 
71*16362Skarels 	(void) sprintf(full_tty, "/dev/%s", request->r_tty);
72*16362Skarels 	if (access(full_tty, 0) != 0)
73*16362Skarels 		return (FAILED);
74*16362Skarels 	if ((tf = fopen(full_tty, "w")) == NULL)
75*16362Skarels 		return (PERMISSION_DENIED);
76*16362Skarels 	/*
77*16362Skarels 	 * Open gratuitously attaches the talkd to
78*16362Skarels 	 * any tty it opens, so disconnect us from the
79*16362Skarels 	 * tty before we catch a signal
80*16362Skarels 	 */
81*16362Skarels 	ioctl(fileno(tf), TIOCNOTTY, (struct sgttyb *) 0);
82*16362Skarels 	if (fstat(fileno(tf), &stbuf) < 0)
83*16362Skarels 		return (PERMISSION_DENIED);
84*16362Skarels 	if ((stbuf.st_mode&02) == 0)
85*16362Skarels 		return (PERMISSION_DENIED);
86*16362Skarels 	print_mesg(tf, request, remote_machine);
87*16362Skarels 	fclose(tf);
88*16362Skarels 	return (SUCCESS);
8916341Skarels }
9016341Skarels 
9116341Skarels #define max(a,b) ( (a) > (b) ? (a) : (b) )
9216341Skarels #define N_LINES 5
9316341Skarels #define N_CHARS 120
9416341Skarels 
95*16362Skarels /*
96*16362Skarels  * Build a block of characters containing the message.
97*16362Skarels  * It is sent blank filled and in a single block to
98*16362Skarels  * try to keep the message in one piece if the recipient
99*16362Skarels  * in in vi at the time
100*16362Skarels  */
10116341Skarels print_mesg(tf, request, remote_machine)
102*16362Skarels 	FILE *tf;
103*16362Skarels 	CTL_MSG *request;
104*16362Skarels 	char *remote_machine;
10516341Skarels {
106*16362Skarels 	struct timeval clock;
107*16362Skarels 	struct timezone zone;
108*16362Skarels 	struct tm *localtime();
109*16362Skarels 	struct tm *localclock;
110*16362Skarels 	char line_buf[N_LINES][N_CHARS];
111*16362Skarels 	int sizes[N_LINES];
112*16362Skarels 	char big_buf[N_LINES*N_CHARS];
113*16362Skarels 	char *bptr, *lptr;
114*16362Skarels 	int i, j, max_size;
11516341Skarels 
116*16362Skarels 	i = 0;
117*16362Skarels 	max_size = 0;
118*16362Skarels 	gettimeofday(&clock, &zone);
119*16362Skarels 	localclock = localtime( &clock.tv_sec );
120*16362Skarels 	sprintf(line_buf[i], " ");
121*16362Skarels 	sizes[i] = strlen(line_buf[i]);
122*16362Skarels 	max_size = max(max_size, sizes[i]);
123*16362Skarels 	i++;
124*16362Skarels 	sprintf(line_buf[i], "Message from Talk_Daemon@%s at %d:%02d ...",
12516341Skarels 	hostname, localclock->tm_hour , localclock->tm_min );
126*16362Skarels 	sizes[i] = strlen(line_buf[i]);
127*16362Skarels 	max_size = max(max_size, sizes[i]);
128*16362Skarels 	i++;
129*16362Skarels 	sprintf(line_buf[i], "talk: connection requested by %s@%s.",
13016341Skarels 		request->l_name, remote_machine);
131*16362Skarels 	sizes[i] = strlen(line_buf[i]);
132*16362Skarels 	max_size = max(max_size, sizes[i]);
133*16362Skarels 	i++;
134*16362Skarels 	sprintf(line_buf[i], "talk: respond with:  talk %s@%s",
13516341Skarels 		request->l_name, remote_machine);
136*16362Skarels 	sizes[i] = strlen(line_buf[i]);
137*16362Skarels 	max_size = max(max_size, sizes[i]);
138*16362Skarels 	i++;
139*16362Skarels 	sprintf(line_buf[i], " ");
140*16362Skarels 	sizes[i] = strlen(line_buf[i]);
141*16362Skarels 	max_size = max(max_size, sizes[i]);
142*16362Skarels 	i++;
143*16362Skarels 	bptr = big_buf;
144*16362Skarels 	*(bptr++) = ''; /* send something to wake them up */
14516341Skarels 	*(bptr++) = '\r';	/* add a \r in case of raw mode */
14616341Skarels 	*(bptr++) = '\n';
147*16362Skarels 	for (i = 0; i < N_LINES; i++) {
148*16362Skarels 		/* copy the line into the big buffer */
149*16362Skarels 		lptr = line_buf[i];
150*16362Skarels 		while (*lptr != '\0')
151*16362Skarels 			*(bptr++) = *(lptr++);
152*16362Skarels 		/* pad out the rest of the lines with blanks */
153*16362Skarels 		for (j = sizes[i]; j < max_size + 2; j++)
154*16362Skarels 			*(bptr++) = ' ';
155*16362Skarels 		*(bptr++) = '\r';	/* add a \r in case of raw mode */
156*16362Skarels 		*(bptr++) = '\n';
157*16362Skarels 	}
158*16362Skarels 	*bptr = '\0';
159*16362Skarels 	fprintf(tf, big_buf);
160*16362Skarels 	fflush(tf);
161*16362Skarels 	ioctl(fileno(tf), TIOCNOTTY, (struct sgttyb *) 0);
16216341Skarels }
163