1 /* finger.c
2  * finger:// processing
3  * (c) 2002 Mikulas Patocka
4  * This file is a part of the Links program, released under GPL.
5  */
6 
7 #include "links.h"
8 
9 static void finger_send_request(struct connection *);
10 static void finger_sent_request(struct connection *);
11 static void finger_get_response(struct connection *, struct read_buffer *);
12 static void finger_end_request(struct connection *, int);
13 
finger_func(struct connection * c)14 void finger_func(struct connection *c)
15 {
16 	int p;
17 	if ((p = get_port(c->url)) == -1) {
18 		setcstate(c, S_BAD_URL);
19 		abort_connection(c);
20 		return;
21 	}
22 	c->from = 0;
23 	make_connection(c, p, &c->sock1, finger_send_request);
24 }
25 
finger_send_request(struct connection * c)26 static void finger_send_request(struct connection *c)
27 {
28 	unsigned char *req = init_str();
29 	int rl = 0;
30 	unsigned char *user;
31 	add_to_str(&req, &rl, cast_uchar "/W");
32 	if ((user = get_user_name(c->url))) {
33 		add_to_str(&req, &rl, cast_uchar " ");
34 		add_to_str(&req, &rl, user);
35 		mem_free(user);
36 	}
37 	add_to_str(&req, &rl, cast_uchar "\r\n");
38 	write_to_socket(c, c->sock1, req, rl, finger_sent_request);
39 	mem_free(req);
40 	setcstate(c, S_SENT);
41 }
42 
finger_sent_request(struct connection * c)43 static void finger_sent_request(struct connection *c)
44 {
45 	struct read_buffer *rb;
46 	set_timeout(c);
47 	if (!(rb = alloc_read_buffer(c))) return;
48 	rb->close = 1;
49 	read_from_socket(c, c->sock1, rb, finger_get_response);
50 }
51 
finger_get_response(struct connection * c,struct read_buffer * rb)52 static void finger_get_response(struct connection *c, struct read_buffer *rb)
53 {
54 	int l;
55 	int a;
56 	set_timeout(c);
57 	if (!c->cache) {
58 		if (get_cache_entry(c->url, &c->cache)) {
59 			setcstate(c, S_OUT_OF_MEM);
60 			abort_connection(c);
61 			return;
62 		}
63 		c->cache->refcount--;
64 	}
65 	if (rb->close == 2) {
66 		finger_end_request(c, S__OK);
67 		return;
68 	}
69 	l = rb->len;
70 	if ((off_t)(0UL + c->from + l) < 0) {
71 		setcstate(c, S_LARGE_FILE);
72 		abort_connection(c);
73 		return;
74 	}
75 	c->received += l;
76 	a = add_fragment(c->cache, c->from, rb->data, l);
77 	if (a < 0) {
78 		setcstate(c, a);
79 		abort_connection(c);
80 		return;
81 	}
82 	if (a == 1) c->tries = 0;
83 	c->from += l;
84 	kill_buffer_data(rb, l);
85 	read_from_socket(c, c->sock1, rb, finger_get_response);
86 	setcstate(c, S_TRANS);
87 }
88 
finger_end_request(struct connection * c,int state)89 static void finger_end_request(struct connection *c, int state)
90 {
91 	if (state == S__OK) {
92 		if (c->cache) {
93 			truncate_entry(c->cache, c->from, 1);
94 			c->cache->incomplete = 0;
95 		}
96 	}
97 	setcstate(c, state);
98 	abort_connection(c);
99 }
100