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