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