xref: /csrg-svn/libexec/talkd/announce.c (revision 16341)
1 /* $Header: /a/guest/moore/talk/RCS/announce.c,v 1.8 83/07/06 00:16:57 moore Exp $ */
2 
3 #include "ctl.h"
4 
5 #include <sys/stat.h>
6 #include <sgtty.h>
7 #include <sys/ioctl.h>
8 #include <sys/time.h>
9 #include <stdio.h>
10 #include <sys/wait.h>
11 #include <errno.h>
12 
13 char *sprintf();
14 
15 extern int errno;
16 extern char hostname[];
17 int nofork = 0;		/* to be set from the debugger */
18 
19 /*
20  * Because the tty driver insists on attaching a terminal-less
21  * process to any terminal that it writes on, we must fork a child
22  * to protect ourselves
23  */
24 
25 announce(request, remote_machine)
26 CTL_MSG *request;
27 char *remote_machine;
28 {
29     int pid, val, status;
30 
31     if (nofork) {
32 	return(announce_proc(request, remote_machine));
33     }
34 
35     if ( pid = fork() ) {
36 
37 	    /* we are the parent, so wait for the child */
38 
39 	if (pid == -1) {
40 		/* the fork failed */
41 	    return(FAILED);
42 	}
43 
44 	do {
45 	    val = wait(&status);
46 	    if (val == -1) {
47 		if (errno == EINTR) {
48 		    continue;
49 		} else {
50 			/* shouldn't happen */
51 		    print_error("wait");
52 		    return(FAILED);
53 		}
54 	    }
55 	} while (val != pid);
56 
57 	if (status&0377 > 0) {
58 		/* we were killed by some signal */
59 	    return(FAILED);
60 	}
61 
62 	    /* Get the second byte, this is the exit/return code */
63 
64 	return((status>>8)&0377);
65 
66     } else {
67 	    /* we are the child, go and do it */
68 	_exit(announce_proc(request, remote_machine));
69     }
70 }
71 
72 
73     /* See if the user is accepting messages. If so, announce that
74        a talk is requested.
75      */
76 
77 announce_proc(request, remote_machine)
78 CTL_MSG *request;
79 char *remote_machine;
80 {
81     int pid, status;
82     char full_tty[32];
83     FILE *tf;
84     struct stat stbuf;
85 
86 
87     (void) sprintf(full_tty, "/dev/%s", request->r_tty);
88 
89     if (access(full_tty, 0) != 0) {
90 	return(FAILED);
91     }
92 
93     if ((tf = fopen(full_tty, "w")) == NULL) {
94 	return(PERMISSION_DENIED);
95     }
96 
97 	/* open gratuitously attaches the talkd to
98 	   any tty it opens, so disconnect us from the
99 	   tty before we catch a signal */
100 
101     ioctl(fileno(tf), TIOCNOTTY, (struct sgttyb *) 0);
102 
103     if (fstat(fileno(tf), &stbuf) < 0) {
104 	return(PERMISSION_DENIED);
105     }
106 
107     if ((stbuf.st_mode&02) == 0) {
108 	return(PERMISSION_DENIED);
109     }
110 
111     print_mesg(tf, request, remote_machine);
112     fclose(tf);
113     return(SUCCESS);
114 }
115 
116 #define max(a,b) ( (a) > (b) ? (a) : (b) )
117 #define N_LINES 5
118 #define N_CHARS 120
119 
120     /*
121      * build a block of characters containing the message.
122      * It is sent blank filled and in a single block to
123      * try to keep the message in one piece if the recipient
124      * in in vi at the time
125      */
126 
127 print_mesg(tf, request, remote_machine)
128 FILE *tf;
129 CTL_MSG *request;
130 char *remote_machine;
131 {
132     struct timeval clock;
133     struct timezone zone;
134     struct tm *localtime();
135     struct tm *localclock;
136     char line_buf[N_LINES][N_CHARS];
137     int sizes[N_LINES];
138     char big_buf[N_LINES*N_CHARS];
139     char *bptr, *lptr;
140     int i, j, max_size;
141 
142     i = 0;
143     max_size = 0;
144 
145     gettimeofday(&clock, &zone);
146     localclock = localtime( &clock.tv_sec );
147 
148     sprintf(line_buf[i], " ");
149 
150     sizes[i] = strlen(line_buf[i]);
151     max_size = max(max_size, sizes[i]);
152     i++;
153 
154     sprintf(line_buf[i], "Message from Talk_Daemon@%s at %d:%02d ...",
155 	hostname, localclock->tm_hour , localclock->tm_min );
156 
157     sizes[i] = strlen(line_buf[i]);
158     max_size = max(max_size, sizes[i]);
159     i++;
160 
161     sprintf(line_buf[i], "talk: connection requested by %s@%s.",
162 		request->l_name, remote_machine);
163 
164     sizes[i] = strlen(line_buf[i]);
165     max_size = max(max_size, sizes[i]);
166     i++;
167 
168     sprintf(line_buf[i], "talk: respond with:  talk %s@%s",
169 		request->l_name, remote_machine);
170 
171     sizes[i] = strlen(line_buf[i]);
172     max_size = max(max_size, sizes[i]);
173     i++;
174 
175     sprintf(line_buf[i], " ");
176 
177     sizes[i] = strlen(line_buf[i]);
178     max_size = max(max_size, sizes[i]);
179     i++;
180 
181     bptr = big_buf;
182     *(bptr++) = '';	/* send something to wake them up */
183     *(bptr++) = '\r';	/* add a \r in case of raw mode */
184     *(bptr++) = '\n';
185     for(i = 0; i < N_LINES; i++) {
186 
187 	    /* copy the line into the big buffer */
188 
189 	lptr = line_buf[i];
190 	while (*lptr != '\0') {
191 	    *(bptr++) = *(lptr++);
192 	}
193 
194 	    /* pad out the rest of the lines with blanks */
195 
196 	for(j = sizes[i]; j < max_size + 2; j++) {
197 	    *(bptr++) = ' ';
198 	}
199 
200 	*(bptr++) = '\r';	/* add a \r in case of raw mode */
201 	*(bptr++) = '\n';
202     }
203     *bptr = '\0';
204 
205     fprintf(tf, big_buf);
206     fflush(tf);
207     ioctl(fileno(tf), TIOCNOTTY, (struct sgttyb *) 0);
208 }
209