1 /* $Header: talkd.c 1.5 83/05/10 13:57:29 moore Exp $ */ 2 3 /* The top level of the daemon, the format is heavily borrowed 4 from rwhod.c. Basically: find out who and where you are; 5 disconnect all descriptors and ttys, and then endless 6 loop on waiting for and processing requests 7 */ 8 9 #include "ctl.h" 10 11 #include <stdio.h> 12 #include <errno.h> 13 #include <sgtty.h> 14 #include <sys/ioctl.h> 15 16 #define MAX_ERR 20 /* Number of times to attempt to open the 17 control socket */ 18 19 extern errno; 20 21 struct sockaddr_in sin = { AF_INET }; 22 23 CTL_MSG request; 24 CTL_RESPONSE response; 25 int sockt; 26 char hostname[HOST_NAME_LENGTH]; 27 28 struct hostent *gethostbyname(); 29 struct servent *getservbyname(); 30 31 int debug = 0; 32 33 main(argc) 34 int argc; 35 { 36 struct sockaddr_in from; 37 int from_size; 38 int cc; 39 int name_length = sizeof(hostname); 40 struct servent *sp; 41 struct hostent *hp; 42 43 44 if ( argc > 1 ) { 45 debug = 1; 46 } 47 48 if ( !debug ) { 49 if (fork()) { 50 exit(0); 51 } 52 } 53 54 gethostname(hostname, &name_length); 55 56 hp = gethostbyname(hostname); 57 if (hp == (struct hostent *) 0) { 58 fprintf(stderr, "talkd: Cannot obtain local address\n"); 59 exit(1); 60 } 61 62 #ifdef NTALK 63 sp = getservbyname("ntalk", "udp"); 64 #else 65 sp = getservbyname("talk", "udp"); 66 #endif 67 68 if (sp == 0) { 69 fprintf(stderr, "talkd: udp/talk: unknown service\n"); 70 exit(1); 71 } 72 73 if (getuid()) { 74 fprintf(stderr, "Talkd : not super user\n"); 75 exit(1); 76 } 77 78 setup_desc(); 79 80 sin.sin_port = sp->s_port; 81 sockt = socket(AF_INET, SOCK_DGRAM, 0, 0); 82 if (sockt < 0) { 83 print_error("talkd: socket"); 84 exit(1); 85 } 86 87 if (bind(sockt, (caddr_t)&sin, sizeof (sin), 0) < 0) { 88 print_error("bind"); 89 exit(1); 90 } 91 92 for (;;) { 93 94 from_size = sizeof(from); 95 cc = recvfrom(sockt, (char *)&request, sizeof (request), 0, 96 &from, &from_size); 97 98 if (cc != sizeof(request)) { 99 if (cc < 0 && errno != EINTR) { 100 print_error("receive"); 101 } 102 } else { 103 104 if (debug) printf("Request received : \n"); 105 if (debug) print_request(&request); 106 107 process_request(&request, &response); 108 109 if (debug) printf("Response sent : \n"); 110 if (debug) print_response(&response); 111 112 /* can block here, is this what I want? */ 113 114 cc = sendto(sockt, (char *) &response, sizeof(response), 0, 115 &request.ctl_addr, sizeof(request.ctl_addr)); 116 117 if (cc != sizeof(response)) { 118 print_error("Send"); 119 } 120 } 121 } 122 } 123 124 /* disconnect all descriptors, remove ourself from the process 125 * group that spawned us 126 */ 127 128 setup_desc() 129 { 130 int s; 131 132 if (debug) return; 133 134 for (s = 0; s < 10; s++) { 135 (void) close(s); 136 } 137 138 (void) open("/dev/null", 0); 139 (void) dup2(0, 1); 140 (void) dup2(0, 2); 141 142 s = open("/dev/tty", 2); 143 144 if (s >= 0) { 145 ioctl(s, TIOCNOTTY, (struct sgttyb *) 0); 146 (void) close(s); 147 } 148 149 (void) chdir("/dev"); 150 } 151 152 extern int sys_nerr; 153 extern char *sys_errlist[]; 154 155 print_error(string) 156 char *string; 157 { 158 FILE *cons; 159 char *err_dev = "/dev/console"; 160 char *sys; 161 int val, pid; 162 163 if (debug) err_dev = "/dev/tty"; 164 165 sys = "Unknown error"; 166 167 if(errno < sys_nerr) { 168 sys = sys_errlist[errno]; 169 } 170 171 /* don't ever open tty's directly, let a child do it */ 172 if ((pid = fork()) == 0) { 173 cons = fopen(err_dev, "a"); 174 if (cons != NULL) { 175 fprintf(cons, "Talkd : %s : %s(%d)\n\r", string, sys, 176 errno); 177 fclose(cons); 178 } 179 exit(0); 180 } else { 181 /* wait for the child process to return */ 182 do { 183 val = wait(0); 184 if (val == -1) { 185 if (errno == EINTR) { 186 continue; 187 } else if (errno == ECHILD) { 188 break; 189 } 190 } 191 } while (val != pid); 192 } 193 } 194