home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1995 April / Internet Tools.iso / infoserv / www / ncsa / tools / gsql / gsql.c.Z / gsql.c
Encoding:
C/C++ Source or Header  |  1994-06-26  |  19.5 KB  |  876 lines

  1. /*
  2. *
  3. * GSQL - a Mosaic gateway to SQL applications.
  4. * Jason Ng, NCSA, 
  5. * University of Illinois Urbana-Champaign 
  6. * 1994
  7. * This is public domain software. There is one requirement: if you use this
  8. * software, you should include a link in your forms or documents that
  9. * would mention GSQL and NCSA, and would point to the Tutorial on GSQL,
  10. * ie http://www.ncsa.uiuc.edu/SDG/People/jason/pub/gsql/starthere.html
  11. * */
  12.  
  13.  
  14. #include <string.h>
  15. #include <stdio.h>
  16.  
  17. #define SELECTKEYWORD "SELECT"
  18.  
  19. static int dbg = 0;
  20. static int dd  = 0;
  21.  
  22. static char *sqlprogram = NULL;
  23.  
  24. static FILE * fstream = NULL; /* procfile file descriptor */
  25.  
  26. #define NM 101
  27. #define NITEMS 2010
  28. static int nmenus = 0;
  29. static char *menuvname[NM];
  30. static char *menutitle[NM];
  31. static char *mitem[NITEMS][NM];
  32. static int nitems[NM];
  33. static int menutype[NM];
  34.  
  35. #define M_BUTTON   0
  36. #define M_FIELD    1
  37. #define M_SCROLL   2
  38. #define M_PULLDOWN 3
  39. #define M_RADIO    4
  40. #define M_BUTTONSET 5
  41.  
  42. static int g_widgettypes[] =
  43. { M_FIELD, M_BUTTON, M_SCROLL, M_PULLDOWN, M_RADIO, M_BUTTONSET };
  44. static char *g_widgetnames[] =
  45. { "FIELD", "BUTTON", "SCROLL", "PULLDOWN", "RADIO", "BUTTONSET" };
  46. #define g_ndefwidtypes (sizeof(g_widgettypes)/sizeof(int))
  47.  
  48. #define LLEN 5000
  49. newmenu(title, vname,type) char *title, *vname; char *type;
  50. {
  51.   int i,t, id;
  52.   char mtype[50];
  53.   /* fprintf(stderr, "NEWMENU [%s] [%s] type [%s]\n", title, vname, type);  */
  54.  
  55.   sscanf(type,"%s", mtype);
  56.   for(t=-1, i=0;i<g_ndefwidtypes;i++) 
  57.     if(!strcmp(mtype,g_widgetnames[i])) { t = g_widgettypes[i]; break; }
  58.  
  59.   if(t==-1) return(-1);
  60.  
  61.   menuvname[nmenus] = strdup(vname);
  62.   menutitle[nmenus] = strdup(title);
  63.   menutype[nmenus] = t;
  64.   nitems[nmenus] = 0;
  65.   id = nmenus; nmenus++;
  66.   return(id);
  67. }
  68.  
  69. addmenuitem(id, itemname) int id; char *itemname;
  70. {
  71.   int n = nitems[id];
  72.    /* fprintf(stderr,"added [%s] ",itemname);  */
  73.   mitem[n][id] = strdup(itemname);
  74.   nitems[id]++;
  75. }
  76.  
  77. makeform () {
  78.   int a;
  79.   char buf[LLEN];
  80.  
  81.   printf("<H1> New Mosaic-SQL interface </H1> <HR>\n");
  82.   if (getdirective("HEADING", buf))  
  83.       printf("%s\n",buf);
  84.   else
  85.       printf("<H1> Type-2 SQL Forms <H2>\n",buf);
  86.  
  87.   printf("<FORM>\n");
  88.   for (a=0; a< (int) getitemcount(); a++) {
  89.       int itemid;
  90.       char type[10];
  91.      fetchitem (a , type, &itemid);
  92.       if (!strcmp(type,"TEXT"))
  93.          displaytext(itemid);
  94.       else if (!strcmp(type,"MENU"))
  95.          displaymenu(itemid);
  96.       else if (!strcmp(type,"EXEC")) {
  97.             getscript(itemid, buf);
  98.          execscript (buf);
  99.             }
  100.       }
  101.   printf(" <p> <INPUT TYPE=\"submit\" VALUE=\"Doit!\"> <P>\n");
  102.   printf("</FORM>\n");
  103.  
  104.  if (dbg)  showmenus(); 
  105. }
  106.  
  107. /* displays the menu specified by id - index into the menu structure */
  108. displaymenu(id) int id;
  109. {
  110.       int j, maxsize;
  111.       printf("<p> %s ", menutitle[id]);
  112.      if     (menutype[id]==M_FIELD ) { /* input field */
  113.         printf(" <INPUT NAME=\"%s\">\n", menuvname[id]);
  114.      }
  115.      else if (menutype[id]==M_BUTTON) { /* toggle button */
  116.         printf("<INPUT TYPE=\"checkbox\" NAME=\"%s\" > \n", 
  117.                  menuvname[id]);
  118.      }
  119.      else if (menutype[id]==M_BUTTONSET || menutype[id]==M_RADIO) { /* buttons */
  120.        for(j=0;j<nitems[id];j++) {
  121.          if(menutype[id]==M_BUTTONSET)
  122.             printf("<INPUT TYPE=\"checkbox\" NAME=\"%s\" VALUE=\"%s\"> %s\n", 
  123.                  menuvname[id], mitem[j][id] , mitem[j][id]);
  124.          else if(menutype[id]==M_RADIO)
  125.             printf("<INPUT TYPE=\"radio\" NAME=\"%s\" VALUE=\"%s\"> %s\n", 
  126.                  menuvname[id], mitem[j][id] , mitem[j][id]);
  127.         }
  128.      }
  129.      else if (menutype[id]==M_SCROLL || menutype[id]==M_PULLDOWN) { /* menus */
  130.        maxsize  = nitems[id] -1 ; if (maxsize<2) maxsize=2;
  131.        if(menutype[id]==M_SCROLL)
  132.           printf("<SELECT NAME=\"%s\" MULTIPLE>\n", menuvname[id], maxsize);
  133.        else if(menutype[id]==M_PULLDOWN)
  134.           printf("<SELECT NAME=\"%s\">\n", menuvname[id]);
  135.        for(j=0;j<nitems[id];j++) {
  136.              if(j==0)
  137.                printf(" <OPTION SELECTED>  %s\n", mitem[j][id]);
  138.              else
  139.                 printf(" <OPTION>  %s\n", mitem[j][id]);
  140.             }
  141.        printf("</SELECT><p>\n");
  142.           }
  143. }
  144.  
  145. showmenus() {
  146.   int i,j;
  147.   fprintf(stderr,"SHOWALL\n");
  148.   for(i=0;i<nmenus;i++) {
  149.     fprintf(stderr, "MENU title [%s] [%s][%d]\n", 
  150.                         menutitle[i],menuvname[i], menutype[i]);
  151.      for(j=0;j<nitems[i];j++) {
  152.          fprintf(stderr, "\t [%s]\n", mitem[j][i]);
  153.         }
  154.     }
  155. }
  156.  
  157. /* ARGS: arg[1] = procfilename 
  158.          arg[2-..] user inputs from form output 
  159.             Minimally, procfilename is needed.
  160. */
  161. main(ac,av) int ac; char**av; {
  162.  
  163.  int i;
  164.  char * procfilename;
  165.  
  166.  printf("Content-type: text/html \n\n");
  167.  
  168.  /*
  169.  printf("NEW STUFF "); fflush(stdout);
  170.  printf("NARGS %d \n", ac); if (ac>3) { printf(" SHOULD BE 3 <p>"); }
  171.  for(i=0;i<ac;i++) { printf("<b>%d</b> [%s]\n", i,av[i]); } printf("<p>");
  172.  */
  173.  
  174.  if(ac<2) {
  175.      printf("Usage: %s procfilename user-inputs...\n",av[0]); 
  176.      exit(0); 
  177.      }
  178.  else if(ac==2) { 
  179.       procfilename = av[1];
  180.      parsefile1(procfilename);
  181.      makeform();
  182.      exit(0);
  183.       }
  184.   else {
  185.      char buf[LLEN];
  186.      procfilename = av[1];
  187.      combineargs(ac,av,buf);
  188.      /* printf("AFTER COMBINE args is <pre><tt> [%s]</tt></pre> \n", buf); */ 
  189.     parseinputs(buf); /* buf: "v1=n1&v2=b2&...&vx=bx", b's can be empty */
  190.  
  191.     parsefile2(procfilename);
  192.      mergeall();
  193.    }
  194.  }
  195.  
  196.  
  197.  combineargs(ac,av,buf) 
  198.  int ac;
  199.  char *av[], *buf;
  200.  {
  201.     int i;
  202.  
  203.      /* av[1] is the procfilename - skip over */
  204.      if(ac<3) return;
  205.     strcpy(buf,av[2]);
  206.      for(i=3;i<ac;i++) {
  207.       strcat(buf,av[i]);
  208.          }
  209.  }
  210.  
  211.  /* data structure to receive user inputs - conv to name-value pairs */
  212. #define NU 200
  213.  static char *u_vname[NU];
  214.  static char *u_vval[NU];
  215.  static int  u_vspecial[NU]; /* 1 if that varname starts with "_" */
  216.  static int  n_u = 0;
  217.  
  218.  
  219.  parseinputs (inbuf) char *inbuf;
  220.  {
  221.     char *s, *s1=inbuf;
  222.     char *headv, *tailv;
  223.     int i;
  224.  
  225.     for(i=0;i<NU;i++) { /* init */
  226.       u_vname[i]    = u_vval[i] = NULL;
  227.       u_vspecial[i] = 0;
  228.       }
  229.  
  230.     i = 0;
  231.     printf("<pre>");
  232.    while(NULL!=( s = strtok(s1,"&"))) {
  233.        {{
  234.         char *b1, *b2;
  235.         b1 = strchr(s,'='); if(b1==NULL) continue;
  236.         *b1 = '\0';
  237.         headv = strdup(s);
  238.         b1++;
  239.         if(b1) tailv = strdup(b1); 
  240.        }}
  241.        if(headv[0]=='_') u_vspecial[i] = 1; 
  242.        u_vname[i] = strdup(headv);
  243.        u_vval[i]  = strdup(tailv);
  244.        if(dd) { printf(" <li> userinput [%s] [%s]",u_vname[i], u_vval[i]);
  245.                  if (u_vspecial[i] ) printf(" <b> special </b>\n");
  246.                     }
  247.        i++;
  248.       s1=NULL;
  249.        }
  250.     n_u = i;
  251.  
  252.    printf("</pre>");
  253.  }
  254.  
  255. /* parses only display and exec directives */
  256. parsefile1 (filename) char *filename; 
  257. {
  258.  char buf[LLEN];
  259.  char title[LLEN];
  260.  char vname[LLEN];
  261.  int id;
  262.  
  263.  if (NULL == (fstream= fopen(filename,"r"))) {
  264.      printf("parsefile1: Cannot open procfile [%s]\n", filename); 
  265.      exit(0);
  266.      }
  267.  
  268.  while( getword(buf)) {
  269.     if (buf[0]=='#') {  /* comment - ignore */
  270.       flushline(); 
  271.       }
  272.     else if (!strcmp(buf,"TEXT")) {
  273.       getline(buf);
  274.       id = savetext(buf);
  275.       registeritem ("TEXT", id);
  276.       }
  277.     else if (!strcmp(buf,"HEADING")) {
  278.       getline(buf);
  279.       savedirective("HEADING", buf);
  280.       }
  281.     else if (!strcmp(buf,"SHOW")) {
  282.       getword(vname);
  283.       if (dbg) fprintf(stderr,"VARIABLE [%s]\n", vname);
  284.       getword(buf);
  285.       getquotedline(title); 
  286.  
  287.       getline(buf); 
  288.       id = newmenu(title,vname, buf);
  289.       makemenu (id, buf);
  290.       registeritem ("MENU", id);
  291.  
  292.       }
  293.     else if (!strcmp(buf,"EXEC")) {
  294.       getline(buf);
  295.       id = savescript(buf);
  296.       registeritem ("EXEC", id);
  297.      }
  298.    }
  299.   fclose (fstream);
  300.  }
  301.  
  302. /* will scan to last semi-colon, and truncate the rest of line */
  303. getline(ss) char*ss;
  304. {
  305.       char *sp, sbuf[LLEN];
  306.  
  307.       ss[0] ='\0';
  308.       while(1) {
  309.         if (NULL==fgets(sbuf,LLEN,fstream)) { 
  310.               return(0); 
  311.               }
  312.          if(sbuf[0] =='#') {
  313.               if(dbg) fprintf(stderr," found comment [%s]\n", sbuf);
  314.               continue;  /* ignore comment, get another line  */
  315.               }
  316.          sp = strrchr(sbuf,';');
  317.          if (sp) { /* found semicolon - concat and return  */ 
  318.               sp[0] = '\0'; /* chop off rest of line */
  319.              strcat(ss,sbuf);
  320.              return(1);
  321.              }
  322.         /* semicolon not found, concat and get more lines */
  323.              strcat(ss,sbuf);
  324.         }
  325. }
  326.  
  327. /* look for and return the next quoted string "xxx"  */
  328. getquotedline(ss) char*ss;
  329. {
  330.       char  sbuf[LLEN], *sp = sbuf;
  331.       int c;
  332.  
  333.       ss[0] ='\0';
  334.  
  335.       while (EOF != (c = fgetc(fstream)) ) {
  336.             if (c== '\"')  /* opening quote */
  337.                 break;
  338.             }
  339.  
  340.       while (EOF != (c = fgetc(fstream)) ) {
  341.  
  342.             if (c== '\"') { /* closing quote */
  343.                *sp++ = '\0';
  344.                 strcpy(ss,sbuf);
  345.                 return(1);
  346.                 }
  347.             else {
  348.                *sp++ = c; 
  349.                }
  350.          }
  351. }
  352.  
  353. flushline() { /* throw away rst of line in input stream */
  354.     char  sbuf[LLEN];
  355.    fgets(sbuf,LLEN,fstream);
  356.     }
  357.  
  358. getword(ss) char*ss;
  359. {
  360. char *sp;
  361. char sbuf[LLEN];
  362.  
  363. if( EOF== fscanf(fstream,"%s",sbuf) ) return(0);
  364.  
  365. if (sp = strrchr(sbuf,';')) { *sp = '\0';  } /* remove semicolon */ 
  366.  
  367. sscanf(sbuf,"%s", ss);
  368. return(1); 
  369. }
  370.  
  371.  
  372. /* for each item, need to remove leading and trailing blanks */ 
  373. /* Note that mline  must have a first word of the menu type keyword */ 
  374. makemenu (menuid, mline ) int menuid; char *mline ; {
  375. #define PATTERN  ","
  376.  
  377.  char *s, *s1;
  378.  char *zz = mline;
  379.  
  380.  /* skip past first word  */
  381.   while( zz && isspace(*zz) ) { zz++; }  if (zz==NULL) return; 
  382.   while( zz && !isspace(*zz) ) { zz++; }  if (zz==NULL) return; 
  383.  
  384.  if (dbg) fprintf(stderr,"DOIT rest ID %d[%s]\n", menuid, zz);
  385.  
  386.  if (NULL!=(s1 = strstr(zz,"EXEC"))) {
  387.     FILE *f;
  388.     char buf[LLEN];
  389.     execcommand((s1+4), &f); 
  390.     while(NULL!=fgets(buf, LLEN, f)){
  391.       addmenuitem(menuid, buf);
  392.       }
  393.    fclose(f);
  394.     return;
  395.     }
  396.  
  397.  s1=zz;
  398.  while(NULL!=( s = strtok(s1,PATTERN))) {
  399.     chopblanks(&s);
  400.     addmenuitem(menuid, s);
  401.    s1=NULL;
  402.  }
  403.  
  404. }
  405. chopblanks(ss) char **ss;
  406. {
  407.   char *sp = *ss;
  408.   int n;
  409.   while(isspace(*sp) ) sp++;
  410.   *ss = sp;
  411.   
  412.   sp = *ss;
  413.   n = strlen(*ss);
  414.   sp = *ss+(n-1);
  415.   while(isspace(*sp)) { *sp = '\0'; sp--; }
  416.     
  417. }
  418.  
  419. /* ================================================================== */
  420. /* list of graphic objects */
  421. #define NOBJ 200
  422. static int obj_ref[NOBJ]; /* actually a unique reference int */ 
  423. static int obj_type[NOBJ]; /* t - text, m - menu, e -exec */
  424. static int n_obj = 0;
  425.  
  426. /* rets its ordering , or -1 if error */
  427. int registeritem(type, ref) char *type; int ref;
  428. {
  429.     int t , n;
  430.  
  431.    if (!strcmp(type,"TEXT")) {
  432.         t = 't';
  433.         }
  434.    else if (!strcmp(type,"MENU")) {
  435.         t = 'm';
  436.         }
  437.    else if (!strcmp(type,"EXEC")) {
  438.         t = 'e';
  439.         }
  440.    else { return(-1); }
  441.  
  442.     n = n_obj;
  443.     obj_ref[n]  = ref;
  444.     obj_type[n] = t;
  445.     n_obj++;
  446.     return (n);
  447. }
  448.  
  449. getitemcount() { return (n_obj); }
  450.  
  451. fetchitem (which, type, ref )
  452. int which; /* its ordering as ret from registeritem() */
  453. int  *ref; /* output */
  454. char *type; /* output */
  455. {
  456.    *ref = obj_ref[which];
  457.    switch (obj_type[which]) {
  458.         case 't': strcpy(type,"TEXT"); break;
  459.         case 'm': strcpy(type,"MENU"); break;
  460.         case 'e': strcpy(type,"EXEC"); break;
  461.         default : strcpy(type,"NONE"); return(0);  break;
  462.         }
  463.    return(1);
  464.         
  465. }
  466.  
  467. /* ================================================================== */
  468. /* storage for user's scripts and executables */
  469. #define NEX 80
  470. static char * d_ex[NEX];
  471. static int   n_ex  = 0;
  472.  
  473. /* rets id of script , else -1 */
  474. int savescript(ex) char *ex;
  475. {
  476.   int id;
  477.   d_ex[n_ex] = strdup ( ex );
  478.   id = n_ex;  n_ex++; 
  479.   return (id);
  480. }
  481.  
  482. getscript (id, ex) int id; char *ex;
  483. {
  484.   strcpy(ex, d_ex[id] );
  485. }
  486. execscript (ex) char *ex;
  487. {
  488.   char tfile[500];
  489.   char buf[LLEN];
  490.   FILE *f;
  491.  
  492.   tmpnam(tfile);
  493.   sprintf(buf, "%s > %s ", ex, tfile);
  494.  
  495.   system( buf );
  496.   f = fopen(tfile,"r");
  497.   if(f==NULL) { printf("cannot open %s \n", tfile); return; }
  498.  
  499.   while(NULL!= fgets(buf, LLEN, f)) printf("%s",buf);
  500.   fclose(f);
  501. }     
  502.  
  503. execcommand (ex,fhandle) char *ex; FILE **fhandle;
  504. {
  505.   char tfile[500];
  506.   char buf[LLEN];
  507.   FILE *f;
  508.  
  509.  
  510.   tmpnam(tfile);
  511.   sprintf(buf, "%s > %s ", ex, tfile);
  512.  
  513.   system( buf );
  514.   f = fopen(tfile,"r");
  515.   if(f==NULL) { printf("cannot open %s \n", tfile); *fhandle = NULL; return; }
  516.   *fhandle = f;
  517.  
  518. }
  519.  
  520. /* ================================================================== */
  521. /* storage for user's text */
  522. #define NTXT 80
  523. static char * d_text[NTXT];
  524. static int   n_txt = 0;
  525.  
  526. /* rets id of text, else -1 */
  527. int savetext(text) char *text;
  528. {
  529.   int id;
  530.   d_text[n_txt] = strdup ( text);
  531.   id = n_txt;  n_txt++; 
  532.   return (id);
  533. }
  534.  
  535. gettext (id, text) int id; char *text;
  536. {
  537.   strcpy(text, d_text[id] );
  538. }
  539. displaytext ( id) int id;
  540. {
  541.   char text[LLEN];
  542.   gettext(id, text);
  543.   printf("%s", text);
  544. }
  545.  
  546. /* ================================================================== */
  547. /* defines from DEFINE */
  548. /* sql directives and the expansion */
  549.  
  550. /* general sql directives */
  551. static char * d_cmd[] = { "FROMLIST", "SELECTLIST", "WHERELIST", "SORTLIST", "HEADING" };
  552. #define NW   ( sizeof(d_cmd)/sizeof(char *) )
  553. static char * d_mean[NW];
  554. static int   n_cmd = NW;
  555.  
  556. /* defines from DEFINE */
  557. #define MDEF 40
  558. static char * d_defvar[MDEF];
  559. static char * d_defval[MDEF];
  560. static int n_def = 0;
  561.  
  562. /* variables from SUB */
  563. #define NV 200
  564. static char * var_name[NV];
  565. static char * var_mean[NV];
  566. static char * var_kind[NV]; /* what list it's part of eg SELECT or WHERE */
  567. static char * var_fmt[NV]; /* string to format output as */
  568. static int   var_used[NV]; /* 1 if has user input */
  569. static int n_var = 0;
  570.  
  571. parsefile2 (filename) char *filename; 
  572. {
  573.  char buf[LLEN], tbuf[LLEN];
  574.  char vname[LLEN];
  575.  int id, i;
  576.  
  577.  if (NULL == (fstream= fopen(filename,"r"))) {
  578.      printf("parsefile2: Cannot open procfile [%s]\n", filename); 
  579.      exit(0);
  580.      }
  581.  
  582. for(i=0;i<NW;i++) {  d_mean[i] = NULL; }
  583.  
  584. for(i=0;i<NV;i++) { /* init */
  585.   var_name[i] = var_mean[i] = var_kind[i] = NULL; 
  586.   var_used[i] = 0;
  587.   var_fmt[i] = NULL;
  588.   }
  589.  
  590.  printf("<PRE>");
  591.  while( getword(buf)) {
  592.     if (buf[0]=='#') { 
  593.       if(dbg) fprintf(stderr,"comment word [%s]\n", buf);
  594.       flushline(); 
  595.     }
  596.     else if (!strcmp(buf,"HEADING")) {
  597.       getline(buf);
  598.       savedirective("HEADING", buf);
  599.       }
  600.     else if (!strcmp(buf,"SUB")) {
  601.       getword(vname); 
  602.       var_name[n_var] = strdup(vname);
  603.       getword(buf); /* kind */
  604.       var_kind[n_var] = strdup(buf);
  605.       getword(buf); /* AS */
  606.       getline(buf); /* meaning */
  607.       var_mean[n_var] = strdup(buf);
  608.       if(dd) printf("<li> FILE VAR [%s] [%s] [%s] \n", 
  609.                     var_name[n_var], var_kind[n_var], var_mean[n_var]);
  610.       n_var++;
  611.       }
  612.     else if (!strcmp(buf,"SQLPROG")) {
  613.         getline(tbuf);
  614.         sqlprogram = strdup(tbuf);
  615.         }
  616.     else if (!strcmp(buf,"DEFINE")) {
  617.        getword(tbuf);
  618.         sscanf(tbuf,"%s",buf);
  619.        d_defvar[n_def] = strdup(buf);
  620.        getline(tbuf);
  621.         sscanf(tbuf,"%s",buf);
  622.        d_defval[n_def] = strdup(buf);
  623.        if(dd) printf("<li> usrdefine [%s] [%s]\n", d_defvar[n_def], d_defval[n_def]);
  624.        n_def++;
  625.       }
  626.     else { /* save if is a sql directive */
  627.        getline(tbuf);
  628.         savedirective (buf, tbuf);
  629.  
  630.         }
  631.   }
  632.  printf("</PRE>");
  633.   fclose (fstream);
  634. }
  635.  
  636. /* ------------------------------------------------------------------ */
  637. /* returns the meaning of a SUB variable */
  638. lookupmean (var, meaning) char *var, *meaning;
  639. {
  640.     int i;
  641.    for (i=0;i<n_var;i++) 
  642.         if (!strcmp(var, var_name[i])) {
  643.           strcpy(meaning, var_mean[i]);
  644.           return(1);
  645.           }
  646.    return(0);        
  647. }
  648. /* ------------------------------------------------------------------ */
  649. /* updates the var_xxx structures with info from user */
  650. /* doesn't account for duplicate vars for now */
  651.  
  652. mergeall() 
  653. {
  654.    
  655.     int i, j, t, num;
  656.     char *vname;
  657.     char buf[LLEN]; /* contains all matches (comma-separated) for a variable */
  658.     int match[200], nm;
  659.     char sqlstr[LLEN];
  660.  
  661.     /* -- sub user inputs in the variables --- */
  662.     /* some vars (arrays) can have multiple userinput values */
  663.    for (i=0;i<n_var;i++) {
  664.         vname = var_name[i];
  665.         for (nm=0, t=0; t<n_u; t++) {
  666.           if (!strcmp(vname, u_vname[t])) {
  667.                  if (strlen(u_vval[t])>0) { /* don't bother if empty value */
  668.                    var_used[i] = 1;
  669.                    match[nm] = t; nm++;
  670.                    }
  671.                  }
  672.             }
  673.         if (nm>0) { /* build the match string */
  674.             buf[0]='\0';
  675.            for (j=0;j<nm;j++) {
  676.                 t = match[j];
  677.               if (u_vspecial[t]) { /* look up its meaning */
  678.                     char tbuf[LLEN];
  679.                     if (!lookupmean (u_vval[t], tbuf)) {
  680.                         strcpy(tbuf,"Undefined"); 
  681.                         printf("<li>UNDEFINED [%s]\n", u_vval[t]);
  682.                         }
  683.                else {
  684.                      if (j!=0) strcat(buf, ",");
  685.                     strcat(buf, tbuf);
  686.                     }
  687.                   }
  688.             else { /* just use the input */
  689.                    if (j!=0) strcat(buf, ",");
  690.                   strcat(buf, u_vval[t]);
  691.                }
  692.             }
  693.            substitute(&var_mean[i], buf);
  694.          }
  695.       }
  696.  
  697.   /* --- build the sql string from the pieces ---  */
  698.  
  699.      sqlstr[0] ='\0';
  700.      strcat (sqlstr," \" " );
  701.      strcat( sqlstr, SELECTKEYWORD);
  702.  
  703.        num = 0;
  704.      if( getdirective("SELECTLIST", buf)) {
  705.        strcat(sqlstr,  buf );
  706.          num = 1;
  707.         }
  708.     for (i=0;i<n_var;i++) {
  709.         if (var_used[i]) { 
  710.               if (!strcmp(var_kind[i],"SELECTLIST")) {
  711.                  if(num>0) strcat(sqlstr, ", ");
  712.              strcat(sqlstr, var_mean[i]);
  713.                  num++;
  714.                  }
  715.              }
  716.         }
  717.      if (num==0) { /* yikes..no user-selected values, & no default select list */
  718.          printf(" <H1> You must select field(s) to display. </H1> "); 
  719.          return; 
  720.          }
  721.  
  722.  
  723.      if( getdirective("FROMLIST", buf)) {
  724.        strcat(sqlstr, " FROM ");
  725.        strcat(sqlstr,  buf );
  726.          }
  727.  
  728.      num = 0;
  729.     strcat(sqlstr, " WHERE ");
  730.     for (i=0;i<n_var;i++) {
  731.           if (var_used[i]) {
  732.               if (!strcmp(var_kind[i],"WHERELIST")) {
  733.                  if(num>0) strcat(sqlstr, " AND ");
  734.              strcat(sqlstr, var_mean[i]);
  735.                  num++;
  736.               }
  737.            }
  738.         }
  739.      if( getdirective("WHERELIST", buf)) {
  740.        if (num>0) strcat(sqlstr, " AND  ");
  741.        strcat(sqlstr,  buf );
  742.         }
  743.  
  744.      if( getdirective("SORTLIST", buf)) {
  745.        strcat(sqlstr,  buf );
  746.         }
  747.  
  748.     strcat(sqlstr, " \" "); /* entire sql string is quoted */
  749.  
  750.      if(dd) printf("<b> SQL </b> <tt> %s </tt> <p> \n", sqlstr);
  751.  
  752.     stuffmenu("Here is the SQL Query ", sqlstr );
  753.  
  754.     strcat(sqlstr," ");
  755.    for(i=0;i<n_def;i++) {
  756.          char zz[LLEN];
  757.          sprintf(zz," \"%s %s\" ",d_defvar[i], d_defval[i]);
  758.          strcat(sqlstr,zz);
  759.          }
  760.  
  761.   if (getdirective("HEADING", buf))  printf("%s\n",buf);
  762.    printf("<P>");
  763.  
  764.     {{ char cmd[LLEN];
  765.         if (sqlprogram==0) {
  766.             printf("<H1> Sorry..I don't know what SQL program to run.");
  767.             printf("<p>SQLPROG is not specified! </H1>");
  768.             exit(0);
  769.             }
  770.         sprintf(cmd," %s %s ", sqlprogram, sqlstr);
  771.         /* stuffmenu("Here is the cmd ", cmd); */
  772.  
  773.         fflush(stdout);
  774.       system(cmd);
  775.     }}
  776.  
  777. }
  778.  
  779. savedirective(cmd, meaning) 
  780. char * cmd , *meaning;
  781. {
  782.    int i;
  783.  
  784.     for(i=0;i<NW;i++)  
  785.         if (!strcmp(cmd , d_cmd[i])) {
  786.          d_mean[i] = strdup(meaning); 
  787.             return(1);
  788.             break;
  789.         }
  790.     return(0);
  791. }
  792.  
  793. getdirective (cmd , meaning)
  794. char * cmd , *meaning;
  795. {
  796.     int i;
  797.     for (i=0;i<n_cmd;i++) 
  798.         if (!strcmp(d_cmd[i], cmd)) {
  799.             if(NULL==d_mean[i]) return (0);
  800.             strcpy(meaning, d_mean[i]);
  801.             return(1);
  802.           }
  803.     return(0);
  804. }
  805.  
  806.  
  807. /* substitute all occurences of $ in x1 with x2 */
  808. /* this means reallocing the string at x1 */
  809. substitute(x1, x2) char **x1, *x2; {
  810.     char buf[LLEN];
  811.     char *orig = *x1;
  812.     char *sp;
  813.  
  814.     /* printf("<p> sub [%s] inside [%s] ", x2, orig); */
  815.     sp = strchr(orig,'$');
  816.     if (sp==NULL) return;
  817.  
  818.     buf[0] = '\0';
  819.    
  820.     *sp ='\0';
  821.    strcat(buf,orig);  /* first portion */
  822.  
  823.    strcat(buf,x2);    /* substituted portion */
  824.  
  825.    sp++;
  826.     if(sp) {        /* end portion */
  827.       strcat(buf,sp);
  828.      }
  829.  
  830.    *x1 = strdup(buf);
  831.     /* printf("new string is [%s] ", *x1); */
  832. }
  833.  
  834. /* stuff some text into a menu */
  835. stuffmenu(title, string) char *title, *string;
  836. {
  837.        int n;
  838.          char *stringbuf;
  839.          char buf[LLEN];
  840.          char *ss, *s2, *s1;
  841.  
  842.  
  843.          stringbuf = strdup(string);
  844.          /* remove quotes */
  845.          s1 = strchr(stringbuf,  '\"'); if(s1) *s1 = ' ';
  846.          s1 = strrchr(stringbuf,  '\"'); if(s1) *s1 = ' ';
  847.  
  848.          printf("<FORM>");
  849.         printf("<SELECT NAME=\"sql-query\">\n" );
  850.         printf(" <OPTION>  %s \n", title);
  851.  
  852.        s1 = ss = stringbuf;
  853.        while(1) {
  854.              s2 = strchr(s1, ' ');
  855.              if(s2==NULL) break;
  856.              n = s2 - ss;
  857.           if (n > 80) {
  858.                 strncpy(buf,ss,n); buf[n]='\0';
  859.                 printf(" <OPTION>  %s\n", buf);
  860.                 ss = ++s2; if(ss==NULL) break;
  861.                 }
  862.           else {
  863.              s1 = s2+1;
  864.                 }
  865.  
  866.           }
  867.          if (ss) printf(" <OPTION>  %s\n", ss); /* trailing text */
  868.        printf("</SELECT><p>\n");
  869.          printf("</FORM>");
  870.  
  871.          fflush(stdout);
  872. }
  873.