Subversion Repositories wimsdev

Rev

Rev 5518 | Rev 6184 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*    Copyright (C) 1998-2003 XIAO, Gang of Universite de Nice - Sophia Antipolis
  2.  *
  3.  *  This program is free software; you can redistribute it and/or modify
  4.  *  it under the terms of the GNU General Public License as published by
  5.  *  the Free Software Foundation; either version 2 of the License, or
  6.  *  (at your option) any later version.
  7.  *
  8.  *  This program is distributed in the hope that it will be useful,
  9.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.  *  GNU General Public License for more details.
  12.  *
  13.  *  You should have received a copy of the GNU General Public License
  14.  *  along with this program; if not, write to the Free Software
  15.  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16.  */
  17.  
  18. /* Web mathematical exerciser */
  19.  
  20. #define WEBMATH 1
  21. #include "Lib/libwims.h"
  22. #include "wims.h"
  23. #include <sys/socket.h>
  24. #include <sys/un.h>
  25.  
  26. #define evalue strevalue
  27. char *robot_session="../tmp/robot";
  28. int robot_access=0,human_access=0;
  29. int user_error_nolog=0;
  30. char *good_agent[]={
  31.       "Mozilla","Netscape","Opera","WIMS",
  32.       "MSIE","Konqueror","Java"
  33. };
  34. #define good_agent_no (sizeof(good_agent)/sizeof(good_agent[0]))
  35.  
  36. char *bad_agent[]={ /* These are really bad agents: prohibited. */
  37.         "HTTrack","MemoWeb","Teleport","Offline","Wget","eCatch",
  38.       "Powermarks","EmailSiphon", "WebCopier"
  39. };
  40. #define bad_agent_no (sizeof(bad_agent)/sizeof(bad_agent[0]))
  41.  
  42. /* used for debugging */
  43. int debug=0;
  44.  
  45. char class_dir[MAX_FNAME+1]; /* directory name of this class */
  46.  
  47. struct {
  48.     char *name;
  49.     char *value;
  50. } user_variable[MAX_VAR_NUM];
  51. int user_var_no;
  52.  
  53. struct VAR_DEF {
  54.     char *name;
  55.     short int beg,end;
  56.     char allow, log_num, defined_in_parm, unused_padding;
  57. } var_def[MAX_VAR_NUM];
  58. int defined_var_total;
  59.  
  60.         /* Destinated to module error messages */
  61. WORKING_FILE m_file,svar_file,mcache[MAX_MCACHE];
  62. int mcachecnt;
  63.  
  64.         /* Limit for any data working files. */
  65. int WORKFILE_LIMIT=2048*1024;
  66.  
  67.         /* whether the user has defined language */
  68. int user_lang=0;
  69.  
  70.         /* for instex grouping */
  71. int instex_cnt=0, getwimstexsize=1;
  72. char instex_src[MAX_LINELEN+1], instex_fname[MAX_LINELEN+1];
  73. char *instex_processor="tex..gif";
  74.  
  75.         /* Cookie management */
  76. char cookiegot[256], cookieset[256], cookieheader[64]="WIMSUSER=";
  77.  
  78.         /* multipart boundary */
  79. char mpboundary[1024];
  80. int  deplen=0; /* length of deposit */
  81.  
  82. int confset=0; /* set to 1 if setvar for config */
  83.  
  84.         /* Operating mode: default, popup, raw, etc. */
  85. enum {mode_default, mode_popup, mode_raw} NAME_MODES;
  86. int mode=mode_default;
  87.  
  88.         /* Switch; notice subroutines wherether we are outputing. */
  89. int outputing;
  90.  
  91. char *home_module="home"; /* name of home module */
  92. extern char **environ;          /* table of environment variables */
  93. int module_defined=0;
  94.  
  95.         /* directory prefix buffers */
  96. char session_prefix[MAX_FNAME+1], s2_prefix[MAX_FNAME+1], module_prefix[MAX_FNAME+1];
  97.  
  98. char *stdinbuf;
  99. int sesrandomtab[MAX_SESRANDOM];        /* session random values */
  100. char multiexec_random[64];
  101. int executed_gotos; /* number of goto's executed. to check with GOTO_LIMIT. */
  102. int insert_no; /* number of instex, insplot, insPLOT. */
  103. int output_length; /* length of the output. */
  104. int isexam=0;   /* non-zero if request is exam */
  105. int simuxam=0;  /* exam is simulation */
  106. int is_multiexec=0;     /* for execredirected */
  107. int multiexec_index;
  108. int direct_datafile=0;
  109. int exec_is_module=0;
  110.   /* root directory of modules */
  111. char *module_dir="modules";
  112. int new_session=0; /* =1 if new session created */
  113. int good_httpd=0;       /* Whether the http server is intelligent */
  114. /* int internal_sql=0; */ /* for internal sql use */
  115. int direct_exec=0; /* calc routine is exected by exec if 1 */
  116. int print_precision=8; /* precision when printing real numbers */
  117. int session_serial; /* request serial for session control */
  118. int form_access=0;      /* identifies form access, for robot identification */
  119. int lastout_file=-1;    /* file to hold last output */
  120. char *instex_style="";          /* "": text "$": math "$$": displaymath */
  121. int instex_usedynamic=0;        /* always dynamic if 1 */
  122. int wrapexec=0;         /* if set to 1, change uid (nobody) to euid (wims).
  123.                          * if set to -1, change euid to uid when exec(). */
  124. int parm_restore=0;     /* Restoring saved parameters? */
  125. int exec_wait=1;        /* whether to wait for fork return */
  126. int execnt=0;           /* count executions */
  127. int readnest;           /* nested read count */
  128. int mfilecnt=0;         /* count working files */
  129. int forceresume=0;      /* force user to resume old request */
  130. int manageable=0;       /* whether the connection may be site manager
  131.                          * 0: no; 1: maybe; 2: sure */
  132. int ismhelp=0;          /* 1 if session is in mhelp. */
  133. int getvar_len;         /* length of the last-got variable. */
  134. int noout=0;            /* if set to 1 then output is skipped */
  135. char tmp_dir[MAX_FNAME+1];      /* temporary directory */
  136. char *bin_dir="bin";    /* directory containing executable scripts and programs. */
  137. char cwdbuf[MAX_FNAME+1];       /* store current working directory */
  138. char var_hacking=0;     /* Trying to hack a variable? */
  139. char *tmp_debug="no";
  140. char ins_alt[MAX_LINELEN+1];    /* dynamic insertion alternative text */
  141. char *devel_modules="close";    /* whether to open devel modules */
  142. int isclassmodule=0;    /* 1 if the module is class module */
  143. int isdevelmodule=0;    /* development module? */
  144. int setcookie=0;        /* 1 if need to set cookie */
  145. int killpid=0;          /* pid of process to kill by alarm */
  146. char *mathalign_sup1, *mathalign_sup2;  /* see mathalign_base */
  147. int substnest=0;        /* nesting level of substit() */
  148. int exodepOK=1;
  149. long int startmtime;    /* start time in milliseconds */
  150. long int startmtime2;   /* start time in microseconds */
  151. int backslash_insmath=0;        /* \(...) substitution? */
  152. char examlogf[MAX_FNAME+1];     /* examlog file name */
  153. char examlogd[MAX_FNAME+1];     /* examlog file name */
  154. char exam_sheetexo[32]; /* sheet data of an exam */
  155. char loadavg[64];
  156.                         /* user file variable access control. */
  157. char *var_readable, *var_writable, *var_nr, *var_nw, *var_pfx;
  158. int hostcquota;
  159. int var_noexport;       /* do not export variable */
  160.  
  161. char tmplbuf[MAX_LINELEN+1];    /* for temporary uses not thru subroutines. */
  162.  
  163. struct tm *now, Now;    /* time of request */
  164. time_t nowtime, limtime, limtimex;
  165. char nowstr[32];
  166.  
  167.         /* Resource limits. Capital names are reserved by system. */
  168. int rlimit_cpu=20;      /* cpu time in seconds */
  169. int rlimit_fsize=8388608;/* file size */
  170. int rlimit_as=614457600;/* virtual memory size */
  171. int rlimit_data=204857600;/* data segment size; maxima requires a lot (must be lower than rlimit_as)*/
  172. int rlimit_stack=2097152;/* stack size */
  173. int rlimit_core=0;      /* core dump size */
  174. int rlimit_rss=16777216;        /* resident size */
  175. int rlimit_nproc=1024;  /* number of processes */
  176. int rlimit_nofile=512;  /* number of open files */
  177. int rlimit_memlock=2097152;/* locked-in-memory address space */
  178.  
  179. char *var_str; /* malloc'ed buffer to hold translated query_string */
  180.  
  181.         /* buffer to hold module's variable definition file, malloc'ed. */
  182. char *var_def_buf;
  183.  
  184.         /* job_identifier is even a reserved variable name */
  185. char job_identifier[32];
  186.  
  187.   /* site manager definition IPv4 IPv6*/
  188. char *manager_site="127.0.0.1 ::1";
  189. int   manager_https=0;
  190.  
  191.         /* sheet and exercise information */
  192. int wims_sheet=0,wims_exo=0;
  193.  
  194.         /* Form method: get or post */
  195. char *default_form_method="post";
  196.  
  197.         /* Je suis maintenant oblige de passer a l'anglais
  198.          * pour la langue de defaut. */
  199. char lang[16]="en";
  200. char available_lang[MAX_LANGUAGES][4]={"en","fr"};
  201. int available_lang_no=2;
  202. char pre_language[4]="";
  203. char *protocol="http"; /* http or https */
  204.  
  205.         /* check for coordinate input. This will mean that
  206.          * the request is manual, but not robot. */
  207. int coord_input=0;
  208.  
  209.         /* These are readonly environment variable names */
  210.         /* special parm used for special cmds (getins, etc). */
  211. char *ro_name[]={
  212.       "cmd" ,
  213.       "empty",
  214.       "lang" ,
  215.       "module" ,
  216.       "session" ,
  217.       "special_parm",
  218.       "special_parm2",
  219.       "special_parm3",
  220.       "special_parm4",
  221.       "useropts" ,
  222.       "wims_session",
  223.       "wims_subsession",
  224.       "wims_window",
  225.       "worksheet"
  226. };
  227. enum {
  228.     ro_cmd, ro_empty, ro_lang, ro_module, ro_session, ro_special_parm,
  229.       ro_special_parm2, ro_special_parm3, ro_special_parm4, ro_useropts, ro_wsession, ro_subsession, ro_win, ro_worksheet
  230. } RO_NAMES;
  231. #define RO_NAME_NO (sizeof(ro_name)/sizeof(ro_name[0]))
  232.  
  233. int cmd_type;
  234. char *commands[]={
  235.     "intro" , "new" , "renew" , "reply" , "config" , "hint" , "help" ,
  236.       "resume", "next", "getins", "getframe", "getfile", "close", "ref"
  237. };
  238. enum {
  239.     cmd_intro, cmd_new, cmd_renew, cmd_reply, cmd_config, cmd_hint, cmd_help,
  240.       cmd_resume, cmd_next, cmd_getins, cmd_getframe, cmd_getfile, cmd_close,
  241.       cmd_ref
  242. }COMMANDS;
  243. #define CMD_NO (sizeof(commands)/sizeof(commands[0]))
  244.  
  245.         /* stat=0: saved variables */
  246.         /* all names starting with wims_priv_ are also internal. */
  247. struct {
  248.     char *name; int stat;
  249. } internal_name[]={
  250.       {"accessright",   1},     /* right to access commercial resources */
  251.       {"caller",        1},     /* caller session */
  252.       {"check",         1},     /* for exam check use */
  253.       {"class",         1},
  254.       {"class_examlog", 1},
  255.       {"class_exolog",  1},
  256.       {"class_limit",   1},
  257.       {"class_quota",   1},
  258.       {"class_regpass", 1},
  259.       {"class_user_limit",1},
  260.       {"classdir",      1},
  261.       {"classname",     1},
  262.       {"devel_modules", 1},
  263.       {"developer",     1},
  264.       {"doc_quota",     1},
  265.       {"doc_regpass",   1},
  266.       {"email",         1},
  267.       {"exo",           0},     /* exercise number */
  268.       {"exoption",      1},     /* exercise option */
  269.       {"firstname",     1},
  270.       {"forum_limit",   1},
  271.       {"home",          1},
  272.       {"institutionname",       1},
  273.       {"isexam",        0},     /* whether the sheet is an exam sheet */
  274.       {"ismanager",     0},
  275.       {"lastname",      1},
  276.       {"mode",          0},     /* operating mode */
  277.       {"module_start_time",0},
  278.       {"now",           1},     /* date and time, yyyymmdd.hh:mm:ss */
  279.       {"nowseconds",    1},     /* date and time, seconds since EPOCH */
  280.       {"nr",            1},     /* non-readable variables in user file, words */
  281.       {"nw",            1},     /* non-writable variables in user file, words */
  282.       {"otherclass",    1},     /* Remember other logins */
  283.       {"participate",   1},     /* superclass definition */
  284.       {"prefix",        1},     /* user file prefix */
  285.       {"protocol",      0},     /* http protocol */
  286.       {"rafale",        0},     /* rapidfire request information */
  287.       {"readable",      1},     /* readable variables in user file, words */
  288.       {"realuser",      1},     /* real user for supervisor in gateway */
  289.       {"req_time",      0},     /* time of the request */
  290.       {"sclassdir",     1},
  291.       {"scorereg",      0},     /* score registration flag */
  292.       {"sequence", 0},  /*sequence number */
  293.       {"sescookie",     1},     /* session cookie */
  294.       {"sesdir",        1},
  295.       {"session_serial",0},     /* request serial in the session */
  296.       {"session_start_time",0},
  297.       {"sheet",         0},     /* sheet number */
  298.       {"sup_secure",    1},     /* secure level of supervisor */
  299.       {"superclass",    1},     /* superclass code */
  300.       {"superclass_quota",      1},
  301.       {"supertype",     1},     /* superclass type */
  302.       {"supervise",     1},     /* superclass definition */
  303.       {"supervisor",    1},     /* real name of the supervisor */
  304.       {"supervisormail",1},     /* email of supervisor */
  305.       {"trustfile",     1},     /* trusted files in special adm modules */
  306.       {"useropts",      1},     /* user options */
  307.       {"writable",      1},     /* writable variables in user file, words */
  308. };
  309. #define INTERNAL_NAME_NO (sizeof(internal_name)/sizeof(internal_name[0]))
  310.  
  311. char *httpd_vars[]={
  312.       "HTTP_ACCEPT",
  313.       "HTTP_ACCEPT_CHARSET",
  314.       "HTTP_ACCEPT_LANGUAGE",
  315.       "HTTP_COOKIE",
  316.       "HTTP_HOST",
  317.       "HTTP_USER_AGENT",
  318.       "HTTPS",
  319.       "QUERY_STRING",
  320.       "REMOTE_HOST",
  321.       "REMOTE_ADDR",
  322.       "REMOTE_PORT",
  323.       "REQUEST_METHOD",
  324.       "SCRIPT_NAME",
  325.       "SERVER_NAME",
  326.       "SERVER_SOFTWARE",
  327.       "SERVER_PROTOCOL"
  328. };
  329. #define HTTPD_VAR_NO (sizeof(httpd_vars)/sizeof(httpd_vars[0]))
  330.  
  331.         /* security: these variables will not be visible to
  332.          * child processes */
  333. char *unsetvars[]={
  334.         "DOCUMENT_ROOT","SERVER_SIGNATURE","SERVER_SOFTWARE",
  335.       "UNIQUE_ID","HTTP_KEEP_ALIVE","SSL_SESSION_ID"
  336. };
  337. #define unsetvarcnt (sizeof(unsetvars)/sizeof(unsetvars[0]))
  338.  
  339. enum {httpd_apache, httpd_wims};
  340. int httpd_type=httpd_apache;
  341.  
  342. char *remote_addr="";   /* storing for performance */
  343. char *remote_host="";
  344.  
  345. char ref_name[2048], ref_base[2048];
  346.  
  347. void put_special_page(char *pname);
  348. void useropts(void);
  349.  
  350. #include "lines.c"
  351. #include "var.c"
  352. #include "config.c"
  353. #include "cleaning.c"
  354. #include "files.c"
  355. #include "pedia.c"
  356. #include "evalue.c"
  357. #include "test.c"
  358. #include "compare.c"
  359. #include "html.c"
  360. #include "mathml.c"
  361. #include "texmath.c"
  362. #include "rawmath.c"
  363. #include "insmath.c"
  364. #include "matrix.c"
  365. #include "score.c"
  366. #include "calc.c"
  367. #include "exec.c"
  368. #include "auth.c"
  369. #include "variables.c"
  370. #include "exam.c"
  371. #include "log.c"
  372.  
  373.         /* Make certain httpd variables readable by modules */
  374. void take_httpd_vars(void)
  375. {
  376.     int i;
  377.     char *p, buf[MAX_NAMELEN+1];
  378.     var_noexport=1;
  379.     for(i=0;i<HTTPD_VAR_NO;i++) {
  380.         snprintf(buf,sizeof(buf),"httpd_%s",httpd_vars[i]);
  381.         if((p=getenv(httpd_vars[i]))!=NULL) setvar(buf,p);
  382.     }
  383.     var_noexport=0;
  384.    
  385.     for(i=0;i<unsetvarcnt;i++) unsetenv(unsetvars[i]);
  386.      /* IPv4 IPv6*/
  387.     p=getenv("REMOTE_ADDR");if(p!=NULL && (strcmp(p,"127.0.0.1")==0 || strcmp(p,"::1")==0)) human_access=1;
  388.     p=getenv("HTTP_REFERER"); if(p!=NULL && *p!=0) setvar("wims_referer",p);
  389. }
  390.  
  391. void cookie2session(void)
  392. {
  393.     char cksession[64], psession[32], *ckey, *p;
  394.     char nbuf[MAX_FNAME+1];
  395.  
  396.     if(mode==mode_popup) return;
  397.     if(cookiegot[0]==0 || ro_cmd==cmd_close) {
  398.         ckset: cookiegot[0]=0; setcookie=1; return;
  399.     }
  400.     p=getvar("special_parm");
  401.     if(p!=NULL && strcmp(p,"ignorecookie")==0) return;
  402.     mystrncpy(cksession,cookiegot,sizeof(cksession));
  403.     ckey=strchr(cksession,'-');
  404.     if(ckey==NULL) goto ckset; else *ckey++=0;
  405.     p=getvar("wims_session"); if(p==NULL) p="";
  406.     if(strstr(p,"new")!=NULL) goto ckset;
  407.     mystrncpy(psession,p,sizeof(psession));
  408.     p=strchr(psession,'_'); if(p!=NULL) *p=0;
  409.     if(psession[0]!=0) {
  410.         if(strcmp(psession,cksession)==0) return;
  411.         if(session_exists(psession)) goto ckset;
  412.         if(session_exists(cksession)) goto change;
  413.     }
  414.     else {
  415.         if(!session_exists(cksession)) return;
  416.         change:
  417.         p=getenv("HTTPS");
  418.         if(p!=NULL && strcasecmp(p,"on")==0) goto ckset;
  419.         mkfname(nbuf,"%s/%s/var",session_dir,cksession);
  420.         getdef(nbuf,"w_wims_ismanager",tmplbuf);
  421.         if(tmplbuf[0]!=0 && tmplbuf[0]!='0') goto ckset;
  422.         getdef(nbuf,"w_wims_protocol",tmplbuf);
  423.         if(strcasecmp(tmplbuf,"https")==0) goto ckset;
  424.         mkfname(nbuf,"%s/%s/var.stat",session_dir,cksession);
  425.         getdef(nbuf,"wims_user",tmplbuf);
  426.         if(tmplbuf[0]!=0) goto ckset;
  427.         force_setvar(ro_name[ro_session],cksession);
  428.         setsesdir(cksession);
  429.         force_setvar("wims_subsession","");
  430.         session_serial=0;
  431.     }
  432. }
  433.  
  434. void determine_font(char *l)
  435. {
  436.     int i;
  437.    
  438.     if(l==NULL || *l==0) return;
  439.     for(i=0;i<charname_no && memcmp(charname[i].name,l,2);i++);
  440.     if(i<charname_no) setvar("wims_main_font",charname[i].font);
  441. }
  442.  
  443. void determine_dirn(char *l)
  444. {
  445.     int i;
  446.    
  447.     if(l==NULL || *l==0) return;
  448.     for(i=0;i<dirnname_no && memcmp(dirnname[i].name,l,2);i++);
  449.     if(i<dirnname_no) setvar("wims_main_dirn",dirnname[i].dirn);
  450. }
  451.  
  452. void predetermine_language(void)
  453. {
  454.     char *p;
  455.     int i,n;
  456.  
  457.     if(pre_language[0]!=0) p=pre_language;
  458.     else p=getenv("HTTP_ACCEPT_LANGUAGE");
  459.     if(p!=NULL && strlen(p)>=2) {
  460.       for(i=0;i<available_lang_no && memcmp(p,available_lang[i],2)!=0;i++);
  461.       if(i<available_lang_no) goto lend;
  462.     }
  463.     p=getenv("HTTP_USER_AGENT");
  464.     if(p!=NULL && strlen(p)>=5) {
  465.         char *q;
  466.         if((q=strchr(p,'['))!=NULL && islower(*(q+1)) && islower(*(q+2)) && *(q+3)==']') {
  467.             char bb[4];
  468.             bb[0]=*(q+1);bb[1]=*(q+2);bb[2]=0;
  469.             for(i=0;i<available_lang_no && memcmp(bb,available_lang[i],2)!=0;i++);
  470.             if(i<available_lang_no) {
  471.                 memmove(lang,bb,2); lang[2]=0;
  472.                 goto lend2;
  473.             }
  474.         }
  475.     }
  476.     p=getenv("HTTP_HOST"); if(p==NULL) goto lend2;
  477.     n=strlen(p); if(n<=3 || *(p+n-3)!='.') goto lend2;
  478.     p=p+n-2;
  479.     for(i=0;i<available_lang_no && memcmp(p,available_lang[i],2)!=0;i++);
  480.     if(i<available_lang_no) {
  481.         lend:   memmove(lang,p,2); lang[2]=0;
  482.         lend2:  determine_font(lang);determine_dirn(lang);
  483.     }
  484. }
  485.  
  486.         /* print a special page */
  487. void put_special_page(char *pname)
  488. {
  489.     determine_font(lang);
  490.     determine_dirn(lang);
  491.     phtml_put_base(mkfname(NULL,"%s.phtml.%s",pname,lang),0);
  492.     write_logs();free(var_str);
  493. }
  494.  
  495.         /* check whether the connection is a site manager. */
  496. void manager_check(void)
  497. {
  498.     char *p, *pp, buf[16];
  499.     struct stat confstat;
  500.     int i;
  501.    
  502.     manageable=0;
  503.     if(robot_access || *manager_site==0 || checkhost(manager_site)<1)
  504.       goto mend;
  505.     if(manager_https) {
  506.         p=getenv("HTTPS");
  507.         if(p==NULL || strcmp(p,"on")!=0) goto mend;
  508.     }
  509.  /* IPv4 IPv6*/
  510.     if(strcmp(remote_addr,"127.0.0.1")==0 || strcmp(remote_addr,"::1")==0) {
  511.         int port, port2;
  512.         char tester[128];
  513.         p=getenv("REMOTE_PORT"); if(p==NULL) goto mend;
  514.         port=atoi(p); if(port<1024 || port>65535) goto mend;
  515.         p=getenv("SERVER_PORT"); if(p==NULL) goto mend;
  516.         port2=atoi(p); if(port2>=10000 || port2<=0) goto mend;
  517.                 /* this is very non-portable */
  518.         manageable=1;
  519.         accessfile(tmplbuf,"r","/proc/net/tcp");
  520.         snprintf(tester,sizeof(tester)," 0100007F:%04X 0100007F:%04X ",
  521.                  port,port2);
  522.         p=strstr(tmplbuf,tester);
  523.         if(p!=NULL) {
  524.             pp=strchr(p,'\n'); if(pp!=NULL) *pp=0;
  525.             if(strlen(p)>=75) {
  526.                 p=find_word_start(p+70); *find_word_end(p)=0;
  527.                 if(atoi(p)==geteuid()) manageable=2;
  528.             }
  529.         }
  530.     }
  531.     else manageable=1;
  532.     i=stat(config_file,&confstat);
  533.     if(i==0 && manageable>0 && (confstat.st_mode&(S_IRWXO|S_IRWXG))!=0) manageable=-1;
  534.     if(manageable>0 && !trusted_module()) manageable=0;
  535.     if(manageable==1) {
  536.         accessfile(tmplbuf,"r","%s/.manager",session_prefix);
  537.         if(strstr(tmplbuf,"yes")!=NULL) manageable=2;
  538.     }
  539.     if(manageable==1) {
  540.         p=getvar(ro_name[ro_module]);
  541.         if(p!=NULL && strncmp(p,"adm/manage",strlen("adm/manage"))==0) {
  542.             struct stat pstat;
  543.             if(stat("../log/.wimspass",&pstat)==0) {
  544.                 if((S_IFMT&pstat.st_mode)!=S_IFREG ||
  545.                    ((S_IRWXO|S_IRWXG)&pstat.st_mode)!=0)
  546.                   manageable=-2;
  547.             }
  548.         }
  549.     }
  550.     mend:
  551.     mystrncpy(buf,int2str(manageable),sizeof(buf));
  552.     force_setvar("wims_ismanager",buf);
  553.     if(manageable>=2) {
  554.         struct rlimit rlim;
  555.         rlimit_cpu*=10;
  556.         rlim.rlim_cur=rlim.rlim_max=rlimit_cpu;
  557.         setrlimit(RLIMIT_CPU,&rlim);
  558.         mystrncpy(buf,int2str(rlimit_cpu),sizeof(buf));
  559.         setvar("wims_cpu_limit",buf);
  560.         initalarm();
  561.     }
  562. }
  563.  
  564.         /* check for robot access */
  565. void robot_check(void)
  566. {
  567.     char *ua, *p, *ses, *c, *mod;
  568.     int i;
  569.  
  570.     if(human_access) return;
  571.     mod=getvar(ro_name[ro_module]);
  572.     if(mod!=NULL && strcmp(mod,"adm/raw")==0) return;
  573.     ses=getvar(ro_name[ro_session]);
  574.         /* user has valid session; OK */
  575.     if(ses!=NULL && strncmp(ses,robot_session,strlen(robot_session))!=0
  576.        && strchr(ses,'/')==NULL
  577.        && ftest(mkfname(NULL,"%s/%s",s2_dir,ses))==is_dir)
  578.       return;
  579.     ua=getenv("HTTP_USER_AGENT"); if(ua==NULL) ua="";
  580.     ua=find_word_start(ua);
  581.     if(strncasecmp(ua,"Mozilla",strlen("Mozilla"))==0 &&
  582.        (p=strstr(ua,"compatible"))!=NULL)
  583.       ua=find_word_start(find_word_end(p));
  584.     if(*ua) {
  585.         for(i=0;i<good_agent_no
  586.             && strncasecmp(ua,good_agent[i],strlen(good_agent[i]));i++);
  587.         if(i<good_agent_no) return;
  588.         for(i=0;i<bad_agent_no
  589.             && strstr(ua,bad_agent[i])==NULL;i++);
  590.         if(i<bad_agent_no) user_error("trapped");
  591.     }
  592.     force_setvar(ro_name[ro_session],robot_session);
  593.     setsesdir(robot_session);
  594.     c=getvar(ro_name[ro_cmd]);
  595.     robot_access=1;
  596.     if(c!=NULL && strcmp(c,"new") && strcmp(c,"intro")) {
  597.         force_setvar(ro_name[ro_cmd],"robot_error");
  598.         nph_header(450); put_special_page("robot");
  599.         flushoutput(); flushlog(); exit(0);
  600.     }
  601. }
  602.  
  603.         /* type=0: ordinary; type=1: multipart/form-data */
  604. void parse_query_string(int len, int type)
  605. {
  606.     int i,j,l,v,cmd_defined;
  607.     int parenth=-1, ll, lb, dlen;
  608.     char *start, *p, *p1, *pt, *b1="";
  609.    
  610.     cmd_defined=0;
  611.     setvar("wims_subsession","");
  612.     ll=lb=0;
  613.     if(type) {
  614.         ll=strlen(mpboundary);
  615.         start=strstr(var_str,mpboundary);
  616.         if(start==NULL) start=var_str+strlen(var_str);
  617.         if(strstr(var_str,"\r\n\r\n")!=NULL) b1="\r\n\r\n";
  618.         else b1="\n\n";
  619.         lb=strlen(b1);
  620.     }
  621.     else start=var_str;
  622.     for(v=0, p1=start;p1<var_str+len;p1+=l) {
  623.         if(type) {
  624.             char *p2, *p3, *p4, *p5;
  625.             p2=p1+ll; p3=memstr(p2,mpboundary,var_str+len-p2); l=p3-p1;
  626.             p=memstr(p2,b1,var_str+len-p2); if(p>=p3) continue;
  627.             p+=lb; if(p3<var_str+len) {
  628.                 while(*p3!='\n' && p3>p2) p3--; *p3=0;
  629.                 p3--; if(*p3=='\r') *p3=0;
  630.             }
  631.             dlen=p3-p;
  632.             p2=memstr(p2,"name=",p3-p2); if(p2>=p3) continue;
  633.             p2+=strlen("name="); if(*p2=='"') p2++;
  634.             for(p3=p2; myisalnum(*p3) || strchr("._",*p3)!=NULL; p3++);
  635.             if(p3==p2) continue;
  636.             if(p3-p2==strlen("wims_deposit") &&
  637.                strncmp(p2,"wims_deposit",p3-p2)==0) {
  638.                 p4=memstr(p1,"filename=",p-p1); if(p4<p) {
  639.                     p4+=strlen("filename="); if(*p4=='"') {
  640.                         p4++; p5=strchr(p4,'"');
  641.                         if(p5==NULL || p5-p4>=MAX_FNAME) goto emptyquote;
  642.                     }
  643.                     else {
  644.                         emptyquote:
  645.                         for(p5=p4; p5<p && !isspace(*p5) &&
  646.                             strchr(";\"~#*?=,'",*p5)==NULL; p5++);
  647.                     }
  648.                     if(p5>p4) {
  649.                         *p5=0;
  650.                         for(p5--;
  651.                             p5>=p4 && !isspace(*p5) && strchr("/\\:",*p5)==NULL;
  652.                             p5--);
  653.                         if(p5>=p4) p4=p5+1; if(*p4==0) goto noname;
  654.                         if(strstr(p4,"..")!=NULL || *p4=='.')
  655.                           p4="noname.file";
  656.                         setvar("wims_deposit",p4);
  657.                     }
  658.                     else {
  659.                         noname: setvar("wims_deposit","noname.file");
  660.                     }
  661.                 }
  662.                 deplen=dlen;
  663.             }
  664.             *p3=0; l-=p2-p1; p1=p2;
  665.         }
  666.         else {
  667.             p1=find_word_start(p1);
  668.             l=strlen(p1)+1; p=strchr(p1,'=');
  669.             if(p==NULL) p=p1+strlen(p1);
  670.             if(*p==0 && l>1) {
  671.                 user_variable[v].name="no_name";
  672.                 user_variable[v].value=p1;
  673.                 coord_input=1;
  674.                 goto nnext;
  675.             }
  676.             *p++=0;
  677.         }
  678.                 /* empty name or empty value: ignore */
  679.         if(*p1==0 || *p==0) continue;
  680.                 /* We do not treat names containing '.' */
  681.         for(pt=strchr(p1,'.'); pt; pt=strchr(++pt,'.')) *pt='_';
  682.                 /* Restrictions on variable names */
  683.         for(pt=p1; myisalnum(*pt) || *pt=='_'; pt++);
  684.         if(*pt) continue;
  685.         if(strcmp(p1,"wims_deposit")!=0) _tolinux(p);
  686.                 /* This is a restriction:
  687.                  * Every parameter must have matching parentheses. */
  688.         if(parenth==-1 && strncmp(p1,"freepar_",strlen("freepar_"))!=0
  689.            && strcmp(p1,"wims_deposit")!=0
  690.            && check_parentheses(p,1)) parenth=v;
  691.         if(strcmp(p1,"special_parm")==0 && strcmp(p,"wims")==0)
  692.           human_access=1;
  693.         j=search_list(ro_name,RO_NAME_NO,sizeof(ro_name[0]),p1);
  694.         if(j>=0) {
  695.             if(j==ro_session) {
  696.                 p=find_word_start(p); *find_word_end(p)=0;
  697.                 if(strlen(p)>MAX_SESSIONLEN) continue;
  698.                 if(strcmp(p,robot_session)==0) p="";
  699.                 if(strcasecmp(p,"popup")==0) {
  700.                     mode=mode_popup;
  701.                     force_setvar("wims_mode","popup");
  702.                     force_setvar("session","");
  703.                     continue;
  704.                 }
  705.             }
  706.             if(j==ro_module) module_defined=1;
  707.             if(j==ro_cmd) {
  708.                 p=find_word_start(p); *find_word_end(p)=0;
  709.                 if(strlen(p)>16) continue;
  710.                 cmd_defined=1;
  711.             }
  712.             if(j==ro_lang) {
  713.                 if(strlen(p)!=2) continue;
  714.                 for(i=0;i<available_lang_no && strcmp(available_lang[i],p)!=0;i++);
  715.                 if(i<available_lang_no) {user_lang=1; ovlstrcpy(lang,p);}
  716.                 else continue;
  717.             }
  718.             /* strip leading and trailing '/'s in module name */
  719.             if(j==ro_module) {
  720.                 p=find_word_start(p); *find_word_end(p)=0;
  721.                 while(*p=='/') p++;
  722.                 while(*p!=0 && *(p+strlen(p)-1)=='/') *(p+strlen(p)-1)=0;
  723.                 if(strlen(p)>MAX_MODULELEN) continue;
  724.             }
  725.             setvar(p1,p);
  726.             if(j==ro_session && mode!=mode_popup) {
  727.                 char *pp, *pr;
  728.                 char buf[1024];
  729.                 mystrncpy(buf,p,sizeof(buf));
  730.                 if((pp=strchr(buf,'.'))!=NULL) {
  731.                     *pp++=0; session_serial=atoi(pp);
  732.                     if(pp<0) pp=0;
  733.                 }
  734.                 else session_serial=0;
  735.                 pp=strchr(buf,'_');
  736.                 if(pp!=NULL && (pr=strstr(pp,"_mhelp"))!=NULL) {
  737.                     *pr=0; ismhelp=1; lastout_file=-1;
  738.                     setvar("wims_inssub","mh");
  739.                 }
  740.                 force_setvar("wims_session",buf);
  741.                 if(pp!=NULL) force_setvar("wims_subsession",pp);
  742.             }
  743.             continue;
  744.         }
  745.         user_variable[v].name=p1;
  746.         user_variable[v].value=p;
  747. nnext:  v++; if(v>=MAX_VAR_NUM) user_error("too_many_variables");
  748.     }
  749.     user_var_no=v;
  750.     if(parenth>=0) {
  751.         char buf[16];
  752.         mystrncpy(buf,int2str(user_var_no),sizeof(buf));
  753.         setvar("user_var_no",buf);
  754.         for(i=0;i<user_var_no;i++) {
  755.             snprintf(buf,sizeof(buf),"name%d",i);
  756.             setvar(buf,user_variable[i].name);
  757.             snprintf(buf,sizeof(buf),"value%d",i);
  758.             setvar(buf,user_variable[i].value);
  759.         }
  760.         mystrncpy(buf,int2str(parenth),sizeof(buf));
  761.         setvar("bad_parentheses",buf);
  762.         user_error("unmatched_parentheses");
  763.     }
  764.     p=getenv("SCRIPT_NAME");
  765.     if(p!=NULL && (p=strstr(p,"/getfile/"))!=NULL) {
  766.         p+=strlen("/getfile/");
  767.         force_setvar(ro_name[ro_cmd],commands[cmd_getfile]);
  768.         force_setvar("special_parm",p);
  769.         cmd_defined=1;
  770.     }
  771.     if(module_defined && !cmd_defined) setvar(ro_name[ro_cmd],commands[cmd_intro]);
  772.     robot_check(); cookie2session();
  773. }
  774.  
  775.         /* parse special commands */
  776. void special_cmds(void)
  777. {
  778.     char *c, *p;
  779.     int i;
  780.     long int l=-1;
  781.    
  782.     c=getvar(ro_name[ro_cmd]);
  783.     if(c==NULL || *c==0) {  /* no module name nor command */
  784.         setvar(ro_name[ro_module],home_module);
  785.         setvar(ro_name[ro_cmd],commands[cmd_new]);
  786.         return;
  787.     }
  788.     for(i=0;i<CMD_NO && strcmp(commands[i],c)!=0; i++);
  789.     switch(i) {
  790.         case cmd_intro: {
  791.             set_module_prefix();
  792.             default_form_method="get";
  793.             if(ftest(mkfname(NULL,"%s/%s",module_prefix,intro_file))<0) {
  794.                 force_setvar(ro_name[ro_cmd],commands[cmd_new]);
  795.                 return;
  796.             }
  797.             p=getvar("wims_session");
  798.             if(p!=NULL && *p!=0) {
  799.                 if(set_session_prefix()==0) check_session();
  800.                 else {
  801.                     trap_check(p);
  802.                     if(strchr(p,'_')!=NULL && strchr(p,'/')==NULL) {
  803.                         get_static_session_var();
  804.                     }
  805.                 }
  806.             }
  807.             /* determine http protocol name. How to detect? */
  808.             p=getenv("HTTPS"); if(p!=NULL && strcmp(p,"on")==0) {
  809.                 protocol="https"; set_protocol();
  810.             }
  811.             force_setvar("wims_protocol",protocol);
  812.             determine_font(lang);
  813.             determine_dirn(lang);
  814.             main_phtml_put(intro_file); debug_output();
  815.             introend: write_logs();free(var_str);
  816.             delete_pid(); exit(0);
  817.         }
  818.         case cmd_ref: {
  819.             set_module_prefix();
  820.             default_form_method="get";
  821.             p=getvar("wims_session");
  822.             if(p!=NULL && *p!=0) {
  823.                 if(set_session_prefix()==0) check_session();
  824.                 else trap_check(p);
  825.             }
  826.             determine_font(lang);
  827.             determine_dirn(lang);
  828.             main_phtml_put(ref_file); goto introend;
  829.         }
  830.         case cmd_getins: {
  831.             c=getvar(ro_name[ro_special_parm]);
  832.             if(c==NULL || *c==0) {
  833.                 user_error_nolog=1; user_error("no_insnum");
  834.             }
  835.             if(*c=='/' || strstr(c,"..")!=NULL) goto badins;
  836.             set_session_prefix();
  837.             if(strstr(session_prefix,"robot")!=NULL) exit(0);
  838.             l=filelength("%s/%s",s2_prefix,c);
  839.             if(l<0) {
  840.                 badins: user_error_nolog=1; user_error("bad_insnum");
  841.             }
  842.             {
  843.                 char *fmt;
  844.                 fmt=strchr(c,'.');
  845.                 if(fmt==NULL) {
  846.                     user_error_nolog=1; user_error("bad_insnum");
  847.                 }
  848.                 else fmt++;
  849.                
  850.                 nph_header(200);
  851. /* insert format problem; bricolage */
  852.                 printf("Content-type: image/%s\r\n\
  853. Content-length: %ld\r\n\r\n",fmt,l);
  854.                 catfile(stdout,"%s/%s",s2_prefix,c); exit(0);
  855.             }
  856.         }
  857.         case cmd_getfile: {
  858.             char fname[MAX_FNAME+1];
  859.             c=getvar(ro_name[ro_special_parm]);
  860.             if(c==NULL || *c==0) {
  861.                 user_error_nolog=1; user_error("no_insnum");
  862.             }
  863.             if(*c=='/' || strstr(c,"..")!=NULL) goto badfile;
  864.            
  865.             set_session_prefix();
  866.             if(strstr(session_prefix,"robot")!=NULL) exit(0);
  867.             mkfname(fname,"%s/getfile/%s",session_prefix,c);
  868.             l=filelength("%s",fname);
  869.             if(l<0 && strchr(session_prefix,'_')!=NULL) {
  870.                 char *pt;
  871.                 mystrncpy(fname,session_prefix,sizeof(fname));
  872.                 pt=strrchr(fname,'_'); if(pt) *pt=0;
  873.                 snprintf(fname+(pt-fname),sizeof(fname)-(pt-fname),
  874.                         "/getfile/%s",c);
  875.                 l=filelength("%s",fname);
  876.             }
  877.             if(l<0) {
  878.                 badfile: user_error_nolog=1; user_error("bad_insnum");
  879.             }
  880.             if(l>512*1024) {
  881.                 struct rlimit rlim;
  882.                 rlimit_cpu*=l/(10*1024);
  883.                 rlim.rlim_cur=rlim.rlim_max=rlimit_cpu;
  884.                 initalarm();
  885.             }
  886.             {
  887.                 char *p1;
  888.                 char mime[MAX_LINELEN+1];
  889.                 for(p1=c+strlen(c);p1>c && isalpha(*(p1-1)); p1--);
  890.                 ovlstrcpy(mime,"application/octet-stream");
  891.                 if(p1>c && *(p1-1)=='.') {
  892.                     setvar("translator_unknown",mime);
  893.                     setvar("dictionary","bases/sys/mime");
  894.                     snprintf(mime,sizeof(mime),"translator %s",p1);
  895.                     calc_exec(mime);
  896.                 }
  897.                 nph_header(200);
  898.                 printf("Content-type: %s\r\n\
  899. Content-length: %ld\r\n\r\n",mime,l);
  900.                 catfile(stdout,"%s",fname); exit(0);
  901.             }
  902.         }
  903.         case cmd_close: {
  904.             char *p, b2[32]; int w;
  905.             char nbuf[MAX_FNAME+1], vbuf[MAX_LINELEN+1];
  906.             p=getvar(ro_name[ro_session]);
  907.             if(p==NULL || strlen(p)<10 ||
  908.                strchr(p,'/')!=NULL) return;
  909.             mystrncpy(b2,p,sizeof(b2));
  910.             p=strchr(b2,'.'); if(p!=NULL) *p=0;
  911.             mkfname(nbuf,"%s/%s/var.stat",session_dir,b2);
  912.             getdef(nbuf,"wims_caller",vbuf);
  913.             if(vbuf[0]!=0) force_setvar(ro_name[ro_session],vbuf);
  914.             w=wrapexec; wrapexec=1;
  915.             call_sh("rm -Rf %s/%s* %s/%s* >/dev/null 2>&1",session_dir,b2,s2_dir,b2);
  916.             wrapexec=w; cookiegot[0]=0;
  917.             force_setvar(ro_name[ro_cmd],"new");
  918.         }
  919.         default: return;
  920.     }
  921. }
  922.  
  923.         /* This is run only when manually invoking the program.
  924.          * Verifies the orderedness of various list tables. */
  925. int verify_tables(void)
  926. {
  927.     if(verify_order(calc_routine,CALC_FN_NO,sizeof(calc_routine[0]))) return -1;
  928.     if(verify_order(exec_routine,EXEC_FN_NO,sizeof(exec_routine[0]))) return -1;
  929.     if(verify_order(main_config,MAIN_CONFIG_NO,sizeof(main_config[0]))) return -1;
  930.     if(verify_order(mathname,mathname_no,sizeof(mathname[0]))) return -1;
  931.     if(verify_order(hmname,hmname_no,sizeof(hmname[0]))) return -1;
  932.     if(verify_order(ro_name,RO_NAME_NO,sizeof(ro_name[0]))) return -1;
  933.     if(verify_order(distr_cmd,distr_cmd_no,sizeof(distr_cmd[0]))) return -1;
  934.     if(verify_order(internal_name,INTERNAL_NAME_NO,
  935.                     sizeof(internal_name[0]))) return -1;
  936.     if(verify_order(tmathfn,tmathfn_no,sizeof(tmathfn[0]))) return -1;
  937.     if(verify_order(tmathvar,tmathvar_no,sizeof(tmathvar[0]))) return -1;
  938.     if(verify_order(modindex,MODINDEX_NO,sizeof(modindex[0]))) return -1;
  939.     if(verify_order(exportvars,exportvarcnt,sizeof(exportvars[0]))) return -1;
  940.     if(evaltab_verify()) return -1;
  941.     if(textab_verify()) return -1;
  942.     return 0;
  943. }
  944.  
  945. void config_defaults(void)
  946. {
  947.     int i;
  948.     for(i=0;i<MAIN_CONFIG_NO;i++) {
  949.         if((1&main_config[i].is_integer)==1) {
  950.             int *pi = (int*)main_config[i].address;
  951.             printf("DF_%s=%d\n",main_config[i].name, *pi);
  952.         }
  953.         else {
  954.             char **ps = (char**)main_config[i].address;
  955.             printf("DF_%s=%s\n",main_config[i].name,*ps);
  956.         }
  957.     }
  958. }
  959.  
  960.         /* get and set useroptions */
  961. void useropts(void)
  962. {
  963.     char *p;
  964.     setvar("lang",lang);
  965.     p=getvar("useropts");
  966.     if(p==NULL || *p==0) p=getvar("wims_useropts");
  967.     if(p!=NULL && *p!=0) {
  968.         if(myisdigit(p[0])) {
  969.             usertexsize=p[0]-'0';
  970.             if(p[1]!=0) {
  971.                 mathalign_base=p[1]-'0';
  972.             }
  973.         }
  974.     }
  975.     if(mathalign_base==1) {
  976.         mathalign_sup1="<sup>"; mathalign_sup2="</sup>";
  977.     }
  978.     else mathalign_sup1=mathalign_sup2="";
  979. }
  980.  
  981.         /* popup module help */
  982. void mhelp(void)
  983. {
  984.     char *p, buf[MAX_LINELEN+1];
  985.     main_phtml_put(""); buf[0]=0;
  986.     if(cmd_type!=cmd_help) {
  987.         phtml_put_base("closemhelp.phtml",0);
  988.     }
  989.     else {
  990.         phtml_put_base("mhelpheader.phtml",0);
  991.         p=getvar("special_parm");
  992.         if(p!=NULL && strcmp(p,"about")==0)
  993.           phtml_put("about.phtml",0);
  994.         else phtml_put("help.phtml",0); phtml_put_base("mhelptail.phtml",0);
  995.         exec_tail(buf);
  996.     }
  997. }
  998.  
  999. #define READSTDIN_WINDOW 4096
  1000.  
  1001. void readstdin(int len)
  1002. {
  1003.     int ll, l1, lt, lr;
  1004.     int cpulim;
  1005.    
  1006.     cpulim=rlimit_cpu; rlimit_cpu=3;
  1007.     lr=len; l1=0;
  1008.     while(lr>0) {
  1009.         nowtime=time(0); initalarm();
  1010.         ll=lr; if(ll>READSTDIN_WINDOW) ll=READSTDIN_WINDOW;
  1011.         lt=fread(stdinbuf+l1,1,ll,stdin);
  1012.         if(lt!=ll) user_error("parm_too_long");
  1013.         lr-=ll; l1+=ll;
  1014.     }
  1015.     if(l1!=len) user_error("parm_too_long");
  1016.     stdinbuf[len]=0; rlimit_cpu=cpulim;
  1017. }
  1018.  
  1019.         /* input: p=QUERY_STRING. output: parameter length. */
  1020.         /* Netscape puts form content into /tmp. */
  1021. int formdata(char *p)
  1022. {
  1023.     char *pp;
  1024.     int inlen;
  1025.     char *ctype;
  1026.     inlen=0; ctype=getenv("CONTENT_TYPE");
  1027.     if(ctype==NULL || strstr(ctype,"multipart/form-data")==NULL
  1028.        || (p=strstr(ctype,"boundary="))==NULL) {
  1029.         bad: stdinbuf=""; return 0;
  1030.     }
  1031.     pp=getenv("CONTENT_LENGTH");
  1032.     if(pp==NULL) goto bad;
  1033.     inlen=atoi(pp); if(inlen<=10) goto bad;
  1034.     if(inlen>=MAX_DEPOSITLEN) user_error("parm_too_long");
  1035.     stdinbuf=xmalloc(inlen+1); readstdin(inlen);
  1036.     p+=strlen("boundary=");
  1037.     for(pp=p;myisalnum(*pp) || *pp=='-'; pp++);
  1038.     if(pp-p<sizeof(mpboundary)-2) {
  1039.         memmove(mpboundary,p,pp-p); mpboundary[pp-p]=0;
  1040.     }
  1041.                 /* empty data */
  1042.     if(strstr(stdinbuf,mpboundary)==NULL || strstr(stdinbuf,"name=")==NULL) {
  1043.         free(stdinbuf); goto bad;
  1044.     }
  1045.     form_access=1; post_log();
  1046.     return inlen;
  1047. }
  1048.  
  1049.         /* get the content of POST */
  1050. void getpost(void)
  1051. {
  1052.     int ll;
  1053.     char *pp;
  1054.     pp=getenv("CONTENT_LENGTH");
  1055.     if(pp==NULL || (ll=atoi(pp))<=0) {
  1056.         stdinbuf=xmalloc(16); stdinbuf[0]=0;
  1057.     }
  1058.     else {
  1059.         if(ll>QUERY_STRING_LIMIT) user_error("parm_too_long");
  1060.         stdinbuf=xmalloc(ll+16); readstdin(ll);
  1061.         if(ll>0) {
  1062.             setenv("QUERY_STRING",stdinbuf,1);
  1063.             form_access=1; post_log();
  1064.         }
  1065.     }
  1066. }
  1067.  
  1068. void buffer_init(void)
  1069. {
  1070.     struct timeval tv;
  1071.    
  1072.     mcachecnt=readnest=0;
  1073.     mpboundary[0]=cookiegot[0]=cookieset[0]=cwdbuf[0]=0;
  1074.     rscore_class[0]=rscore_user[0]=multiexec_random[0]=0;
  1075.     lastftest[0]=0;
  1076.     lastdatafile[0]=0; lastdata=xmalloc(WORKFILE_LIMIT);
  1077.     outptr=outbuf;
  1078.     instex_src[0]=instex_fname[0]=module_prefix[0]=0;
  1079.     examlogf[0]=examlogd[0]=exam_sheetexo[0]=0;
  1080.     stdinbuf=NULL;
  1081.     mkfname(tmp_dir,"../tmp/forall");
  1082.     mkfname(session_dir,"../%s",SESSION_BASE);
  1083.     mkfname(s2_dir,"../%s",S2_BASE);
  1084.     if(gettimeofday(&tv,NULL)) startmtime=startmtime2=0;
  1085.     else {
  1086.         startmtime=((tv.tv_sec%10000)*1000+tv.tv_usec/1000);
  1087.         startmtime2=(tv.tv_sec%1000)*1000000+tv.tv_usec;
  1088.     }
  1089. }
  1090.  
  1091. int main(int argc, char *argv[], char *envp[])
  1092. {
  1093.     char *p, homebuf[MAX_FNAME+1], lbuf[32];
  1094.     int inlen=0;
  1095. /*    int mfd;
  1096. */
  1097.     error1=user_error; error2=module_error; error3=internal_error;
  1098.     class_dir[0]=0;
  1099.     substitute=substit; buffer_init(); var_init();
  1100.         /* WIMS internal locale is always C. */
  1101.     setenv("LANG","C",1); umask(022);
  1102.     setenv("LANGUAGE","us",1);
  1103.     setenv("LC_ALL","C",1);
  1104.     if(argc>1) {
  1105.         if(strcasecmp(argv[1],"table")==0) {
  1106.             if(verify_tables()) internal_error("Table disorder.");
  1107.             else printf("Table orders OK.\n");
  1108.             return 0;
  1109.         }
  1110.         if(strcasecmp(argv[1],"version")==0) {
  1111.             printf("%s",wims_version); return 0;
  1112.         }
  1113.         if(strcasecmp(argv[1],"defaults")==0) {
  1114.             config_defaults(); return 0;
  1115.         }
  1116.     }
  1117.     p=getenv("SERVER_SOFTWARE"); if(p!=NULL && strcasecmp(p,"WIMS")==0)
  1118.       httpd_type=httpd_wims;
  1119.     p=getenv("REMOTE_ADDR"); if(p!=NULL) remote_addr=p;
  1120.     p=getenv("REMOTE_HOST"); if(p!=NULL) remote_host=p;
  1121.     nowtime=time(0); now=localtime(&nowtime);
  1122.     memmove(&Now, now, sizeof(Now)); now=&Now;
  1123.     snprintf(nowstr,sizeof(nowstr),"%04d%02d%02d.%02d:%02d:%02d",
  1124.              (now->tm_year)+1900,(now->tm_mon)+1,now->tm_mday,
  1125.              now->tm_hour,now->tm_min,now->tm_sec);
  1126.     p=getenv("QUERY_STRING");
  1127.     if(p==NULL || *p==0) getpost();
  1128.     else if(strncmp(p,"form-data",9)==0) inlen=formdata(p);
  1129.    
  1130.     force_setvar("wims_now",nowstr);
  1131.     snprintf(lbuf,sizeof(lbuf),"%lu",nowtime);
  1132.     force_setvar("wims_nowseconds",lbuf);
  1133.     nowtime=time(0);
  1134.     initalarm();
  1135.    
  1136.     executed_gotos=insert_no=output_length=0; ins_alt[0]=0;
  1137.     setvar("empty","");         /* lock this variable */
  1138.     setvar("wims_version",wims_version);
  1139.     setvar("wims_version_date",wims_version_date);
  1140.     setvar("wims_main_font","utf-8");
  1141.     take_httpd_vars();
  1142.  
  1143.     main_configure();
  1144.     checklogd();
  1145. /*    mfd=shm_open(SHM_NAME,O_RDONLY,-1);
  1146.     if(mfd==-1) internal_error("Unable to find shared memory.");
  1147.     shmptr=mmap(0,SHM_SIZE,PROT_READ,MAP_SHARED,mfd,0);
  1148.     if(shmptr==MAP_FAILED) internal_error("Shared memory failure.");
  1149. */
  1150.     getppid();  /* this is the first sysmask trigger, must be after checklogd() */
  1151.     predetermine_language();
  1152.     set_rlimits();
  1153.     init_random();
  1154.     module_configure();
  1155.     set_job_ident();
  1156.     m_file.name[0]=0;m_file.linecnt=m_file.linepointer=0;
  1157.     p=getenv("QUERY_STRING");
  1158.     if(p==NULL || strlen(p)==0) {
  1159.         setvar("lang",lang);
  1160.         snprintf(homebuf,sizeof(homebuf),"module=%s",home_module);
  1161.         p=homebuf;
  1162.     }
  1163.     if(strlen(p)>=QUERY_STRING_LIMIT) user_error("parm_too_long");
  1164.     if(mpboundary[0]==0) {
  1165.         var_str=xmalloc(strlen(p)+2);
  1166.         parse_query_string(http2env(var_str,p),0);
  1167.     }
  1168.     else {
  1169.         var_str=stdinbuf;
  1170.         parse_query_string(inlen,1);
  1171.     }
  1172.     if(ismhelp) {
  1173.         p=getvar(ro_name[ro_cmd]);
  1174.         if(p==NULL || (strcmp(p,"help")!=0 && strcmp(p,"getins")!=0)) {
  1175.             mhelp(); goto outgo;
  1176.         }
  1177.     }
  1178.     check_exam();
  1179.     useropts();
  1180.     special_cmds();
  1181.     parse_ro_names();
  1182.     manager_check();
  1183.     access_check(0);
  1184.     set_variables();
  1185.     determine_font(getvar("module_language"));
  1186.     determine_dirn(getvar("module_language"));
  1187.     if(!robot_access && session_prefix[0]!=0 && cmd_type!=cmd_help && !ismhelp)
  1188.       lastout_file=creat(mkfname(NULL,"%s/%s",s2_prefix,lastout),
  1189.                          S_IRUSR|S_IWUSR);
  1190.     p=getvar("module_category");
  1191.     if(p==NULL || strstr(p,"tool")==NULL) default_form_method="get";
  1192.     if(noout) {
  1193.         write_logs(); save_session_vars();
  1194.         goto outgo;
  1195.     }
  1196.     if(ismhelp) {
  1197.         mhelp();
  1198.     }
  1199.     else {
  1200.         main_phtml_put(html_file);
  1201.         if(lastout_file!=-1) {
  1202.             flushoutput(); close(lastout_file); putlastout();
  1203.         }
  1204.         write_logs(); save_session_vars();
  1205.     }
  1206.     outgo:
  1207.     debug_output();
  1208.     if(var_str!=stdinbuf) free(var_str);
  1209.     delete_pid();
  1210.     if(mode!=mode_popup && trusted_module()) {
  1211.         p=getvar("wims_mode");
  1212.         if(p!=NULL && strcmp(p,"popup")==0) mode=mode_popup;
  1213.     }
  1214.     if(mode==mode_popup && insert_no==0) {
  1215.         p=getvar("wims_mode");
  1216.         if(p!=NULL && strcmp(p,"popup")==0) {
  1217.             remove_tree(session_prefix);
  1218.            
  1219.             remove_tree(s2_prefix);
  1220.         }
  1221.     }
  1222.     return 0;
  1223. }
  1224.  
  1225.