/* * * GSQL - a Mosaic gateway to SQL applications. * * Jason Ng, NCSA, * University of Illinois Urbana-Champaign * 1994 * * This is public domain software. There is one requirement: if you use this * software, you should include a link in your forms or documents that * would mention GSQL and NCSA, and would point to the Tutorial on GSQL, * ie http://www.ncsa.uiuc.edu/SDG/People/jason/pub/gsql/starthere.html * * Modified by David Jones for scripting system used by OSU's VMS HTTP server: * * Assumes program is run directly from URL and portion trailing URL is * name of form file (for security, form file name is translated against * rule file. The generated form specifies a method of POST so we can * use the method to determine whether response is to be a form or * a query. * * This file include cgilib.h and must be linked with cgilib.obj and * scriptlib.obj. * * The command defined by SQLPROG is chained to with a do_command rather * than spawning a system call. * * */ #include #include #include #include #include "cgilib.h" #define printf cgi_printf #define strdup(s) strcpy(malloc(strlen(s)+1),s) #define SELECTKEYWORD "SELECT" static int dbg = 0; static int dd = 0; static char *sqlprogram = NULL; static FILE * fstream = NULL; /* procfile file descriptor */ #define NM 101 #define NITEMS 2010 static int nmenus = 0; static char *menuvname[NM]; static char *menutitle[NM]; static char *mitem[NITEMS][NM]; static int nitems[NM]; static int menutype[NM]; #define M_BUTTON 0 #define M_FIELD 1 #define M_SCROLL 2 #define M_PULLDOWN 3 #define M_RADIO 4 #define M_BUTTONSET 5 static int g_widgettypes[] = { M_FIELD, M_BUTTON, M_SCROLL, M_PULLDOWN, M_RADIO, M_BUTTONSET }; static char *g_widgetnames[] = { "FIELD", "BUTTON", "SCROLL", "PULLDOWN", "RADIO", "BUTTONSET" }; #define g_ndefwidtypes (sizeof(g_widgettypes)/sizeof(int)) #define LLEN 5000 newmenu(title, vname,type) char *title, *vname; char *type; { int i,t, id; char mtype[50]; /* fprintf(stderr, "NEWMENU [%s] [%s] type [%s]\n", title, vname, type); */ sscanf(type,"%s", mtype); for(t=(-1), i=0;i New Mosaic-SQL interface
\n"); if (getdirective("HEADING", buf)) printf("%s\n",buf); else printf("

Type-2 SQL Forms

\n",buf); printf("
\n"); for (a=0; a< (int) getitemcount(); a++) { int itemid; char type[10]; fetchitem (a , type, &itemid); if (!strcmp(type,"TEXT")) displaytext(itemid); else if (!strcmp(type,"MENU")) displaymenu(itemid); else if (!strcmp(type,"EXEC")) { getscript(itemid, buf); execscript (buf); } } printf("

\n"); printf("

\n"); if (dbg) showmenus(); } /* displays the menu specified by id - index into the menu structure */ displaymenu(id) int id; { int j, maxsize; printf("

