Unleashed v1.4
[unleashed.git] / usr / src / cmd / cmd-inet / usr.sbin / in.talkd / process.c
blob7ea602704e21972745bda8136510e29939b24ea5
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
21 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
22 * Use is subject to license terms.
26 * Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T
27 * All Rights Reserved.
31 * University Copyright- Copyright (c) 1982, 1986, 1988
32 * The Regents of the University of California.
33 * All Rights Reserved.
35 * University Acknowledgment- Portions of this document are derived from
36 * software developed by the University of California, Berkeley, and its
37 * contributors.
40 #pragma ident "%Z%%M% %I% %E% SMI"
44 * process.c handles the requests, which can be of three types:
46 * ANNOUNCE - announce to a user that a talk is wanted
48 * LEAVE_INVITE - insert the request into the table
50 * LOOK_UP - look up to see if a request is waiting in
51 * in the table for the local user
53 * DELETE - delete invitation
57 #include <sys/types.h>
58 #include <sys/stat.h>
59 #include <sys/param.h>
60 #include <fcntl.h>
61 #include <syslog.h>
62 #include <string.h>
63 #include <utmpx.h>
64 #include <unistd.h>
65 #include <stdlib.h>
66 #include <stdio.h>
67 #include "talkd_impl.h"
69 static void do_announce(CTL_MSG *request, CTL_RESPONSE *response);
70 static int find_user(char *name, char *tty);
72 void
73 process_request(CTL_MSG *request, CTL_RESPONSE *response)
75 CTL_MSG *ptr;
77 response->type = request->type;
78 response->id_num = 0;
81 * Check if any of the strings within the request structure aren't
82 * NUL terminated, and if so don't bother processing the request
83 * further.
85 if ((memchr(request->l_name, '\0', sizeof (request->l_name)) == NULL) ||
86 (memchr(request->r_name, '\0', sizeof (request->r_name)) == NULL) ||
87 (memchr(request->r_tty, '\0', sizeof (request->r_tty)) == NULL)) {
88 response->answer = FAILED;
89 openlog("talk", 0, LOG_AUTH);
90 syslog(LOG_CRIT, "malformed talk request\n");
91 closelog();
92 return;
95 switch (request->type) {
97 case ANNOUNCE :
99 do_announce(request, response);
100 break;
102 case LEAVE_INVITE :
104 ptr = find_request(request);
105 if (ptr != NULL) {
106 response->id_num = ptr->id_num;
107 response->answer = SUCCESS;
108 } else {
109 insert_table(request, response);
111 break;
113 case LOOK_UP :
115 ptr = find_match(request);
116 if (ptr != NULL) {
117 response->id_num = ptr->id_num;
118 response->addr = ptr->addr;
119 response->answer = SUCCESS;
120 } else {
121 response->answer = NOT_HERE;
123 break;
125 case DELETE :
127 response->answer = delete_invite(request->id_num);
128 break;
130 default :
132 response->answer = UNKNOWN_REQUEST;
133 break;
137 static void
138 do_announce(CTL_MSG *request, CTL_RESPONSE *response)
140 struct hostent *hp;
141 CTL_MSG *ptr;
142 int result;
145 * See if the user is logged.
147 result = find_user(request->r_name, request->r_tty);
148 if (result != SUCCESS) {
149 response->answer = result;
150 return;
153 hp = gethostbyaddr((const char *)&request->ctl_addr.sin_addr,
154 sizeof (struct in_addr), AF_INET);
155 if (hp == NULL) {
156 response->answer = MACHINE_UNKNOWN;
157 return;
160 ptr = find_request(request);
161 if (ptr == NULL) {
162 insert_table(request, response);
163 response->answer = announce(request, hp->h_name);
164 } else if (request->id_num > ptr->id_num) {
166 * This is an explicit re-announce, so update the id_num
167 * field to avoid duplicates and re-announce the talk.
169 ptr->id_num = response->id_num = new_id();
170 response->answer = announce(request, hp->h_name);
171 } else {
172 /* a duplicated request, so ignore it */
173 response->id_num = ptr->id_num;
174 response->answer = SUCCESS;
179 * Search utmp for the local user.
182 static int
183 find_user(char *name, char *tty)
185 struct utmpx *ubuf;
186 int tfd;
187 char dev[MAXPATHLEN];
188 struct stat stbuf;
189 int problem = NOT_HERE;
191 setutxent(); /* reset the utmpx file */
193 while (ubuf = getutxent()) {
194 if (ubuf->ut_type == USER_PROCESS &&
195 strncmp(ubuf->ut_user, name, sizeof (ubuf->ut_user)) == 0) {
197 * Check if this entry is really a tty.
199 (void) snprintf(dev, sizeof (dev), "/dev/%.*s",
200 sizeof (ubuf->ut_line), ubuf->ut_line);
201 if ((tfd = open(dev, O_WRONLY|O_NOCTTY)) == -1) {
202 continue;
204 if (!isatty(tfd)) {
205 (void) close(tfd);
206 openlog("talk", 0, LOG_AUTH);
207 syslog(LOG_CRIT, "%.*s in utmp is not a tty\n",
208 sizeof (ubuf->ut_line), ubuf->ut_line);
209 closelog();
210 continue;
212 if (*tty == '\0') {
214 * No particular tty was requested.
216 if (fstat(tfd, &stbuf) < 0 ||
217 (stbuf.st_mode&020) == 0) {
218 (void) close(tfd);
219 problem = PERMISSION_DENIED;
220 continue;
222 (void) close(tfd);
223 (void) strlcpy(tty, ubuf->ut_line, TTY_SIZE);
224 endutxent(); /* close the utmpx file */
225 return (SUCCESS);
227 (void) close(tfd);
228 if (strcmp(ubuf->ut_line, tty) == 0) {
229 endutxent(); /* close the utmpx file */
230 return (SUCCESS);
235 endutxent(); /* close the utmpx file */
236 return (problem);