xref: /csrg-svn/libexec/talkd/process.c (revision 37991)
1 /*
2  * Copyright (c) 1983 Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #ifndef lint
19 static char sccsid[] = "@(#)process.c	5.8 (Berkeley) 05/11/89";
20 #endif /* not lint */
21 
22 /*
23  * process.c handles the requests, which can be of three types:
24  *	ANNOUNCE - announce to a user that a talk is wanted
25  *	LEAVE_INVITE - insert the request into the table
26  *	LOOK_UP - look up to see if a request is waiting in
27  *		  in the table for the local user
28  *	DELETE - delete invitation
29  */
30 #include <sys/types.h>
31 #include <sys/stat.h>
32 #include <stdio.h>
33 #include <syslog.h>
34 #include <netdb.h>
35 #include <netinet/in.h>
36 
37 #include <protocols/talkd.h>
38 #include <paths.h>
39 
40 char	*strcpy();
41 CTL_MSG *find_request();
42 CTL_MSG *find_match();
43 
44 process_request(mp, rp)
45 	register CTL_MSG *mp;
46 	register CTL_RESPONSE *rp;
47 {
48 	register CTL_MSG *ptr;
49 	extern int debug;
50 
51 	rp->vers = TALK_VERSION;
52 	rp->type = mp->type;
53 	rp->id_num = htonl(0);
54 	if (mp->vers != TALK_VERSION) {
55 		syslog(LOG_WARNING, "Bad protocol version %d", mp->vers);
56 		rp->answer = BADVERSION;
57 		return;
58 	}
59 	mp->id_num = ntohl(mp->id_num);
60 	mp->addr.sa_family = ntohs(mp->addr.sa_family);
61 	if (mp->addr.sa_family != AF_INET) {
62 		syslog(LOG_WARNING, "Bad address, family %d",
63 		    mp->addr.sa_family);
64 		rp->answer = BADADDR;
65 		return;
66 	}
67 	mp->ctl_addr.sa_family = ntohs(mp->ctl_addr.sa_family);
68 	if (mp->ctl_addr.sa_family != AF_INET) {
69 		syslog(LOG_WARNING, "Bad control address, family %d",
70 		    mp->ctl_addr.sa_family);
71 		rp->answer = BADCTLADDR;
72 		return;
73 	}
74 	mp->pid = ntohl(mp->pid);
75 	if (debug)
76 		print_request("process_request", mp);
77 	switch (mp->type) {
78 
79 	case ANNOUNCE:
80 		do_announce(mp, rp);
81 		break;
82 
83 	case LEAVE_INVITE:
84 		ptr = find_request(mp);
85 		if (ptr != (CTL_MSG *)0) {
86 			rp->id_num = htonl(ptr->id_num);
87 			rp->answer = SUCCESS;
88 		} else
89 			insert_table(mp, rp);
90 		break;
91 
92 	case LOOK_UP:
93 		ptr = find_match(mp);
94 		if (ptr != (CTL_MSG *)0) {
95 			rp->id_num = htonl(ptr->id_num);
96 			rp->addr = ptr->addr;
97 			rp->addr.sa_family = htons(ptr->addr.sa_family);
98 			rp->answer = SUCCESS;
99 		} else
100 			rp->answer = NOT_HERE;
101 		break;
102 
103 	case DELETE:
104 		rp->answer = delete_invite(mp->id_num);
105 		break;
106 
107 	default:
108 		rp->answer = UNKNOWN_REQUEST;
109 		break;
110 	}
111 	if (debug)
112 		print_response("process_request", rp);
113 }
114 
115 do_announce(mp, rp)
116 	register CTL_MSG *mp;
117 	CTL_RESPONSE *rp;
118 {
119 	struct hostent *hp;
120 	CTL_MSG *ptr;
121 	int result;
122 
123 	/* see if the user is logged */
124 	result = find_user(mp->r_name, mp->r_tty);
125 	if (result != SUCCESS) {
126 		rp->answer = result;
127 		return;
128 	}
129 #define	satosin(sa)	((struct sockaddr_in *)(sa))
130 	hp = gethostbyaddr(&satosin(&mp->ctl_addr)->sin_addr,
131 		sizeof (struct in_addr), AF_INET);
132 	if (hp == (struct hostent *)0) {
133 		rp->answer = MACHINE_UNKNOWN;
134 		return;
135 	}
136 	ptr = find_request(mp);
137 	if (ptr == (CTL_MSG *) 0) {
138 		insert_table(mp, rp);
139 		rp->answer = announce(mp, hp->h_name);
140 		return;
141 	}
142 	if (mp->id_num > ptr->id_num) {
143 		/*
144 		 * This is an explicit re-announce, so update the id_num
145 		 * field to avoid duplicates and re-announce the talk.
146 		 */
147 		ptr->id_num = new_id();
148 		rp->id_num = htonl(ptr->id_num);
149 		rp->answer = announce(mp, hp->h_name);
150 	} else {
151 		/* a duplicated request, so ignore it */
152 		rp->id_num = htonl(ptr->id_num);
153 		rp->answer = SUCCESS;
154 	}
155 }
156 
157 #include <utmp.h>
158 
159 /*
160  * Search utmp for the local user
161  */
162 find_user(name, tty)
163 	char *name, *tty;
164 {
165 	struct utmp ubuf;
166 	int status;
167 	FILE *fd;
168 	struct stat statb;
169 	char ftty[20];
170 
171 	if ((fd = fopen(_PATH_UTMP, "r")) == NULL) {
172 		fprintf(stderr, "talkd: can't read %s.\n", _PATH_UTMP);
173 		return (FAILED);
174 	}
175 #define SCMPN(a, b)	strncmp(a, b, sizeof (a))
176 	status = NOT_HERE;
177 	(void) strcpy(ftty, _PATH_DEV);
178 	while (fread((char *) &ubuf, sizeof ubuf, 1, fd) == 1)
179 		if (SCMPN(ubuf.ut_name, name) == 0) {
180 			if (*tty == '\0') {
181 				status = PERMISSION_DENIED;
182 				/* no particular tty was requested */
183 				(void) strcpy(ftty+5, ubuf.ut_line);
184 				if (stat(ftty,&statb) == 0) {
185 					if (!(statb.st_mode & 020))
186 						continue;
187 					(void) strcpy(tty, ubuf.ut_line);
188 					status = SUCCESS;
189 					break;
190 				}
191 			}
192 			if (strcmp(ubuf.ut_line, tty) == 0) {
193 				status = SUCCESS;
194 				break;
195 			}
196 		}
197 	fclose(fd);
198 	return (status);
199 }
200