Subversion Repositories wimsdev

Rev

Rev 11125 | Rev 13011 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 11125 Rev 12242
Line 62... Line 62...
62
void delete_pid(void);
62
void delete_pid(void);
63
 
63
 
64
/* Internal use only */
64
/* Internal use only */
65
void _debug(char *s,...)
65
void _debug(char *s,...)
66
{
66
{
67
    va_list vp;
67
  va_list vp;
68
    char buf[MAX_LINELEN+1];
68
  char buf[MAX_LINELEN+1];
69
 
69
 
70
    va_start(vp,s);
70
  va_start(vp,s);
71
    vsnprintf(buf,sizeof(buf),s,vp);
71
  vsnprintf(buf,sizeof(buf),s,vp);
72
    va_end(vp);
72
  va_end(vp);
73
    setvar("debug",buf); module_error("debug");
73
  setvar("debug",buf); module_error("debug");
74
    exit(1);
74
  exit(1);
75
}
75
}
76
 
76
 
77
 
77
 
78
/* HTTP response header for non-processed CGI interface */
78
/* HTTP response header for non-processed CGI interface */
79
void nph_header(int code)
79
void nph_header(int code)
80
{
80
{
81
    char *cstr;
81
  char *cstr;
82
    switch(code) {
82
  switch(code) {
83
      case 200: cstr="OK"; break;
83
    case 200: cstr="OK"; break;
84
      case 301: cstr="Moved Permanently"; break;
84
    case 301: cstr="Moved Permanently"; break;
85
      case 302: cstr="Moved Temporarily"; break;
85
    case 302: cstr="Moved Temporarily"; break;
86
      case 420: cstr="WIMS Nested Error"; break;
86
    case 420: cstr="WIMS Nested Error"; break;
87
      case 450: cstr="WIMS User Error"; break;
87
    case 450: cstr="WIMS User Error"; break;
88
      case 500: cstr="WIMS Internal Error"; break;
88
    case 500: cstr="WIMS Internal Error"; break;
89
      case 550: cstr="WIMS Module Error"; break;
89
    case 550: cstr="WIMS Module Error"; break;
90
      default: cstr="ERROR"; break;
90
    default: cstr="ERROR"; break;
91
    }
91
  }
92
    if(httpd_type!=httpd_wims) printf("Status: %d %s\r\n",code,cstr);
92
  if(httpd_type!=httpd_wims) printf("Status: %d %s\r\n",code,cstr);
93
    else {
93
  else {
94
      char *p, tbuf[256];
94
    char *p, tbuf[256];
95
      mystrncpy(tbuf,ctime(&nowtime),sizeof(tbuf));
95
    mystrncpy(tbuf,ctime(&nowtime),sizeof(tbuf));
96
      for(p=tbuf+strlen(tbuf);p>=tbuf && (*(p-1)=='\n' || *(p-1)=='\r'); p--);
96
    for(p=tbuf+strlen(tbuf);p>=tbuf && (*(p-1)=='\n' || *(p-1)=='\r'); p--);
97
      *p=0;
97
    *p=0;
98
      printf("HTTP/1.0 %d %s\r\n\
98
    printf("HTTP/1.0 %d %s\r\n\
99
Date: %s\r\n\
99
Date: %s\r\n\
100
Connection: close\r\n\
100
Connection: close\r\n\
101
",code,cstr,tbuf);
101
",code,cstr,tbuf);
102
    }
102
  }
103
}
103
}
104
 
104
 
105
void flushoutput(void)
105
void flushoutput(void)
106
{
106
{
107
    int l2;
107
  int l2;
108
    if(outptr<=outbuf) return;
108
  if(outptr<=outbuf) return;
109
    l2=outptr-outbuf;
109
  l2=outptr-outbuf;
110
    if(lastout_file!=-1) (void)write(lastout_file,outbuf,l2);
110
  if(lastout_file!=-1) (void)write(lastout_file,outbuf,l2);
111
    else fwrite(outbuf,l2,1,stdout);
111
  else fwrite(outbuf,l2,1,stdout);
112
    outptr=outbuf;
112
  outptr=outbuf;
113
}
113
}
114
 
114
 
115
void internal_warn(char msg[])
115
void internal_warn(char msg[])
116
{
116
{
117
    char buf[1024];
117
  char buf[1024];
118
    fprintf(stderr,"wims: %s\n%s\n",msg,strerror(errno));
118
  fprintf(stderr,"wims: %s\n%s\n",msg,strerror(errno));
119
    snprintf(buf,sizeof(buf),"%s: %s\n",nowstr,msg);
119
  snprintf(buf,sizeof(buf),"%s: %s\n",nowstr,msg);
120
    accessfile(buf,"a","%s/internal_error.log",log_dir);
120
  accessfile(buf,"a","%s/internal_error.log",log_dir);
121
}
121
}
122
 
122
 
123
/* Internal error: panic and forget about requester. */
123
/* Internal error: panic and forget about requester. */
124
void internal_error(char msg[])
124
void internal_error(char msg[])
125
{
125
{
126
    if(error_status<2) {
126
  if(error_status<2) {
127
      nph_header(500);
127
    nph_header(500);
128
      printf("Cache-Control: no-cache\nPragma: no-cache\r\n\
128
    printf("Cache-Control: no-cache\nPragma: no-cache\r\n\
129
Content-type: text/plain\r\n\r\n\r\n\
129
Content-type: text/plain\r\n\r\n\r\n\
130
WIMS panick! %s\n%s\n",msg,strerror(errno));
130
WIMS panick! %s\n%s\n",msg,strerror(errno));
131
      error_status=2; internal_warn(msg);
131
      error_status=2; internal_warn(msg);
132
    }
132
  }
133
    delete_pid(); exit(1);
133
  delete_pid(); exit(1);
134
}
134
}
135
 
135
 
136
void tex_nospace(char *p)
136
void tex_nospace(char *p)
137
{
137
{
138
    char *p1, *p2;
138
  char *p1, *p2;
139
    char buf[MAX_LINELEN+1];
139
  char buf[MAX_LINELEN+1];
140
    for(p1=buf,p2=p;*p2 && p1-buf<MAX_LINELEN-4;p2++) {
140
  for(p1=buf,p2=p;*p2 && p1-buf<MAX_LINELEN-4;p2++) {
141
      if(!isspace(*p2)) {*p1++=*p2;continue;}
141
    if(!isspace(*p2)) {*p1++=*p2;continue;}
142
      while(isspace(*p2)) p2++;
142
    while(isspace(*p2)) p2++;
143
      if(*(p1-1)=='\\' ||
143
    if(*(p1-1)=='\\' ||
144
         (p1>buf && myisalnum(*(p1-1)) && myisalnum(*p2)))
144
       (p1>buf && myisalnum(*(p1-1)) && myisalnum(*p2)))
145
        *p1++=' ';
145
      *p1++=' ';
146
      *p1++=*p2;
146
    *p1++=*p2;
147
    }
147
  }
148
    *p1++=0; memmove(p,buf,p1-buf);
148
  *p1++=0; memmove(p,buf,p1-buf);
149
}
149
}
150
 
150
 
151
void nametoolong(char *p)
151
void nametoolong(char *p)
152
{
152
{
153
    char buf[MAX_FNAME+17];
153
  char buf[MAX_FNAME+17];
154
    snprintf(buf,sizeof(buf),"%s...",p);
154
  snprintf(buf,sizeof(buf),"%s...",p);
155
    force_setvar("wims_error_data",buf);
155
  force_setvar("wims_error_data",buf);
156
    module_error("file_name_too_long");
156
  module_error("file_name_too_long");
157
}
157
}
158
 
158
 
159
off_t ftest_size;
159
off_t ftest_size;
160
 
160
 
161
/* A simple front-end of stat(). */
161
/* A simple front-end of stat(). */
162
int ftest(char *fname)
162
int ftest(char *fname)
163
{
163
{
164
    if(strcmp(fname,lastftest)==0) return lastftype;
164
  if(strcmp(fname,lastftest)==0) return lastftype;
165
/* if(fname[0]=='/' || fname[0]=='.') fprintf(stderr,"ftest: %s\n",fname); */
165
/* if(fname[0]=='/' || fname[0]=='.') fprintf(stderr,"ftest: %s\n",fname); */
166
    mystrncpy(lastftest,fname,sizeof(lastftest));
166
  mystrncpy(lastftest,fname,sizeof(lastftest));
167
    if(stat(fname,&ftst)) return lastftype=-1;
167
  if(stat(fname,&ftst)) return lastftype=-1;
168
    ftest_size=ftst.st_size;
168
  ftest_size=ftst.st_size;
169
    if(S_ISREG(ftst.st_mode)) {
169
  if(S_ISREG(ftst.st_mode)) {
170
      if((ftst.st_mode&(S_IXUSR|S_IXGRP|S_IXOTH))!=0) return lastftype=is_exec;
170
    if((ftst.st_mode&(S_IXUSR|S_IXGRP|S_IXOTH))!=0) return lastftype=is_exec;
171
      else return lastftype=is_file;
171
    else return lastftype=is_file;
172
    }
172
  }
173
    if(S_ISDIR(ftst.st_mode)) return lastftype=is_dir;
173
  if(S_ISDIR(ftst.st_mode)) return lastftype=is_dir;
174
    if(S_ISFIFO(ftst.st_mode)) return lastftype=is_fifo;
174
  if(S_ISFIFO(ftst.st_mode)) return lastftype=is_fifo;
175
    if(S_ISSOCK(ftst.st_mode)) return lastftype=is_socket;
175
  if(S_ISSOCK(ftst.st_mode)) return lastftype=is_socket;
176
    return lastftype=is_unknown;
176
  return lastftype=is_unknown;
177
}
177
}
178
 
178
 
179
char fnbuf[MAX_FNAME+1];
179
char fnbuf[MAX_FNAME+1];
180
 
180
 
181
/* make a filename and check length */
181
/* make a filename and check length */
182
char *mkfname(char buf[], char *s,...)
182
char *mkfname(char buf[], char *s,...)
183
{
183
{
184
    va_list vp;
184
  va_list vp;
185
    char *p;
185
  char *p;
186
 
186
 
187
    if(buf==NULL) p=fnbuf; else p=buf;
187
  if(buf==NULL) p=fnbuf; else p=buf;
188
    va_start(vp,s);
188
  va_start(vp,s);
189
    vsnprintf(p,MAX_FNAME,s,vp);
189
  vsnprintf(p,MAX_FNAME,s,vp);
190
    va_end(vp);
190
  va_end(vp);
191
    if(strlen(p)>=MAX_FNAME-1) nametoolong(p);
191
  if(strlen(p)>=MAX_FNAME-1) nametoolong(p);
192
    return p;
192
  return p;
193
}
193
}
194
 
194
 
195
void sysmask_trigger(char *s)
195
void sysmask_trigger(char *s)
196
{
196
{
197
    char buf[MAX_FNAME+1];
197
  char buf[MAX_FNAME+1];
198
    struct stat st;
198
  struct stat st;
199
    mkfname(buf,"%s/%s",sysmask_trigger_dir,s);
199
  mkfname(buf,"%s/%s",sysmask_trigger_dir,s);
200
    stat(buf,&st);
200
  stat(buf,&st);
201
}
201
}
202
 
202
 
203
/* read-in a file into buffer. Use open() and read().
203
/* read-in a file into buffer. Use open() and read().
204
       * Return buffer address which will be malloc'ed if buf=NULL. */
204
       * Return buffer address which will be malloc'ed if buf=NULL. */
205
char *readfile(char *fname, char buf[], long int buflen)
205
char *readfile(char *fname, char buf[], long int buflen)
206
{
206
{
207
    int fd, t, st;
207
  int fd, t, st;
208
    long int l, lc;
208
  long int l, lc;
209
    char *bf;
209
  char *bf;
210
    t=0; if(buf) buf[0]=0;
210
  t=0; if(buf) buf[0]=0;
211
    st=ftest(fname); if(st!=is_file) {
211
  st=ftest(fname); if(st!=is_file) {
212
      if(st==is_exec) { /* refuse to open executable file */
212
    if(st==is_exec) { /* refuse to open executable file */
213
          setvar("executable",fname); module_error("executable");
213
      setvar("executable",fname); module_error("executable");
214
      }
-
 
215
      return NULL;
-
 
216
    }
214
    }
-
 
215
    return NULL;
-
 
216
  }
217
    l=ftst.st_size; if(l<0) return NULL;
217
  l=ftst.st_size; if(l<0) return NULL;
218
    if(l>=buflen) {
218
  if(l>=buflen) {
219
      if(buflen<MAX_LINELEN) l=buflen-1;
219
    if(buflen<MAX_LINELEN) l=buflen-1;
220
      else {
220
    else {
221
          if(strncmp(fname,"modules/",strlen("modules/"))==0) {
221
      if(strncmp(fname,"modules/",strlen("modules/"))==0) {
222
            setvar(error_data_string,fname); module_error("file_too_long");
222
        setvar(error_data_string,fname); module_error("file_too_long");
223
          }
-
 
224
          else user_error("cmd_output_too_long");
-
 
225
      }
223
      }
-
 
224
      else user_error("cmd_output_too_long");
226
    }
225
    }
-
 
226
  }
227
    fd=open(fname,O_RDONLY); if(fd==-1) return NULL;
227
  fd=open(fname,O_RDONLY); if(fd==-1) return NULL;
228
    if(buf==NULL) bf=xmalloc(l+8); else {bf=buf;if(l==0) {t=1; l=buflen-1;}}
228
  if(buf==NULL) bf=xmalloc(l+8); else {bf=buf;if(l==0) {t=1; l=buflen-1;}}
229
    lc=read(fd,bf,l); close(fd);
229
  lc=read(fd,bf,l); close(fd);
230
    if(lc<0 || lc>l || (lc!=l && t==0))
230
  if(lc<0 || lc>l || (lc!=l && t==0)){
231
      {if(buf==NULL) free(bf); else buf[0]=0; return NULL;}
231
    if(buf==NULL) free(bf); else buf[0]=0; return NULL;
-
 
232
  }
232
    bf[lc]=0; _tolinux(bf); return bf;
233
  bf[lc]=0; _tolinux(bf); return bf;
233
}
234
}
234
 
235
 
235
/* Get a line in a stored working file.
236
/* Get a line in a stored working file.
236
       * Buffer length is always MAX_LINELEN. */
237
       * Buffer length is always MAX_LINELEN. */
237
int wgetline(char buf[], size_t buflen, WORKING_FILE *f)
238
int wgetline(char buf[], size_t buflen, WORKING_FILE *f)
238
{
239
{
239
    int i,j; unsigned int n;
240
  int i,j; unsigned int n;
240
    i=f->linepointer; buf[0]=0;
241
  i=f->linepointer; buf[0]=0;
241
    if(i>=f->linecnt || f->textbuf==NULL) return EOF;
242
  if(i>=f->linecnt || f->textbuf==NULL) return EOF;
242
    n=f->lines[i].llen;
243
  n=f->lines[i].llen;
243
    if(n>=buflen) n=buflen-1;
244
  if(n>=buflen) n=buflen-1;
244
    if(n>0) memmove(buf,f->lines[i].address,n);
245
  if(n>0) memmove(buf,f->lines[i].address,n);
245
    buf[n]=0;
246
  buf[n]=0;
246
    for(j=i+1;j<f->linecnt && f->lines[j].isstart==0;j++);
247
  for(j=i+1;j<f->linecnt && f->lines[j].isstart==0;j++);
247
    f->l=i; f->linepointer=j;
248
  f->l=i; f->linepointer=j;
248
    if(j>=f->linecnt && n==0) return EOF; else return n;
249
  if(j>=f->linecnt && n==0) return EOF; else return n;
249
}
250
}
250
 
251
 
251
int get_cached_file(char *name)
252
int get_cached_file(char *name)
252
{
253
{
253
    int i,l,flag;
254
  int i,l,flag;
254
    l=strlen(name); if(l>=127) return -1;
255
  l=strlen(name); if(l>=127) return -1;
255
    if(strncmp(module_prefix,module_dir,strlen(module_dir))!=0) flag=8; else flag=0;
256
  if(strncmp(module_prefix,module_dir,strlen(module_dir))!=0) flag=8; else flag=0;
256
    for(i=0;i<mcachecnt;i++) {
257
  for(i=0;i<mcachecnt;i++) {
257
      if(flag==mcache[i].nocache && strcmp(name,mcache[i].name)==0) {
258
    if(flag==mcache[i].nocache && strcmp(name,mcache[i].name)==0) {
258
          memmove(&m_file,mcache+i,sizeof(WORKING_FILE));
259
      memmove(&m_file,mcache+i,sizeof(WORKING_FILE));
259
          m_file.nocache|=4;
260
      m_file.nocache|=4;
260
          return i;
261
      return i;
261
      }
-
 
262
    }
262
    }
-
 
263
  }
263
    return -1;
264
  return -1;
264
}
265
}
265
 
266
 
266
/* Open a work file. Returns 0 if OK. */
267
/* Open a work file. Returns 0 if OK. */
267
int open_working_file(WORKING_FILE *f, char *fname)
268
int open_working_file(WORKING_FILE *f, char *fname)
268
{
269
{
269
    char *p, *q;
270
  char *p, *q;
270
    void *vp;
271
  void *vp;
271
    int i,j,k,laststart,lc[LINE_LIMIT];
272
  int i,j,k,laststart,lc[LINE_LIMIT];
272
 
273
 
273
    f->linecnt=f->linepointer=0;
274
  f->linecnt=f->linepointer=0;
274
    f->for_idx=f->nocache=0;
275
  f->for_idx=f->nocache=0;
275
    f->l=-1; f->lines=NULL;
276
  f->l=-1; f->lines=NULL;
276
    strncpy(f->filepath,fname,MAX_FNAME+1);
277
  strncpy(f->filepath,fname,MAX_FNAME+1);
277
    f->textbuf=readfile(fname,NULL,WORKFILE_LIMIT);
278
  f->textbuf=readfile(fname,NULL,WORKFILE_LIMIT);
278
    if(f->textbuf==NULL) return -1;
279
  if(f->textbuf==NULL) return -1;
279
    p=f->textbuf; if(*p) {
280
  p=f->textbuf; if(*p) {
280
      for(i=0,p--; i<LINE_LIMIT-1 && p!=NULL;p=strchr(p,'\n')) {
281
    for(i=0,p--; i<LINE_LIMIT-1 && p!=NULL;p=strchr(p,'\n')) {
281
          if(i>0) *p=0;
282
      if(i>0) *p=0;
282
          lc[i++]=(++p-f->textbuf);
283
      lc[i++]=(++p-f->textbuf);
-
 
284
    }
-
 
285
  }
-
 
286
  else i=0;
-
 
287
  if(i>=LINE_LIMIT-1) module_error("file_too_long");
-
 
288
  lc[i]=lc[i-1]+strlen(f->textbuf+lc[i-1])+1;
-
 
289
  f->textbuf[lc[i]]=0;
-
 
290
  f->linecnt=i; laststart=0;
-
 
291
  f->for_stack=xmalloc(MAX_FOR_LEVEL*sizeof(FOR_STACK)+(i+1)*sizeof(LINE_STRUCT));
-
 
292
  vp=f->for_stack+MAX_FOR_LEVEL; f->lines=vp;
-
 
293
  for(j=0;j<i;j++) {
-
 
294
    f->lines[j].address=p=(f->textbuf)+lc[j];
-
 
295
    f->lines[j].llen=lc[j+1]-lc[j]-1;
-
 
296
    (f->lines[j]).execcode=(f->lines[j]).varcode=-1;
-
 
297
    if(j==0) goto normal;
-
 
298
    q=f->lines[laststart].address+f->lines[laststart].llen-1;
-
 
299
    if(q>=f->textbuf && *q=='\\') {
-
 
300
      f->lines[laststart].llen+=f->lines[j].llen; *q='\n';
-
 
301
      f->lines[j].isstart=f->lines[j].llen=0;
-
 
302
      memmove(q+1,p,lc[j+1]-lc[j]);
-
 
303
    }
-
 
304
    else {
-
 
305
      normal: for(q=p;myislspace(*q);q++);
-
 
306
      f->lines[j].isstart=1; laststart=j; k=0;
-
 
307
      switch(*q) {
-
 
308
                /* isstart: bit 1 = start.
-
 
309
                 * bit 2 = exec
-
 
310
                 * bit 3 (4) = label
-
 
311
                 * bit 4 (8) = hard comment (!!)
-
 
312
                 * bit 5 (16) = soft comment (#) */
-
 
313
        case exec_prefix_char: {
-
 
314
          if(myisalpha(q[1])) f->lines[j].isstart=3;
-
 
315
          else f->lines[j].isstart=9;
-
 
316
          k=1; break;
-
 
317
        }
-
 
318
        case label_prefix_char: {f->lines[j].isstart=5; k=1; break;}
-
 
319
        case comment_prefix_char: {f->lines[j].isstart=17; break;}
-
 
320
        default: {f->lines[j].isstart=1; break;}
283
      }
321
      }
-
 
322
      if(k && q>p) {f->lines[j].address=q;f->lines[j].llen-=q-p;}
284
    }
323
    }
285
    else i=0;
-
 
286
    if(i>=LINE_LIMIT-1) module_error("file_too_long");
-
 
287
    lc[i]=lc[i-1]+strlen(f->textbuf+lc[i-1])+1;
-
 
288
    f->textbuf[lc[i]]=0;
-
 
289
    f->linecnt=i; laststart=0;
-
 
290
    f->for_stack=xmalloc(MAX_FOR_LEVEL*sizeof(FOR_STACK)+(i+1)*sizeof(LINE_STRUCT));
-
 
291
    vp=f->for_stack+MAX_FOR_LEVEL; f->lines=vp;
-
 
292
    for(j=0;j<i;j++) {
-
 
293
      f->lines[j].address=p=(f->textbuf)+lc[j];
-
 
294
      f->lines[j].llen=lc[j+1]-lc[j]-1;
-
 
295
      (f->lines[j]).execcode=(f->lines[j]).varcode=-1;
-
 
296
      if(j==0) goto normal;
-
 
297
      q=f->lines[laststart].address+f->lines[laststart].llen-1;
-
 
298
      if(q>=f->textbuf && *q=='\\') {
-
 
299
          f->lines[laststart].llen+=f->lines[j].llen; *q='\n';
-
 
300
          f->lines[j].isstart=f->lines[j].llen=0;
-
 
301
          memmove(q+1,p,lc[j+1]-lc[j]);
-
 
302
      }
-
 
303
      else {
-
 
304
          normal: for(q=p;myislspace(*q);q++);
-
 
305
          f->lines[j].isstart=1; laststart=j; k=0;
-
 
306
          switch(*q) {
-
 
307
                  /* isstart: bit 1 = start.
-
 
308
                   * bit 2 = exec
-
 
309
                   * bit 3 (4) = label
-
 
310
                   * bit 4 (8) = hard comment (!!)
-
 
311
                   * bit 5 (16) = soft comment (#) */
-
 
312
            case exec_prefix_char: {
-
 
313
                if(myisalpha(q[1])) f->lines[j].isstart=3;
-
 
314
                else f->lines[j].isstart=9;
-
 
315
                k=1; break;
-
 
316
            }
-
 
317
            case label_prefix_char: {f->lines[j].isstart=5; k=1; break;}
-
 
318
            case comment_prefix_char: {f->lines[j].isstart=17; break;}
-
 
319
            default: {f->lines[j].isstart=1; break;}
-
 
320
          }
-
 
321
          if(k && q>p) {f->lines[j].address=q;f->lines[j].llen-=q-p;}
-
 
322
      }
-
 
323
    }
324
  }
324
    f->lines[i].isstart=1; f->lines[i].llen=0;
325
  f->lines[i].isstart=1; f->lines[i].llen=0;
325
    f->lines[i].address=(f->textbuf)+lc[i];
326
  f->lines[i].address=(f->textbuf)+lc[i];
326
    mfilecnt++; return 0;
327
  mfilecnt++; return 0;
327
}
328
}
328
 
329
 
329
/* close an earlier opened working file */
330
/* close an earlier opened working file */
330
void close_working_file(WORKING_FILE *f, int cache)
331
void close_working_file(WORKING_FILE *f, int cache)
331
{
332
{
332
    f->linepointer=f->l=0;
333
  f->linepointer=f->l=0;
333
    if(cache && untrust==0 && mcachecnt<MAX_MCACHE && (f->nocache&7)==0) {
334
  if(cache && untrust==0 && mcachecnt<MAX_MCACHE && (f->nocache&7)==0) {
334
      memmove(mcache+mcachecnt,f,sizeof(WORKING_FILE));
335
    memmove(mcache+mcachecnt,f,sizeof(WORKING_FILE));
335
      mcachecnt++;
336
    mcachecnt++;
336
    }
337
  }
337
    else if((f->nocache&4)==0) {
338
  else if((f->nocache&4)==0) {
338
      if(f->for_stack!=NULL) free(f->for_stack);
339
    if(f->for_stack!=NULL) free(f->for_stack);
339
      if(f->textbuf!=NULL) free(f->textbuf);
340
    if(f->textbuf!=NULL) free(f->textbuf);
340
    }
341
  }
341
    f->for_stack=NULL; f->textbuf=NULL; f->linecnt=0;
342
  f->for_stack=NULL; f->textbuf=NULL; f->linecnt=0;
342
}
343
}
343
 
344
 
344
void free_mcache(void)
345
void free_mcache(void)
345
{
346
{
346
    int i;
347
  int i;
347
    untrust=0;
348
  untrust=0;
348
    for(i=mcachecnt-1;i>=0;i--) close_working_file(mcache+i,0);
349
  for(i=mcachecnt-1;i>=0;i--) close_working_file(mcache+i,0);
349
    mcachecnt=0;
350
  mcachecnt=0;
350
}
351
}
351
 
352
 
352
void cleantmpdir(void);
353
void cleantmpdir(void);
353
void user_error_log(char msg[]);
354
void user_error_log(char msg[]);
354
 
355
 
355
void nested_error(char msg[])
356
void nested_error(char msg[])
356
{
357
{
357
    fprintf(stderr,"\nNested error! %s\n",msg);
358
  fprintf(stderr,"\nNested error! %s\n",msg);
358
    nph_header(420);
359
  nph_header(420);
359
    printf("\r\n\r\nWIMS error processing aborted on nested error.\r\n\r\n%s\r\n",msg);
360
  printf("\r\n\r\nWIMS error processing aborted on nested error.\r\n\r\n%s\r\n",msg);
360
    delete_pid(); exit(1);
361
  delete_pid(); exit(1);
361
}
362
}
362
 
363
 
363
/* Send an error message to requester and exit.
364
/* Send an error message to requester and exit.
364
 * This is for user errors, language-sensitive.
365
 * This is for user errors, language-sensitive.
365
 */
366
 */
366
void user_error(char msg[])
367
void user_error(char msg[])
367
{
368
{
368
    char erfname[MAX_FNAME+1];
369
  char erfname[MAX_FNAME+1];
369
 
370
 
370
    if(error_status) nested_error(msg);
371
  if(error_status) nested_error(msg);
371
    error_status=1;
372
  error_status=1;
372
    mkfname(erfname,"%s.%s",user_error_msg_file,lang);
373
  mkfname(erfname,"%s.%s",user_error_msg_file,lang);
373
    if(ftest(erfname)!=is_file) internal_error("user_error(): error message file not found.\n\
374
  if(ftest(erfname)!=is_file) internal_error("user_error(): error message file not found.\n\
374
Bad installation.");
375
Bad installation.");
375
    force_setvar("wims_user_error",msg);
376
  force_setvar("wims_user_error",msg);
376
    if(strcmp(msg,"threshold")!=0) user_error_log(msg);
377
  if(strcmp(msg,"threshold")!=0) user_error_log(msg);
377
    memmove(module_prefix,".",2);
378
  memmove(module_prefix,".",2);
378
    if(lastout_file!=-1 && outputing) {
379
  if(lastout_file!=-1 && outputing) {
379
      flushoutput(); close(lastout_file); lastout_file=-1;
380
    flushoutput(); close(lastout_file); lastout_file=-1;
380
    }
381
  }
381
    nph_header(450);
382
  nph_header(450);
382
    phtml_put_base(erfname,0);
383
  phtml_put_base(erfname,0);
383
    if(strcmp(msg,"double_click")!=0) delete_pid();
384
  if(strcmp(msg,"double_click")!=0) delete_pid();
384
    else {
385
  else {
385
      cleantmpdir(); flushlog();
386
    cleantmpdir(); flushlog();
386
    }
387
  }
387
    flushoutput(); exit(0);
388
  flushoutput(); exit(0);
388
}
389
}
389
 
390
 
390
void module_error_log(char msg[]);
391
void module_error_log(char msg[]);
391
 
392
 
392
/* Messages for module errors. English only.
393
/* Messages for module errors. English only.
393
 * This is really rudimentary for the time being.
394
 * This is really rudimentary for the time being.
394
 */
395
 */
395
void module_error(char msg[])
396
void module_error(char msg[])
396
{
397
{
397
    int send=0;
398
  int send=0;
398
    char *p;
399
  char *p;
399
    WORKING_FILE mf;
400
  WORKING_FILE mf;
400
 
401
 
401
    if(error_status) nested_error(msg);
402
  if(error_status) nested_error(msg);
402
    error_status=1; untrust=0;
403
  error_status=1; untrust=0;
403
    module_error_log(msg);
404
  module_error_log(msg);
404
    nph_header(550);
405
  nph_header(550);
405
    printf("Server: %s %s (%s)\r\n", SHORTSWNAME,wims_version,LONGSWNAME);
406
  printf("Server: %s %s (%s)\r\n", SHORTSWNAME,wims_version,LONGSWNAME);
406
    p=getvar("wims_main_font");
407
  p=getvar("wims_main_font");
407
    if(p!=NULL && *p!=0) printf("Content-type: text/plain; charset=%s\r\n\r\n",p);
408
  if(p!=NULL && *p!=0) printf("Content-type: text/plain; charset=%s\r\n\r\n",p);
408
    else printf("Content-type: text/plain\r\n\r\n");
409
  else printf("Content-type: text/plain\r\n\r\n");
409
    p=getvar(ro_name[ro_module]); if(p==NULL) p="???";
410
  p=getvar(ro_name[ro_module]); if(p==NULL) p="???";
410
    printf("ERROR.\n\nwims has detected an error in the module '%s'.",p);
411
  printf("ERROR.\n\nwims has detected an error in the module '%s'.",p);
411
    if(m_file.l>=0) printf("\n\nIn file '%s', line %d:",
412
  if(m_file.l>=0) printf("\n\nIn file '%s', line %d:", m_file.name,m_file.l+1);
412
                     m_file.name,m_file.l+1);
-
 
413
    printf(" %s.\n\n",msg);
413
  printf(" %s.\n\n",msg);
414
    if(open_working_file(&mf,mkfname(NULL,"%s.%s",module_error_msg_file,lang))!=0)
414
  if(open_working_file(&mf,mkfname(NULL,"%s.%s",module_error_msg_file,lang))!=0)
415
      internal_error("module_error(): error message file not found.");
415
    internal_error("module_error(): error message file not found.");
416
    while(wgetline(tmplbuf,MAX_LINELEN,&mf)!=EOF) {
416
  while(wgetline(tmplbuf,MAX_LINELEN,&mf)!=EOF) {
417
      if(tmplbuf[0]!=tag_prefix_char) {
417
    if(tmplbuf[0]!=tag_prefix_char) {
418
          if(send) {substit(tmplbuf); puts(tmplbuf);}
418
      if(send) {substit(tmplbuf); puts(tmplbuf);}
419
          continue;
419
      continue;
420
      }
-
 
421
      strip_trailing_spaces(tmplbuf);
-
 
422
      if(tmplbuf[1]==0 || strcmp(msg,tmplbuf+1)==0) send=1;
-
 
423
      else send=0;
-
 
424
    }
420
    }
-
 
421
    strip_trailing_spaces(tmplbuf);
-
 
422
    if(tmplbuf[1]==0 || strcmp(msg,tmplbuf+1)==0) send=1;
-
 
423
    else send=0;
-
 
424
  }
425
    close_working_file(&mf,0);
425
  close_working_file(&mf,0);
426
    outptr=outbuf; delete_pid(); exit(1);
426
  outptr=outbuf; delete_pid(); exit(1);
427
}
427
}
428
 
428
 
429
/* Output kernel routine */
429
/* Output kernel routine */
430
void _output_(char *s)
430
void _output_(char *s)
431
{
431
{
432
    int l,l2;
432
  int l,l2;
433
    l=strlen(s); output_length+=l;
433
  l=strlen(s); output_length+=l;
434
    if(output_length>=OUTPUT_LENGTH_LIMIT) {
434
  if(output_length>=OUTPUT_LENGTH_LIMIT) {
435
      module_error("output_too_long"); return;
435
    module_error("output_too_long"); return;
436
    }
436
  }
437
    l2=sizeof(outbuf)-(outptr-outbuf);
437
  l2=sizeof(outbuf)-(outptr-outbuf);
438
    put: if(l<=l2) {
438
  put: if(l<=l2) {
439
      memmove(outptr,s,l); outptr+=l; return;
439
    memmove(outptr,s,l); outptr+=l; return;
440
    }
440
  }
441
    memmove(outptr,s,l2); s+=l2; l-=l2;
441
  memmove(outptr,s,l2); s+=l2; l-=l2;
442
    if(lastout_file!=-1) (void)write(lastout_file,outbuf,sizeof(outbuf));
442
  if(lastout_file!=-1) (void)write(lastout_file,outbuf,sizeof(outbuf));
443
    else fwrite(outbuf,sizeof(outbuf),1,stdout);
443
  else fwrite(outbuf,sizeof(outbuf),1,stdout);
444
    outptr=outbuf; l2=sizeof(outbuf); goto put;
444
  outptr=outbuf; l2=sizeof(outbuf); goto put;
445
}
445
}
446
 
446
 
447
/* Output with no var. */
447
/* Output with no var. */
448
void output0(char buf[])
448
void output0(char buf[])
449
{
449
{
450
    char *p1, *p2, *ps;
450
  char *p1, *p2, *ps;
451
    int dynsave;
451
  int dynsave;
452
    if(backslash_insmath) {
452
  if(backslash_insmath) {
453
     ps=buf; dynsave=instex_usedynamic;
453
    ps=buf; dynsave=instex_usedynamic;
454
     for(p1=strstr(buf,"\\("); p1; p1=strstr(p2,"\\(")) {
454
    for(p1=strstr(buf,"\\("); p1; p1=strstr(p2,"\\(")) {
455
         p2=find_matching(p1+2,')');
455
      p2=find_matching(p1+2,')');
456
         if(p2==NULL) break;
456
      if(p2==NULL) break;
457
         if(p1>buf && *(p1-1)=='\\') continue;
457
      if(p1>buf && *(p1-1)=='\\') continue;
458
         *p1=0; if(*(p2-1)=='\\') *(p2-1)=0; *p2++=0; _output_(ps); ps=p2;
458
      *p1=0; if(*(p2-1)=='\\') *(p2-1)=0; *p2++=0; _output_(ps); ps=p2;
459
         instex_usedynamic=1; insmath(p1+2);
459
      instex_usedynamic=1; insmath(p1+2);
460
     }
460
    }
461
     if(*ps) _output_(ps);
461
    if(*ps) _output_(ps);
462
     instex_usedynamic=dynsave;
462
    instex_usedynamic=dynsave;
463
    }
463
  }
464
    else _output_(buf);
464
  else _output_(buf);
465
}
465
}
466
 
466
 
467
/* Output routine */
467
/* Output routine */
468
void output(char *s,...)
468
void output(char *s,...)
469
{
469
{
470
    va_list vp;
470
  va_list vp;
471
    char buf[4*MAX_LINELEN+1];
471
  char buf[4*MAX_LINELEN+1];
472
 
472
 
473
    va_start(vp,s);
473
  va_start(vp,s);
474
    vsnprintf(buf,sizeof(buf),s,vp);
474
  vsnprintf(buf,sizeof(buf),s,vp);
475
    va_end(vp);
475
  va_end(vp);
476
    output0(buf);
476
  output0(buf);
477
}
477
}
478
 
478
 
479
/* read in tmpf in tmp directory, and places in p.
479
/* read in tmpf in tmp directory, and places in p.
480
 * Maximal length: MAX_LINELEN.
480
 * Maximal length: MAX_LINELEN.
481
 */
481
 */
482
void read_tmp_file(char *p, const char *fname)
482
void read_tmp_file(char *p, const char *fname)
483
{
483
{
484
    char *name, *pp;
484
  char *name, *pp;
485
    name=mkfname(NULL,"%s/%s",tmp_dir,fname);
485
  name=mkfname(NULL,"%s/%s",tmp_dir,fname);
486
    if(!exec_is_module || !outputing || !direct_exec
486
  if(!exec_is_module || !outputing || !direct_exec
487
       || strcmp(fname,"exec.out")!=0) {
487
     || strcmp(fname,"exec.out")!=0) {
488
      readfile(name,p,MAX_LINELEN);
488
    readfile(name,p,MAX_LINELEN);
489
      pp=getvar("wims_exec_dollar_double");
489
    pp=getvar("wims_exec_dollar_double");
490
      if(pp && strcmp(pp,"yes")==0) {
490
    if(pp && strcmp(pp,"yes")==0) {
491
          for(pp=strchr(p,'$'); pp; pp=strchr(pp+2,'$'))
491
      for(pp=strchr(p,'$'); pp; pp=strchr(pp+2,'$'))
492
            string_modify(p,pp,pp+1,"$$");
492
        string_modify(p,pp,pp+1,"$$");
493
      }
493
    }
494
    }
494
  }
495
    else {
495
  else {
496
      char *s;
496
    char *s;
497
      s=readfile(name,NULL,OUTPUT_LENGTH_LIMIT);
497
    s=readfile(name,NULL,OUTPUT_LENGTH_LIMIT);
498
      if(s==NULL) {*p=0; return;}
498
    if(s==NULL) {*p=0; return;}
499
      if(memcmp(s,"Error: ", strlen("Error: "))==0) mystrncpy(p,s,MAX_LINELEN);
499
    if(memcmp(s,"Error: ", strlen("Error: "))==0) mystrncpy(p,s,MAX_LINELEN);
500
      output_length+=strlen(s);
500
    output_length+=strlen(s);
501
      if(output_length>=OUTPUT_LENGTH_LIMIT) module_error("output_too_long");
501
    if(output_length>=OUTPUT_LENGTH_LIMIT) module_error("output_too_long");
502
      else _output_(s);
502
    else _output_(s);
503
      free(s); *p=0;
503
    free(s); *p=0;
504
      chmod(name,S_IRUSR|S_IWUSR);
504
    chmod(name,S_IRUSR|S_IWUSR);
505
    }
505
  }
506
}
506
}
507
 
507
 
508
/* verify whether the module is trusted.
508
/* verify whether the module is trusted.
509
 * Returns 1 if yes, 0 if no. -1 for error.
509
 * Returns 1 if yes, 0 if no. -1 for error.
510
 */
510
 */
511
int trusted_module(void)
511
int trusted_module(void)
512
{
512
{
513
    char *modname, *w, buf[MAX_LINELEN+1];
513
  char *modname, *w, buf[MAX_LINELEN+1];
514
    int i,n;
514
  int i,n;
515
    static int _trusted=-1;      /* avoid repeated computations */
515
  static int _trusted=-1;      /* avoid repeated computations */
516
 
516
 
517
    if(untrust&255) return 0;
517
  if(untrust&255) return 0;
518
    if(_trusted>=0) return _trusted;
518
  if(_trusted>=0) return _trusted;
519
    modname=getvar(ro_name[ro_module]);
519
  modname=getvar(ro_name[ro_module]);
520
    if(modname==NULL || *modname==0) return 0;
520
  if(modname==NULL || *modname==0) return 0;
521
    if(memcmp(modname,"adm/",strlen("adm/"))==0 ||
521
  if(memcmp(modname,"adm/",strlen("adm/"))==0 ||
522
       memcmp(modname,"classes/",strlen("classes/"))==0 ||
522
     memcmp(modname,"classes/",strlen("classes/"))==0 ||
523
       strcmp(modname,home_module)==0 ||
523
     strcmp(modname,home_module)==0 ||
524
       memcmp(modname,"help/",strlen("help/"))==0) {
524
     memcmp(modname,"help/",strlen("help/"))==0) {
525
      tr:
525
    tr:
526
      if(memcmp(modname,"classes/",strlen("classes/"))==0)
526
    if(memcmp(modname,"classes/",strlen("classes/"))==0)
527
        is_class_module=1;
527
      is_class_module=1;
528
      setenv("trusted_module","yes",1);
528
    setenv("trusted_module","yes",1);
529
      return _trusted=1;
529
    return _trusted=1;
530
    }
530
  }
531
    n=wordnum(trusted_modules); for(i=0;i<n;i++) {
531
  n=wordnum(trusted_modules);
-
 
532
  for(i=0;i<n;i++) {
532
      w=fnd_word(trusted_modules,i+1,buf);
533
    w=fnd_word(trusted_modules,i+1,buf);
533
      if(strcmp(w,modname)==0) goto tr;
534
    if(strcmp(w,modname)==0) goto tr;
534
    }
535
  }
535
    return _trusted=0;
536
  return _trusted=0;
536
}
537
}
537
 
538
 
538
/* file should be in the module directory, but
539
/* file should be in the module directory, but
539
 * it may also be somewhere else.
540
 * it may also be somewhere else.
540
 * buf[] requires MAX_FNAME+1 length.
541
 * buf[] requires MAX_FNAME+1 length.
541
 * Returns 0 if found.
542
 * Returns 0 if found.
542
 */
543
 */
543
int find_module_file(char *fname, char buf[], int mode)
544
int find_module_file(char *fname, char buf[], int mode)
544
{
545
{
545
    char *p, dtest[32];
546
  char *p, dtest[32];
546
 
547
 
547
    fname=find_word_start(fname);
548
  fname=find_word_start(fname);
548
    if(*fname==0) return -1;
549
  if(*fname==0) return -1;
549
/* Name checking: no directory backtracing. */
550
/* Name checking: no directory backtracing. */
550
    if(strstr(fname,parent_dir_string)!=NULL) {
551
  if(strstr(fname,parent_dir_string)!=NULL) {
551
      setvar(error_data_string,fname); module_error("illegal_fname");
552
    setvar(error_data_string,fname); module_error("illegal_fname");
-
 
553
    return -1;
-
 
554
  }
-
 
555
  p=strchr(fname,'/'); if(p==NULL || p>fname+10) goto openit;
-
 
556
  memmove(dtest,fname,p-fname); dtest[p-fname]=0;
-
 
557
  if(strcmp(dtest,"datamodule")==0) {
-
 
558
    mkfname(buf,"modules/data%s",p); goto lastopen;
-
 
559
  }
-
 
560
  if(strcmp(dtest,"wimshome")==0 && trusted_module()) {
-
 
561
    mkfname(buf,"%s%s",getvar("wims_home"),p); goto lastopen;
-
 
562
  }
-
 
563
  if(strcmp(dtest,"writable")==0) {
-
 
564
    if(strncmp(p+1,"TEMP_",5)==0 && strchr(p+1,'/')==NULL) {
-
 
565
      mkfname(buf,"%s/%s",tmp_dir,p+1);
-
 
566
    }
-
 
567
    else {
-
 
568
      mkfname(buf,"w/%s/%s",module_prefix,p+1);
-
 
569
    }
-
 
570
    untrust|=4;
-
 
571
  }
-
 
572
  else {
-
 
573
    openit: mkfname(buf,"%s/%s",module_prefix,fname);
-
 
574
  }
-
 
575
  if(mode) return 0;
-
 
576
  if(ftest(buf)!=is_file) {
-
 
577
    if(lastftype==is_exec) {
-
 
578
isexec:
-
 
579
      setvar("executable",fname); module_error("executable");
552
      return -1;
580
      return -1;
553
    }
581
    }
554
    p=strchr(fname,'/'); if(p==NULL || p>fname+10) goto openit;
-
 
555
    memmove(dtest,fname,p-fname); dtest[p-fname]=0;
-
 
556
    if(strcmp(dtest,"datamodule")==0) {
582
    if(strncmp(fname,"adm/",4)==0 &&
557
      mkfname(buf,"modules/data%s",p); goto lastopen;
-
 
558
    }
-
 
559
    if(strcmp(dtest,"wimshome")==0 && trusted_module()) {
583
       (!trusted_module() || is_class_module)) return -1;
560
      mkfname(buf,"%s%s",getvar("wims_home"),p); goto lastopen;
-
 
561
    }
-
 
562
    if(strcmp(dtest,"writable")==0) {
-
 
563
      if(strncmp(p+1,"TEMP_",5)==0 && strchr(p+1,'/')==NULL) {
-
 
564
          mkfname(buf,"%s/%s",tmp_dir,p+1);
584
      mkfname(buf,"scripts/%s",fname);
565
      }
-
 
566
      else {
-
 
567
          mkfname(buf,"w/%s/%s",module_prefix,p+1);
-
 
568
      }
-
 
569
      untrust|=4;
-
 
570
    }
-
 
571
    else {
585
    lastopen:
572
      openit: mkfname(buf,"%s/%s",module_prefix,fname);
-
 
573
    }
-
 
574
    if(mode) return 0;
586
    if(mode) return 0;
575
    if(ftest(buf)!=is_file) {
587
    if(ftest(buf)!=is_file) {
576
      if(lastftype==is_exec) {
-
 
577
isexec:
-
 
578
          setvar("executable",fname); module_error("executable");
-
 
579
          return -1;
-
 
580
      }
-
 
581
      if(strncmp(fname,"adm/",4)==0 &&
-
 
582
         (!trusted_module() || is_class_module)) return -1;
-
 
583
      mkfname(buf,"scripts/%s",fname);
-
 
584
      lastopen:
-
 
585
      if(mode) return 0;
-
 
586
      if(ftest(buf)!=is_file) {
-
 
587
          if(lastftype==is_exec) goto isexec;
588
      if(lastftype==is_exec) goto isexec;
588
          else return -1;
589
      else return -1;
589
      }
-
 
590
    }
590
    }
-
 
591
  }
591
    return 0;
592
  return 0;
592
}
593
}
593
 
594
 
594
/* check whether a file is user-submitted
595
/* check whether a file is user-submitted
595
 * This is deprecated because of the wimshome/ method.
596
 * This is deprecated because of the wimshome/ method.
596
 */
597
 */
Line 603... Line 604...
603
}
604
}
604
 */
605
 */
605
 
606
 
606
/* returns 1 if violation */
607
/* returns 1 if violation */
607
int datafile_check(char *name) {
608
int datafile_check(char *name) {
608
    if((untrust&255)==0) return 0;
609
  if((untrust&255)==0) return 0;
609
    if(strncmp(name,"data/",strlen("data/"))==0) return 0;
610
  if(strncmp(name,"data/",strlen("data/"))==0) return 0;
610
    if(strncmp(name,"authors/",strlen("authors/"))==0) return 0;
611
  if(strncmp(name,"authors/",strlen("authors/"))==0) return 0;
611
    if(strncmp(name,"datamodule/",strlen("datamodule/"))==0) return 0;
612
  if(strncmp(name,"datamodule/",strlen("datamodule/"))==0) return 0;
612
    return 1;
613
  return 1;
613
}
614
}
614
 
615
 
615
/* returns 0 if success */
616
/* returns 0 if success */
616
void readdatafile(char *name)
617
void readdatafile(char *name)
617
{
618
{
618
    char *pp;
619
  char *pp;
619
    if(strcmp(name,lastdatafile)==0) return;
620
  if(strcmp(name,lastdatafile)==0) return;
620
    lastdata[0]=0; readfile(name,lastdata,WORKFILE_LIMIT);
621
  lastdata[0]=0; readfile(name,lastdata,WORKFILE_LIMIT);
621
    mystrncpy(lastdatafile,name,sizeof(lastdatafile));
622
  mystrncpy(lastdatafile,name,sizeof(lastdatafile));
622
    datacache[0]=lastdata; nextdatacache=1;
623
  datacache[0]=lastdata; nextdatacache=1;
623
    if(lastdata[0]==tag_string[1]) {
624
  if(lastdata[0]==tag_string[1]) {
624
      datacache[1]=lastdata; nextdatacache++;
625
    datacache[1]=lastdata; nextdatacache++;
625
    }
626
  }
626
    pp=strstr(lastdata,tag_string);
627
  pp=strstr(lastdata,tag_string);
627
    if(pp) datacache[nextdatacache]=pp;
628
  if(pp) datacache[nextdatacache]=pp;
628
    else datacache[nextdatacache]=lastdata+strlen(lastdata);
629
  else datacache[nextdatacache]=lastdata+strlen(lastdata);
629
}
630
}
630
 
631
 
631
char *_nextdata(char *p)
632
char *_nextdata(char *p)
632
{
633
{
633
    char *pp;
634
  char *pp;
634
    if(!*p) return p;
635
  if(!*p) return p;
635
    pp=strstr(p,tag_string);
636
  pp=strstr(p,tag_string);
636
    if(pp) return pp;
637
  if(pp) return pp;
637
    else return p+strlen(p);
638
  else return p+strlen(p);
638
}
639
}
639
 
640
 
640
/* datafile structure: number of records.
641
/* datafile structure: number of records.
641
 * tag=1 if direct access
642
 * tag=1 if direct access
642
 */
643
 */
643
unsigned int datafile_recordnum(char *p)
644
unsigned int datafile_recordnum(char *p)
644
{
645
{
645
    char nbuf[MAX_LINELEN+1], *pp;
646
  char nbuf[MAX_LINELEN+1], *pp;
646
    int i, t, ret;
647
  int i, t, ret;
647
 
648
 
648
    t=untrust; ret=0;
649
  t=untrust; ret=0;
649
    if(direct_datafile) mystrncpy(nbuf,p,sizeof(nbuf));
650
  if(direct_datafile) mystrncpy(nbuf,p,sizeof(nbuf));
650
    else if(datafile_check(p)!=0 || find_module_file(p,nbuf,0)) goto ret;
651
  else if(datafile_check(p)!=0 || find_module_file(p,nbuf,0)) goto ret;
651
    readdatafile(nbuf);
652
  readdatafile(nbuf);
652
    for(i=nextdatacache, pp=datacache[i]; *pp;) {
653
  for(i=nextdatacache, pp=datacache[i]; *pp;) {
-
 
654
    pp=_nextdata(pp+1); i++;
-
 
655
    if(i<DATAFIELD_LIMIT) {
-
 
656
      datacache[i]=pp; nextdatacache=i;
-
 
657
    }
-
 
658
  }
-
 
659
  ret=i-1;
-
 
660
  ret:
-
 
661
  untrust=t;
-
 
662
  return ret;
-
 
663
}
-
 
664
 
-
 
665
/* datafile structure: find record n, starting from 1 */
-
 
666
char *datafile_fnd_record(char *p, int n, char bf[])
-
 
667
{
-
 
668
  char nbuf[MAX_LINELEN+1], *pp, *p2;
-
 
669
  int i, t;
-
 
670
 
-
 
671
  bf[0]=0; t=untrust;
-
 
672
  if(n<0) goto ret;
-
 
673
  if(direct_datafile) mystrncpy(nbuf,p,sizeof(nbuf));
-
 
674
  else if(datafile_check(p)!=0 || find_module_file(p,nbuf,0)) goto ret;
-
 
675
  readdatafile(nbuf); if(*lastdata==0) goto ret;
-
 
676
  if(n>nextdatacache) {
-
 
677
    for(i=nextdatacache, pp=datacache[i]; i<n && *pp;) {
653
      pp=_nextdata(pp+1); i++;
678
      pp=_nextdata(pp+1); i++;
654
      if(i<DATAFIELD_LIMIT) {
679
      if(i<DATAFIELD_LIMIT) {
655
          datacache[i]=pp; nextdatacache=i;
680
        datacache[i]=pp; nextdatacache=i;
656
      }
681
      }
657
    }
682
    }
658
    ret=i-1;
-
 
659
    ret:
-
 
660
    untrust=t;
-
 
661
    return ret;
-
 
662
}
-
 
663
 
-
 
664
/* datafile structure: find record n, starting from 1 */
-
 
665
char *datafile_fnd_record(char *p, int n, char bf[])
-
 
666
{
-
 
667
    char nbuf[MAX_LINELEN+1], *pp, *p2;
-
 
668
    int i, t;
-
 
669
 
-
 
670
    bf[0]=0; t=untrust;
-
 
671
    if(n<0) goto ret;
-
 
672
    if(direct_datafile) mystrncpy(nbuf,p,sizeof(nbuf));
-
 
673
    else if(datafile_check(p)!=0 || find_module_file(p,nbuf,0)) goto ret;
-
 
674
    readdatafile(nbuf); if(*lastdata==0) goto ret;
-
 
675
    if(n>nextdatacache) {
-
 
676
      for(i=nextdatacache, pp=datacache[i]; i<n && *pp;) {
-
 
677
          pp=_nextdata(pp+1); i++;
-
 
678
          if(i<DATAFIELD_LIMIT) {
-
 
679
            datacache[i]=pp; nextdatacache=i;
-
 
680
          }
-
 
681
      }
-
 
682
    }
683
  }
683
    else pp=datacache[n];
684
  else pp=datacache[n];
684
    if(!*pp) goto ret;
685
  if(!*pp) goto ret;
685
    if(n>1 || (n==1 && *pp!=tag_string[1])) pp+=strlen(tag_string);
686
  if(n>1 || (n==1 && *pp!=tag_string[1])) pp+=strlen(tag_string);
686
    else if(n==1) pp+=strlen(tag_string)-1;
687
  else if(n==1) pp+=strlen(tag_string)-1;
687
    if(n<nextdatacache) p2=datacache[n+1];
688
  if(n<nextdatacache) p2=datacache[n+1];
688
    else {
689
  else {
689
      p2=strstr(pp,tag_string); if(p2==NULL) p2=pp+strlen(pp);
690
    p2=strstr(pp,tag_string); if(p2==NULL) p2=pp+strlen(pp);
690
      if(n<DATAFIELD_LIMIT-1 && n==nextdatacache) {
691
    if(n<DATAFIELD_LIMIT-1 && n==nextdatacache) {
691
          nextdatacache++; datacache[nextdatacache]=p2;
692
          nextdatacache++; datacache[nextdatacache]=p2;
692
      }
-
 
693
    }
693
    }
-
 
694
  }
694
    if(p2-pp>=MAX_LINELEN) p2=pp+MAX_LINELEN-1;
695
  if(p2-pp>=MAX_LINELEN) p2=pp+MAX_LINELEN-1;
695
    if(p2<pp) p2=pp;
696
  if(p2<pp) p2=pp;
696
    memmove(bf,pp,p2-pp); bf[p2-pp]=0;
697
  memmove(bf,pp,p2-pp); bf[p2-pp]=0;
697
    ret:
698
  ret:
698
    untrust=t; return bf;
699
  untrust=t; return bf;
699
}
700
}
700
 
701
 
701
char hex2char(char c1, char c2)
702
char hex2char(char c1, char c2)
702
{
703
{
703
    char tbuf[16];
704
  char tbuf[16];
704
    if(c1<'0' || c1>'f' || c2<'0' || c2>'f') {
705
  if(c1<'0' || c1>'f' || c2<'0' || c2>'f') {
705
invl:
706
invl:
706
      snprintf(tbuf,sizeof(tbuf),"%%%c%c",c1,c2);
707
    snprintf(tbuf,sizeof(tbuf),"%%%c%c",c1,c2);
707
      setvar(error_data_string,tbuf);
708
    setvar(error_data_string,tbuf);
708
      user_error("invalid_char_in_query_string");
709
    user_error("invalid_char_in_query_string");
709
    }
710
  }
710
    c1=toupper(c1);c2=toupper(c2);
711
  c1=toupper(c1);c2=toupper(c2);
711
    if(c1>'9' && c1<'A') goto invl;
712
  if(c1>'9' && c1<'A') goto invl;
712
    if(c2>'9' && c2<'A') goto invl;
713
  if(c2>'9' && c2<'A') goto invl;
713
    if(c1>'F' || c2>'F') goto invl;
714
  if(c1>'F' || c2>'F') goto invl;
714
    if(c1>='A') c1=c1-'A'+'9'+1;
715
  if(c1>='A') c1=c1-'A'+'9'+1;
715
    if(c2>='A') c2=c2-'A'+'9'+1;
716
  if(c2>='A') c2=c2-'A'+'9'+1;
716
    return (c1-'0')*16+c2-'0';
717
  return (c1-'0')*16+c2-'0';
717
}
718
}
718
 
719
 
719
/* Converts back http escaped chars, slight. Does not check buffer length.
720
/* Converts back http escaped chars, slight. Does not check buffer length.
720
 * Returns converted string length.
721
 * Returns converted string length.
721
 */
722
 */
722
int _http2env(char outs[], char ins[])
723
int _http2env(char outs[], char ins[])
723
{
724
{
724
    int j,k,l;
725
  int j,k,l;
725
    l=strlen(ins);
726
  l=strlen(ins);
726
    for(j=k=0;j<l && !isspace(ins[j]);j++,k++) {
727
  for(j=k=0;j<l && !isspace(ins[j]);j++,k++) {
727
      if(isspace(ins[j])) {  /* skip space characters in query string */
728
    if(isspace(ins[j])) {  /* skip space characters in query string */
728
          k--;continue;
729
      k--;continue;
729
      }
730
    }
730
      if(ins[j]=='%') {
731
    if(ins[j]=='%') {
731
/* skip Carriage-Return. */
732
/* skip Carriage-Return. */
732
          if(ins[j+1]=='0' && (ins[j+2]=='d' || ins[j+2]=='D')) {
733
        if(ins[j+1]=='0' && (ins[j+2]=='d' || ins[j+2]=='D')) {
733
            j+=2; k--; continue;
734
          j+=2; k--; continue;
734
          }
735
        }
735
          outs[k]=hex2char(ins[j+1],ins[j+2]);
736
        outs[k]=hex2char(ins[j+1],ins[j+2]);
736
          j+=2; continue;
737
        j+=2; continue;
737
      }
738
    }
738
      outs[k]=ins[j];
739
    outs[k]=ins[j];
739
    }
740
  }
740
    outs[k]=0;
741
  outs[k]=0;
741
    return k;
742
  return k;
742
}
743
}
743
 
744
 
744
/* Converts back http escaped chars. Does not check buffer length.
745
/* Converts back http escaped chars. Does not check buffer length.
745
 * Returns converted string length.
746
 * Returns converted string length.
746
 */
747
 */
747
int http2env(char outs[], char ins[])
748
int http2env(char outs[], char ins[])
748
{
749
{
749
    int j,k,l;
750
  int j,k,l;
750
    l=strlen(ins);
751
  l=strlen(ins);
751
    for(j=k=0;j<l && !isspace(ins[j]);j++,k++) {
752
  for(j=k=0;j<l && !isspace(ins[j]);j++,k++) {
752
      if(isspace(ins[j])) {  /* skip space characters in query string */
753
    if(isspace(ins[j])) {  /* skip space characters in query string */
753
          k--;continue;
754
      k--;continue;
754
      }
755
    }
755
      if(ins[j]=='%') {
756
    if(ins[j]=='%') {
756
/* skip Carriage-Return. */
757
/* skip Carriage-Return. */
757
          if(ins[j+1]=='0' && (ins[j+2]=='d' || ins[j+2]=='D')) {
758
      if(ins[j+1]=='0' && (ins[j+2]=='d' || ins[j+2]=='D')) {
758
            j+=2; k--; continue;
759
        j+=2; k--; continue;
759
          }
-
 
760
          outs[k]=hex2char(ins[j+1],ins[j+2]);
-
 
761
          j+=2; continue;
-
 
762
      }
760
      }
763
      if(ins[j]=='+') {
-
 
764
          outs[k]=' '; continue;
-
 
765
      }
-
 
766
      if(ins[j]=='?' || ins[j]=='&') {
761
      outs[k]=hex2char(ins[j+1],ins[j+2]);
767
          outs[k]=0; continue;
762
      j+=2; continue;
768
      }
-
 
769
      outs[k]=ins[j];
-
 
770
    }
763
    }
-
 
764
    if(ins[j]=='+') {
-
 
765
      outs[k]=' '; continue;
-
 
766
    }
-
 
767
    if(ins[j]=='?' || ins[j]=='&') {
-
 
768
      outs[k]=0; continue;
-
 
769
    }
-
 
770
    outs[k]=ins[j];
-
 
771
  }
771
    outs[k]=0;
772
  outs[k]=0;
772
    return k;
773
  return k;
773
}
774
}
774
 
775
 
775
/* translate a string to http querystring style.
776
/* translate a string to http querystring style.
776
 * '&' is not translated.
777
 * '&' is not translated.
777
 * Buffer p must be at least MAX_LINELEN.
778
 * Buffer p must be at least MAX_LINELEN.
778
 */
779
 */
779
void tohttpquery(char *p)
780
void tohttpquery(char *p)
780
{
781
{
781
    char trlist[]="     ()[]{}+-*^|/\"\'!:;,<>\n";
782
  char trlist[]="       ()[]{}+-*^|/\"\'!:;,<>\n";
782
    char *pp;
783
  char *pp;
783
    for(pp=p;*pp;pp++) {
784
  for(pp=p;*pp;pp++) {
784
      if(*pp==' ') {
785
    if(*pp==' ') {
785
          *pp='+'; continue;
786
      *pp='+'; continue;
786
      }
787
    }
787
      if(strchr(trlist,*pp)==NULL) continue;
788
    if(strchr(trlist,*pp)==NULL) continue;
788
      if(*pp=='+' && pp>p && *(pp-1)=='&') continue;
789
    if(*pp=='+' && pp>p && *(pp-1)=='&') continue;
789
      if(pp>p && *(pp-1)=='\\') {
790
    if(pp>p && *(pp-1)=='\\') {
790
          ovlstrcpy(pp-1,pp);pp--;continue;
791
      ovlstrcpy(pp-1,pp);pp--;continue;
791
      }
792
    }
792
      if(*pp=='\n') {
793
    if(*pp=='\n') {
793
          string_modify(p,pp,pp+1,"%%0D%%0A");pp+=5;
794
      string_modify(p,pp,pp+1,"%%0D%%0A");pp+=5;
794
      }
795
    }
795
      else {
796
    else {
796
          string_modify(p,pp,pp+1,"%%%02X",*pp);pp+=2;
797
        string_modify(p,pp,pp+1,"%%%02X",*pp);pp+=2;
797
      }
-
 
798
    }
798
    }
-
 
799
  }
799
}
800
}
800
 
801
 
801
/* substitute backslash parameters. Internal use only. */
802
/* substitute backslash parameters. Internal use only. */
802
void slashsubst(char *p)
803
void slashsubst(char *p)
803
{
804
{
804
    char *p1, *p2, *pt, *pp, namebuf[128];
805
  char *p1, *p2, *pt, *pp, namebuf[128];
805
    int n;
806
  int n;
806
 
807
 
807
    n=strlen(mathfont_prefix); memmove(namebuf,mathfont_prefix,n+1);
808
  n=strlen(mathfont_prefix); memmove(namebuf,mathfont_prefix,n+1);
808
    for(p1=strchr(p,'\\'); p1!=NULL; p1=strchr(p1,'\\')) {
809
  for(p1=strchr(p,'\\'); p1!=NULL; p1=strchr(p1,'\\')) {
809
      p1++; for(p2=p1; myisalnum(*p2) || *p2=='_'; p2++);
810
    p1++; for(p2=p1; myisalnum(*p2) || *p2=='_'; p2++);
810
      if(p2<=p1 || p2>p1+100) continue;
811
    if(p2<=p1 || p2>p1+100) continue;
811
      memmove(namebuf+n,p1,p2-p1); namebuf[p2-p1+n]=0;
812
    memmove(namebuf+n,p1,p2-p1); namebuf[p2-p1+n]=0;
812
      pt=_getvar(namebuf); if(pt==NULL) continue;
813
    pt=_getvar(namebuf); if(pt==NULL) continue;
813
      if(*p2=='[' && (pp=find_matching(p2+1,']'))!=NULL) {
814
    if(*p2=='[' && (pp=find_matching(p2+1,']'))!=NULL) {
814
          string_modify(p,pp+1,pp+1,")");
815
      string_modify(p,pp+1,pp+1,")");
815
          string_modify(p,p1-1,p1,"$(%s",mathfont_prefix);
816
      string_modify(p,p1-1,p1,"$(%s",mathfont_prefix);
816
      }
-
 
817
      else string_modify(p,p1-1,p1,"$%s",mathfont_prefix);
-
 
818
    }
817
    }
-
 
818
    else string_modify(p,p1-1,p1,"$%s",mathfont_prefix);
-
 
819
  }
819
}
820
}
820
 
821
 
821
/* two alarm handlers. */
822
/* two alarm handlers. */
822
void alarm1(int s)
823
void alarm1(int s)
823
{
824
{
824
    if(killpid>0 && kill(killpid,SIGKILL)) module_error("timeup");
825
  if(killpid>0 && kill(killpid,SIGKILL)) module_error("timeup");
825
    killpid=0;
826
  killpid=0;
826
}
827
}
827
 
828
 
828
void alarm2(int s)
829
void alarm2(int s)
829
{
830
{
830
    cleantmpdir();
831
  cleantmpdir();
831
    alarm1(s); module_error("timeup");
832
  alarm1(s); module_error("timeup");
832
}
833
}
833
 
834
 
834
void finalalarm(void)
835
void finalalarm(void)
835
{
836
{
836
    time_t curr;
837
  time_t curr;
837
    curr=time(0);
838
  curr=time(0);
838
    if(curr>=limtime) alarm2(SIGALRM);
839
  if(curr>=limtime) alarm2(SIGALRM);
839
    errno=0;
840
  errno=0;
840
    if(signal(SIGALRM,alarm2)==SIG_ERR)
841
  if(signal(SIGALRM,alarm2)==SIG_ERR)
841
      internal_error(strerror(errno));
842
    internal_error(strerror(errno));
842
    alarm(limtime-curr+1);
843
  alarm(limtime-curr+1);
843
}
844
}
844
 
845
 
845
void initalarm(void)
846
void initalarm(void)
846
{
847
{
847
    limtimex=nowtime+4*rlimit_cpu/3;
848
  limtimex=nowtime+4*rlimit_cpu/3;
848
    limtime=limtimex+2; finalalarm();
849
  limtime=limtimex+2; finalalarm();
849
}
850
}
850
 
851
 
851
void forkalarm(void)
852
void forkalarm(void)
852
{
853
{
853
    time_t curr;
854
  time_t curr;
854
    curr=time(0);
855
  curr=time(0);
855
    if(curr>=limtimex) {alarm1(SIGALRM); return;}
856
  if(curr>=limtimex) {alarm1(SIGALRM); return;}
856
    if(signal(SIGALRM,alarm1)==SIG_ERR)
857
  if(signal(SIGALRM,alarm1)==SIG_ERR)
857
      internal_error(strerror(errno));
858
    internal_error(strerror(errno));
858
    alarm(limtimex-curr+1);
859
  alarm(limtimex-curr+1);
859
}
860
}
860
 
861
 
861
/* create pid tag */
862
/* create pid tag */
862
void create_pid(void)
863
void create_pid(void)
863
{
864
{
864
    char buf[MAX_FNAME+1], pbuf[256], obuf[MAX_FNAME+1];
865
  char buf[MAX_FNAME+1], pbuf[256], obuf[MAX_FNAME+1];
865
    struct stat dst;
866
  struct stat dst;
866
    struct utimbuf ub;
867
  struct utimbuf ub;
867
 
868
 
868
    if(robot_access || *session_prefix==0) return;
869
  if(robot_access || *session_prefix==0) return;
869
    if(cmd_type==cmd_getframe) return;
870
  if(cmd_type==cmd_getframe) return;
870
    mkfname(buf,"%s/.pid",s2_prefix);
871
  mkfname(buf,"%s/.pid",s2_prefix);
871
/* another process running? */
872
/* another process running? */
872
    if(readfile(buf,pbuf,sizeof(pbuf))!=NULL) {
873
  if(readfile(buf,pbuf,sizeof(pbuf))!=NULL) {
873
      mkfname(obuf,"/proc/%s",pbuf);
874
    mkfname(obuf,"/proc/%s",pbuf);
874
      if(stat(obuf,&dst)==0) user_error("double_click");
875
    if(stat(obuf,&dst)==0) user_error("double_click");
875
    }
876
  }
876
    snprintf(pidbuf,sizeof(pidbuf),"%u",getpid());
877
  snprintf(pidbuf,sizeof(pidbuf),"%u",getpid());
877
    accessfile(pidbuf,"w","%s",buf);
878
  accessfile(pidbuf,"w","%s",buf);
878
/* Touch session time */
879
/* Touch session time */
879
    if(strstr(session_prefix,"sessions/")==NULL) return;
880
  if(strstr(session_prefix,"sessions/")==NULL) return;
880
    ub.actime=ub.modtime=nowtime;
881
  ub.actime=ub.modtime=nowtime;
881
    utime(session_prefix,&ub);
882
  utime(session_prefix,&ub);
882
    if(strchr(session_prefix,'_')!=NULL) { /* touch parent too */
883
  if(strchr(session_prefix,'_')!=NULL) { /* touch parent too */
883
      char sbuf[MAX_FNAME+1], *p;
884
    char sbuf[MAX_FNAME+1], *p;
884
      mystrncpy(sbuf,session_prefix,sizeof(sbuf));
885
    mystrncpy(sbuf,session_prefix,sizeof(sbuf));
885
      p=strchr(sbuf,'_'); if(p!=NULL) *p=0;
886
    p=strchr(sbuf,'_'); if(p!=NULL) *p=0;
886
      utime(sbuf,&ub);
887
    utime(sbuf,&ub);
887
    }
888
  }
888
}
889
}
889
 
890
 
890
struct mxtab mxtab[MAX_MULTIEXEC];
891
struct mxtab mxtab[MAX_MULTIEXEC];
891
int mxno=0;
892
int mxno=0;
892
 
893
 
893
int execredirected(char *cmdf, char *inf, char *outf, char *errf, char *arg[])
894
int execredirected(char *cmdf, char *inf, char *outf, char *errf, char *arg[])
894
{
895
{
895
    pid_t pid;
896
  pid_t pid;
896
    int status, t;
897
  int status, t;
897
 
898
 
898
    if(robot_access) return 0;
899
  if(robot_access) return 0;
899
    if(time(0)>=limtimex) {
900
  if(time(0)>=limtimex) {
900
      if(errf!=NULL)
901
    if(errf!=NULL)
901
        accessfile("No time left to execute subprograms.\n","w","%s",errf);
902
      accessfile("No time left to execute subprograms.\n","w","%s",errf);
902
      return -100;
903
    return -100;
903
    }
904
  }
904
    lastdatafile[0]=lastftest[0]=0;
905
  lastdatafile[0]=lastftest[0]=0;
905
    fflush(NULL); /* flush all output streams before forking
906
  fflush(NULL); /* flush all output streams before forking
906
                   * otherwise they will be doubled
907
                 * otherwise they will be doubled
907
                   */
908
                 */
908
    pid=fork(); if(pid==-1) return -1;
909
  pid=fork(); if(pid==-1) return -1;
909
    if(!pid) {      /* child */
910
  if(!pid) {      /* child */
910
      char buf[MAX_LINELEN+1]; int k;
911
    char buf[MAX_LINELEN+1]; int k;
911
      (void)nice(10);      /* lower priority for children */
912
    (void)nice(10);      /* lower priority for children */
912
      if(is_multiexec) {
913
    if(is_multiexec) {
913
          dup2(mxtab[multiexec_index].pipe_stdin[0],0);
914
      dup2(mxtab[multiexec_index].pipe_stdin[0],0);
914
          dup2(mxtab[multiexec_index].pipe_stdout[1],1);
915
      dup2(mxtab[multiexec_index].pipe_stdout[1],1);
915
          dup2(mxtab[multiexec_index].pipe_stderr[1],2);
916
      dup2(mxtab[multiexec_index].pipe_stderr[1],2);
916
      }
917
    }
917
      else {
918
    else {
918
          if(inf!=NULL) (void)freopen(inf,"r",stdin);
919
      if(inf!=NULL) (void)freopen(inf,"r",stdin);
919
          if(outf!=NULL) (void)freopen(outf,"w",stdout);
920
      if(outf!=NULL) (void)freopen(outf,"w",stdout);
920
          if(errf!=NULL) (void)freopen(errf,"w",stderr);
921
      if(errf!=NULL) (void)freopen(errf,"w",stderr);
921
      }
922
    }
922
/* This is to patch LinuxPPC uid wrapping
923
/* This is to patch LinuxPPC uid wrapping
923
 * for scripts */
924
 * for scripts */
924
      t=0; if(strchr(cmdf,'/')) {
925
    t=0; if(strchr(cmdf,'/')) {
925
          int tf;
926
      int tf;
926
          char tbuf[16];
927
      char tbuf[16];
927
          tf=open(cmdf,O_RDONLY); (void)read(tf,tbuf,8); close(tf);
928
      tf=open(cmdf,O_RDONLY); (void)read(tf,tbuf,8); close(tf);
928
          if(memcmp(tbuf+1,"ELF",3)!=0) t=1;
929
      if(memcmp(tbuf+1,"ELF",3)!=0) t=1;
929
      }
930
    }
930
      if(wrapexec==-1) {
931
    if(wrapexec==-1) {
931
          setreuid(getuid(),getuid());setregid(getgid(),getgid());
932
      setreuid(getuid(),getuid());setregid(getgid(),getgid());
932
      }
933
    }
933
      if(wrapexec==1 || (t==1 && wrapexec==0)) {
934
    if(wrapexec==1 || (t==1 && wrapexec==0)) {
934
          setreuid(geteuid(),geteuid());setregid(getegid(),getegid());
935
      setreuid(geteuid(),geteuid());setregid(getegid(),getegid());
935
      }
936
    }
936
      errno=0;
937
    errno=0;
937
      if(strchr(cmdf,'/')) execve(cmdf,arg,environ);
938
    if(strchr(cmdf,'/')) execve(cmdf,arg,environ);
938
      else execvp(cmdf,arg);
939
    else execvp(cmdf,arg);
939
      snprintf(buf,sizeof(buf),"Failed to execute");
940
    snprintf(buf,sizeof(buf),"Failed to execute");
940
      for(k=0;arg[k];k++) {
941
    for(k=0;arg[k];k++) {
941
          t=strlen(buf);
-
 
942
          snprintf(buf+t,sizeof(buf)-t," %s",arg[k]);
-
 
943
      }
-
 
944
      t=strlen(buf);
942
      t=strlen(buf);
945
      snprintf(buf+t,sizeof(buf)-t,"\n  %s\n",strerror(errno));
943
      snprintf(buf+t,sizeof(buf)-t," %s",arg[k]);
946
      accessfile(buf,"a","%s/exec.fail",tmp_dir);
-
 
947
      exit(127);
-
 
948
    }
944
    }
-
 
945
    t=strlen(buf);
-
 
946
    snprintf(buf+t,sizeof(buf)-t,"\n    %s\n",strerror(errno));
-
 
947
    accessfile(buf,"a","%s/exec.fail",tmp_dir);
-
 
948
    exit(127);
-
 
949
  }
949
    else {      /* parent */
950
  else {      /* parent */
950
      wrapexec=0; status=0;
951
    wrapexec=0; status=0;
951
      if(exec_wait && !is_multiexec) {
952
    if(exec_wait && !is_multiexec) {
952
          killpid=pid; forkalarm();
953
      killpid=pid; forkalarm();
953
          waitpid(pid,&status,0); killpid=0; finalalarm();
954
      waitpid(pid,&status,0); killpid=0; finalalarm();
954
      }
-
 
955
      return WEXITSTATUS(status);
-
 
956
    }
955
    }
-
 
956
    return WEXITSTATUS(status);
-
 
957
  }
957
}
958
}
958
 
959
 
959
/* preparation for resident execution.
960
/* preparation for resident execution.
960
 * Returns 1 if already up, otherwise 0.
961
 * Returns 1 if already up, otherwise 0.
961
 */
962
 */
962
int multiexec(char *cmd, char **abuf)
963
int multiexec(char *cmd, char **abuf)
963
{
964
{
964
    char *p;
965
  char *p;
965
    int i;
966
  int i;
966
 
967
 
967
    if(robot_access) return 0;
968
  if(robot_access) return 0;
968
    if(strstr(tmp_dir,"sessions/")==NULL) return 0;
969
  if(strstr(tmp_dir,"sessions/")==NULL) return 0;
969
    if(strstr(tmp_debug,"yes")!=NULL && checkhost(manager_site)>=1)
970
  if(strstr(tmp_debug,"yes")!=NULL && checkhost(manager_site)>=1)
970
      setenv("multiexec_debug","yes",1);
971
    setenv("multiexec_debug","yes",1);
971
    p=getvar("wims_multiexec");
972
  p=getvar("wims_multiexec");
972
    if(p==NULL || wordchr(p,cmd)==NULL) return 0; /* not allowed */
973
  if(p==NULL || wordchr(p,cmd)==NULL) return 0; /* not allowed */
973
    if(!multiexec_random[0]) {
974
  if(!multiexec_random[0]) {
974
      snprintf(multiexec_random, sizeof(multiexec_random),
975
    snprintf(multiexec_random, sizeof(multiexec_random),
975
             "%lX%lX%lX%lX%lX%lX%lX%lX",
976
           "%lX%lX%lX%lX%lX%lX%lX%lX",
976
             random(),random(),random(),random(),
977
           random(),random(),random(),random(),
977
             random(),random(),random(),random());
978
           random(),random(),random(),random());
978
      setenv("multiexec_random",multiexec_random,1);
979
    setenv("multiexec_random",multiexec_random,1);
979
    }
980
  }
980
    for(i=0;i<mxno && strcmp(cmd,mxtab[i].cmd)!=0; i++);
981
  for(i=0;i<mxno && strcmp(cmd,mxtab[i].cmd)!=0; i++);
981
    multiexec_index=i;
982
  multiexec_index=i;
982
    if(i==mxno) {
983
  if(i==mxno) {
983
      if(mxno>=MAX_MULTIEXEC) return 0;
984
    if(mxno>=MAX_MULTIEXEC) return 0;
984
      if(pipe(mxtab[i].pipe_stdin)<0) return 0;
985
    if(pipe(mxtab[i].pipe_stdin)<0) return 0;
985
      if(pipe(mxtab[i].pipe_stdout)<0) return 0;
986
    if(pipe(mxtab[i].pipe_stdout)<0) return 0;
986
      if(pipe(mxtab[i].pipe_stderr)<0) return 0;
987
    if(pipe(mxtab[i].pipe_stderr)<0) return 0;
987
      mystrncpy(mxtab[i].cmd,cmd,sizeof(mxtab[i].cmd));
988
    mystrncpy(mxtab[i].cmd,cmd,sizeof(mxtab[i].cmd));
988
      mxno++;      is_multiexec=1;
989
    mxno++;      is_multiexec=1;
989
      exportall(); setenv("wims_exec_parm",multiexec_random,1);
990
    exportall(); setenv("wims_exec_parm",multiexec_random,1);
990
      execredirected(abuf[0],NULL,NULL,NULL,abuf);
991
    execredirected(abuf[0],NULL,NULL,NULL,abuf);
991
    }
992
  }
992
    is_multiexec=0;
993
  is_multiexec=0;
993
    return 1;
994
  return 1;
994
}
995
}
995
 
996
 
996
/* my system(), but with variable parms
997
/* my system(), but with variable parms
997
 * More secure than system(), and direct fork.
998
 * More secure than system(), and direct fork.
998
 */
999
 */
999
int call_ssh(char *s,...)
1000
int call_ssh(char *s,...)
1000
{
1001
{
1001
    va_list vp;
1002
  va_list vp;
1002
    char buf[MAX_LINELEN+1];
1003
  char buf[MAX_LINELEN+1];
1003
    char *arg[1024];
1004
  char *arg[1024];
1004
    char *inf=NULL, *outf=NULL, *errf=NULL;
1005
  char *inf=NULL, *outf=NULL, *errf=NULL;
1005
    char *cmdf, *p, *p2;
1006
  char *cmdf, *p, *p2;
1006
    int i, d;
1007
  int i, d;
1007
 
1008
 
1008
    if(robot_access) return 0;
1009
  if(robot_access) return 0;
1009
    va_start(vp,s);
1010
  va_start(vp,s);
1010
    vsnprintf(buf,sizeof(buf),s,vp);
1011
  vsnprintf(buf,sizeof(buf),s,vp);
1011
    va_end(vp);
1012
  va_end(vp);
1012
    p=find_word_start(buf); if(*p==0) return 0;
1013
  p=find_word_start(buf); if(*p==0) return 0;
1013
    cmdf=p;
1014
  cmdf=p;
1014
    for(i=0;*p!=0 && i<1000; p=find_word_start(p2)) {
1015
  for(i=0;*p!=0 && i<1000; p=find_word_start(p2)) {
1015
      switch(*p) {
1016
    switch(*p) {
1016
          case '\'': {
1017
      case '\'': {
1017
            p++; p2=strchr(p,'\''); if(p2==NULL) p2=p+strlen(p);
1018
        p++; p2=strchr(p,'\''); if(p2==NULL) p2=p+strlen(p);
1018
            d=0; break;
1019
        d=0; break;
1019
          }
1020
      }
1020
          case '"': {
1021
      case '"': {
1021
            p++; p2=strchr(p,'"'); if(p2==NULL) p2=p+strlen(p);
1022
        p++; p2=strchr(p,'"'); if(p2==NULL) p2=p+strlen(p);
1022
            d=0; break;
1023
        d=0; break;
1023
          }
1024
      }
1024
          default: d=1; p2=find_word_end(p); break;
1025
      default: d=1; p2=find_word_end(p); break;
1025
      }
1026
    }
1026
      if(*p2) *p2++=0;
1027
    if(*p2) *p2++=0;
1027
      if(!d) {arg[i++]=p; continue;}
1028
    if(!d) {arg[i++]=p; continue;}
1028
      switch(*p) {
1029
    switch(*p) {
1029
          case '<': inf=++p; break;
1030
      case '<': inf=++p; break;
1030
          case '>': {
1031
      case '>': {
-
 
1032
        p++;
1031
            p++; if(*p=='&') {
1033
        if(*p=='&') {
1032
                merge: p++; errf=outf=p; break;
1034
          merge: p++; errf=outf=p; break;
1033
            }
1035
        }
1034
            else outf=p;
1036
        else outf=p;
1035
            break;
1037
        break;
1036
          }
1038
      }
1037
          case '&': {
1039
      case '&': {
-
 
1040
        p++;
1038
            p++; if(*p=='>') goto merge;
1041
        if(*p=='>') goto merge;
1039
            else break;
1042
        else break;
1040
          }
1043
      }
1041
          case '2': {
1044
      case '2': {
1042
            if(*(p+1)=='>') {errf=p+2; break;}
1045
        if(*(p+1)=='>') {errf=p+2; break;}
1043
          }
-
 
1044
          default: arg[i++]=p; break;
-
 
1045
      }
1046
      }
-
 
1047
      default: arg[i++]=p; break;
1046
    }
1048
    }
-
 
1049
  }
1047
    arg[i]=NULL;
1050
  arg[i]=NULL;
1048
    return execredirected(cmdf,inf,outf,errf,arg);
1051
  return execredirected(cmdf,inf,outf,errf,arg);
1049
}
1052
}
1050
 
1053
 
1051
/* Read/write to a file with variable parms to print filename */
1054
/* Read/write to a file with variable parms to print filename */
1052
void accessfile(char *content, char *type, char *s,...)
1055
void accessfile(char *content, char *type, char *s,...)
1053
{
1056
{
1054
    va_list vp;
1057
  va_list vp;
1055
    char buf[MAX_FNAME+1];
1058
  char buf[MAX_FNAME+1];
1056
    int fd;
1059
  int fd;
1057
 
1060
 
1058
    if(robot_access) return;
1061
  if(robot_access) return;
1059
    va_start(vp,s);
1062
  va_start(vp,s);
1060
    vsnprintf(buf,sizeof(buf),s,vp);
1063
  vsnprintf(buf,sizeof(buf),s,vp);
1061
    va_end(vp);
1064
  va_end(vp);
1062
    if(strlen(buf)>=MAX_FNAME-1) nametoolong(buf);
1065
  if(strlen(buf)>=MAX_FNAME-1) nametoolong(buf);
1063
    switch(*type) {
1066
  switch(*type) {
1064
      case 'r': readfile(buf,content,MAX_LINELEN); return;
1067
    case 'r': readfile(buf,content,MAX_LINELEN); return;
1065
      case 'e': readfile(buf,content,MAX_LINELEN/4); return; /* limited read */
1068
    case 'e': readfile(buf,content,MAX_LINELEN/4); return; /* limited read */
1066
      case 'w': fd=creat(buf,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); break;
1069
    case 'w': fd=creat(buf,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); break;
1067
      case 'a': fd=open(buf,O_WRONLY|O_CREAT|O_APPEND,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); break;
1070
    case 'a': fd=open(buf,O_WRONLY|O_CREAT|O_APPEND,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH); break;
1068
      default : return;
1071
    default : return;
1069
    }
1072
  }
1070
    lastdatafile[0]=lastftest[0]=0;
1073
  lastdatafile[0]=lastftest[0]=0;
1071
    if(fd==-1) return;
1074
  if(fd==-1) return;
1072
    (void)write(fd,content,strlen(content)); close(fd);
1075
  (void)write(fd,content,strlen(content)); close(fd);
1073
}
1076
}
1074
 
1077
 
1075
/* system(), but with variable parms
1078
/* system(), but with variable parms
1076
 * Uses sh to execute command.
1079
 * Uses sh to execute command.
1077
 */
1080
 */
1078
int call_sh(char *s,...)
1081
int call_sh(char *s,...)
1079
{
1082
{
1080
    va_list vp;
1083
  va_list vp;
1081
    char buf[MAX_LINELEN+1];
1084
  char buf[MAX_LINELEN+1];
1082
    char *abuf[8];
1085
  char *abuf[8];
1083
 
1086
 
1084
    if(robot_access) return 0;
1087
  if(robot_access) return 0;
1085
    va_start(vp,s);
1088
  va_start(vp,s);
1086
    vsnprintf(buf,sizeof(buf),s,vp);
1089
  vsnprintf(buf,sizeof(buf),s,vp);
1087
    va_end(vp);
1090
  va_end(vp);
1088
    abuf[0]="sh"; abuf[1]="-c"; abuf[2]=buf; abuf[3]=NULL;
1091
  abuf[0]="sh"; abuf[1]="-c"; abuf[2]=buf; abuf[3]=NULL;
1089
    return execredirected(abuf[0],NULL,NULL,NULL,abuf);
1092
  return execredirected(abuf[0],NULL,NULL,NULL,abuf);
1090
}
1093
}
1091
 
1094
 
1092
void _getdef(char buf[], char *name, char value[])
1095
void _getdef(char buf[], char *name, char value[])
1093
{
1096
{
1094
    char *p1, *p2, *p3, *p4;
1097
  char *p1, *p2, *p3, *p4;
1095
 
1098
 
1096
    if(*name==0) goto nothing;      /* this would create segfault. */
1099
  if(*name==0) goto nothing;      /* this would create segfault. */
1097
    for(p1=strstr(buf,name); p1!=NULL; p1=strstr(p1+1,name)) {
1100
  for(p1=strstr(buf,name); p1!=NULL; p1=strstr(p1+1,name)) {
1098
      p2=find_word_start(p1+strlen(name));
1101
    p2=find_word_start(p1+strlen(name));
1099
      if((p1>buf && !isspace(*(p1-1))) || *p2!='=') continue;
1102
    if((p1>buf && !isspace(*(p1-1))) || *p2!='=') continue;
1100
      p3=p1; while(p3>buf && *(p3-1)!='\n') p3--;
1103
    p3=p1; while(p3>buf && *(p3-1)!='\n') p3--;
1101
      p3=find_word_start(p3);
1104
    p3=find_word_start(p3);
1102
      if(p3<p1 && *p3!='!') continue;
1105
    if(p3<p1 && *p3!='!') continue;
1103
      if(p3<p1) {
1106
    if(p3<p1) {
1104
          p3++; p4=find_word_end(p3);
1107
      p3++; p4=find_word_end(p3);
1105
          if(find_word_start(p4)!=p1) continue;
1108
      if(find_word_start(p4)!=p1) continue;
1106
          if(p4-p3!=3 || (strncmp(p3,"set",3)!=0 &&
1109
      if(p4-p3!=3 || (strncmp(p3,"set",3)!=0 &&
1107
             strncmp(p3,"let",3)!=0 &&
1110
           strncmp(p3,"let",3)!=0 &&
1108
             strncmp(p3,"def",3)!=0)) {
1111
           strncmp(p3,"def",3)!=0)) {
1109
            if(p4-p3!=6 || strncmp(p3,"define",6)!=0) continue;
1112
        if(p4-p3!=6 || strncmp(p3,"define",6)!=0) continue;
1110
          }
-
 
1111
      }
1113
      }
1112
      p2++;p3=strchr(p2,'\n'); if(p3==NULL) p3=p2+strlen(p2);
-
 
1113
      p2=find_word_start(p2);
-
 
1114
      if(p2>p3) goto nothing;
-
 
1115
      if(p3-p2>=MAX_LINELEN) user_error("cmd_output_too_long");
-
 
1116
      memmove(value,p2,p3-p2); value[p3-p2]=0;
-
 
1117
      strip_trailing_spaces(value); return;
-
 
1118
    }
1114
    }
-
 
1115
    p2++;p3=strchr(p2,'\n'); if(p3==NULL) p3=p2+strlen(p2);
-
 
1116
    p2=find_word_start(p2);
-
 
1117
    if(p2>p3) goto nothing;
-
 
1118
    if(p3-p2>=MAX_LINELEN) user_error("cmd_output_too_long");
-
 
1119
    memmove(value,p2,p3-p2); value[p3-p2]=0;
-
 
1120
    strip_trailing_spaces(value); return;
-
 
1121
  }
1119
nothing:
1122
nothing:
1120
    value[0]=0; return;
1123
  value[0]=0; return;
1121
}
1124
}
1122
 
1125
 
1123
/* Get variable definition from a file.
1126
/* Get variable definition from a file.
1124
 * Result stored in buffer value of length MAX_LINELEN.
1127
 * Result stored in buffer value of length MAX_LINELEN.
1125
 */
1128
 */
1126
void getdef(char *fname, char *name, char value[])
1129
void getdef(char *fname, char *name, char value[])
1127
{
1130
{
1128
    char buf[MAX_LINELEN+1], tbuf[MAX_LINELEN+1], nbuf[MAX_NAMELEN+1];
1131
  char buf[MAX_LINELEN+1], tbuf[MAX_LINELEN+1], nbuf[MAX_NAMELEN+1];
1129
    char *p1, *p2;
1132
  char *p1, *p2;
-
 
1133
 
-
 
1134
  value[0]=0; if(readfile(fname,buf,sizeof(buf)-16)==NULL) return;
-
 
1135
  mystrncpy(value,name,MAX_LINELEN);
-
 
1136
  for(p1=value; *p1; p1=p2) {
-
 
1137
    while(*p1 && !myisalnum(*p1) && *p1!='_') p1++;
-
 
1138
    if(*p1==0) break;
-
 
1139
    for(p2=p1; myisalnum(*p2) || *p2=='_'; p2++);
-
 
1140
    if(p2-p1>MAX_NAMELEN) continue;
-
 
1141
    memmove(nbuf,p1,p2-p1); nbuf[p2-p1]=0;
-
 
1142
    _getdef(buf,nbuf,tbuf);
-
 
1143
    string_modify(value,p1,p2,"%s",tbuf);
-
 
1144
    p2=p1+strlen(tbuf);
-
 
1145
  }
-
 
1146
}
-
 
1147
 
-
 
1148
int _setdef_changed;
-
 
1149
 
-
 
1150
void _setdef(char buf[], char *name, char *value)
-
 
1151
{
-
 
1152
  char *p1, *p2, *p3;
-
 
1153
  int n;
1130
 
1154
 
1131
    value[0]=0; if(readfile(fname,buf,sizeof(buf)-16)==NULL) return;
1155
  for(p1=strstr(buf,name); p1!=NULL; p1=strstr(p1+1,name)) {
1132
    mystrncpy(value,name,MAX_LINELEN);
1156
    p2=find_word_start(p1+strlen(name));
1133
    for(p1=value; *p1; p1=p2) {
-
 
1134
      while(*p1 && !myisalnum(*p1) && *p1!='_') p1++;
1157
    if((p1>buf && !isspace(*(p1-1))) || *p2!='=') continue;
1135
      if(*p1==0) break;
-
 
1136
      for(p2=p1; myisalnum(*p2) || *p2=='_'; p2++);
1158
    p3=p1; while(p3>buf && *(p3-1)==' ') p3--;
1137
      if(p2-p1>MAX_NAMELEN) continue;
1159
    if(p3>buf && *(p3-1)!='\n') continue;
1138
      memmove(nbuf,p1,p2-p1); nbuf[p2-p1]=0;
1160
    p2++;p3=strchr(p2,'\n'); if(p3==NULL) p3=p2+strlen(p2);
1139
      _getdef(buf,nbuf,tbuf);
1161
    if(strlen(value)!=p3-p2 || strncmp(value,p2,p3-p2)!=0) {
1140
      string_modify(value,p1,p2,"%s",tbuf);
1162
      string_modify(buf,p2,p3,"%s",value);
1141
      p2=p1+strlen(tbuf);
1163
      _setdef_changed++;
1142
    }
1164
    }
1143
}
-
 
1144
 
-
 
1145
int _setdef_changed;
-
 
1146
 
-
 
1147
void _setdef(char buf[], char *name, char *value)
-
 
1148
{
-
 
1149
    char *p1, *p2, *p3;
-
 
1150
    int n;
-
 
1151
 
-
 
1152
    for(p1=strstr(buf,name); p1!=NULL; p1=strstr(p1+1,name)) {
-
 
1153
      p2=find_word_start(p1+strlen(name));
-
 
1154
      if((p1>buf && !isspace(*(p1-1))) || *p2!='=') continue;
-
 
1155
      p3=p1; while(p3>buf && *(p3-1)==' ') p3--;
-
 
1156
      if(p3>buf && *(p3-1)!='\n') continue;
-
 
1157
      p2++;p3=strchr(p2,'\n'); if(p3==NULL) p3=p2+strlen(p2);
-
 
1158
      if(strlen(value)!=p3-p2 || strncmp(value,p2,p3-p2)!=0) {
-
 
1159
          string_modify(buf,p2,p3,"%s",value);
-
 
1160
          _setdef_changed++;
-
 
1161
      }
-
 
1162
      return;
1165
    return;
1163
    }
1166
  }
1164
    n=strlen(buf);
1167
  n=strlen(buf);
1165
    if(n>0 && buf[n-1]!='\n')
1168
  if(n>0 && buf[n-1]!='\n')
1166
      snprintf(buf+n,MAX_LINELEN-n,"\n%s=%s\n",name,value);
1169
    snprintf(buf+n,MAX_LINELEN-n,"\n%s=%s\n",name,value);
1167
    else
1170
  else
1168
      snprintf(buf+n,MAX_LINELEN-n,"%s=%s\n",name,value);
1171
    snprintf(buf+n,MAX_LINELEN-n,"%s=%s\n",name,value);
1169
    _setdef_changed++;
1172
  _setdef_changed++;
1170
}
1173
}
1171
 
1174
 
1172
/* Set variable definition to a file. */
1175
/* Set variable definition to a file. */
1173
void setdef(char *fname, char *name)
1176
void setdef(char *fname, char *name)
1174
{
1177
{
1175
    char buf[MAX_LINELEN+1];
1178
  char buf[MAX_LINELEN+1];
1176
    char *p1, *p2, *p3;
1179
  char *p1, *p2, *p3;
1177
 
1180
 
1178
    _setdef_changed=0;
1181
  _setdef_changed=0;
1179
    if(strchr(name,'=')==NULL) return;
1182
  if(strchr(name,'=')==NULL) return;
1180
    for(p1=name;*p1;p1++) {
1183
  for(p1=name;*p1;p1++) {
1181
      if(isspace(*p1) && *p1!=' ' && *p1!='\n') *p1=' ';
1184
    if(isspace(*p1) && *p1!=' ' && *p1!='\n') *p1=' ';
1182
      if(*p1==' ') {
1185
    if(*p1==' ') {
1183
          for(p2=p1+1; isspace(*p2) && *p2!='\n'; p2++);
1186
      for(p2=p1+1; isspace(*p2) && *p2!='\n'; p2++);
1184
          if(p2>p1+1) ovlstrcpy(p1+1,p2);
1187
      if(p2>p1+1) ovlstrcpy(p1+1,p2);
1185
          p2=p1+1; if(*p2=='=' || *p2=='\n') ovlstrcpy(p1,p2);
1188
      p2=p1+1; if(*p2=='=' || *p2=='\n') ovlstrcpy(p1,p2);
1186
      }
1189
    }
1187
    }
1190
  }
1188
    if(readfile(fname,buf,sizeof(buf))==NULL) buf[0]=0;
1191
  if(readfile(fname,buf,sizeof(buf))==NULL) buf[0]=0;
1189
    for(p1=find_word_start(name); p1!=NULL; p1=p2) {
1192
  for(p1=find_word_start(name); p1!=NULL; p1=p2) {
1190
      p2=strchr(p1,'\n'); if(p2!=NULL) *p2++=0;
1193
    p2=strchr(p1,'\n'); if(p2!=NULL) *p2++=0;
1191
      p1=find_word_start(p1);
1194
    p1=find_word_start(p1);
1192
      p3=strchr(p1,'='); if(p3==NULL) continue;
1195
    p3=strchr(p1,'='); if(p3==NULL) continue;
1193
      *p3++=0; p3=find_word_start(p3);
1196
    *p3++=0; p3=find_word_start(p3);
1194
      _setdef(buf,p1,p3);
1197
    _setdef(buf,p1,p3);
1195
    }
1198
  }
1196
    if(_setdef_changed) accessfile(buf,"w","%s",fname);
1199
  if(_setdef_changed) accessfile(buf,"w","%s",fname);
1197
}
1200
}
1198
 
1201
 
1199
/* check whether connecting host is part of given list.
1202
/* check whether connecting host is part of given list.
1200
 * Returns 0 if no, 1 if yes.
1203
 * Returns 0 if no, 1 if yes.
1201
 */
1204
 */
1202
int checkhost(char *hlist)
1205
int checkhost(char *hlist)
1203
{
1206
{
1204
    char buf[MAX_LINELEN+1];
1207
  char buf[MAX_LINELEN+1];
1205
    char lbuf[1024], hbuf1[256], hbuf2[256];
1208
  char lbuf[1024], hbuf1[256], hbuf2[256];
1206
    char *p1, *p2, *pb, *pe, *pp;
1209
  char *p1, *p2, *pb, *pe, *pp;
1207
 
1210
 
1208
    if(*remote_addr==0) return 0;
1211
  if(*remote_addr==0) return 0;
1209
    snprintf(hbuf1,sizeof(hbuf1),"+%s+",remote_addr);
1212
  snprintf(hbuf1,sizeof(hbuf1),"+%s+",remote_addr);
1210
    if(*remote_host!=0) {
1213
  if(*remote_host!=0) {
1211
      snprintf(hbuf2,sizeof(hbuf2),"+%s+",remote_host);
1214
    snprintf(hbuf2,sizeof(hbuf2),"+%s+",remote_host);
1212
      for(p1=hbuf2; *p1; p1++) *p1=tolower(*p1);
1215
    for(p1=hbuf2; *p1; p1++) *p1=tolower(*p1);
1213
    }
1216
  }
1214
    else hbuf2[0]=0;
1217
  else hbuf2[0]=0;
1215
    mystrncpy(buf,find_word_start(hlist),sizeof(buf)); strip_trailing_spaces(buf);
1218
  mystrncpy(buf,find_word_start(hlist),sizeof(buf)); strip_trailing_spaces(buf);
1216
    for(p1=buf; *p1; p1++) {
1219
  for(p1=buf; *p1; p1++) {
1217
      *p1=tolower(*p1);
1220
    *p1=tolower(*p1);
1218
      if(!myisalnum(*p1) && strchr(".-_",*p1)==NULL) *p1=' ';
1221
    if(!myisalnum(*p1) && strchr(".-_",*p1)==NULL) *p1=' ';
1219
    }
1222
  }
1220
    if(strcmp(buf,"all")==0) return 1;      /* all is all */
1223
  if(strcmp(buf,"all")==0) return 1;      /* all is all */
1221
    for(p1=find_word_start(buf); *p1; p1=find_word_start(p2)) {
1224
  for(p1=find_word_start(buf); *p1; p1=find_word_start(p2)) {
1222
      p2=find_word_end(p1); if(*p2) *p2++=0;
1225
    p2=find_word_end(p1); if(*p2) *p2++=0;
1223
      if(p2-p1<3) continue;
1226
    if(p2-p1<3) continue;
1224
      if(myisalnum(*p1)) pb="+"; else pb="";
1227
    if(myisalnum(*p1)) pb="+"; else pb="";
1225
      if(myisalnum(*(p2-1))) pe="+"; else pe="";
1228
    if(myisalnum(*(p2-1))) pe="+"; else pe="";
1226
      snprintf(lbuf,sizeof(lbuf),"%s%s%s",pb,p1,pe);
1229
    snprintf(lbuf,sizeof(lbuf),"%s%s%s",pb,p1,pe);
1227
      for(pp=p1; *pp && (myisdigit(*pp) || *pp=='.'); pp++);
1230
    for(pp=p1; *pp && (myisdigit(*pp) || *pp=='.'); pp++);
1228
      if(*pp) pp=hbuf2;      /* host name */
1231
    if(*pp) pp=hbuf2;      /* host name */
1229
      else pp=hbuf1;         /* ip number */
1232
    else pp=hbuf1;         /* ip number */
1230
      if(strstr(pp,lbuf)!=NULL) return 1;      /* found */
1233
    if(strstr(pp,lbuf)!=NULL) return 1;      /* found */
1231
    }
1234
  }
1232
    return 0;
1235
  return 0;
1233
}
1236
}
1234
 
1237
 
1235
/* return 1 if a word of bf2 is a substring of host.
1238
/* return 1 if a word of bf2 is a substring of host.
1236
 * Like checkhost, but with time check.
1239
 * Like checkhost, but with time check.
1237
 * The content of bf2[] is destroyed.
1240
 * The content of bf2[] is destroyed.
1238
 */
1241
 */
1239
int checkhostt(char bf2[])
1242
int checkhostt(char bf2[])
1240
{
1243
{
1241
    char *p1, *p2, *p3;
1244
  char *p1, *p2, *p3;
1242
/* compare with starting time */
1245
/* compare with starting time */
1243
    for(p1=strchr(bf2,'>'); p1!=NULL; p1=strchr(p1+1,'>')) {
1246
  for(p1=strchr(bf2,'>'); p1!=NULL; p1=strchr(p1+1,'>')) {
1244
      if(p1>bf2 && !isspace(*(p1-1))) continue;
1247
    if(p1>bf2 && !isspace(*(p1-1))) continue;
1245
      p3=find_word_start(++p1); p2=find_word_end(p3);
1248
    p3=find_word_start(++p1); p2=find_word_end(p3);
1246
      if(p2-p3!=14) continue;
1249
    if(p2-p3!=14) continue;
1247
      p3[8]='.'; p3[11]=':'; if(*p2) *p2++=0;
1250
    p3[8]='.'; p3[11]=':'; if(*p2) *p2++=0;
1248
      if(strncmp(nowstr,p3,14)<0) return 0;
1251
    if(strncmp(nowstr,p3,14)<0) return 0;
1249
      ovlstrcpy(p1-1,p2); p1-=2;
1252
    ovlstrcpy(p1-1,p2); p1-=2;
1250
    }
1253
  }
1251
/* compare with ending time */
1254
/* compare with ending time */
1252
    for(p1=strchr(bf2,'<'); p1!=NULL; p1=strchr(p1+1,'<')) {
1255
  for(p1=strchr(bf2,'<'); p1!=NULL; p1=strchr(p1+1,'<')) {
1253
      if(p1>bf2 && !isspace(*(p1-1))) continue;
1256
    if(p1>bf2 && !isspace(*(p1-1))) continue;
1254
      p3=find_word_start(++p1); p2=find_word_end(p3);
1257
    p3=find_word_start(++p1); p2=find_word_end(p3);
1255
      if(p2-p3!=14) continue;
1258
    if(p2-p3!=14) continue;
1256
      p3[8]='.'; p3[11]=':'; if(*p2) *p2++=0;
1259
    p3[8]='.'; p3[11]=':'; if(*p2) *p2++=0;
1257
      if(strncmp(nowstr,p3,14)>0) return 0;
1260
    if(strncmp(nowstr,p3,14)>0) return 0;
1258
      ovlstrcpy(p1-1,p2); p1-=2;
1261
    ovlstrcpy(p1-1,p2); p1-=2;
1259
    }
1262
  }
1260
    p1=find_word_start(bf2); if(*p1==0) return 1;
1263
  p1=find_word_start(bf2); if(*p1==0) return 1;
1261
    return checkhost(p1);
1264
  return checkhost(p1);
1262
}
1265
}
1263
 
1266
 
1264
/* bad identification */
1267
/* bad identification */
1265
void bad_ident(void)
1268
void bad_ident(void)
1266
{
1269
{
1267
    if(cookiegot[0]!=0) {
1270
  if(cookiegot[0]!=0) {
1268
    }
1271
  }
1269
    user_error("bad_ident");
1272
  user_error("bad_ident");
1270
}
1273
}
1271
 
1274
 
1272
void instex_flush(void)
1275
void instex_flush(void)
1273
{
1276
{
1274
    char *p;
1277
  char *p;
1275
    setenv("texgif_style","",1);
1278
  setenv("texgif_style","",1);
1276
    setenv("texgif_tmpdir",tmp_dir,1);
1279
  setenv("texgif_tmpdir",tmp_dir,1);
1277
    setenv("texgif_src",instex_src,1);
1280
  setenv("texgif_src",instex_src,1);
1278
    setenv("texgif_outfile",instex_fname,1);
1281
  setenv("texgif_outfile",instex_fname,1);
1279
    unsetenv("w_instex_color");
1282
  unsetenv("w_instex_color");
1280
    getwimstexsize=0; fix_tex_size(); getwimstexsize=1;
1283
  getwimstexsize=0; fix_tex_size(); getwimstexsize=1;
1281
    for(p=instex_fname;*p;p++) if(*p=='\n') *p=' ';
1284
  for(p=instex_fname;*p;p++) if(*p=='\n') *p=' ';
1282
    wrapexec=0; call_ssh("%s/%s >%s/ins.Out 2>%s/ins.Err",
1285
  wrapexec=0; call_ssh("%s/%s >%s/ins.Out 2>%s/ins.Err",
1283
                   bin_dir,instex_processor,
1286
                 bin_dir,instex_processor,
1284
                   tmp_dir,tmp_dir);
1287
                 tmp_dir,tmp_dir);
1285
    call_ssh("mv %s %s >/dev/null 2>/dev/null", instex_fname,s2_prefix);
1288
  call_ssh("mv %s %s >/dev/null 2>/dev/null", instex_fname,s2_prefix);
1286
    instex_src[0]=instex_fname[0]=0; instex_cnt=0;
1289
  instex_src[0]=instex_fname[0]=0; instex_cnt=0;
1287
}
1290
}
1288
 
1291
 
1289
/* put last.phtml */
1292
/* put last.phtml */
1290
void putlastout(void)
1293
void putlastout(void)
1291
{
1294
{
1292
    int t;
1295
  int t;
1293
    if(instex_cnt>0) instex_flush();
1296
  if(instex_cnt>0) instex_flush();
1294
    t=catfile(stdout,"%s/%s",s2_prefix,lastout);
1297
  t=catfile(stdout,"%s/%s",s2_prefix,lastout);
1295
    if(t==0) printf("Content-type: text/plain\r\n\r\n");
1298
  if(t==0) printf("Content-type: text/plain\r\n\r\n");
1296
}
1299
}
1297
 
1300
 
1298
struct sockaddr_un sun;
1301
struct sockaddr_un sun;
1299
 
1302
 
1300
/* returns >=0 if OK. */
1303
/* returns >=0 if OK. */
1301
 
1304
 
1302
int kerneld(char *p, int bufsize)
1305
int kerneld(char *p, int bufsize)
1303
{
1306
{
1304
    int sock, s, t, t1, l, *ip;
1307
  int sock, s, t, t1, l, *ip;
1305
    struct timeval tv;
1308
  struct timeval tv;
1306
    fd_set rset;
1309
  fd_set rset;
1307
    sock=socket(PF_UNIX,SOCK_STREAM,0);
1310
  sock=socket(PF_UNIX,SOCK_STREAM,0);
1308
    s=connect(sock,(const struct sockaddr *)&sun,sizeof(sun));
1311
  s=connect(sock,(const struct sockaddr *)&sun,sizeof(sun));
1309
    if(s) {bad: close(sock); return -1;}
1312
  if(s) {bad: close(sock); return -1;}
1310
    ip=(int *) p;
1313
  ip=(int *) p;
1311
    l=strlen(p+sizeof(int)); *ip=l;
1314
  l=strlen(p+sizeof(int)); *ip=l;
1312
    s=write(sock,p,l+sizeof(int)); if(s!=l+sizeof(int)) goto bad;
1315
  s=write(sock,p,l+sizeof(int)); if(s!=l+sizeof(int)) goto bad;
1313
    for(t=0, l=bufsize-1; t<l+sizeof(int);) {
1316
  for(t=0, l=bufsize-1; t<l+sizeof(int);) {
1314
      tv.tv_sec=2; tv.tv_usec=0;
1317
    tv.tv_sec=2; tv.tv_usec=0;
1315
      FD_ZERO(&rset); FD_SET(sock,&rset);
1318
    FD_ZERO(&rset); FD_SET(sock,&rset);
1316
      if(select(sock+1,&rset,NULL,NULL,&tv)<=0) goto bad;
1319
    if(select(sock+1,&rset,NULL,NULL,&tv)<=0) goto bad;
1317
      t1=read(sock,p+t,l+sizeof(int)-t);
1320
    t1=read(sock,p+t,l+sizeof(int)-t);
1318
      if(t1+t<sizeof(int)) goto bad;
1321
    if(t1+t<sizeof(int)) goto bad;
1319
      if (t1 < 0) goto bad;
1322
    if (t1 < 0) goto bad;
1320
      l=*ip; if(l<=0) goto bad;
1323
    l=*ip; if(l<=0) goto bad;
1321
      if(l>=bufsize-sizeof(int)-4) user_error("cmd_output_too_long");
1324
    if(l>=bufsize-sizeof(int)-4) user_error("cmd_output_too_long");
1322
      t+=t1;
1325
    t+=t1;
1323
    }
1326
  }
1324
    p[l+sizeof(int)]=0;
1327
  p[l+sizeof(int)]=0;
1325
    close(sock);
1328
  close(sock);
1326
    return l+sizeof(int);
1329
  return l+sizeof(int);
1327
}
1330
}
1328
 
1331
 
1329
void _daemoncmd(char *p)
1332
void _daemoncmd(char *p)
1330
{
1333
{
1331
    char buf[MAX_LINELEN+1+sizeof(int)];
1334
  char buf[MAX_LINELEN+1+sizeof(int)];
1332
    char *p1, *p2, *p3;
1335
  char *p1, *p2, *p3;
1333
    mystrncpy(buf+sizeof(int),p,sizeof(buf)-sizeof(int));
1336
  mystrncpy(buf+sizeof(int),p,sizeof(buf)-sizeof(int));
1334
    if(kerneld(buf,sizeof(buf))<0)
1337
  if(kerneld(buf,sizeof(buf))<0)
1335
      internal_error("Daemon communication error.");
1338
    internal_error("Daemon communication error.");
1336
    p1=find_word_start(buf+sizeof(int));
1339
  p1=find_word_start(buf+sizeof(int));
1337
    p2=find_word_end(p1); if(*p2) *p2++=0;
1340
  p2=find_word_end(p1); if(*p2) *p2++=0;
1338
    if(strcmp(p1,"OK")==0) {
1341
  if(strcmp(p1,"OK")==0) {
1339
      mystrncpy(p,p2,MAX_LINELEN); return;
1342
    mystrncpy(p,p2,MAX_LINELEN); return;
1340
    }
1343
  }
1341
    p1=find_word_start(p2); p2=find_word_end(p1); if(*p2) *p2++=0;
1344
  p1=find_word_start(p2); p2=find_word_end(p1); if(*p2) *p2++=0;
1342
    p2=find_word_start(p2); p3=find_word_end(p2);
1345
  p2=find_word_start(p2); p3=find_word_end(p2);
1343
    if(*p3) {
1346
  if(*p3) {
1344
      *p3++=0; p3=find_word_start(p3); strip_trailing_spaces(p3);
1347
    *p3++=0; p3=find_word_start(p3); strip_trailing_spaces(p3);
1345
      setvar("wims_error_data",p3);
1348
    setvar("wims_error_data",p3);
1346
    }
1349
  }
1347
    switch(*p1) {
1350
  switch(*p1) {
1348
      case '1': user_error(p2);
1351
    case '1': user_error(p2);
1349
      case '2': module_error(p2);
1352
    case '2': module_error(p2);
1350
      case '3':
1353
    case '3':
1351
      default: internal_error(p2);
1354
    default: internal_error(p2);
1352
    }
1355
  }
1353
    *p=0;
1356
  *p=0;
1354
}
1357
}
1355
 
-