%s ", menutitle[id]); if (menutype[id]==M_FIELD ) { /* input field */ printf(" \n", menuvname[id]); } else if (menutype[id]==M_BUTTON) { /* toggle button */ printf(" \n", menuvname[id]); } else if (menutype[id]==M_BUTTONSET || menutype[id]==M_RADIO) { /* buttons */ for(j=0;j %s\n", menuvname[id], mitem[j][id] , mitem[j][id]); else if(menutype[id]==M_RADIO) printf(" %s\n", menuvname[id], mitem[j][id] , mitem[j][id]); } } else if (menutype[id]==M_SCROLL || menutype[id]==M_PULLDOWN) { /* menus */ maxsize = nitems[id] -1 ; if (maxsize<2) maxsize=2; if(menutype[id]==M_SCROLL) printf("\n", menuvname[id]); for(j=0;j %s\n", mitem[j][id]); else printf("

\n"); } } showmenus() { int i,j; fprintf(stderr,"SHOWALL\n"); for(i=0;i3) { printf(" SHOULD BE 3

"); } for(i=0;i%d [%s]\n", i,av[i]); } printf("

"); */ if(ac<2) { printf("Usage: %s procfilename user-inputs...\n",av[0]); exit(0); } else if(ac==2) { procfilename = av[1]; parsefile1(procfilename); makeform(); exit(0); } else { char buf[LLEN]; procfilename = av[1]; combineargs(ac,av,buf); /* printf("AFTER COMBINE args is

 [%s]
\n", buf); */ parseinputs(buf); /* buf: "v1=n1&v2=b2&...&vx=bx", b's can be empty */ parsefile2(procfilename); mergeall(); } } main(ac,av) int ac; char**av; { int i, status; char * procfilename, *content_length, *search_arg, *content_l; /* * Initialize communication with server. */ status = cgi_init ( ac, av ); if ( (status&1) == 0 ) exit ( status ); procfilename = cgi_info ( "PATH_TRANSLATED" ); fprintf ( stderr, "procfile: '%s'\n", procfilename ? procfilename : "?" ); search_arg = cgi_info ( "QUERY_STRING" ); fprintf ( stderr, "query: '%s'\n", search_arg ? search_arg : "?" ); cgi_printf("Content-type: text/html \n\n"); if ( !search_arg ) search_arg = ""; if ( (ac > 1) && (strcmp(av[1],"GET")==0) ) { /* * Get method is for retrieving forms. */ parsefile1(procfilename); makeform(); exit(0); } else if ( (ac>1) && (strcmp(av[1], "POST")==0) ) { /* * Post method is for submitted form. */ char buf[LLEN]; int length; content_l = cgi_info ( "CONTENT_LENGTH" ); if ( content_l ) { length = atoi ( content_l ); length = cgi_read ( buf, (length > LLEN-1) ? LLEN-1 : length ); } else { /* Try to use query string. */ strncpy ( buf, search_arg, LLEN-1 ); length = LLEN-1; } buf[length] = '\0'; parseinputs(buf); /* buf: "v1=n1&v2=b2&...&vx=bx", b's can be empty */ parsefile2(procfilename); mergeall(); } else { cgi_printf ( "Invalid request (%s), must be GET or POST\n", ac > 1 ? av[1] : "" ); exit ( 0 ); } } combineargs(ac,av,buf) int ac; char *av[], *buf; { int i; /* av[1] is the procfilename - skip over */ if(ac<3) return; strcpy(buf,av[2]); for(i=3;i"); while(NULL!=( s = strtok(s1,"&"))) { {{ char *b1, *b2; b1 = strchr(s,'='); if(b1==NULL) continue; *b1 = '\0'; headv = strdup(s); b1++; if(b1) tailv = strdup(b1); }} if(headv[0]=='_') u_vspecial[i] = 1; u_vname[i] = strdup(headv); u_vval[i] = strdup(tailv); if(dd) { printf("
  • userinput [%s] [%s]",u_vname[i], u_vval[i]); if (u_vspecial[i] ) printf(" special \n"); } i++; s1=NULL; } n_u = i; printf(""); } /* parses only display and exec directives */ parsefile1 (filename) char *filename; { char buf[LLEN]; char title[LLEN]; char vname[LLEN]; int id; if (NULL == (fstream= fopen(filename,"r"))) { printf("parsefile1: Cannot open procfile [%s]\n", filename); exit(0); } while( getword(buf)) { if (buf[0]=='#') { /* comment - ignore */ flushline(); } else if (!strcmp(buf,"TEXT")) { getline(buf); id = savetext(buf); registeritem ("TEXT", id); } else if (!strcmp(buf,"HEADING")) { getline(buf); savedirective("HEADING", buf); } else if (!strcmp(buf,"SHOW")) { getword(vname); if (dbg) fprintf(stderr,"VARIABLE [%s]\n", vname); getword(buf); getquotedline(title); getline(buf); id = newmenu(title,vname, buf); makemenu (id, buf); registeritem ("MENU", id); } else if (!strcmp(buf,"EXEC")) { getline(buf); id = savescript(buf); registeritem ("EXEC", id); } } fclose (fstream); } /* will scan to last semi-colon, and truncate the rest of line */ getline(ss) char*ss; { char *sp, sbuf[LLEN]; ss[0] ='\0'; while(1) { if (NULL==fgets(sbuf,LLEN,fstream)) { return(0); } if(sbuf[0] =='#') { if(dbg) fprintf(stderr," found comment [%s]\n", sbuf); continue; /* ignore comment, get another line */ } sp = strrchr(sbuf,';'); if (sp) { /* found semicolon - concat and return */ sp[0] = '\0'; /* chop off rest of line */ strcat(ss,sbuf); return(1); } /* semicolon not found, concat and get more lines */ strcat(ss,sbuf); } } /* look for and return the next quoted string "xxx" */ getquotedline(ss) char*ss; { char sbuf[LLEN], *sp = sbuf; int c; ss[0] ='\0'; while (EOF != (c = fgetc(fstream)) ) { if (c== '\"') /* opening quote */ break; } while (EOF != (c = fgetc(fstream)) ) { if (c== '\"') { /* closing quote */ *sp++ = '\0'; strcpy(ss,sbuf); return(1); } else { *sp++ = c; } } } flushline() { /* throw away rst of line in input stream */ char sbuf[LLEN]; fgets(sbuf,LLEN,fstream); } getword(ss) char*ss; { char *sp; char sbuf[LLEN]; if( EOF== fscanf(fstream,"%s",sbuf) ) return(0); if (sp = strrchr(sbuf,';')) { *sp = '\0'; } /* remove semicolon */ sscanf(sbuf,"%s", ss); return(1); } /* for each item, need to remove leading and trailing blanks */ /* Note that mline must have a first word of the menu type keyword */ makemenu (menuid, mline ) int menuid; char *mline ; { #define PATTERN "," char *s, *s1; char *zz = mline; /* skip past first word */ while( zz && isspace(*zz) ) { zz++; } if (zz==NULL) return; while( zz && !isspace(*zz) ) { zz++; } if (zz==NULL) return; if (dbg) fprintf(stderr,"DOIT rest ID %d[%s]\n", menuid, zz); if (NULL!=(s1 = strstr(zz,"EXEC"))) { FILE *f; char buf[LLEN]; execcommand((s1+4), &f); while(NULL!=fgets(buf, LLEN, f)){ addmenuitem(menuid, buf); } fclose(f); return; } s1=zz; while(NULL!=( s = strtok(s1,PATTERN))) { chopblanks(&s); addmenuitem(menuid, s); s1=NULL; } } chopblanks(ss) char **ss; { char *sp = *ss; int n; while(isspace(*sp) ) sp++; *ss = sp; sp = *ss; n = strlen(*ss); sp = *ss+(n-1); while(isspace(*sp)) { *sp = '\0'; sp--; } } /* ================================================================== */ /* list of graphic objects */ #define NOBJ 200 static int obj_ref[NOBJ]; /* actually a unique reference int */ static int obj_type[NOBJ]; /* t - text, m - menu, e -exec */ static int n_obj = 0; /* rets its ordering , or -1 if error */ int registeritem(type, ref) char *type; int ref; { int t , n; if (!strcmp(type,"TEXT")) { t = 't'; } else if (!strcmp(type,"MENU")) { t = 'm'; } else if (!strcmp(type,"EXEC")) { t = 'e'; } else { return(-1); } n = n_obj; obj_ref[n] = ref; obj_type[n] = t; n_obj++; return (n); } getitemcount() { return (n_obj); } fetchitem (which, type, ref ) int which; /* its ordering as ret from registeritem() */ int *ref; /* output */ char *type; /* output */ { *ref = obj_ref[which]; switch (obj_type[which]) { case 't': strcpy(type,"TEXT"); break; case 'm': strcpy(type,"MENU"); break; case 'e': strcpy(type,"EXEC"); break; default : strcpy(type,"NONE"); return(0); break; } return(1); } /* ================================================================== */ /* storage for user's scripts and executables */ #define NEX 80 static char * d_ex[NEX]; static int n_ex = 0; /* rets id of script , else -1 */ int savescript(ex) char *ex; { int id; d_ex[n_ex] = strdup ( ex ); id = n_ex; n_ex++; return (id); } getscript (id, ex) int id; char *ex; { strcpy(ex, d_ex[id] ); } execscript (ex) char *ex; { char tfile[500]; char buf[LLEN]; FILE *f; tmpnam(tfile); sprintf(buf, "%s > %s ", ex, tfile); system( buf ); f = fopen(tfile,"r"); if(f==NULL) { printf("cannot open %s \n", tfile); return; } while(NULL!= fgets(buf, LLEN, f)) printf("%s",buf); fclose(f); } execcommand (ex,fhandle) char *ex; FILE **fhandle; { char tfile[500]; char buf[LLEN]; FILE *f; tmpnam(tfile); sprintf(buf, "%s > %s ", ex, tfile); system( buf ); f = fopen(tfile,"r"); if(f==NULL) { printf("cannot open %s \n", tfile); *fhandle = NULL; return; } *fhandle = f; } /* ================================================================== */ /* storage for user's text */ #define NTXT 80 static char * d_text[NTXT]; static int n_txt = 0; /* rets id of text, else -1 */ int savetext(text) char *text; { int id; d_text[n_txt] = strdup ( text); id = n_txt; n_txt++; return (id); } gettext (id, text) int id; char *text; { strcpy(text, d_text[id] ); } displaytext ( id) int id; { char text[LLEN]; gettext(id, text); printf("%s", text); } /* ================================================================== */ /* defines from DEFINE */ /* sql directives and the expansion */ /* general sql directives */ static char * d_cmd[] = { "FROMLIST", "SELECTLIST", "WHERELIST", "SORTLIST", "HEADING" }; #define NW ( sizeof(d_cmd)/sizeof(char *) ) static char * d_mean[NW]; static int n_cmd = NW; /* defines from DEFINE */ #define MDEF 40 static char * d_defvar[MDEF]; static char * d_defval[MDEF]; static int n_def = 0; /* variables from SUB */ #define NV 200 static char * var_name[NV]; static char * var_mean[NV]; static char * var_kind[NV]; /* what list it's part of eg SELECT or WHERE */ static char * var_fmt[NV]; /* string to format output as */ static int var_used[NV]; /* 1 if has user input */ static int n_var = 0; parsefile2 (filename) char *filename; { char buf[LLEN], tbuf[LLEN]; char vname[LLEN]; int id, i; if (NULL == (fstream= fopen(filename,"r"))) { printf("parsefile2: Cannot open procfile [%s]\n", filename); exit(0); } for(i=0;i"); while( getword(buf)) { if (buf[0]=='#') { if(dbg) fprintf(stderr,"comment word [%s]\n", buf); flushline(); } else if (!strcmp(buf,"HEADING")) { getline(buf); savedirective("HEADING", buf); } else if (!strcmp(buf,"SUB")) { getword(vname); var_name[n_var] = strdup(vname); getword(buf); /* kind */ var_kind[n_var] = strdup(buf); getword(buf); /* AS */ getline(buf); /* meaning */ var_mean[n_var] = strdup(buf); if(dd) printf("
  • FILE VAR [%s] [%s] [%s] \n", var_name[n_var], var_kind[n_var], var_mean[n_var]); n_var++; } else if (!strcmp(buf,"SQLPROG")) { getline(tbuf); sqlprogram = strdup(tbuf); } else if (!strcmp(buf,"DEFINE")) { getword(tbuf); sscanf(tbuf,"%s",buf); d_defvar[n_def] = strdup(buf); getline(tbuf); sscanf(tbuf,"%s",buf); d_defval[n_def] = strdup(buf); if(dd) printf("
  • usrdefine [%s] [%s]\n", d_defvar[n_def], d_defval[n_def]); n_def++; } else { /* save if is a sql directive */ getline(tbuf); savedirective (buf, tbuf); } } printf(""); fclose (fstream); } /* ------------------------------------------------------------------ */ /* returns the meaning of a SUB variable */ lookupmean (var, meaning) char *var, *meaning; { int i; for (i=0;i0) { /* don't bother if empty value */ var_used[i] = 1; match[nm] = t; nm++; } } } if (nm>0) { /* build the match string */ buf[0]='\0'; for (j=0;jUNDEFINED [%s]\n", u_vval[t]); } else { if (j!=0) strcat(buf, ","); strcat(buf, tbuf); } } else { /* just use the input */ if (j!=0) strcat(buf, ","); strcat(buf, u_vval[t]); } } substitute(&var_mean[i], buf); } } /* --- build the sql string from the pieces --- */ sqlstr[0] ='\0'; strcat (sqlstr," \" " ); strcat( sqlstr, SELECTKEYWORD); num = 0; if( getdirective("SELECTLIST", buf)) { strcat(sqlstr, buf ); num = 1; } for (i=0;i0) strcat(sqlstr, ", "); strcat(sqlstr, var_mean[i]); num++; } } } if (num==0) { /* yikes..no user-selected values, & no default select list */ printf("

    You must select field(s) to display.

    "); return; } if( getdirective("FROMLIST", buf)) { strcat(sqlstr, " FROM "); strcat(sqlstr, buf ); } num = 0; strcat(sqlstr, " WHERE "); for (i=0;i0) strcat(sqlstr, " AND "); strcat(sqlstr, var_mean[i]); num++; } } } if( getdirective("WHERELIST", buf)) { if (num>0) strcat(sqlstr, " AND "); strcat(sqlstr, buf ); } if( getdirective("SORTLIST", buf)) { strcat(sqlstr, buf ); } strcat(sqlstr, " \" "); /* entire sql string is quoted */ if(dd) printf(" SQL %s

    \n", sqlstr); stuffmenu("Here is the SQL Query ", sqlstr ); strcat(sqlstr," "); for(i=0;i"); {{ char cmd[LLEN], symname[4]; int i, n, length; $DESCRIPTOR(command,""); $DESCRIPTOR(symbol,"C00"); $DESCRIPTOR(value,""); if (sqlprogram==0) { printf("

    Sorry..I don't know what SQL program to run."); printf("

    SQLPROG is not specified!

    "); exit(0); } /* * Break sqlstr into a series of DCL symbols of no more than * 255 characters. */ length = strlen ( sqlstr ); symbol.dsc$a_pointer = symname; for ( n = i = 0; i < length; i += 255 ) { value.dsc$w_length = length - i; if ( value.dsc$w_length > 255 ) value.dsc$w_length = 255; value.dsc$a_pointer = &sqlstr[i]; sprintf(symname,"C%02d", n++ ); LIB$SET_SYMBOL ( &symbol, &value ); } fprintf(stderr,"sql, %d parts: %s\n", n, sqlstr ); sprintf(cmd,"%s 'C00''C01''C02''C03''C04'", sqlprogram ); /* stuffmenu("Here is the cmd ", cmd); */ fflush(stdout); cgi_set_dcl_env("WWW_"); command.dsc$a_pointer = cmd; command.dsc$w_length = strlen(cmd); fprintf(stderr,"cmd: %s\n", cmd ); LIB$DO_COMMAND ( &command ); printf("

    Error chaining to SQLPROG\n"); /* should never get here */ }} } savedirective(cmd, meaning) char * cmd , *meaning; { int i; for(i=0;i sub [%s] inside [%s] ", x2, orig); */ sp = strchr(orig,'$'); if (sp==NULL) return; buf[0] = '\0'; *sp ='\0'; strcat(buf,orig); /* first portion */ strcat(buf,x2); /* substituted portion */ sp++; if(sp) { /* end portion */ strcat(buf,sp); } *x1 = strdup(buf); /* printf("new string is [%s] ", *x1); */ } /* stuff some text into a menu */ stuffmenu(title, string) char *title, *string; { int n; char *stringbuf; char buf[LLEN]; char *ss, *s2, *s1; stringbuf = strdup(string); /* remove quotes */ s1 = strchr(stringbuf, '\"'); if(s1) *s1 = ' '; s1 = strrchr(stringbuf, '\"'); if(s1) *s1 = ' '; printf("

    "); printf("

    \n"); printf("

    "); fflush(stdout); }