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