xref: /original-bsd/libexec/talkd/process.c (revision 57124d5e)
1 /*
2  * Copyright (c) 1983 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #ifndef lint
8 static char sccsid[] = "@(#)process.c	5.4 (Berkeley) 03/13/86";
9 #endif not lint
10 
11 /*
12  * process.c handles the requests, which can be of three types:
13  *	ANNOUNCE - announce to a user that a talk is wanted
14  *	LEAVE_INVITE - insert the request into the table
15  *	LOOK_UP - look up to see if a request is waiting in
16  *		  in the table for the local user
17  *	DELETE - delete invitation
18  */
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <stdio.h>
22 #include <syslog.h>
23 #include <netdb.h>
24 #include <netinet/in.h>
25 
26 #include <protocols/talkd.h>
27 
28 char	*strcpy();
29 CTL_MSG *find_request();
30 CTL_MSG *find_match();
31 
32 process_request(mp, rp)
33 	register CTL_MSG *mp;
34 	register CTL_RESPONSE *rp;
35 {
36 	register CTL_MSG *ptr;
37 	extern int debug;
38 
39 	rp->vers = TALK_VERSION;
40 	rp->type = mp->type;
41 	rp->id_num = htonl(0);
42 	if (mp->vers != TALK_VERSION) {
43 		syslog(LOG_WARNING, "Bad protocol version %d", mp->vers);
44 		rp->answer = BADVERSION;
45 		return;
46 	}
47 	mp->id_num = ntohl(mp->id_num);
48 	mp->addr.sa_family = ntohs(mp->addr.sa_family);
49 	if (mp->addr.sa_family != AF_INET) {
50 		syslog(LOG_WARNING, "Bad address, family %d",
51 		    mp->addr.sa_family);
52 		rp->answer = BADADDR;
53 		return;
54 	}
55 	mp->ctl_addr.sa_family = ntohs(mp->ctl_addr.sa_family);
56 	if (mp->ctl_addr.sa_family != AF_INET) {
57 		syslog(LOG_WARNING, "Bad control address, family %d",
58 		    mp->ctl_addr.sa_family);
59 		rp->answer = BADCTLADDR;
60 		return;
61 	}
62 	mp->pid = ntohl(mp->pid);
63 	if (debug)
64 		print_request("process_request", mp);
65 	switch (mp->type) {
66 
67 	case ANNOUNCE:
68 		do_announce(mp, rp);
69 		break;
70 
71 	case LEAVE_INVITE:
72 		ptr = find_request(mp);
73 		if (ptr != (CTL_MSG *)0) {
74 			rp->id_num = htonl(ptr->id_num);
75 			rp->answer = SUCCESS;
76 		} else
77 			insert_table(mp, rp);
78 		break;
79 
80 	case LOOK_UP:
81 		ptr = find_match(mp);
82 		if (ptr != (CTL_MSG *)0) {
83 			rp->id_num = htonl(ptr->id_num);
84 			rp->addr = ptr->addr;
85 			rp->addr.sa_family = htons(ptr->addr.sa_family);
86 			rp->answer = SUCCESS;
87 		} else
88 			rp->answer = NOT_HERE;
89 		break;
90 
91 	case DELETE:
92 		rp->answer = delete_invite(mp->id_num);
93 		break;
94 
95 	default:
96 		rp->answer = UNKNOWN_REQUEST;
97 		break;
98 	}
99 	if (debug)
100 		print_response("process_request", rp);
101 }
102 
103 do_announce(mp, rp)
104 	register CTL_MSG *mp;
105 	CTL_RESPONSE *rp;
106 {
107 	struct hostent *hp;
108 	CTL_MSG *ptr;
109 	int result;
110 
111 	/* see if the user is logged */
112 	result = find_user(mp->r_name, mp->r_tty);
113 	if (result != SUCCESS) {
114 		rp->answer = result;
115 		return;
116 	}
117 #define	satosin(sa)	((struct sockaddr_in *)(sa))
118 	hp = gethostbyaddr(&satosin(&mp->ctl_addr)->sin_addr,
119 		sizeof (struct in_addr), AF_INET);
120 	if (hp == (struct hostent *)0) {
121 		rp->answer = MACHINE_UNKNOWN;
122 		return;
123 	}
124 	ptr = find_request(mp);
125 	if (ptr == (CTL_MSG *) 0) {
126 		insert_table(mp, rp);
127 		rp->answer = announce(mp, hp->h_name);
128 		return;
129 	}
130 	if (mp->id_num > ptr->id_num) {
131 		/*
132 		 * This is an explicit re-announce, so update the id_num
133 		 * field to avoid duplicates and re-announce the talk.
134 		 */
135 		ptr->id_num = new_id();
136 		rp->id_num = htonl(ptr->id_num);
137 		rp->answer = announce(mp, hp->h_name);
138 	} else {
139 		/* a duplicated request, so ignore it */
140 		rp->id_num = htonl(ptr->id_num);
141 		rp->answer = SUCCESS;
142 	}
143 }
144 
145 #include <utmp.h>
146 
147 /*
148  * Search utmp for the local user
149  */
150 find_user(name, tty)
151 	char *name, *tty;
152 {
153 	struct utmp ubuf;
154 	int status;
155 	FILE *fd;
156 	struct stat statb;
157 	char ftty[20];
158 
159 	if ((fd = fopen("/etc/utmp", "r")) == NULL) {
160 		perror("Can't open /etc/utmp");
161 		return (FAILED);
162 	}
163 #define SCMPN(a, b)	strncmp(a, b, sizeof (a))
164 	status = NOT_HERE;
165 	(void) strcpy(ftty, "/dev/");
166 	while (fread((char *) &ubuf, sizeof ubuf, 1, fd) == 1)
167 		if (SCMPN(ubuf.ut_name, name) == 0) {
168 			if (*tty == '\0') {
169 				status = PERMISSION_DENIED;
170 				/* no particular tty was requested */
171 				(void) strcpy(ftty+5, ubuf.ut_line);
172 				if (stat(ftty,&statb) == 0) {
173 					if (!(statb.st_mode & 020))
174 						continue;
175 					(void) strcpy(tty, ubuf.ut_line);
176 					status = SUCCESS;
177 					break;
178 				}
179 			}
180 			if (strcmp(ubuf.ut_line, tty) == 0) {
181 				status = SUCCESS;
182 				break;
183 			}
184 		}
185 	fclose(fd);
186 	return (status);
187 }
188