]> mj.ucw.cz Git - eval.git/blob - judge/io.c
Handle exit code translation failures gracefully.
[eval.git] / judge / io.c
1 /*
2  *      I/O functions for judges
3  *
4  *      (c) 2007 Martin Mares <mj@ucw.cz>
5  */
6
7 #include <stdlib.h>
8 #include <string.h>
9 #include <unistd.h>
10 #include <fcntl.h>
11
12 #include "judge.h"
13
14 #define BUFSIZE 65536
15
16 struct stream *sopen_fd(char *name, int fd)
17 {
18   struct stream *s = xmalloc(sizeof(*s) + BUFSIZE + strlen(name) + 1);
19   s->fd = fd;
20   s->pos = s->stop = s->buf;
21   s->end = s->buf + BUFSIZE;
22   s->name = s->end;
23   strcpy(s->name, name);
24   return s;
25 }
26
27 struct stream *sopen_read(char *name)
28 {
29   int fd = open(name, O_RDONLY);
30   if (fd < 0)
31     die("Unable to open %s for reading: %m", name);
32   return sopen_fd(name, fd);
33 }
34
35 struct stream *sopen_write(char *name)
36 {
37   int fd = open(name, O_WRONLY | O_CREAT | O_TRUNC, 0666);
38   if (fd < 0)
39     die("Unable to open %s for writing: %m", name);
40   return sopen_fd(name, fd);
41 }
42
43 void sflush(struct stream *s)
44 {
45   if (s->pos > s->stop)
46     {
47       char *p = s->buf;
48       int len = s->pos - s->buf;
49       while (len > 0)
50         {
51           int c = write(s->fd, p, len);
52           if (c <= 0)
53             die("Error writing %s: %m", s->name);
54           p += c;
55           len -= c;
56         }
57     }
58   s->pos = s->stop = s->buf;
59 }
60
61 void sclose(struct stream *s)
62 {
63   sflush(s);
64   close(s->fd);
65   free(s);
66 }
67
68 static int srefill(struct stream *s)
69 {
70   int len = read(s->fd, s->buf, BUFSIZE);
71   if (len < 0)
72     die("Error reading %s: %m", s->name);
73   s->pos = s->buf;
74   s->stop = s->buf + len;
75   return len;
76 }
77
78 int sgetc_slow(struct stream *s)
79 {
80   return (srefill(s) ? *s->pos++ : -1);
81 }
82
83 int speekc_slow(struct stream *s)
84 {
85   return (srefill(s) ? *s->pos : -1);
86 }