diff options
author | jcid <devnull@localhost> | 2007-12-06 18:12:02 +0100 |
---|---|---|
committer | jcid <devnull@localhost> | 2007-12-06 18:12:02 +0100 |
commit | 30995b73e26311c3d2f3a4e646254181020e1e6a (patch) | |
tree | 533b2e4539e80e81c37b342a500b880329d8774b /dpid | |
parent | 128f4f70c67071351e7d1312bc762978fc2d0bcb (diff) |
- * Improved the dpi framework. Now dpi-programs can be specified in dpidrc,
and there's no need to touch dillo's sources to add new dpi services.
Just make your dpi program, add a dpidrc line and play with it!
Diffstat (limited to 'dpid')
-rw-r--r-- | dpid/Makefile.am | 5 | ||||
-rw-r--r-- | dpid/dpid.c | 175 | ||||
-rw-r--r-- | dpid/dpid.h | 16 | ||||
-rw-r--r-- | dpid/main.c | 4 |
4 files changed, 182 insertions, 18 deletions
diff --git a/dpid/Makefile.am b/dpid/Makefile.am index cd15afd4..938a6244 100644 --- a/dpid/Makefile.am +++ b/dpid/Makefile.am @@ -24,3 +24,8 @@ dpid_SOURCES = \ install-data-local : $(mkinstalldirs) $(DESTDIR)$(sysconfdir) echo dpi_dir=$(libdir)/dillo/dpi > $(DESTDIR)$(sysconfdir)/dpidrc + echo >> $(DESTDIR)$(sysconfdir)/dpidrc + echo "proto.file=file/file.dpi" >> $(DESTDIR)$(sysconfdir)/dpidrc + echo "proto.ftp=ftp/ftp.filter.dpi" >> $(DESTDIR)$(sysconfdir)/dpidrc + echo "proto.https=https/https.filter.dpi" >> $(DESTDIR)$(sysconfdir)/dpidrc + echo "proto.data=datauri/datauri.filter.dpi" >> $(DESTDIR)$(sysconfdir)/dpidrc diff --git a/dpid/dpid.c b/dpid/dpid.c index 1bb918ed..46c80109 100644 --- a/dpid/dpid.c +++ b/dpid/dpid.c @@ -138,6 +138,20 @@ void free_plugin_list(struct dp **dpi_attr_list_ptr, int numdpis) *dpi_attr_list_ptr = NULL; } +/*! Free memory used by the services list + */ +void free_services_list(Dlist *s_list) +{ + int i = 0; + struct service *s; + + for (i=0; i < dList_length(s_list) ; i++) { + s = dList_nth_data(s_list, i); + dFree(s->name); + } + dList_free(s_list); +} + /*! \todo * Remove terminator and est_terminator unless we really want to clean up * on abnormal exit. @@ -331,7 +345,7 @@ int register_all(struct dp **attlist) DIR *user_dir_stream, *sys_dir_stream; char *user_dpidir = NULL, *sys_dpidir = NULL, *dpidrc = NULL; struct dirent *user_dirent, *sys_dirent; - int j, st, not_in_user_list; + int st; int snum, usr_srv_num; size_t dp_sz = sizeof(struct dp); @@ -384,19 +398,10 @@ int register_all(struct dp **attlist) while ((sys_dirent = readdir(sys_dir_stream)) != NULL) { if (sys_dirent->d_name[0] == '.') continue; - not_in_user_list = 1; - for (j = 0; j < usr_srv_num; j++) { - if (strcmp(sys_dirent->d_name, (*attlist)[j].id) == 0) { - not_in_user_list = 0; - break; - } - } - if (not_in_user_list) { - *attlist = (struct dp *) dRealloc(*attlist, (snum + 1) * dp_sz); - st=get_dpi_attr(sys_dpidir, sys_dirent->d_name, &(*attlist)[snum]); - if (st == 0) - snum++; - } + *attlist = (struct dp *) dRealloc(*attlist, (snum + 1) * dp_sz); + st=get_dpi_attr(sys_dpidir, sys_dirent->d_name, &(*attlist)[snum]); + if (st == 0) + snum++; } closedir(sys_dir_stream); } @@ -409,6 +414,112 @@ int register_all(struct dp **attlist) return (snum); } +/* + * Compare two struct service pointers + * This function is used for sorting services + */ +static int services_alpha_comp(const struct service *s1, + const struct service *s2) +{ + return -strcmp(s1->name, s2->name); +} + +/*! Add services reading a dpidrc file + * each non empty or commented line has the form + * service = path_relative_to_dpidir + * \Return: + * \li Returns number of available services on success + * \li -1 on failure + */ +int fill_services_list(struct dp *attlist, int numdpis, Dlist **services_list) +{ + FILE *dpidrc_stream; + char *p, *line = NULL; + char *service, *path; + int i; + struct service *s; + char *user_dpidir = NULL, *sys_dpidir = NULL, *dpidrc = NULL; + + user_dpidir = dStrconcat(dGethomedir(), "/", dotDILLO_DPI, NULL); + if (access(user_dpidir, F_OK) == -1) { + /* no dpis in user's space */ + dFree(user_dpidir); + user_dpidir = NULL; + } + dpidrc = dStrconcat(dGethomedir(), "/", dotDILLO_DPIDRC, NULL); + if (access(dpidrc, F_OK) == -1) { + dFree(dpidrc); + dpidrc = dStrdup(DPIDRC_SYS); + if (access(dpidrc, F_OK) == -1) { + dFree(dpidrc); + dpidrc = NULL; + } + } + if (!dpidrc || (sys_dpidir = get_dpi_dir(dpidrc)) == NULL) + sys_dpidir = NULL; + + if (!user_dpidir && !sys_dpidir) { + ERRMSG("fill_services_list", "Fatal error ", 0); + MSG_ERR("\n - Can't find the directory for dpis.\n"); + exit(1); + } + + if ((dpidrc_stream = fopen(dpidrc, "r")) == NULL) { + ERRMSG("fill_services_list", "popen failed", errno); + dFree(dpidrc); + dFree(sys_dpidir); + dFree(user_dpidir); + return (-1); + } + + if (*services_list != NULL) { + ERRMSG("fill_services_list", "services_list parameter is not NULL", 0); + return -1; + } + *services_list = dList_new(8); + + /* dpidrc parser loop */ + while ((line = dGetline(dpidrc_stream)) != NULL) { + + if (dParser_get_rc_pair(&line, &service, &path) == -1) { + if (line[0] && line[0] != '#' && (!service || !path)) { + MSG_ERR("Syntax error in %s: service=\"%s\" path=\"%s\"\n", + dpidrc, service, path); + } + continue; + } + + /* ignore dpi_dir silently */ + if (strcmp(service, "dpi_dir") == 0) + continue; + + s = dNew(struct service, 1); + /* init services list entry */ + s->name = dStrdup(service); + s->dp_index = -1; + + dList_append(*services_list, s); + /* search the dpi for a service by its path */ + for (i = 0; i < numdpis; i++) + if ((p = strstr(attlist[i].path, path)) && *(p - 1) == '/' && + strlen(p) == strlen(path)) + break; + /* if the dpi exist bind service and dpi */ + if (i < numdpis) + s->dp_index = i; + dFree(line); + } + fclose(dpidrc_stream); + + dList_sort(*services_list, (dCompareFunc)services_alpha_comp); + + dFree(dpidrc); + dFree(sys_dpidir); + dFree(user_dpidir); + + return (dList_length(*services_list)); +} + /*! Initialise the service request socket * \Return: * \li Number of sockets (1 == success) @@ -496,7 +607,8 @@ int init_dpi_socket(struct dp *dpi_attr, char *sockdir) dpi_attr->sa.sun_family = AF_LOCAL; dpi_nm = get_basename(dpi_attr->path); - dpi_attr->sockpath = dStrconcat(sockdir, "/", dpi_nm, NULL); + dpi_attr->sockpath = dStrconcat(sockdir, "/", dpi_nm, "-XXXXXX", NULL); + mktemp(dpi_attr->sockpath); if (strlen(dpi_attr->sockpath) > sp_len) { ERRMSG("init_all_dpi_sockets", "socket path is too long", 0); MSG_ERR("\n - it should be <= %lu chars", (ulong_t)sp_len); @@ -668,11 +780,14 @@ int register_all_cmd(char *sockdir) stop_active_dpis(dpi_attr_list, numdpis); rm_dpi_sockets(dpi_attr_list, numdpis); free_plugin_list(&dpi_attr_list, numdpis); + free_services_list(services_list); + services_list = NULL; numdpis = 0; numsocks = 1; /* the srs socket */ FD_ZERO(&sock_set); FD_SET(srs, &sock_set); numdpis = register_all(&dpi_attr_list); + fill_services_list(dpi_attr_list, numdpis, &services_list); numsocks = init_all_dpi_sockets(dpi_attr_list, sockdir); return (numdpis); } @@ -697,6 +812,24 @@ char *get_message(int sock, char *dpi_tag) return (msg); } +/* + * Compare a struct service pointer and a service name + * This function is used for searching services by name + */ +int service_match(const struct service *A, const char *B) +{ + int A_len, B_len, len; + + A_len = strlen(A->name); + B_len = strlen(B); + len = MAX (A_len, B_len); + + if (A->name[A_len - 1] == '*') + len = A_len - 1; + + return(dStrncasecmp(A->name, B, len)); +} + /*! * Send socket path that matches dpi_id to client */ @@ -705,12 +838,18 @@ void send_sockpath(int sock, char *dpi_tag, struct dp *dpi_attr_list) int i; char *dpi_id; char *d_cmd; + struct service *serv; dReturn_if_fail((dpi_id = get_message(sock, dpi_tag)) != NULL); - for (i = 0; i < numdpis; i++) - if (strstr(dpi_attr_list[i].id, dpi_id)) - break; + serv = dList_find_custom(services_list,dpi_id,(dCompareFunc)service_match); + + if (serv == NULL || (i = serv->dp_index) == -1) + for (i = 0; i < numdpis; i++) + if (!strncmp(dpi_attr_list[i].id, dpi_id, + dpi_attr_list[i].id - strchr(dpi_attr_list[i].id, '.'))) + break; + if (i < numdpis) { /* found */ if (access(dpi_attr_list[i].path, F_OK) == -1) { diff --git a/dpid/dpid.h b/dpid/dpid.h index 2a41f538..0a80dfdc 100644 --- a/dpid/dpid.h +++ b/dpid/dpid.h @@ -45,6 +45,13 @@ struct dp { int filter; }; +/*! bind dpi with service + */ +struct service { + char *name; + int dp_index; +}; + /*! Number of available plugins */ int numdpis; @@ -54,6 +61,9 @@ int numsocks; /*! State information for each plugin. */ struct dp *dpi_attr_list; +/*! service served for each plugin */ +Dlist *services_list; + /*! Set of sockets watched for connections */ fd_set sock_set; @@ -70,6 +80,8 @@ void free_dpi_attr(struct dp *dpi_attr); void free_plugin_list(struct dp **dpi_attr_list_ptr, int numdpis); +void free_services_list(Dlist *s_list); + enum file_type get_file_type(char *file_name); int get_dpi_attr(char *dpi_dir, char *service, struct dp *dpi_attr); @@ -78,6 +90,8 @@ int register_service(struct dp *dpi_attr, char *service); int register_all(struct dp **attlist); +int fill_services_list(struct dp *attlist, int numdpis, Dlist **services_list); + int init_srs_socket(char *sockdir); int init_dpi_socket(struct dp *dpi_attr, char *sockdir); @@ -98,6 +112,8 @@ int register_all_cmd(char *sockdir); char *get_message(int sock, char *dpi_tag); +int service_match(const struct service *A, const char *B); + void send_sockpath(int sock, char * dpi_tag, struct dp *dpi_attr_list); #endif diff --git a/dpid/main.c b/dpid/main.c index 09c46968..9a6ac6e1 100644 --- a/dpid/main.c +++ b/dpid/main.c @@ -228,6 +228,7 @@ int main(void) fd_set selected_set; dpi_attr_list = NULL; + services_list = NULL; //daemon(0,0); /* Use 0,1 for feedback */ /* todo: call setsid() ?? */ @@ -258,6 +259,9 @@ int main(void) exit(1); } + /* Init and get services list */ + fill_services_list(dpi_attr_list, numdpis, &services_list); + /* Remove any sockets that may have been leftover from a crash */ cleanup(sockdir); /* Initialise sockets */ |