Commit | Line | Data |
---|---|---|
610b175a MK |
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++) = '\a'; /* 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 | } |