1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 * 22 * Copyright 2002 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T 28 * All Rights Reserved. 29 */ 30 31 /* 32 * University Copyright- Copyright (c) 1982, 1986, 1988 33 * The Regents of the University of California. 34 * All Rights Reserved. 35 * 36 * University Acknowledgment- Portions of this document are derived from 37 * software developed by the University of California, Berkeley, and its 38 * contributors. 39 */ 40 41 #pragma ident "%Z%%M% %I% %E% SMI" 42 43 44 /* 45 * process.c handles the requests, which can be of three types: 46 * 47 * ANNOUNCE - announce to a user that a talk is wanted 48 * 49 * LEAVE_INVITE - insert the request into the table 50 * 51 * LOOK_UP - look up to see if a request is waiting in 52 * in the table for the local user 53 * 54 * DELETE - delete invitation 55 * 56 */ 57 58 #include <sys/types.h> 59 #include <sys/stat.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" 68 69 static void do_announce(CTL_MSG *request, CTL_RESPONSE *response); 70 static int find_user(char *name, char *tty); 71 72 void 73 process_request(CTL_MSG *request, CTL_RESPONSE *response) 74 { 75 CTL_MSG *ptr; 76 77 response->type = request->type; 78 response->id_num = 0; 79 80 /* 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. 84 */ 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; 93 } 94 95 switch (request->type) { 96 97 case ANNOUNCE : 98 99 do_announce(request, response); 100 break; 101 102 case LEAVE_INVITE : 103 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); 110 } 111 break; 112 113 case LOOK_UP : 114 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; 122 } 123 break; 124 125 case DELETE : 126 127 response->answer = delete_invite(request->id_num); 128 break; 129 130 default : 131 132 response->answer = UNKNOWN_REQUEST; 133 break; 134 } 135 } 136 137 static void 138 do_announce(CTL_MSG *request, CTL_RESPONSE *response) 139 { 140 struct hostent *hp; 141 CTL_MSG *ptr; 142 int result; 143 144 /* 145 * See if the user is logged. 146 */ 147 result = find_user(request->r_name, request->r_tty); 148 if (result != SUCCESS) { 149 response->answer = result; 150 return; 151 } 152 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; 158 } 159 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) { 165 /* 166 * This is an explicit re-announce, so update the id_num 167 * field to avoid duplicates and re-announce the talk. 168 */ 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; 175 } 176 } 177 178 /* 179 * Search utmp for the local user. 180 */ 181 182 static int 183 find_user(char *name, char *tty) 184 { 185 struct utmpx *ubuf; 186 int tfd; 187 char dev[MAXPATHLEN]; 188 189 setutxent(); /* reset the utmpx file */ 190 191 while (ubuf = getutxent()) { 192 if (ubuf->ut_type == USER_PROCESS && 193 strncmp(ubuf->ut_user, name, sizeof (ubuf->ut_user)) == 0) { 194 /* 195 * Check if this entry is really a tty. 196 */ 197 (void) snprintf(dev, sizeof (dev), "/dev/%.*s", 198 sizeof (ubuf->ut_line), ubuf->ut_line); 199 if ((tfd = open(dev, O_WRONLY|O_NOCTTY)) == -1) { 200 continue; 201 } 202 if (!isatty(tfd)) { 203 (void) close(tfd); 204 openlog("talk", 0, LOG_AUTH); 205 syslog(LOG_CRIT, "%.*s in utmp is not a tty\n", 206 sizeof (ubuf->ut_line), ubuf->ut_line); 207 closelog(); 208 continue; 209 } 210 (void) close(tfd); 211 if (*tty == '\0') { 212 /* 213 * No particular tty was requested. 214 */ 215 (void) strlcpy(tty, ubuf->ut_line, TTY_SIZE); 216 endutxent(); /* close the utmpx file */ 217 return (SUCCESS); 218 } else if (strcmp(ubuf->ut_line, tty) == 0) { 219 endutxent(); /* close the utmpx file */ 220 return (SUCCESS); 221 } 222 } 223 } 224 225 endutxent(); /* close the utmpx file */ 226 return (NOT_HERE); 227 } 228