source: trunk/minix/commands/talkd/process.c@ 15

Last change on this file since 15 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 5.7 KB
RevLine 
[9]1/* process.c Copyright Michael Temari 07/22/1996 All Rights Reserved */
2
3#include <sys/types.h>
4#include <sys/stat.h>
5#include <stdio.h>
6#include <string.h>
7#include <unistd.h>
8#include <stdlib.h>
9#include <ctype.h>
10#include <time.h>
11#include <net/hton.h>
12#include <net/gen/socket.h>
13#include <net/gen/in.h>
14#include <net/gen/netdb.h>
15
16#include "talk.h"
17#include "talkd.h"
18#include "process.h"
19#include "finduser.h"
20
21struct entry {
22 struct entry *prev;
23 struct talk_request rq;
24 time_t expire;
25 struct entry *next;
26};
27
28_PROTOTYPE(static int announce, (struct talk_request *request, char *rhost));
29_PROTOTYPE(static struct talk_request *lookup, (struct talk_request *request, int type));
30_PROTOTYPE(static int addreq, (struct talk_request *request));
31_PROTOTYPE(static delete_invite, (long id));
32_PROTOTYPE(static long nextid, (void));
33_PROTOTYPE(static void delete, (struct entry *e));
34
35static struct entry *entry = (struct entry *)NULL;
36
37int processrequest(request, reply)
38struct talk_request *request;
39struct talk_reply *reply;
40{
41char *p;
42struct talk_request *rq;
43struct hostent *hp;
44
45 reply->version = TALK_VERSION;
46 reply->type = request->type;
47 reply->answer = 0;
48 reply->junk = 0;
49 reply->id = htonl(0);
50
51
52 /* check version */
53 if(request->version != TALK_VERSION) {
54 reply->answer = BADVERSION;
55 return(0);
56 }
57
58 /* check address family */
59 if(ntohs(request->addr.sa_family) != AF_INET) {
60 reply->answer = BADADDR;
61 return(0);
62 }
63
64 /* check control address family */
65 if(ntohs(request->ctl_addr.sa_family) != AF_INET) {
66 reply->answer = BADCTLADDR;
67 return(0);
68 }
69
70 /* check local name */
71 p = request->luser;
72 while(*p)
73 if(!isprint(*p)) {
74 reply->answer = FAILED;
75 return(0);
76 } else
77 p++;
78
79 switch(request->type) {
80 case ANNOUNCE:
81 reply->answer = find_user(request->ruser, request->rtty);
82 if(reply->answer != SUCCESS) break;
83 hp = gethostbyaddr((char *)&request->ctl_addr.sin_addr, sizeof(ipaddr_t), AF_INET);
84 if(hp == (struct hostent *)NULL) {
85 reply->answer = MACHINE_UNKNOWN;
86 break;
87 }
88 if((rq = lookup(request, 1)) == (struct talk_request *)NULL) {
89 reply->id = addreq(request);
90 reply->answer = announce(request, hp->h_name);
91 break;
92 }
93 if(ntohl(request->id) > ntohl(rq->id)) {
94 rq->id = nextid();
95 reply->id = rq->id;
96 reply->answer = announce(request, hp->h_name);
97 } else {
98 reply->id = rq->id;
99 reply->answer = SUCCESS;
100 }
101 break;
102 case LEAVE_INVITE:
103 rq = lookup(request, 1);
104 if(rq == (struct talk_request *)NULL)
105 reply->id = addreq(request);
106 else {
107 reply->id = rq->id;
108 reply->answer = SUCCESS;
109 }
110 break;
111 case LOOK_UP:
112 if((rq = lookup(request, 0)) == (struct talk_request *)NULL)
113 reply->answer = NOT_HERE;
114 else {
115 reply->id = rq->id;
116 memcpy((char *)&reply->addr, (char *)&rq->addr, sizeof(reply->addr));
117 reply->answer = SUCCESS;
118 }
119 break;
120 case DELETE:
121 reply->answer = delete_invite(request->id);
122 break;
123 default:
124 reply->answer = UNKNOWN_REQUEST;
125 }
126
127 return(0);
128}
129
130static int announce(request, rhost)
131struct talk_request *request;
132char *rhost;
133{
134char tty[5+TTY_SIZE+1];
135struct stat st;
136FILE *fp;
137time_t now;
138struct tm *tm;
139
140 sprintf(tty, "/dev/%s", request->rtty);
141
142 if(stat(tty, &st) < 0)
143 return(PERMISSION_DENIED);
144
145 if(!(st.st_mode & S_IWGRP))
146 return(PERMISSION_DENIED);
147
148 if((fp = fopen(tty, "w")) == (FILE *)NULL)
149 return(PERMISSION_DENIED);
150
151 (void) time(&now);
152
153 tm = localtime(&now);
154
155 fprintf(fp, "\007\007\007\rtalkd: Message from talkd@%s at %d:%02d:%02d\r\n",
156 myhostname, tm->tm_hour, tm->tm_min, tm->tm_sec);
157 fprintf(fp, "talkd: %s@%s would like to talk to you\r\n",
158 request->luser, rhost);
159 fprintf(fp, "talkd: to answer type: talk %s@%s\r\n",
160 request->luser, rhost);
161
162 fclose(fp);
163
164 return(SUCCESS);
165}
166
167static struct talk_request *lookup(request, type)
168struct talk_request *request;
169int type;
170{
171time_t now;
172struct entry *e;
173
174 (void) time(&now);
175
176 for(e = entry; e != (struct entry *)NULL; e = e->next) {
177 if(now > e->expire) {
178 delete(e);
179 continue;
180 }
181 if(type == 0) {
182 if(!strncmp(request->luser, e->rq.ruser, USER_SIZE) &&
183 !strncmp(request->ruser, e->rq.luser, USER_SIZE) &&
184 e->rq.type == LEAVE_INVITE)
185 return(&e->rq);
186 } else {
187 if(request->type == e->rq.type &&
188 request->pid == e->rq.pid &&
189 !strncmp(request->luser, e->rq.luser, USER_SIZE) &&
190 !strncmp(request->ruser, e->rq.ruser, USER_SIZE)) {
191 e->expire = now + MAX_LIFE;
192 return(&e->rq);
193 }
194 }
195 }
196 return((struct talk_request *)NULL);
197}
198
199static int addreq(request)
200struct talk_request *request;
201{
202time_t now;
203struct entry *e;
204
205 (void) time(&now);
206 request->id = nextid();
207 e = (struct entry *) malloc(sizeof(struct entry));
208 if(e == (struct entry *)NULL) {
209 fprintf(stderr, "talkd: out of memory in insert table\n");
210 exit(1);
211 }
212 e->expire = now + MAX_LIFE;
213 memcpy((char *)&e->rq, (char *)request, sizeof(struct talk_request));
214 e->next = entry;
215 if(e->next != (struct entry *)NULL)
216 e->next->prev = e;
217 e->prev = (struct entry *)NULL;
218 entry = e;
219 return(request->id);
220}
221
222static int delete_invite(id)
223long id;
224{
225time_t now;
226struct entry *e;
227
228 (void) time(&now);
229
230 for(e = entry; e != (struct entry *)NULL; e = e->next) {
231 if(now > e->expire) {
232 delete(e);
233 continue;
234 }
235 if(e->rq.id == id) {
236 delete(e);
237 return(SUCCESS);
238 }
239 }
240 return(NOT_HERE);
241}
242
243static void delete(e)
244struct entry *e;
245{
246 if(e == (struct entry *)NULL) return;
247
248 if(entry == e)
249 entry = e->next;
250 else
251 if(e->prev != (struct entry *)NULL)
252 e->prev->next = e->next;
253
254 if(e->next != (struct entry *)NULL)
255 e->next->prev = e->prev;
256
257 free((char *)e);
258
259 return;
260}
261
262static long nextid()
263{
264static long id = 0;
265
266 id++;
267 if(id <= 0) id = 1;
268 return(htonl(id));
269}
Note: See TracBrowser for help on using the repository browser.