Description:
[grader] fixed to work with free pascal git-svn-id: http://theory.cpe.ku.ac.th/grader/judge/trunk/scripts@221 6386c4cd-e34a-4fa8-8920-d93eb39b512e
Commit status:
[Not Reviewed]
References:
Comments:
0 Commit comments 0 Inline Comments
Unresolved TODOs:
There are no unresolved TODOs
Add another comment

r53:45abc6ae27d1 - - 3 files changed: 10 inserted, 7 deleted

@@ -68,384 +68,387
68
68
69 static void NONRET
69 static void NONRET
70 box_exit(void)
70 box_exit(void)
71 {
71 {
72 if (box_pid > 0) {
72 if (box_pid > 0) {
73 if (is_ptraced)
73 if (is_ptraced)
74 ptrace(PTRACE_KILL, box_pid);
74 ptrace(PTRACE_KILL, box_pid);
75 kill(-box_pid, SIGKILL);
75 kill(-box_pid, SIGKILL);
76 kill(box_pid, SIGKILL);
76 kill(box_pid, SIGKILL);
77 }
77 }
78
78
79 struct timeval total;
79 struct timeval total;
80 int wall;
80 int wall;
81 struct rusage rus;
81 struct rusage rus;
82 int stat;
82 int stat;
83 pid_t p;
83 pid_t p;
84
84
85 // wait so that we can get information
85 // wait so that we can get information
86 p = wait4(box_pid, &stat, WUNTRACED, &rus);
86 p = wait4(box_pid, &stat, WUNTRACED, &rus);
87 if (p < 0) {
87 if (p < 0) {
88 fprintf(stderr,"wait4: error\n");
88 fprintf(stderr,"wait4: error\n");
89 print_running_stat(0,0,0,max_mem_used);
89 print_running_stat(0,0,0,max_mem_used);
90 } else if (p != box_pid) {
90 } else if (p != box_pid) {
91 fprintf(stderr,"wait4: unknown pid %d exited!\n", p);
91 fprintf(stderr,"wait4: unknown pid %d exited!\n", p);
92 print_running_stat(0,0,0,max_mem_used);
92 print_running_stat(0,0,0,max_mem_used);
93 } else {
93 } else {
94 if (!WIFEXITED(stat))
94 if (!WIFEXITED(stat))
95 fprintf(stderr,"wait4: unknown status\n");
95 fprintf(stderr,"wait4: unknown status\n");
96 struct timeval total;
96 struct timeval total;
97 int wall;
97 int wall;
98 wall = time(NULL) - start_time;
98 wall = time(NULL) - start_time;
99 timeradd(&rus.ru_utime, &rus.ru_stime, &total);
99 timeradd(&rus.ru_utime, &rus.ru_stime, &total);
100
100
101 print_running_stat((double)wall,
101 print_running_stat((double)wall,
102 (double) rus.ru_utime.tv_sec +
102 (double) rus.ru_utime.tv_sec +
103 ((double) rus.ru_utime.tv_usec/1000000.0),
103 ((double) rus.ru_utime.tv_usec/1000000.0),
104 (double) rus.ru_stime.tv_sec +
104 (double) rus.ru_stime.tv_sec +
105 ((double) rus.ru_stime.tv_usec/1000000.0),
105 ((double) rus.ru_stime.tv_usec/1000000.0),
106 max_mem_used);
106 max_mem_used);
107 }
107 }
108 exit(1);
108 exit(1);
109 }
109 }
110
110
111 static void NONRET __attribute__((format(printf,1,2)))
111 static void NONRET __attribute__((format(printf,1,2)))
112 die(char *msg, ...)
112 die(char *msg, ...)
113 {
113 {
114 va_list args;
114 va_list args;
115 va_start(args, msg);
115 va_start(args, msg);
116 vfprintf(stderr, msg, args);
116 vfprintf(stderr, msg, args);
117 fputc('\n', stderr);
117 fputc('\n', stderr);
118 box_exit();
118 box_exit();
119 }
119 }
120
120
121 static void __attribute__((format(printf,1,2)))
121 static void __attribute__((format(printf,1,2)))
122 log(char *msg, ...)
122 log(char *msg, ...)
123 {
123 {
124 va_list args;
124 va_list args;
125 va_start(args, msg);
125 va_start(args, msg);
126 if (verbose)
126 if (verbose)
127 {
127 {
128 vfprintf(stderr, msg, args);
128 vfprintf(stderr, msg, args);
129 fflush(stderr);
129 fflush(stderr);
130 }
130 }
131 va_end(args);
131 va_end(args);
132 }
132 }
133
133
134 static void
134 static void
135 valid_filename(unsigned long addr)
135 valid_filename(unsigned long addr)
136 {
136 {
137 char namebuf[4096], *p, *end;
137 char namebuf[4096], *p, *end;
138 static int mem_fd;
138 static int mem_fd;
139
139
140 if (!file_access)
140 if (!file_access)
141 die("File access forbidden.");
141 die("File access forbidden.");
142 if (file_access >= 9)
142 if (file_access >= 9)
143 return;
143 return;
144
144
145 if (!mem_fd)
145 if (!mem_fd)
146 {
146 {
147 sprintf(namebuf, "/proc/%d/mem", (int) box_pid);
147 sprintf(namebuf, "/proc/%d/mem", (int) box_pid);
148 mem_fd = open(namebuf, O_RDONLY);
148 mem_fd = open(namebuf, O_RDONLY);
149 if (mem_fd < 0)
149 if (mem_fd < 0)
150 die("open(%s): %m", namebuf);
150 die("open(%s): %m", namebuf);
151 }
151 }
152 p = end = namebuf;
152 p = end = namebuf;
153 do
153 do
154 {
154 {
155 if (p >= end)
155 if (p >= end)
156 {
156 {
157 int remains = PAGE_SIZE - (addr & (PAGE_SIZE-1));
157 int remains = PAGE_SIZE - (addr & (PAGE_SIZE-1));
158 int l = namebuf + sizeof(namebuf) - end;
158 int l = namebuf + sizeof(namebuf) - end;
159 if (l > remains)
159 if (l > remains)
160 l = remains;
160 l = remains;
161 if (!l)
161 if (!l)
162 die("Access to file with name too long.");
162 die("Access to file with name too long.");
163 if (long_seek(mem_fd, addr, SEEK_SET) < 0)
163 if (long_seek(mem_fd, addr, SEEK_SET) < 0)
164 die("long_seek(mem): %m");
164 die("long_seek(mem): %m");
165 remains = read(mem_fd, end, l);
165 remains = read(mem_fd, end, l);
166 if (remains < 0)
166 if (remains < 0)
167 die("read(mem): %m");
167 die("read(mem): %m");
168 if (!remains)
168 if (!remains)
169 die("Access to file with name out of memory.");
169 die("Access to file with name out of memory.");
170 end += l;
170 end += l;
171 addr += l;
171 addr += l;
172 }
172 }
173 }
173 }
174 while (*p++);
174 while (*p++);
175
175
176 log("[%s] ", namebuf);
176 log("[%s] ", namebuf);
177 if (file_access >= 3)
177 if (file_access >= 3)
178 return;
178 return;
179 if (!strchr(namebuf, '/') && strcmp(namebuf, ".."))
179 if (!strchr(namebuf, '/') && strcmp(namebuf, ".."))
180 return;
180 return;
181 if (file_access >= 2)
181 if (file_access >= 2)
182 {
182 {
183 if ((!strncmp(namebuf, "/etc/", 5) ||
183 if ((!strncmp(namebuf, "/etc/", 5) ||
184 !strncmp(namebuf, "/lib/", 5) ||
184 !strncmp(namebuf, "/lib/", 5) ||
185 !strncmp(namebuf, "/usr/lib/", 9))
185 !strncmp(namebuf, "/usr/lib/", 9))
186 && !strstr(namebuf, ".."))
186 && !strstr(namebuf, ".."))
187 return;
187 return;
188 if (!strcmp(namebuf, "/dev/null") ||
188 if (!strcmp(namebuf, "/dev/null") ||
189 !strcmp(namebuf, "/dev/zero") ||
189 !strcmp(namebuf, "/dev/zero") ||
190 !strcmp(namebuf, "/proc/meminfo") ||
190 !strcmp(namebuf, "/proc/meminfo") ||
191 !strcmp(namebuf, "/proc/self/stat") ||
191 !strcmp(namebuf, "/proc/self/stat") ||
192 !strncmp(namebuf, "/usr/share/zoneinfo/", 20))
192 !strncmp(namebuf, "/usr/share/zoneinfo/", 20))
193 return;
193 return;
194 }
194 }
195 die("Forbidden access to file `%s'.", namebuf);
195 die("Forbidden access to file `%s'.", namebuf);
196 }
196 }
197
197
198 static int
198 static int
199 valid_syscall(struct user *u)
199 valid_syscall(struct user *u)
200 {
200 {
201 switch (u->regs.orig_eax)
201 switch (u->regs.orig_eax)
202 {
202 {
203 case __NR_execve:
203 case __NR_execve:
204 {
204 {
205 static int exec_counter;
205 static int exec_counter;
206 return !exec_counter++;
206 return !exec_counter++;
207 }
207 }
208 case __NR_open:
208 case __NR_open:
209 case __NR_creat:
209 case __NR_creat:
210 case __NR_unlink:
210 case __NR_unlink:
211 case __NR_oldstat:
211 case __NR_oldstat:
212 case __NR_access:
212 case __NR_access:
213 case __NR_oldlstat:
213 case __NR_oldlstat:
214 case __NR_truncate:
214 case __NR_truncate:
215 case __NR_stat:
215 case __NR_stat:
216 case __NR_lstat:
216 case __NR_lstat:
217 case __NR_truncate64:
217 case __NR_truncate64:
218 case __NR_stat64:
218 case __NR_stat64:
219 case __NR_lstat64:
219 case __NR_lstat64:
220 valid_filename(u->regs.ebx);
220 valid_filename(u->regs.ebx);
221 return 1;
221 return 1;
222 case __NR_exit:
222 case __NR_exit:
223 case __NR_read:
223 case __NR_read:
224 case __NR_write:
224 case __NR_write:
225 case __NR_close:
225 case __NR_close:
226 case __NR_lseek:
226 case __NR_lseek:
227 case __NR_getpid:
227 case __NR_getpid:
228 case __NR_getuid:
228 case __NR_getuid:
229 case __NR_oldfstat:
229 case __NR_oldfstat:
230 case __NR_dup:
230 case __NR_dup:
231 case __NR_brk:
231 case __NR_brk:
232 case __NR_getgid:
232 case __NR_getgid:
233 case __NR_geteuid:
233 case __NR_geteuid:
234 case __NR_getegid:
234 case __NR_getegid:
235 case __NR_dup2:
235 case __NR_dup2:
236 case __NR_ftruncate:
236 case __NR_ftruncate:
237 case __NR_fstat:
237 case __NR_fstat:
238 case __NR_personality:
238 case __NR_personality:
239 case __NR__llseek:
239 case __NR__llseek:
240 case __NR_readv:
240 case __NR_readv:
241 case __NR_writev:
241 case __NR_writev:
242 case __NR_getresuid:
242 case __NR_getresuid:
243 #ifdef __NR_pread64
243 #ifdef __NR_pread64
244 case __NR_pread64:
244 case __NR_pread64:
245 case __NR_pwrite64:
245 case __NR_pwrite64:
246 #else
246 #else
247 case __NR_pread:
247 case __NR_pread:
248 case __NR_pwrite:
248 case __NR_pwrite:
249 #endif
249 #endif
250 case __NR_ftruncate64:
250 case __NR_ftruncate64:
251 case __NR_fstat64:
251 case __NR_fstat64:
252 case __NR_fcntl:
252 case __NR_fcntl:
253 case __NR_fcntl64:
253 case __NR_fcntl64:
254 case __NR_mmap:
254 case __NR_mmap:
255 case __NR_munmap:
255 case __NR_munmap:
256 case __NR_ioctl:
256 case __NR_ioctl:
257 case __NR_uname:
257 case __NR_uname:
258 case 252:
258 case 252:
259 case 243:
259 case 243:
260 + // added for free pascal
261 + case __NR_ugetrlimit:
262 + case __NR_readlink:
260 return 1;
263 return 1;
261 // case __NR_time:
264 // case __NR_time:
262 case __NR_alarm:
265 case __NR_alarm:
263 // case __NR_pause:
266 // case __NR_pause:
264 case __NR_signal:
267 case __NR_signal:
265 case __NR_fchmod:
268 case __NR_fchmod:
266 case __NR_sigaction:
269 case __NR_sigaction:
267 case __NR_sgetmask:
270 case __NR_sgetmask:
268 case __NR_ssetmask:
271 case __NR_ssetmask:
269 case __NR_sigsuspend:
272 case __NR_sigsuspend:
270 case __NR_sigpending:
273 case __NR_sigpending:
271 case __NR_getrlimit:
274 case __NR_getrlimit:
272 case __NR_getrusage:
275 case __NR_getrusage:
273 case __NR_gettimeofday:
276 case __NR_gettimeofday:
274 case __NR_select:
277 case __NR_select:
275 case __NR_readdir:
278 case __NR_readdir:
276 case __NR_setitimer:
279 case __NR_setitimer:
277 case __NR_getitimer:
280 case __NR_getitimer:
278 case __NR_sigreturn:
281 case __NR_sigreturn:
279 case __NR_mprotect:
282 case __NR_mprotect:
280 case __NR_sigprocmask:
283 case __NR_sigprocmask:
281 case __NR_getdents:
284 case __NR_getdents:
282 case __NR_getdents64:
285 case __NR_getdents64:
283 case __NR__newselect:
286 case __NR__newselect:
284 case __NR_fdatasync:
287 case __NR_fdatasync:
285 case __NR_mremap:
288 case __NR_mremap:
286 case __NR_poll:
289 case __NR_poll:
287 case __NR_getcwd:
290 case __NR_getcwd:
288 case __NR_nanosleep:
291 case __NR_nanosleep:
289 case __NR_rt_sigreturn:
292 case __NR_rt_sigreturn:
290 case __NR_rt_sigaction:
293 case __NR_rt_sigaction:
291 case __NR_rt_sigprocmask:
294 case __NR_rt_sigprocmask:
292 case __NR_rt_sigpending:
295 case __NR_rt_sigpending:
293 case __NR_rt_sigtimedwait:
296 case __NR_rt_sigtimedwait:
294 case __NR_rt_sigqueueinfo:
297 case __NR_rt_sigqueueinfo:
295 case __NR_rt_sigsuspend:
298 case __NR_rt_sigsuspend:
296 case __NR_mmap2:
299 case __NR_mmap2:
297 case __NR__sysctl:
300 case __NR__sysctl:
298 return (filter_syscalls == 1);
301 return (filter_syscalls == 1);
299 case __NR_times:
302 case __NR_times:
300 return allow_times;
303 return allow_times;
301 case __NR_kill:
304 case __NR_kill:
302 if (u->regs.ebx == box_pid)
305 if (u->regs.ebx == box_pid)
303 die("Commited suicide by signal %d.", (int)u->regs.ecx);
306 die("Commited suicide by signal %d.", (int)u->regs.ecx);
304 return 0;
307 return 0;
305 default:
308 default:
306 return 0;
309 return 0;
307 }
310 }
308 }
311 }
309
312
310 static void
313 static void
311 signal_alarm(int unused UNUSED)
314 signal_alarm(int unused UNUSED)
312 {
315 {
313 /* Time limit checks are synchronous, so we only schedule them there. */
316 /* Time limit checks are synchronous, so we only schedule them there. */
314 timer_tick = 1;
317 timer_tick = 1;
315
318
316 //NOTE: do not use alarm, changed to setitimer for precision
319 //NOTE: do not use alarm, changed to setitimer for precision
317 // alarm(1);
320 // alarm(1);
318 }
321 }
319
322
320 static void
323 static void
321 signal_int(int unused UNUSED)
324 signal_int(int unused UNUSED)
322 {
325 {
323 /* Interrupts are fatal, so no synchronization requirements. */
326 /* Interrupts are fatal, so no synchronization requirements. */
324 die("Interrupted.");
327 die("Interrupted.");
325 }
328 }
326
329
327 static void
330 static void
328 check_timeout(void)
331 check_timeout(void)
329 {
332 {
330 double sec;
333 double sec;
331
334
332 if (use_wall_clock)
335 if (use_wall_clock)
333 sec = (double)(time(NULL) - start_time);
336 sec = (double)(time(NULL) - start_time);
334 else
337 else
335 {
338 {
336 char buf[4096], *x;
339 char buf[4096], *x;
337 int c, utime, stime;
340 int c, utime, stime;
338 static int proc_status_fd;
341 static int proc_status_fd;
339 if (!proc_status_fd)
342 if (!proc_status_fd)
340 {
343 {
341 sprintf(buf, "/proc/%d/stat", (int) box_pid);
344 sprintf(buf, "/proc/%d/stat", (int) box_pid);
342 proc_status_fd = open(buf, O_RDONLY);
345 proc_status_fd = open(buf, O_RDONLY);
343 if (proc_status_fd < 0)
346 if (proc_status_fd < 0)
344 die("open(%s): %m", buf);
347 die("open(%s): %m", buf);
345 }
348 }
346 lseek(proc_status_fd, 0, SEEK_SET);
349 lseek(proc_status_fd, 0, SEEK_SET);
347 if ((c = read(proc_status_fd, buf, sizeof(buf)-1)) < 0)
350 if ((c = read(proc_status_fd, buf, sizeof(buf)-1)) < 0)
348 die("read on /proc/$pid/stat: %m");
351 die("read on /proc/$pid/stat: %m");
349 if (c >= (int) sizeof(buf) - 1)
352 if (c >= (int) sizeof(buf) - 1)
350 die("/proc/$pid/stat too long");
353 die("/proc/$pid/stat too long");
351 buf[c] = 0;
354 buf[c] = 0;
352 x = buf;
355 x = buf;
353 while (*x && *x != ' ')
356 while (*x && *x != ' ')
354 x++;
357 x++;
355 while (*x == ' ')
358 while (*x == ' ')
356 x++;
359 x++;
357 if (*x++ != '(')
360 if (*x++ != '(')
358 die("proc syntax error 1");
361 die("proc syntax error 1");
359 while (*x && (*x != ')' || x[1] != ' '))
362 while (*x && (*x != ')' || x[1] != ' '))
360 x++;
363 x++;
361 while (*x == ')' || *x == ' ')
364 while (*x == ')' || *x == ' ')
362 x++;
365 x++;
363 if (sscanf(x, "%*c %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %d %d", &utime, &stime) != 2)
366 if (sscanf(x, "%*c %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %d %d", &utime, &stime) != 2)
364 die("proc syntax error 2");
367 die("proc syntax error 2");
365 //printf("%s - %d\n",x,ticks_per_sec);
368 //printf("%s - %d\n",x,ticks_per_sec);
366 sec = ((double)(utime + stime))/(double)ticks_per_sec;
369 sec = ((double)(utime + stime))/(double)ticks_per_sec;
367 }
370 }
368 if (verbose > 1)
371 if (verbose > 1)
369 fprintf(stderr, "[timecheck: %d seconds]\n", sec);
372 fprintf(stderr, "[timecheck: %d seconds]\n", sec);
370 if (sec > timeout) {
373 if (sec > timeout) {
371 die("Time limit exceeded.",sec,timeout);
374 die("Time limit exceeded.",sec,timeout);
372 }
375 }
373 }
376 }
374
377
375 static void
378 static void
376 check_memory_usage()
379 check_memory_usage()
377 {
380 {
378 char proc_fname[100];
381 char proc_fname[100];
379 sprintf(proc_fname,"/proc/%d/statm",box_pid);
382 sprintf(proc_fname,"/proc/%d/statm",box_pid);
380 //printf("proc fname: %s\n",proc_fname);
383 //printf("proc fname: %s\n",proc_fname);
381 FILE *fp = fopen(proc_fname,"r");
384 FILE *fp = fopen(proc_fname,"r");
382 if(fp!=NULL) {
385 if(fp!=NULL) {
383 char line[1000];
386 char line[1000];
384 fgets(line,999,fp);
387 fgets(line,999,fp);
385 //printf("%s\n",line);
388 //printf("%s\n",line);
386 int m;
389 int m;
387
390
388 if(sscanf(line,"%d",&m)==1) {
391 if(sscanf(line,"%d",&m)==1) {
389 m = (m*page_size+1023)/1024;
392 m = (m*page_size+1023)/1024;
390 if(m>max_mem_used)
393 if(m>max_mem_used)
391 max_mem_used = m;
394 max_mem_used = m;
392 }
395 }
393
396
394 fclose(fp);
397 fclose(fp);
395 }
398 }
396 }
399 }
397
400
398 static void
401 static void
399 boxkeeper(void)
402 boxkeeper(void)
400 {
403 {
401 int syscall_count = 0;
404 int syscall_count = 0;
402 struct sigaction sa;
405 struct sigaction sa;
403
406
404 is_ptraced = 1;
407 is_ptraced = 1;
405 bzero(&sa, sizeof(sa));
408 bzero(&sa, sizeof(sa));
406 sa.sa_handler = signal_int;
409 sa.sa_handler = signal_int;
407 sigaction(SIGINT, &sa, NULL);
410 sigaction(SIGINT, &sa, NULL);
408 start_time = time(NULL);
411 start_time = time(NULL);
409 ticks_per_sec = sysconf(_SC_CLK_TCK);
412 ticks_per_sec = sysconf(_SC_CLK_TCK);
410 page_size = getpagesize();
413 page_size = getpagesize();
411 if (ticks_per_sec <= 0)
414 if (ticks_per_sec <= 0)
412 die("Invalid ticks_per_sec!");
415 die("Invalid ticks_per_sec!");
413
416
414 check_memory_usage();
417 check_memory_usage();
415
418
416 sa.sa_handler = signal_alarm;
419 sa.sa_handler = signal_alarm;
417 sigaction(SIGALRM, &sa, NULL);
420 sigaction(SIGALRM, &sa, NULL);
418 //alarm(1);
421 //alarm(1);
419
422
420 struct itimerval val;
423 struct itimerval val;
421 val.it_interval.tv_sec = 0;
424 val.it_interval.tv_sec = 0;
422 val.it_interval.tv_usec = 50000;
425 val.it_interval.tv_usec = 50000;
423 val.it_value.tv_sec = 0;
426 val.it_value.tv_sec = 0;
424 val.it_value.tv_usec = 50000;
427 val.it_value.tv_usec = 50000;
425 setitimer(ITIMER_REAL,&val,NULL);
428 setitimer(ITIMER_REAL,&val,NULL);
426
429
427 /*
430 /*
428 --- add alarm handler no matter what..
431 --- add alarm handler no matter what..
429 if (timeout)
432 if (timeout)
430 {
433 {
431 sa.sa_handler = signal_alarm;
434 sa.sa_handler = signal_alarm;
432 sigaction(SIGALRM, &sa, NULL);
435 sigaction(SIGALRM, &sa, NULL);
433 alarm(1);
436 alarm(1);
434 }
437 }
435 */
438 */
436
439
437 for(;;)
440 for(;;)
438 {
441 {
439 struct rusage rus;
442 struct rusage rus;
440 int stat;
443 int stat;
441 pid_t p;
444 pid_t p;
442
445
443 if (timer_tick)
446 if (timer_tick)
444 {
447 {
445 check_timeout();
448 check_timeout();
446 check_memory_usage();
449 check_memory_usage();
447 timer_tick = 0;
450 timer_tick = 0;
448 }
451 }
449 p = wait4(box_pid, &stat, WUNTRACED, &rus);
452 p = wait4(box_pid, &stat, WUNTRACED, &rus);
450
453
451 if (p < 0)
454 if (p < 0)
@@ -1,106 +1,106
1 #!/bin/sh
1 #!/bin/sh
2
2
3 ##############################
3 ##############################
4 #
4 #
5 # Standard Compile Script
5 # Standard Compile Script
6 #
6 #
7 # Supported compilers:
7 # Supported compilers:
8 - # gcc, g++, and gpc.
8 + # gcc, g++, and fpc.
9 #
9 #
10 ##############################
10 ##############################
11
11
12 talk ()
12 talk ()
13 {
13 {
14 if [ "$TALKATIVE" != "" ]; then
14 if [ "$TALKATIVE" != "" ]; then
15 echo "$1"
15 echo "$1"
16 fi
16 fi
17 }
17 }
18
18
19 export C_COMPILER=/usr/bin/gcc
19 export C_COMPILER=/usr/bin/gcc
20 export CPLUSPLUS_COMPILER=/usr/bin/g++
20 export CPLUSPLUS_COMPILER=/usr/bin/g++
21 - export PASCAL_COMPILER=/usr/bin/gpc
21 + export PASCAL_COMPILER=/usr/bin/fpc
22
22
23 export C_OPTIONS="-O2 -s -static -lm -Wall"
23 export C_OPTIONS="-O2 -s -static -lm -Wall"
24 export CPLUSPLUS_OPTIONS="-O2 -s -static -lm -Wall"
24 export CPLUSPLUS_OPTIONS="-O2 -s -static -lm -Wall"
25 - export PASCAL_OPTIONS="-O2 -XS -lm -Wall"
25 + export PASCAL_OPTIONS="-O1 -XS"
26
26
27 # Check for the correct number of arguments. Otherwise, print usage.
27 # Check for the correct number of arguments. Otherwise, print usage.
28 if [ $# -eq 0 -o $# -gt 4 ]
28 if [ $# -eq 0 -o $# -gt 4 ]
29 then
29 then
30 echo "Usage: $0 <language> [<source-file>] [<output-file>] [<message-file>]"
30 echo "Usage: $0 <language> [<source-file>] [<output-file>] [<message-file>]"
31 echo
31 echo
32 echo "<source-file> is defaulted to \"source\"."
32 echo "<source-file> is defaulted to \"source\"."
33 echo "<output-file> is defaulted to \"a.out\"."
33 echo "<output-file> is defaulted to \"a.out\"."
34 echo "<message-file> is defaulted to \"compiler_message\"."
34 echo "<message-file> is defaulted to \"compiler_message\"."
35 echo
35 echo
36 exit 127
36 exit 127
37 fi
37 fi
38
38
39 # Retrieve the arguments.
39 # Retrieve the arguments.
40 if [ $# -ge 1 ]
40 if [ $# -ge 1 ]
41 then
41 then
42 export PROG_LANG=$1
42 export PROG_LANG=$1
43 talk "programming language: ${PROG_LANG}"
43 talk "programming language: ${PROG_LANG}"
44 fi
44 fi
45
45
46 if [ $# -ge 2 ]
46 if [ $# -ge 2 ]
47 then
47 then
48 export SOURCE_FILE=$2
48 export SOURCE_FILE=$2
49 else
49 else
50 export SOURCE_FILE=source
50 export SOURCE_FILE=source
51 fi
51 fi
52 talk " source file: $SOURCE_FILE"
52 talk " source file: $SOURCE_FILE"
53
53
54 if [ $# -ge 3 ]
54 if [ $# -ge 3 ]
55 then
55 then
56 export OUTPUT_FILE=$3
56 export OUTPUT_FILE=$3
57 else
57 else
58 export OUTPUT_FILE=a.out
58 export OUTPUT_FILE=a.out
59 fi
59 fi
60 talk " output file: $OUTPUT_FILE"
60 talk " output file: $OUTPUT_FILE"
61
61
62 if [ $# -eq 4 ]
62 if [ $# -eq 4 ]
63 then
63 then
64 export MESSAGE_FILE=$4
64 export MESSAGE_FILE=$4
65 else
65 else
66 export MESSAGE_FILE=compiler_message
66 export MESSAGE_FILE=compiler_message
67 fi
67 fi
68 talk " message file: $MESSAGE_FILE"
68 talk " message file: $MESSAGE_FILE"
69
69
70 # Remove any remaining output files or message files.
70 # Remove any remaining output files or message files.
71 rm -Rf $OUTPUT_FILE
71 rm -Rf $OUTPUT_FILE
72 rm -Rf $MESSAGE_FILE
72 rm -Rf $MESSAGE_FILE
73
73
74 # Check if the source file exists before attempt compiling.
74 # Check if the source file exists before attempt compiling.
75 if [ ! -f $SOURCE_FILE ]
75 if [ ! -f $SOURCE_FILE ]
76 then
76 then
77 talk "ERROR: The source file does not exist!"
77 talk "ERROR: The source file does not exist!"
78 echo "ERROR: The source file did not exist." > $MESSAGE_FILE
78 echo "ERROR: The source file did not exist." > $MESSAGE_FILE
79 exit 127
79 exit 127
80 fi
80 fi
81
81
82 # Compile.
82 # Compile.
83 if [ $PROG_LANG = "c" ]
83 if [ $PROG_LANG = "c" ]
84 then
84 then
85 $C_COMPILER $SOURCE_FILE -o $OUTPUT_FILE $C_OPTIONS 2>$MESSAGE_FILE
85 $C_COMPILER $SOURCE_FILE -o $OUTPUT_FILE $C_OPTIONS 2>$MESSAGE_FILE
86 elif [ $PROG_LANG = "c++" ]
86 elif [ $PROG_LANG = "c++" ]
87 then
87 then
88 $CPLUSPLUS_COMPILER $SOURCE_FILE -o $OUTPUT_FILE $CPLUSPLUS_OPTIONS 2>$MESSAGE_FILE
88 $CPLUSPLUS_COMPILER $SOURCE_FILE -o $OUTPUT_FILE $CPLUSPLUS_OPTIONS 2>$MESSAGE_FILE
89 - elif [ $PROG_LANG = "pascal" ]
89 + elif [ $PROG_LANG = "pas" ]
90 then
90 then
91 - $PASCAL_COMPILER $SOURCE_FILE -o $OUTPUT_FILE $PASCAL_OPTIONS 2>$MESSAGE_FILE
91 + $PASCAL_COMPILER $SOURCE_FILE -o$OUTPUT_FILE $PASCAL_OPTIONS >$MESSAGE_FILE
92 else
92 else
93 talk "ERROR: Invalid language specified!"
93 talk "ERROR: Invalid language specified!"
94 echo "ERROR: Invalid language specified!" > $MESSAGE_FILE
94 echo "ERROR: Invalid language specified!" > $MESSAGE_FILE
95 exit 127
95 exit 127
96 fi
96 fi
97
97
98 # Report success or failure.
98 # Report success or failure.
99 if [ -f $OUTPUT_FILE ]
99 if [ -f $OUTPUT_FILE ]
100 then
100 then
101 talk "Compilation was successful!"
101 talk "Compilation was successful!"
102 else
102 else
103 talk "ERROR: Something was wrong during the compilation!"
103 talk "ERROR: Something was wrong during the compilation!"
104 talk "Dumping compiler message:"
104 talk "Dumping compiler message:"
105 #cat $MESSAGE_FILE
105 #cat $MESSAGE_FILE
106 fi
106 fi
@@ -1,132 +1,132
1 #!/usr/bin/ruby
1 #!/usr/bin/ruby
2
2
3 def log(str='')
3 def log(str='')
4 if ENV['TALKATIVE']!=nil
4 if ENV['TALKATIVE']!=nil
5 puts str
5 puts str
6 end
6 end
7 if ENV['GRADER_LOGGING']!=nil
7 if ENV['GRADER_LOGGING']!=nil
8 log_fname = ENV['GRADER_LOGGING']
8 log_fname = ENV['GRADER_LOGGING']
9 fp = File.open(log_fname,"a")
9 fp = File.open(log_fname,"a")
10 fp.puts("judge: #{Time.new.strftime("%H:%M")} #{str}")
10 fp.puts("judge: #{Time.new.strftime("%H:%M")} #{str}")
11 fp.close
11 fp.close
12 end
12 end
13 end
13 end
14
14
15 problem_home = ENV['PROBLEM_HOME']
15 problem_home = ENV['PROBLEM_HOME']
16
16
17 def execute(command, error_message="")
17 def execute(command, error_message="")
18 if not system(command)
18 if not system(command)
19 msg = "ERROR: #{error_message}"
19 msg = "ERROR: #{error_message}"
20 log msg
20 log msg
21 raise msg
21 raise msg
22 end
22 end
23 end
23 end
24
24
25 # ARGV[0] --- language
25 # ARGV[0] --- language
26 # ARGV[1] --- program source file
26 # ARGV[1] --- program source file
27 # ARGV[2] --- test result directory
27 # ARGV[2] --- test result directory
28 # ARGV[3] --- sandbox directory
28 # ARGV[3] --- sandbox directory
29
29
30 if ARGV.length < 2 || ARGV.length > 4
30 if ARGV.length < 2 || ARGV.length > 4
31 puts "Usage: judge <language> <program-source> [<test-result-directory>] [<sandbox-directory>]"
31 puts "Usage: judge <language> <program-source> [<test-result-directory>] [<sandbox-directory>]"
32 puts " <sandbox-directory> is defaulted to ./sandbox"
32 puts " <sandbox-directory> is defaulted to ./sandbox"
33 puts " <test-result-directory> is defaulted to ./test-result"
33 puts " <test-result-directory> is defaulted to ./test-result"
34 puts "WARNING: The judge script will forcefully create the (implicitly and explicitly) specified directories and remove anything inside it."
34 puts "WARNING: The judge script will forcefully create the (implicitly and explicitly) specified directories and remove anything inside it."
35 exit(127)
35 exit(127)
36 end
36 end
37
37
38 language = ARGV[0]
38 language = ARGV[0]
39 - if language != "c" && language != "c++" && language != "pascal"
39 + if language != "c" && language != "c++" && language != "pas"
40 - log "You specified a language that is not supported."
40 + log "You specified a language that is not supported: #{language}."
41 exit(127)
41 exit(127)
42 end
42 end
43
43
44 source_file = ARGV[1]
44 source_file = ARGV[1]
45 if File.exist?(source_file) == false
45 if File.exist?(source_file) == false
46 log "The source file does not exist."
46 log "The source file does not exist."
47 exit(127)
47 exit(127)
48 end
48 end
49
49
50 log "Making test result and sandbox directories..."
50 log "Making test result and sandbox directories..."
51
51
52 current_dir = `pwd`
52 current_dir = `pwd`
53 current_dir.strip!
53 current_dir.strip!
54
54
55 if ARGV.length >= 3
55 if ARGV.length >= 3
56 test_result_dir = ARGV[2]
56 test_result_dir = ARGV[2]
57 else
57 else
58 test_result_dir = "#{current_dir}/test-result"
58 test_result_dir = "#{current_dir}/test-result"
59 end
59 end
60 log "Test result directory: #{test_result_dir}"
60 log "Test result directory: #{test_result_dir}"
61 system("rm -Rf #{test_result_dir}")
61 system("rm -Rf #{test_result_dir}")
62 execute("mkdir #{test_result_dir}", "Cannot make directory #{test_result_dir}.")
62 execute("mkdir #{test_result_dir}", "Cannot make directory #{test_result_dir}.")
63
63
64 if ARGV.length >= 4
64 if ARGV.length >= 4
65 sandbox_dir = ARGV[3]
65 sandbox_dir = ARGV[3]
66 else
66 else
67 sandbox_dir = "#{current_dir}/sandbox"
67 sandbox_dir = "#{current_dir}/sandbox"
68 end
68 end
69 log "Sandbox directory: #{sandbox_dir}"
69 log "Sandbox directory: #{sandbox_dir}"
70 system("rm -Rf #{sandbox_dir}")
70 system("rm -Rf #{sandbox_dir}")
71 execute("mkdir #{sandbox_dir}", "Cannot make directory #{sandbox_dir}")
71 execute("mkdir #{sandbox_dir}", "Cannot make directory #{sandbox_dir}")
72
72
73 # Compile
73 # Compile
74 log
74 log
75 log "Compiling..."
75 log "Compiling..."
76 execute("cp #{source_file} #{sandbox_dir}", "Cannot copy the source file to #{sandbox_dir}")
76 execute("cp #{source_file} #{sandbox_dir}", "Cannot copy the source file to #{sandbox_dir}")
77 begin
77 begin
78 Dir.chdir sandbox_dir
78 Dir.chdir sandbox_dir
79 rescue
79 rescue
80 log "ERROR: Cannot change directory to #{sandbox_dir}."
80 log "ERROR: Cannot change directory to #{sandbox_dir}."
81 exit(127)
81 exit(127)
82 end
82 end
83 execute("#{problem_home}/script/compile #{language} #{source_file}", "Compilation error!")
83 execute("#{problem_home}/script/compile #{language} #{source_file}", "Compilation error!")
84 compile_message = `cat compiler_message`
84 compile_message = `cat compiler_message`
85 compile_message.strip!
85 compile_message.strip!
86 execute("mv compiler_message #{test_result_dir}", "Cannot move the compiler message to #{test_result_dir}.")
86 execute("mv compiler_message #{test_result_dir}", "Cannot move the compiler message to #{test_result_dir}.")
87 if !FileTest.exist?("a.out")
87 if !FileTest.exist?("a.out")
88 log "Cannot compile the source code. See message in #{test_result_dir}/compile_message"
88 log "Cannot compile the source code. See message in #{test_result_dir}/compile_message"
89 exit(127)
89 exit(127)
90 else
90 else
91 execute("mv a.out #{test_result_dir}", "Cannot move the compiled program to #{test_result_dir}")
91 execute("mv a.out #{test_result_dir}", "Cannot move the compiled program to #{test_result_dir}")
92 system("rm -Rf #{sandbox_dir}/*")
92 system("rm -Rf #{sandbox_dir}/*")
93 end
93 end
94
94
95 require "#{problem_home}/script/test_dsl.rb"
95 require "#{problem_home}/script/test_dsl.rb"
96 load "#{problem_home}/test_cases/all_tests.cfg"
96 load "#{problem_home}/test_cases/all_tests.cfg"
97 problem = Problem.get_instance
97 problem = Problem.get_instance
98
98
99 if problem.well_formed? == false
99 if problem.well_formed? == false
100 log "The problem specification is not well formed."
100 log "The problem specification is not well formed."
101 exit(127)
101 exit(127)
102 end
102 end
103
103
104 # Doing the testing.
104 # Doing the testing.
105 (1..(problem.num_tests)).each do |test_num|
105 (1..(problem.num_tests)).each do |test_num|
106 log "Test number: #{test_num}"
106 log "Test number: #{test_num}"
107 execute("cp #{test_result_dir}/a.out #{sandbox_dir}", "Cannot copy the compiled program into #{sandbox_dir}")
107 execute("cp #{test_result_dir}/a.out #{sandbox_dir}", "Cannot copy the compiled program into #{sandbox_dir}")
108 begin
108 begin
109 execute("#{problem_home}/script/run #{language} #{test_num}", "Error occured during execution of the run script")
109 execute("#{problem_home}/script/run #{language} #{test_num}", "Error occured during execution of the run script")
110 rescue
110 rescue
111 # do nothing
111 # do nothing
112 end
112 end
113 execute("mkdir #{test_result_dir}/#{test_num}", "Cannot create directory #{test_result_dir}/#{test_num}")
113 execute("mkdir #{test_result_dir}/#{test_num}", "Cannot create directory #{test_result_dir}/#{test_num}")
114 execute("mv #{sandbox_dir}/result #{test_result_dir}/#{test_num}", "Cannot copy the result file into #{test_result_dir}/#{test_num}")
114 execute("mv #{sandbox_dir}/result #{test_result_dir}/#{test_num}", "Cannot copy the result file into #{test_result_dir}/#{test_num}")
115 execute("mv #{sandbox_dir}/comment #{test_result_dir}/#{test_num}", "Cannot copy the comment file into #{test_result_dir}/#{test_num}")
115 execute("mv #{sandbox_dir}/comment #{test_result_dir}/#{test_num}", "Cannot copy the comment file into #{test_result_dir}/#{test_num}")
116 execute("mv #{sandbox_dir}/output.txt #{test_result_dir}/#{test_num}", "Cannot copy the output file into #{test_result_dir}/#{test_num}")
116 execute("mv #{sandbox_dir}/output.txt #{test_result_dir}/#{test_num}", "Cannot copy the output file into #{test_result_dir}/#{test_num}")
117 execute("rm -Rf #{sandbox_dir}/*", "Cannot clear #{sandbox_dir}")
117 execute("rm -Rf #{sandbox_dir}/*", "Cannot clear #{sandbox_dir}")
118 end
118 end
119
119
120 # Grade
120 # Grade
121 log
121 log
122 log "Grading..."
122 log "Grading..."
123 begin
123 begin
124 Dir.chdir test_result_dir
124 Dir.chdir test_result_dir
125 rescue
125 rescue
126 log "ERROR: Cannot change directory to #{test_result_dir}."
126 log "ERROR: Cannot change directory to #{test_result_dir}."
127 exit(127)
127 exit(127)
128 end
128 end
129 execute("#{problem_home}/script/grade", "An error occured during grading!")
129 execute("#{problem_home}/script/grade", "An error occured during grading!")
130
130
131 log
131 log
132 log "All done!"
132 log "All done!"
You need to be logged in to leave comments. Login now