summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillaume Friloux <kuri@friloux.me>2014-04-19 22:18:55 +0200
committerGuillaume Friloux <kuri@friloux.me>2014-04-19 22:18:55 +0200
commitab010e15dbe4f593f180a2b62de54f81d637939b (patch)
tree8f4a739889c5e582063faad43390c509c9806d65
parent72857043baad7a4a0095c446ec6c6eef8107a864 (diff)
Make fingered able to send .finger files.
Next step is to make it able to execute .finger files if they are +x.
-rw-r--r--src/bin/main.c171
-rw-r--r--src/include/Fingered.h21
-rw-r--r--src/lib/Makefile.mk1
-rw-r--r--src/lib/fingered_event.c62
-rw-r--r--src/lib/fingered_private.h3
-rw-r--r--src/lib/fingered_user.c64
6 files changed, 319 insertions, 3 deletions
diff --git a/src/bin/main.c b/src/bin/main.c
index e629fa3..7a35246 100644
--- a/src/bin/main.c
+++ b/src/bin/main.c
@@ -1,12 +1,183 @@
1#define _GNU_SOURCE
1#include <Fingered.h> 2#include <Fingered.h>
2 3
4#include <unistd.h>
5#include <pwd.h>
6#define BUFLEN 4096
7
8int _main_log_dom_global = -1;
9
10#define ERR(...) EINA_LOG_DOM_ERR(_main_log_dom_global, __VA_ARGS__)
11#define DBG(...) EINA_LOG_DOM_DBG(_main_log_dom_global, __VA_ARGS__)
12#define NFO(...) EINA_LOG_DOM_INFO(_main_log_dom_global, __VA_ARGS__)
13#define WRN(...) EINA_LOG_DOM_WARN(_main_log_dom_global, __VA_ARGS__)
14#define CRI(...) EINA_LOG_DOM_CRIT(_main_log_dom_global, __VA_ARGS__)
15
16typedef struct _User
17{
18 Fingered_User *fu;
19
20 uid_t uid;
21 gid_t gid;
22 char *dir;
23} User;
24
25
26void
27_user_execute(User *u,
28 const char *s)
29{
30 DBG("u[%p] s[%s]", u, s);
31}
32
33void
34_user_read(User *u,
35 const char *s)
36{
37 Eina_File *ef;
38 size_t l;
39 void *d;
40
41 DBG("u[%p] s[%s]", u, s);
42
43 ef = eina_file_open(s, EINA_FALSE);
44 if (!ef)
45 {
46 ERR("Failed to open %s", s);
47 goto user_read_end;
48 }
49
50 l = eina_file_size_get(ef);
51 if (l > 10240)
52 {
53 WRN("File is over 10KB! We will only send first 10KB!");
54 l = 10240;
55 }
56
57 d = eina_file_map_all(ef, EINA_FILE_SEQUENTIAL);
58 if (!d)
59 {
60 ERR("Failed to mmap file %s", s);
61 goto close_file;
62 }
63
64 fingered_user_send(u->fu, d, l);
65
66close_file:
67 eina_file_close(ef);
68user_read_end:
69 fingered_user_free(u->fu);
70}
71
72void
73_user_check(User *u)
74{
75 char *s;
76 int r;
77
78 DBG("u[%p][%s]", u, u->fu->user);
79
80 s = calloc(1, strlen(u->dir) + 9);
81 sprintf(s, "%s/.finger", u->dir);
82
83 DBG("Checking for finger file %s", s);
84
85 r = access(s, R_OK);
86 if (r)
87 goto free_s;
88
89 r = access(s, X_OK);
90 if (r)
91 _user_read(u, s);
92 else
93 _user_execute(u, s);
94
95free_s:
96 free(s);
97 fingered_user_free(u->fu);
98 free(u->dir);
99 free(u);
100}
101
102
103Eina_Bool
104_user_event(void *data,
105 int type EINA_UNUSED,
106 void *ev)
107{
108 Fingered_User *fu;
109 User *u = NULL;
110 struct passwd pw, *pwp;
111 char buf[BUFLEN];
112 int r;
113
114
115 DBG("data[%p] ev[%p]", data, ev);
116
117 fu = ev;
118
119 setpwent();
120 while (1)
121 {
122 r = getpwent_r(&pw, buf, BUFLEN, &pwp);
123 if (r)
124 break;
125
126 if (strcmp(pwp->pw_name, fu->user))
127 continue;
128
129 u = calloc(1, sizeof(User));
130 if (!u)
131 {
132 ERR("Failed to allocate User structure.");
133 break;
134 }
135
136 u->fu = fu;
137 u->uid = pwp->pw_uid;
138 u->gid = pwp->pw_gid;
139 u->dir = strdup(pwp->pw_dir);
140 if (!u->dir)
141 {
142 ERR("Failed to allocate home directory.");
143 free(u);
144 u = NULL;
145 }
146
147 break;
148 }
149 endpwent();
150
151 if (u)
152 _user_check(u);
153
154 return EINA_TRUE;
155}
156
157
3int main(int argc EINA_UNUSED, char **argv EINA_UNUSED) 158int main(int argc EINA_UNUSED, char **argv EINA_UNUSED)
4{ 159{
5 Fingered *f; 160 Fingered *f;
6 161
7 fingered_init(); 162 fingered_init();
8 163
164 _main_log_dom_global = eina_log_domain_register("fingered",
165 EINA_COLOR_YELLOW);
166 if (_main_log_dom_global < 0)
167 {
168 EINA_LOG_ERR("Fingered can not create a general log domain");
169 return 1;
170 }
171
9 f = fingered_new(); 172 f = fingered_new();
173 if (!f)
174 {
175 ERR("Failed to create new fingered server.");
176 return 1;
177 }
178
179 ecore_event_handler_add(FINGERED_EVENT_USER, _user_event, NULL);
180
10 181
11 ecore_main_loop_begin(); 182 ecore_main_loop_begin();
12 183
diff --git a/src/include/Fingered.h b/src/include/Fingered.h
index b4f7f21..5a83f60 100644
--- a/src/include/Fingered.h
+++ b/src/include/Fingered.h
@@ -2,10 +2,29 @@
2#include <Ecore.h> 2#include <Ecore.h>
3#include <Ecore_Con.h> 3#include <Ecore_Con.h>
4 4
5extern int FINGERED_EVENT_USER;
6
5typedef struct _Fingered Fingered; 7typedef struct _Fingered Fingered;
6 8
7extern int FINGERED_EVENT_USER; 9typedef struct _Fingered_User
10{
11 Fingered *f;
12
13 const char *user;
14 Ecore_Con_Client *cl;
15
16 size_t queued;
17 Eina_Bool delete_me;
18
19 struct
20 {
21 Ecore_Event_Handler *write;
22 } ev;
23} Fingered_User;
8 24
9int fingered_init(void); 25int fingered_init(void);
10int fingered_shutdown(void); 26int fingered_shutdown(void);
11Fingered * fingered_new(void); 27Fingered * fingered_new(void);
28
29Eina_Bool fingered_user_send(Fingered_User *fu, void *data, size_t len);
30Eina_Bool fingered_user_free(Fingered_User *fu);
diff --git a/src/lib/Makefile.mk b/src/lib/Makefile.mk
index f0ed8a8..366dfef 100644
--- a/src/lib/Makefile.mk
+++ b/src/lib/Makefile.mk
@@ -5,6 +5,7 @@ lib_LTLIBRARIES = src/lib/libfingered.la
5src_lib_libfingered_la_SOURCES = \ 5src_lib_libfingered_la_SOURCES = \
6src/lib/fingered_main.c \ 6src/lib/fingered_main.c \
7src/lib/fingered_event.c \ 7src/lib/fingered_event.c \
8src/lib/fingered_user.c \
8src/lib/fingered_private.h \ 9src/lib/fingered_private.h \
9src/include/Fingered.h 10src/include/Fingered.h
10src_lib_libfingered_la_CFLAGS = $(LIBS_CFLAGS) $(EXTRA_CPPFLAGS) 11src_lib_libfingered_la_CFLAGS = $(LIBS_CFLAGS) $(EXTRA_CPPFLAGS)
diff --git a/src/lib/fingered_event.c b/src/lib/fingered_event.c
index 2d984e1..cd94f60 100644
--- a/src/lib/fingered_event.c
+++ b/src/lib/fingered_event.c
@@ -1,5 +1,35 @@
1#include <ctype.h>
1#include "fingered_private.h" 2#include "fingered_private.h"
2 3
4void
5_fingered_event_fake_free(void *d1 EINA_UNUSED,
6 void *d2 EINA_UNUSED)
7{}
8
9
10Eina_Bool
11fingered_event_write(void *data,
12 int type EINA_UNUSED,
13 void *ev)
14{
15 Ecore_Con_Event_Client_Write *write;
16 Fingered_User *fu;
17
18 DBG("data[%p] ev[%p]", data, ev);
19
20 write = ev;
21 fu = data;
22
23 fu->queued -= write->size;
24
25 if (!fu->delete_me)
26 return EINA_TRUE;
27
28 fingered_user_free(fu);
29
30 return EINA_TRUE;
31}
32
3Eina_Bool 33Eina_Bool
4fingered_event_add(void *data, 34fingered_event_add(void *data,
5 int type EINA_UNUSED, 35 int type EINA_UNUSED,
@@ -11,8 +41,6 @@ fingered_event_add(void *data,
11 41
12 add = ev; 42 add = ev;
13 ecore_con_client_timeout_set(add->client, 30); 43 ecore_con_client_timeout_set(add->client, 30);
14
15
16 return EINA_TRUE; 44 return EINA_TRUE;
17} 45}
18 46
@@ -36,12 +64,26 @@ fingered_event_data(void *data,
36 void *ev) 64 void *ev)
37{ 65{
38 Ecore_Con_Event_Client_Data *event; 66 Ecore_Con_Event_Client_Data *event;
67 Fingered *f;
68 Fingered_User *fu;
69 char *n,
70 *p;
39 char fmt[128]; 71 char fmt[128];
40 72
41 DBG("data[%p] ev[%p]", data, ev); 73 DBG("data[%p] ev[%p]", data, ev);
42 74
75 f = data;
43 event = ev; 76 event = ev;
44 77
78 n = memchr(event->data, '\n', event->size);
79 if ((!n) || (event->size == 1) || (*(n-1) != '\r'))
80 {
81 ERR("Invalid data received from %s",
82 ecore_con_client_ip_get(event->client));
83 ecore_con_client_del(event->client);
84 return EINA_TRUE;
85 }
86
45 snprintf(fmt, sizeof(fmt), 87 snprintf(fmt, sizeof(fmt),
46 "Received %i bytes from client:\n" 88 "Received %i bytes from client:\n"
47 ">>>>>\n" 89 ">>>>>\n"
@@ -50,6 +92,22 @@ fingered_event_data(void *data,
50 event->size, event->size); 92 event->size, event->size);
51 printf(fmt, event->data); 93 printf(fmt, event->data);
52 94
95 for (p = event->data; (n - p) > 1; p++)
96 {
97 if (isalnum(*p))
98 continue;
99 ERR("Invalid user requested");
100 ecore_con_client_del(event->client);
101 return EINA_TRUE;
102 }
103
104 fu = fingered_user_new(event->data, n - (char *)event->data - 1,
105 event->client);
106 if (!fu)
107 return EINA_TRUE;
108
109 DBG("fu[%p]", fu);
110 ecore_event_add(FINGERED_EVENT_USER, fu, _fingered_event_fake_free, f);
53 111
54 return EINA_TRUE; 112 return EINA_TRUE;
55} 113}
diff --git a/src/lib/fingered_private.h b/src/lib/fingered_private.h
index fdd9573..0c9c83d 100644
--- a/src/lib/fingered_private.h
+++ b/src/lib/fingered_private.h
@@ -24,3 +24,6 @@ extern int _fingered_log_dom_global;
24Eina_Bool fingered_event_add(void *data, int type, void *ev); 24Eina_Bool fingered_event_add(void *data, int type, void *ev);
25Eina_Bool fingered_event_del(void *data, int type, void *ev); 25Eina_Bool fingered_event_del(void *data, int type, void *ev);
26Eina_Bool fingered_event_data(void *data, int type, void *ev); 26Eina_Bool fingered_event_data(void *data, int type, void *ev);
27Eina_Bool fingered_event_write(void *data, int type, void *ev);
28
29Fingered_User * fingered_user_new(const char *user, size_t len, Ecore_Con_Client *cl);
diff --git a/src/lib/fingered_user.c b/src/lib/fingered_user.c
new file mode 100644
index 0000000..5564a2f
--- /dev/null
+++ b/src/lib/fingered_user.c
@@ -0,0 +1,64 @@
1#include "fingered_private.h"
2
3Fingered_User *
4fingered_user_new(const char *user,
5 size_t len,
6 Ecore_Con_Client *cl)
7{
8 Fingered_User *fu;
9
10 fu = calloc(1, sizeof(Fingered_User));
11 if (!fu)
12 {
13 ERR("Failed to allocate Fingered_User structure");
14 return NULL;
15 }
16
17 fu->user = strndup(user, len);
18 if (!fu->user)
19 {
20 ERR("Failed to duplicate user string");
21 goto free_fu;
22 }
23
24 fu->cl = cl;
25
26#define _EV(_a, _b, _c, _d) \
27 _a = ecore_event_handler_add(ECORE_CON_EVENT_CLIENT_##_b, \
28 fingered_event_##_c, _d)
29 _EV(fu->ev.write, WRITE, write, fu);
30#undef _EV
31 return fu;
32
33free_fu:
34 free(fu);
35 return NULL;
36}
37
38Eina_Bool
39fingered_user_send(Fingered_User *fu,
40 void *data,
41 size_t len)
42{
43 ecore_con_client_send(fu->cl, data, len);
44 fu->queued += len;
45 return EINA_TRUE;
46}
47
48Eina_Bool
49fingered_user_free(Fingered_User *fu)
50{
51 DBG("fu[%p]", fu);
52
53 fu->delete_me = EINA_TRUE;
54 if (fu->queued)
55 return EINA_TRUE;
56
57 DBG("Deleting fu[%p] cl[%p]", fu, fu->cl);
58 ecore_con_client_send(fu->cl, "\r\n", 2);
59 ecore_con_client_flush(fu->cl);
60 ecore_con_client_del(fu->cl);
61 ecore_event_handler_del(fu->ev.write);
62 free(fu);
63 return EINA_TRUE;
64}