]> git.saurik.com Git - apple/network_cmds.git/blob - talkd.tproj/process.c
network_cmds-245.1.tar.gz
[apple/network_cmds.git] / talkd.tproj / process.c
1 /*
2 * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * "Portions Copyright (c) 1999 Apple Computer, Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
12 * this file.
13 *
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
20 * under the License."
21 *
22 * @APPLE_LICENSE_HEADER_END@
23 */
24 /*
25 * Copyright (c) 1983, 1993
26 * The Regents of the University of California. All rights reserved.
27 *
28 * Redistribution and use in source and binary forms, with or without
29 * modification, are permitted provided that the following conditions
30 * are met:
31 * 1. Redistributions of source code must retain the above copyright
32 * notice, this list of conditions and the following disclaimer.
33 * 2. Redistributions in binary form must reproduce the above copyright
34 * notice, this list of conditions and the following disclaimer in the
35 * documentation and/or other materials provided with the distribution.
36 * 3. All advertising materials mentioning features or use of this software
37 * must display the following acknowledgement:
38 * This product includes software developed by the University of
39 * California, Berkeley and its contributors.
40 * 4. Neither the name of the University nor the names of its contributors
41 * may be used to endorse or promote products derived from this software
42 * without specific prior written permission.
43 *
44 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
45 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
46 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
47 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
48 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
49 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
50 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
51 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
52 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
53 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
54 * SUCH DAMAGE.
55 */
56
57 #ifndef lint
58 static char sccsid[] = "@(#)process.c 8.2 (Berkeley) 11/16/93";
59 #endif /* not lint */
60
61 /*
62 * process.c handles the requests, which can be of three types:
63 * ANNOUNCE - announce to a user that a talk is wanted
64 * LEAVE_INVITE - insert the request into the table
65 * LOOK_UP - look up to see if a request is waiting in
66 * in the table for the local user
67 * DELETE - delete invitation
68 */
69 #include <sys/param.h>
70 #include <sys/stat.h>
71 #include <sys/socket.h>
72 #include <netinet/in.h>
73 #include <protocols/talkd.h>
74 #include <netdb.h>
75 #include <syslog.h>
76 #include <stdio.h>
77 #include <string.h>
78 #include <paths.h>
79 #include "talkd.h"
80
81 CTL_MSG *find_request();
82 CTL_MSG *find_match();
83
84 void
85 process_request(mp, rp)
86 register CTL_MSG *mp;
87 register CTL_RESPONSE *rp;
88 {
89 register CTL_MSG *ptr;
90 extern int debug;
91
92 rp->vers = TALK_VERSION;
93 rp->type = mp->type;
94 rp->id_num = htonl(0);
95 if (mp->vers != TALK_VERSION) {
96 syslog(LOG_WARNING, "Bad protocol version %d", mp->vers);
97 rp->answer = BADVERSION;
98 return;
99 }
100 mp->id_num = ntohl(mp->id_num);
101 mp->addr.sa_family = ntohs(mp->addr.sa_family);
102 if (mp->addr.sa_family != AF_INET) {
103 syslog(LOG_WARNING, "Bad address, family %d",
104 mp->addr.sa_family);
105 rp->answer = BADADDR;
106 return;
107 }
108 mp->ctl_addr.sa_family = ntohs(mp->ctl_addr.sa_family);
109 if (mp->ctl_addr.sa_family != AF_INET) {
110 syslog(LOG_WARNING, "Bad control address, family %d",
111 mp->ctl_addr.sa_family);
112 rp->answer = BADCTLADDR;
113 return;
114 }
115 mp->pid = ntohl(mp->pid);
116 if (debug)
117 print_request("process_request", mp);
118 switch (mp->type) {
119
120 case ANNOUNCE:
121 do_announce(mp, rp);
122 break;
123
124 case LEAVE_INVITE:
125 ptr = find_request(mp);
126 if (ptr != (CTL_MSG *)0) {
127 rp->id_num = htonl(ptr->id_num);
128 rp->answer = SUCCESS;
129 } else
130 insert_table(mp, rp);
131 break;
132
133 case LOOK_UP:
134 ptr = find_match(mp);
135 if (ptr != (CTL_MSG *)0) {
136 rp->id_num = htonl(ptr->id_num);
137 rp->addr = ptr->addr;
138 rp->addr.sa_family = htons(ptr->addr.sa_family);
139 rp->answer = SUCCESS;
140 } else
141 rp->answer = NOT_HERE;
142 break;
143
144 case DELETE:
145 rp->answer = delete_invite(mp->id_num);
146 break;
147
148 default:
149 rp->answer = UNKNOWN_REQUEST;
150 break;
151 }
152 if (debug)
153 print_response("process_request", rp);
154 }
155
156 void
157 do_announce(mp, rp)
158 register CTL_MSG *mp;
159 CTL_RESPONSE *rp;
160 {
161 struct hostent *hp;
162 CTL_MSG *ptr;
163 int result;
164
165 /* see if the user is logged */
166 result = find_user(mp->r_name, mp->r_tty);
167 if (result != SUCCESS) {
168 rp->answer = result;
169 return;
170 }
171 #define satosin(sa) ((struct sockaddr_in *)(sa))
172 hp = gethostbyaddr((char *)&satosin(&mp->ctl_addr)->sin_addr,
173 sizeof (struct in_addr), AF_INET);
174 if (hp == (struct hostent *)0) {
175 rp->answer = MACHINE_UNKNOWN;
176 return;
177 }
178 ptr = find_request(mp);
179 if (ptr == (CTL_MSG *) 0) {
180 insert_table(mp, rp);
181 rp->answer = announce(mp, hp->h_name);
182 return;
183 }
184 if (mp->id_num > ptr->id_num) {
185 /*
186 * This is an explicit re-announce, so update the id_num
187 * field to avoid duplicates and re-announce the talk.
188 */
189 ptr->id_num = new_id();
190 rp->id_num = htonl(ptr->id_num);
191 rp->answer = announce(mp, hp->h_name);
192 } else {
193 /* a duplicated request, so ignore it */
194 rp->id_num = htonl(ptr->id_num);
195 rp->answer = SUCCESS;
196 }
197 }
198
199 #include <utmp.h>
200
201 /*
202 * Search utmp for the local user
203 */
204 int
205 find_user(name, tty)
206 char *name, *tty;
207 {
208 struct utmp ubuf;
209 int status;
210 FILE *fd;
211 struct stat statb;
212 char line[sizeof(ubuf.ut_line) + 1];
213 char ftty[sizeof(_PATH_DEV) - 1 + sizeof(line)];
214
215 if ((fd = fopen(_PATH_UTMP, "r")) == NULL) {
216 fprintf(stderr, "talkd: can't read %s.\n", _PATH_UTMP);
217 return (FAILED);
218 }
219 #define SCMPN(a, b) strncmp(a, b, sizeof (a))
220 status = NOT_HERE;
221 (void) strcpy(ftty, _PATH_DEV);
222 while (fread((char *) &ubuf, sizeof ubuf, 1, fd) == 1)
223 if (SCMPN(ubuf.ut_name, name) == 0) {
224 strncpy(line, ubuf.ut_line, sizeof(ubuf.ut_line));
225 line[sizeof(ubuf.ut_line)] = '\0';
226 if (*tty == '\0') {
227 status = PERMISSION_DENIED;
228 /* no particular tty was requested */
229 (void) strcpy(ftty + sizeof(_PATH_DEV) - 1,
230 line);
231 if (stat(ftty, &statb) == 0) {
232 if (!(statb.st_mode & 020))
233 continue;
234 (void) strcpy(tty, line);
235 status = SUCCESS;
236 break;
237 }
238 }
239 if (strcmp(line, tty) == 0) {
240 status = SUCCESS;
241 break;
242 }
243 }
244 fclose(fd);
245 return (status);
246 }