LDFLAGS:=-L${stagedir}/lib
 
 LINK:=libtool --mode=link ${CC} ${LDFLAGS} 
+LTCOMPILE:=libtool --mode=compile ${CC} ${CFLAGS}
+SOLINK:=libtool --mode=link ${CC} -module ${LDFLAGS} -rpath ${stagedir}/lib
 LINKXX:=libtool --mode=link ${CXX} ${LDFLAGS} 
 INSTALL:=libtool --mode=install install
 
-
 daemon:=glite-jp-primarystoraged
 example:=jpps-test
 ps_prefix:=jpps_
 is_prefix:=jpis_
 
+plugins:=glite-jp-tags.la
+
 gsoap_version=`${gsoap_prefix}/bin/soapcpp2 -version 2>&1 | cut -d' ' -f4 | perl -F\\\\. -nae '$$F[2] =~ s/\D*$$//; print $$F[2]+100*$$F[1]+10000*$$F[0]'`
 
 CFLAGS+=-DGSOAP_VERSION=${gsoap_version}
 
 default all: compile
 
-compile: ${daemon} ${example}
+compile: ${daemon} ${example} ${plugins}
 
 ${daemon}: ${OBJS}
        ${LINK} -o $@ ${OBJS} ${BONESLIB} ${COMMONLIB} ${GSOAPLIB} ${GLOBUS_LIBS} 
        @echo 'The following warning "time_t (de)serialization is not MT safe on this platform" is harmless'
        ${CC} -o $@ -c -DWITH_NONAMESPACES -DHAVE_CONFIG_H ${CFLAGS} ${gsoap_prefix}/devel/stdsoap2.c
 
+
+glite-jp-tags.la: tags_plugin.lo
+       ${SOLINK} -o $@ tags_plugin.lo
+
+%.lo: %.c
+       ${LTCOMPILE} -o $@ -c $<
 
 #include <stdsoap2.h>
 #include "glite/security/glite_gsplugin.h"
 
+#include "backend.h"
+#include "file_plugin.h"
 
 
 #include "jpps_H.h"
 
 static glite_jp_context_t      ctx;
 
+static int call_opts(glite_jp_context_t,char *,char *,int (*)(glite_jp_context_t,int,char **));
+
 int main(int argc, char *argv[])
 {
-       int     one = 1;
+       int     one = 1,opt,bend = 0;
        edg_wll_GssStatus       gss_code;
        struct sockaddr_in      a;
 
 
        glite_jp_init_context(&ctx);
 
-       if (glite_jppsbe_init(ctx, &argc, argv)) {
-               /* XXX log */
-               fputs(glite_jp_error_chain(ctx), stderr);
-               exit(1);
+       while ((opt = getopt(argc,argv,"B:P:")) != EOF) switch (opt) {
+               case 'B':
+                       if (call_opts(ctx,optarg,"backend",glite_jppsbe_init)) {
+                               /* XXX log */
+                               fputs(glite_jp_error_chain(ctx), stderr);
+                               exit(1);
+                       }
+                       bend = 1;
+                       break;
+               case 'P':
+                       if (call_opts(ctx,optarg,"plugins",glite_jpps_fplug_load)) {
+                               /* XXX log */
+                               fputs(glite_jp_error_chain(ctx), stderr);
+                               exit(1);
+                       }
        }
 
-       if (glite_jpps_fplug_load(ctx, &argc, argv)) {
-               /* XXX log */
-               fputs(glite_jp_error_chain(ctx), stderr);
-               exit(1);
+       if (!bend) {
+               fputs("-B required\n",stderr);
+               exit (1);
        }
 
        srand48(time(NULL)); /* feed id generation */
        }
 
        if (!server_cert || !server_key)
-               fprintf(stderr, "%s: WARNING: key or certificate file not specified,"
+               fprintf(stderr, "%s: WARNING: key or certificate file not specified, "
                                "can't watch them for changes\n",
                                argv[0]);
 
        return 0;
 }
 
+#define WSPACE "\t\n "
+
+static int call_opts(glite_jp_context_t ctx,char *opt,char *name,int (*f)(glite_jp_context_t,int,char **))
+{
+       int     ac = 1,ret,my_optind; 
+       char    **av = malloc(sizeof *av),*ap;
+
+       *av = name;
+       for (ap = strtok(opt,WSPACE); ap; ap = strtok(NULL,WSPACE)) {
+               av = realloc(av,(ac+1) * sizeof *av);
+               av[ac++] = ap;
+       }
+
+       my_optind = optind;
+       optind = 0;
+       ret = f(ctx,ac,av);
+       optind = my_optind;
+       free(av);
+       return ret;
+}
+
 
 /* XXX: we don't use it */
 SOAP_NMAC struct Namespace namespaces[] = { {NULL,NULL} };
 
        return 0;
 }
 
-int glite_jpps_fplug_load(glite_jp_context_t ctx,int *argc,char **argv)
+int glite_jpps_fplug_load(glite_jp_context_t ctx,int argc,char **argv)
 {
-       int     opt,ret;
-
-       while ((opt = getopt_long(*argc,argv,"p:",opts,NULL)) != EOF) switch (opt) {
-               case 'p':
-                       glite_jp_clear_error(ctx);
-
-                       if (loadit(ctx,optarg)) {
-                               glite_jp_error_t        err;
-                               err.source = __FUNCTION__;
-                               err.code = EINVAL;
-                               err.desc = optarg;
-                               return glite_jp_stack_error(ctx,&err);
-                       }
-                       break;
-               default: break;
+       int     i;
+
+       for (i=1; i<argc; i++) if (loadit(ctx,argv[i])) {
+               glite_jp_error_t        err;
+               err.source = __FUNCTION__;
+               err.code = EINVAL;
+               err.desc = argv[i];
+               return glite_jp_stack_error(ctx,&err);
        }
 
        return 0;
 
 /********************************************************************************/
 int glite_jppsbe_init(
        glite_jp_context_t ctx,
-       int *argc,
+       int argc,
        char *argv[]
 )
 {
 
        config->logname = getlogin();
 
-       while ((opt = getopt_long(*argc, argv, "I:E:G:", ftpbe_opts, NULL)) != EOF) {
+       while ((opt = getopt_long(argc, argv, "I:E:G:", ftpbe_opts, NULL)) != EOF) {
                switch (opt) {
                        case 'I': config->internal_path = optarg; break;
                        case 'E': config->external_path = optarg; break;