X-Git-Url: http://git.indexdata.com/?a=blobdiff_plain;f=www%2Fwproto.c;h=b1e0d1f6e952697bc5a46465315196c625858b18;hb=f96d9ce1f8c00b469ce235791055124b51db2592;hp=6deb504b504966d45a83e56d0853d6c66bb89017;hpb=74a4580ba9945fc86b47654230865a68089245b6;p=egate.git diff --git a/www/wproto.c b/www/wproto.c index 6deb504..b1e0d1f 100644 --- a/www/wproto.c +++ b/www/wproto.c @@ -41,7 +41,83 @@ * USE OR PERFORMANCE OF THIS SOFTWARE. * * $Log: wproto.c,v $ - * Revision 1.7 1995/11/10 14:47:32 adam + * Revision 1.26 1997/12/15 15:05:02 adam + * Enhanced the code that deals with FORM variables. + * + * Revision 1.25 1997/02/10 10:15:38 adam + * Bug fix: egw_source didn't work properly. + * + * Revision 1.24 1997/01/31 11:16:00 adam + * Enhanced the egw_source command. An optional parameter specifies the + * name of a variable in which the HTML output is stored. + * + * Revision 1.23 1997/01/27 11:27:14 adam + * Implemented a new command, egw_clear, to clear http output cache. + * Changed prototype for function wo_clear. + * + * Revision 1.22 1997/01/24 13:13:11 adam + * Implemnted egw_source and added a "raw" option to the URL. + * Fixed a bug in the buffering system of wproto; the macro wo_putc could + * override memory if it was the first HTML generating function called. + * + * Revision 1.21 1996/05/23 15:53:11 adam + * Bug fix: egw_enc failed on 8-bit chars. + * New command: egw_parms. + * + * Revision 1.20 1996/05/21 14:53:04 adam + * Tcl command wform extented; options -raw and -exists added. + * + * Revision 1.19 1996/03/14 11:48:39 adam + * New function egw_prog that returns name of shell. + * + * Revision 1.18 1996/02/12 10:09:23 adam + * New parameter to wproto_init: directory root for the FIFOs (instead + * of using preprocessor defines FIFODIR/FIFOROOT). + * + * Revision 1.17 1996/01/26 09:02:22 adam + * Open of client FIFO called with O_NDELAY when reconnecting to shell + * in order to prevent serious lock if previous shell died without + * unlinking client FIFO. + * + * Revision 1.16 1996/01/24 10:13:56 adam + * Bug fix: in function wo_write realloc is used only when memory is already + * allocated with malloc. + * + * Revision 1.15 1996/01/24 08:25:32 adam + * Buf fix: Uninitialized outbuffer_offset member. + * + * Revision 1.14 1996/01/12 13:08:07 adam + * CGI script passes name of lock file to the shell. The server will not close + * the response FIFO until this file becomes unlocked. This method handles + * cancel operations much better. + * + * Revision 1.13 1996/01/12 10:05:20 adam + * If script name ends with ';' HTTP/GET/Expires will be defined. + * The cgi interface only reads final handshake if response from + * server (shell) was zero-terminated [If it isn't it probably died]. + * + * Revision 1.12 1996/01/05 16:35:02 adam + * Minor changes. + * + * Revision 1.11 1996/01/05 16:21:21 adam + * Bug fix: shell (wproto) sometimes closed server FIFO before cgi + * program opened it - solution: cgi sends OK when response has been read. + * + * Revision 1.10 1995/12/22 14:21:16 adam + * More work on scan. The search.egw script takes care of cached + * query page (doesn't always increment nextSetNo). To make new search set + * either 'New query' must be selected or the query page must be reloaded. + * The msearch script doesn't do this yet, however. + * + * Revision 1.9 1995/11/14 16:31:36 adam + * Temporary remove of ccl entry. + * + * Revision 1.8 1995/11/13 15:41:45 adam + * Arrow gifs. + * Gateway uses record element set names B(rief) and F(ull). + * Bug fix. Didn't save idAuthentication correctly. + * + * Revision 1.7 1995/11/10 14:47:32 adam * Plus (+) characters automatically converted to space in forms. * Work on search in multiple targets. Doesn't work well - yet. * Presentation formats enhanced. @@ -70,6 +146,7 @@ */ #include +#include #include #include #include @@ -79,6 +156,7 @@ #include #include #include +#include #include "wproto.h" @@ -88,11 +166,17 @@ static void wproto_uncache(WCLIENT wc, int level); static char *mod = "wproto"; +void wo_expand (WCLIENT wc, size_t len) +{ + assert (wc->outbuffer); + wc->outbuffer = realloc(wc->outbuffer, wc->outbuffer_size += + ((len >= OUTBUFFER_CHUNK) ? len*2 : OUTBUFFER_CHUNK)); +} + void wo_write (WCLIENT wc, const char *s, size_t len) { if (wc->outbuffer_offset + len >= wc->outbuffer_size) - wc->outbuffer = realloc(wc->outbuffer, wc->outbuffer_size += - OUTBUFFER_CHUNK); + wo_expand (wc, len); memcpy(wc->outbuffer + wc->outbuffer_offset, s, len); wc->outbuffer_offset += len; } @@ -113,35 +197,11 @@ void wo_printf (WCLIENT wc, const char *fmt, ...) va_end(ap); } -void wo_clear (WCLIENT wc, char *type) +void wo_clear (WCLIENT wc) { if (!wc->outbuffer) - wc->outbuffer = malloc(wc->outbuffer_size = OUTBUFFER_CHUNK); + wc->outbuffer = malloc (wc->outbuffer_size = OUTBUFFER_CHUNK); wc->outbuffer_offset = 0; - wo_printf(wc, "Content-type: %s\n\n", type); -} - -int wo_puthtml (WCLIENT wc, char *name) -{ - FILE *f; - char ch; - - wo_clear(wc, "text/html"); - if (!(f = fopen(name, "r"))) - { - wo_printf(wc, "
Failed to open file: %s
", name); - return 0; - } - while (ch = getc(f), !feof(f)) - { - if (wo_putc(wc, ch) < 0) - { - fclose(f); - return -1; - } - } - fclose(f); - return 0; } int wo_flush(WCLIENT wc) @@ -184,18 +244,46 @@ int wo_flush(WCLIENT wc) int wo_overflow(WCLIENT wc, char ch) { gw_log (GW_LOG_DEBUG, mod, "wo_overflow"); - if (wo_flush(wc) < 0) + if (wc->save_level) + wo_expand (wc, 0); + else if (wo_flush(wc) < 0) return -1; return wo_putc(wc, ch); } +void destroy_form (wform_data *p) +{ + while (p) + { + wform_data *p_next = p->next; + + free (p->name); + free (p->value); + free (p); + + p = p_next; + } +} + int wo_finish(WCLIENT wc) { + int fd; gw_log (GW_LOG_DEBUG, mod, "wo_finish"); - + wo_putc (wc, 0); if (wo_flush(wc) < 0) - return -1; + gw_log (GW_LOG_WARN, mod, "wo_flush failed in wo_finish"); + fd = open (wc->wf_serverf, O_RDONLY); + if (fd != -1) + { + struct flock area; + area.l_type = F_RDLCK; + area.l_whence = SEEK_SET; + area.l_start = 0L; + area.l_len = 0L; + fcntl (fd, F_SETLKW, &area); + close (fd); + } close(wc->lineout); wc->lineout = -1; if (wc->cache_fd >= 0) @@ -203,6 +291,9 @@ int wo_finish(WCLIENT wc) close(wc->cache_fd); wc->cache_fd = -1; } + free (wc->wf_parms); + destroy_form (wc->wf_data); + destroy_form (wc->wf_parms_var); return 0; } @@ -235,37 +326,45 @@ static void descramble(char *t, const char *o) *t = '\0'; } -static void decode_form(wform_data *form, char *buf) +wform_data *decode_form(char *buf) { - int i = 0; - char *p; - char tmp[512]; + wform_data *p, **pp = &p; + char tmp[4096]; while (*buf) { - for (p = form[i].name; *buf && *buf != '='; buf++) - *(p++) = *buf; - *p = '\0'; + int l; + + *pp = malloc (sizeof(**pp)); + for (l = 0; *buf && *buf != '='; buf++) + if (l < (sizeof(tmp)-1)) + tmp[l++] = *buf; + tmp[l] = '\0'; + (*pp)->name = malloc (strlen(tmp)+1); + strcpy ((*pp)->name, tmp); if (*buf) buf++; - for (p = tmp; *buf && *buf != '&'; buf++) - *(p++) = *buf; - *p = '\0'; - descramble(form[i].value, tmp); + for (l = 0; *buf && *buf != '&'; buf++) + if (l < (sizeof(tmp)-1)) + tmp[l++] = *buf; + tmp[l] = '\0'; + (*pp)->value = malloc (strlen(tmp)+1); + descramble((*pp)->value, tmp); if (*buf) buf++; - i++; + pp = &(*pp)->next; } - *form[i].name = '\0'; + *pp = NULL; + return p; } char *wgetval(WCLIENT wc, char *name) { - int i; + wform_data *p; - for (i = 0; *wc->wf_data[i].name; i++) - if (!strcmp(name, wc->wf_data[i].name)) - return wc->wf_data[i].value; + for (p = wc->wf_data; p; p = p->next) + if (!strcmp(name, p->name)) + return p->value; return 0; } @@ -301,12 +400,11 @@ int wproto_process(WCLIENT wc, int timeout) if (rs == 0) { gw_log (GW_LOG_STAT, mod, - "wproto_process returning 0 after %d second timeout.", + "select %d second timeout.", timeout); unlink (wc->wf_serverp); return 0; } - /* determine handle (fifo or user) */ if (read(wc->linein, &toread, sizeof(toread)) < sizeof(toread)) { gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, mod, "wp_proc:len read failed"); @@ -321,22 +419,39 @@ int wproto_process(WCLIENT wc, int timeout) p = combuf; for (t = wc->wf_serverp; (*t = *p); t++, p++); p++; - for (t = wc->wf_parms; (*t = *p); t++, p++); + for (t = wc->wf_serverf; (*t = *p); t++, p++); + p++; + for (t = wc->wf_script; *p && *p != '/'; t++, p++) + *t = *p; + *t = '\0'; + if (*p) + p++; + wc->wf_parms_var = decode_form (p); + wc->wf_parms = malloc (strlen(p)+1); + for (t = wc->wf_parms; (*t = *p); t++, p++) + ; p++; p++; /* we don't deal with envvars yet */ - decode_form(wc->wf_data, p); - if (wc->lineout < 0 && (wc->lineout = open(wc->wf_serverp, O_WRONLY)) - < 0) - { - gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, mod, "open %s", wc->wf_serverp); - exit(1); - } + wc->raw_data = p; + wc->wf_data = decode_form (p); + if (wc->lineout < 0) + { + gw_log (GW_LOG_DEBUG, mod, "open %s", wc->wf_serverp); + if ((wc->lineout = open(wc->wf_serverp, O_WRONLY)) < 0) + { + gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, mod, "open %s", + wc->wf_serverp); + exit(1); + } + } /* look in cache only if request carries no forms data. */ - if (!*wc->wf_data[0].name && (level = wproto_findcache(wc, + if (!wc->wf_data && (level = wproto_findcache(wc, wc->wf_parms)) >= 0) { + gw_log (GW_LOG_DEBUG, mod, "wproto_dumpcache"); wproto_dumpcache(wc, level); wo_finish(wc); + } else { @@ -345,14 +460,14 @@ int wproto_process(WCLIENT wc, int timeout) } } -WCLIENT wproto_init(void) +WCLIENT wproto_init (const char *fifoDir, const char *prog) { char *val, path2[256]; - wclient_data *new; + wclient_data *newp; gw_log (GW_LOG_DEBUG, mod, "wproto_init"); close(1); /* release us from the wserver */ - if (!(new = malloc(sizeof(*new)))) + if (!(newp = malloc(sizeof(*newp)))) { gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, mod, "malloc"); exit (1); @@ -362,43 +477,50 @@ WCLIENT wproto_init(void) gw_log (GW_LOG_FATAL, mod, "GWID not set"); exit (1); } - new->id = atoi (val); - sprintf(new->path, "%s/%s/clt%d", FIFOROOT, FIFODIR, new->id); - if (mkfifo(new->path, 0666 | S_IFIFO) < 0) + if (!(newp->prog = malloc (strlen(prog)+1))) { - gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, mod, "mkfifo(%s)", new->path); - exit(1); + gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, mod, "malloc"); + exit (1); } + strcpy (newp->prog, prog); + newp->fifoDir = fifoDir; + newp->id = atoi (val); + sprintf(newp->path, "%s/clt%d", newp->fifoDir, newp->id); + if (mkfifo(newp->path, 0666 | S_IFIFO) < 0) + gw_log (GW_LOG_WARN|GW_LOG_ERRNO, mod, "mkfifo(%s)", newp->path); gw_log (GW_LOG_DEBUG, mod, "Synchronizing with server."); - sprintf(path2, "%s/%s/srv%d", FIFOROOT, FIFODIR, getppid()); - if ((new->lineout = open(path2, O_WRONLY)) < 0) + sprintf(path2, "%s/srv%d", newp->fifoDir, getppid()); + if ((newp->lineout = open(path2, O_WRONLY)) < 0) { gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, mod, "open out %s", path2); exit(1); } - if (write(new->lineout, "OK", 2) < 2) + if (write(newp->lineout, "OK", 2) < 2) { gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, mod, "write"); exit(1); } gw_log (GW_LOG_DEBUG, mod, "Synchronized."); - if ((new->linein = open(new->path, O_RDONLY)) < 0) + if ((newp->linein = open(newp->path, O_RDONLY)) < 0) { - gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, mod, "open input %s", new->path); + gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, mod, "open input %s", newp->path); exit(1); } gw_log (GW_LOG_DEBUG, mod, "init. linein=%d lineout=%d", - new->linein, new->lineout); + newp->linein, newp->lineout); /* we put a handle on this so we get a blocking read when no peer */ - if (open(new->path, O_WRONLY | O_NDELAY) < 0) + if (open(newp->path, O_WRONLY | O_NDELAY) < 0) { - gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, mod, "open dummy %s", new->path); + gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, mod, "open dummy %s", newp->path); exit(1); } - new->outbuffer = 0; - new->cache_level = -1; - new->cache_fd = -1; - return new; + newp->outbuffer = 0; + newp->outbuffer_size = 0; + newp->outbuffer_offset = 0; + newp->cache_level = -1; + newp->cache_fd = -1; + newp->save_level = 0; + return newp; } static void wproto_uncache(WCLIENT wc, int level) @@ -409,6 +531,7 @@ static void wproto_uncache(WCLIENT wc, int level) void wproto_terminate(WCLIENT wc) { + free (wc->prog); close(wc->linein); unlink(wc->path); wproto_uncache(wc, 0); @@ -426,7 +549,7 @@ int wproto_cache(WCLIENT wc, int level) } wproto_uncache(wc, level); p = &wc->cache[++wc->cache_level]; - sprintf(p->path, "%s/%s/csh%d.%d", FIFOROOT, FIFODIR, wc->id, level); + sprintf(p->path, "%s/csh%d.%d", wc->fifoDir, wc->id, level); if ((wc->cache_fd = open(p->path, O_WRONLY|O_CREAT|O_TRUNC, 0600)) < 0) { gw_log (GW_LOG_FATAL|GW_LOG_ERRNO, mod, "open %s", p->path); @@ -446,6 +569,25 @@ static int wproto_findcache(WCLIENT wc, char *name) return -1; } +int wproto_save_push (WCLIENT wc) +{ + wc->save_level++; + return wc->outbuffer_offset; +} + +char *wproto_save_pop (WCLIENT wc, int offset) +{ + char *cp; + if (!wc->save_level) + return NULL; + --(wc->save_level); + assert (offset <= wc->outbuffer_offset); + cp = wc->outbuffer + offset; + wc->outbuffer[wc->outbuffer_offset] = '\0'; + wc->outbuffer_offset = offset; + return cp; +} + static int wproto_dumpcache(WCLIENT wc, int level) { int fd, rd;