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 * Invoked by the Internet daemon to handle talk requests 45 * Processes talk requests until MAX_LIFE seconds go by with 46 * no action, then dies. 47 */ 48 49 #include <stdio.h> 50 #include <errno.h> 51 #include <sys/ioctl.h> 52 #include <sys/time.h> 53 #include <sys/systeminfo.h> 54 #include <sys/wait.h> 55 #include <unistd.h> 56 #include <stdlib.h> 57 #include <string.h> 58 #include "talkd_impl.h" 59 60 static CTL_MSG request; 61 static CTL_RESPONSE response; 62 63 char hostname[HOST_NAME_LENGTH]; 64 int debug = 0; 65 66 static CTL_MSG swapmsg(CTL_MSG req); 67 68 int 69 main() 70 { 71 struct sockaddr_in from; 72 socklen_t from_size = (socklen_t)sizeof (from); 73 int cc; 74 int name_length = sizeof (hostname); 75 fd_set rfds; 76 struct timeval tv; 77 78 (void) sysinfo(SI_HOSTNAME, hostname, name_length); 79 80 for (;;) { 81 tv.tv_sec = MAX_LIFE; 82 tv.tv_usec = 0; 83 FD_ZERO(&rfds); 84 FD_SET(0, &rfds); 85 if (select(1, &rfds, 0, 0, &tv) <= 0) 86 return (0); 87 cc = recvfrom(0, (char *)&request, sizeof (request), 0, 88 (struct sockaddr *)&from, &from_size); 89 90 if (cc != sizeof (request)) { 91 if (cc < 0 && errno != EINTR) { 92 print_error("receive"); 93 } 94 } else { 95 96 if (debug) { 97 (void) printf("Request received : \n"); 98 (void) print_request(&request); 99 } 100 101 request = swapmsg(request); 102 process_request(&request, &response); 103 104 if (debug) { 105 (void) printf("Response sent : \n"); 106 print_response(&response); 107 } 108 109 /* 110 * Can block here, is this what I want? 111 */ 112 cc = sendto(0, (char *)&response, sizeof (response), 0, 113 (struct sockaddr *)&request.ctl_addr, 114 (socklen_t)sizeof (request.ctl_addr)); 115 116 if (cc != sizeof (response)) { 117 print_error("Send"); 118 } 119 } 120 } 121 } 122 123 void 124 print_error(char *string) 125 { 126 FILE *cons; 127 char *err_dev = "/dev/console"; 128 char *sys; 129 pid_t val, pid; 130 131 if (debug) 132 err_dev = "/dev/tty"; 133 134 if ((sys = strerror(errno)) == (char *)NULL) 135 sys = "Unknown error"; 136 137 /* don't ever open tty's directly, let a child do it */ 138 if ((pid = fork()) == 0) { 139 cons = fopen(err_dev, "a"); 140 if (cons != NULL) { 141 (void) fprintf(cons, "Talkd : %s : %s(%d)\n\r", string, 142 sys, errno); 143 (void) fclose(cons); 144 } 145 exit(0); 146 } else { 147 /* wait for the child process to return */ 148 do { 149 val = wait(0); 150 if (val == (pid_t)-1) { 151 if (errno == EINTR) { 152 continue; 153 } else if (errno == ECHILD) { 154 break; 155 } 156 } 157 } while (val != pid); 158 } 159 } 160 161 #define swapshort(a) (((a << 8) | ((unsigned short) a >> 8)) & 0xffff) 162 #define swaplong(a) ((swapshort(a) << 16) | (swapshort(((unsigned)a >> 16)))) 163 164 /* 165 * Heuristic to detect if need to swap bytes. 166 */ 167 168 static CTL_MSG 169 swapmsg(CTL_MSG req) 170 { 171 CTL_MSG swapreq; 172 173 if (req.ctl_addr.sin_family == swapshort(AF_INET)) { 174 swapreq = req; 175 swapreq.id_num = swaplong(req.id_num); 176 swapreq.pid = swaplong(req.pid); 177 swapreq.addr.sin_family = swapshort(req.addr.sin_family); 178 swapreq.ctl_addr.sin_family = 179 swapshort(req.ctl_addr.sin_family); 180 return (swapreq); 181 } else { 182 return (req); 183 } 184 } 185