xref: /csrg-svn/libexec/talkd/talkd.c (revision 16360)
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