source: trunk/jrun/options.c @ 1184

Revision 852, 7.3 KB checked in by cdleonard@…, 4 years ago (diff)

svn:eol-style native in trunk. Also svn:executable on all scripts

  • Property svn:eol-style set to native
Line 
1/*
2 * This file parses options, see jrun.c for usage.
3 * Uses getopt
4 */
5#include "jrun.h"
6#include <getopt.h>
7
8jrun_options jopt;
9
10// Stupid constants used with getopt
11#define OPT_UID                         0
12#define OPT_GID                         1
13#define OPT_DIR                         2
14#define OPT_PROG                        3
15#define OPT_TIME_LIMIT                  4
16#define OPT_WALL_TIME_LIMIT             15
17#define OPT_MEMORY_LIMIT                5
18#define OPT_NICE                        6
19#define OPT_NO_PTRACE                   7
20#define OPT_COPY_LIBS                   8
21#define OPT_VERBOSE                     9
22#define OPT_BLOCK_SYSCALLS              10
23#define OPT_BLOCK_SYSCALLS_FILE         11
24#define OPT_REDIRECT_STDIN               17
25#define OPT_REDIRECT_STDOUT              12
26#define OPT_REDIRECT_STDERR              13
27#define OPT_CHROOT                      14
28
29void jrun_parse_options(int argc, char *argv[])
30{
31    struct option long_options[] = {
32        {"uid",                 1, 0, OPT_UID},
33        {"gid",                 1, 0, OPT_GID},
34        {"dir",                 1, 0, OPT_DIR},
35        {"prog",                1, 0, OPT_PROG},
36        {"time-limit",          1, 0, OPT_TIME_LIMIT},
37        {"wall-time-limit",     1, 0, OPT_WALL_TIME_LIMIT},
38        {"memory-limit",        1, 0, OPT_MEMORY_LIMIT},
39        {"nice",                1, 0, OPT_NICE},
40        {"no-ptrace",           0, 0, OPT_NO_PTRACE},
41        {"copy-libs",           0, 0, OPT_COPY_LIBS},
42        {"verbose",             0, 0, OPT_VERBOSE},
43        {"block-syscalls",      1, 0, OPT_BLOCK_SYSCALLS},
44        {"block-syscalls-file", 1, 0, OPT_BLOCK_SYSCALLS_FILE},
45        {"redirect-stdin",      1, 0, OPT_REDIRECT_STDIN},
46        {"redirect-stdout",     1, 0, OPT_REDIRECT_STDOUT},
47        {"redirect-stderr",     1, 0, OPT_REDIRECT_STDERR},
48        {"chroot",              0, 0, OPT_CHROOT},
49        {0, 0, 0, 0},
50    };
51    int option_index = 0;
52
53    // Initioalize options:
54    memset(jopt.syscall_block, 0, sizeof(jopt.syscall_block));
55    jopt.uid = -1;
56    jopt.gid = -1;
57
58    jopt.prog[0] = 0;
59    getcwd(jopt.dir, sizeof(jopt.dir));
60   
61    jopt.time_limit = 0;
62    jopt.wall_time_limit = -1;
63    jopt.memory_limit = 0;
64
65    jopt.nice_val = -1000;
66    jopt.ptrace = 1;
67    jopt.copy_libs = 0;
68    jopt.min_proc_update_interval = 5;
69
70    jopt.verbose = 0;
71    jopt.chroot = 0;
72    jopt.stdout_file[0] = jopt.stderr_file[0] = jopt.stdin_file[0] = 0;
73
74    while (1) {
75        int opt = getopt_long(argc, argv, "u:g:d:p:n:t:w:m:v", long_options, &option_index);
76        if (opt == -1) {
77            break;
78        }
79        switch (opt) {
80            case 'u': case OPT_UID:
81                if (sscanf(optarg, "%d", &(jopt.uid)) != 1) {
82                    printf("ERROR: --uid needs an int parameter\n");
83                    exit(-1);
84                }
85                break;
86            case 'g': case OPT_GID:
87                if (sscanf(optarg, "%d", &(jopt.gid)) != 1) {
88                    printf("ERROR: --gid needs an int parameter\n");
89                    exit(-1);
90                }
91                break;
92            case 'd': case OPT_DIR:
93                strcpy(jopt.dir, optarg);
94                break;
95            case 'p': case OPT_PROG:
96                strcpy(jopt.prog, optarg);
97                break;
98            case 'n': case OPT_NICE:
99                if (sscanf(optarg, "%d", &jopt.nice_val) != 1) {
100                    printf("ERROR: --nice needs an int parameter\n");
101                    exit(-1);
102                }
103                if (jopt.nice_val < -20 || jopt.nice_val > 19) {
104                    printf("ERROR: nice value has to be in -20..19 range, inclusive\n");
105                    exit(-1);
106                }
107                break;
108            case 't': case OPT_TIME_LIMIT:
109                if (sscanf(optarg, "%d", &jopt.time_limit) != 1) {
110                    printf("ERROR: --time-limit needs an int parameter\n");
111                    exit(-1);
112                }
113                break;
114            case 'w': case OPT_WALL_TIME_LIMIT:
115                if (sscanf(optarg, "%d", &jopt.wall_time_limit) != 1) {
116                    printf("ERROR: --wall-time-limit needs an int parameter\n");
117                    exit(-1);
118                }
119                break;
120            case 'm': case OPT_MEMORY_LIMIT:
121                if (sscanf(optarg, "%d", &jopt.memory_limit) != 1) {
122                    printf("ERROR: --memory-limit needs an int parameter\n");
123                    exit(-1);
124                }
125                break;
126            case 'v': case OPT_VERBOSE:
127                jopt.verbose = 1;
128                break;
129            case OPT_NO_PTRACE:
130                jopt.ptrace = 0;
131                break;
132            case OPT_COPY_LIBS:
133                jopt.copy_libs = 1;
134                break;
135            case OPT_REDIRECT_STDIN: {
136                strcpy(jopt.stdin_file, optarg);
137                break;
138            }
139            case OPT_REDIRECT_STDOUT: {
140                strcpy(jopt.stdout_file, optarg);
141                break;
142            }
143            case OPT_REDIRECT_STDERR: {
144                strcpy(jopt.stderr_file, optarg);
145                break;
146            }
147            case OPT_BLOCK_SYSCALLS: {
148                // Yes, I use strtok.
149                // Yes, I know it's a horrible horrible hack.
150                char* str = strdup(optarg);
151                char* s;
152                int id;
153               
154                s = strtok(str, ",");
155                while (s) {
156                    id = syscall_getid(s);
157                    if (id < 0) {
158                        printf("ERROR: Unknown system call %s\n", s);
159                        exit(-1);
160                    }
161                    jopt.syscall_block[id] = 1;
162                    s = strtok(0, ",");
163                }
164                break;
165            }
166            case OPT_BLOCK_SYSCALLS_FILE: {
167                char buf[200];
168                FILE* f;
169                f = fopen(optarg, "rt");
170                if (f == NULL) {
171                    printf("Failed to open blocked syscalls file\n");
172                    exit(-1);
173                }
174                while (fscanf(f, "%150s", buf) == 1) {
175                    int id;
176                    id = syscall_getid(buf);
177                    if (id < 0) {
178                        printf("ERROR: Unknown system call %s\n", buf);
179                        exit(-1);
180                    } else {
181                        jopt.syscall_block[id] = 1;
182                    }
183                }
184                fclose(f);
185                break;
186            }
187            case OPT_CHROOT: {
188                jopt.chroot = 1;
189                break;
190            }
191            default: {
192                printf("ERROR: Bad command line arguments");
193                exit(-1);
194            }
195        }
196    }
197
198    // After options:
199   
200    // You need to pass the program name.
201    if (jopt.prog[0] == 0) {
202        printf("ERROR: You must give the file to execute\n");
203        exit(-1);
204    }
205
206    // Default wall_time is time_limit + 5 seconds.
207    if (jopt.wall_time_limit == -1 && jopt.time_limit) {
208        jopt.wall_time_limit = jopt.time_limit + 5000;
209    }
210
211    // We can't follow forks. We suck.
212    jopt.syscall_block[syscall_getid("fork")] = 1;
213    jopt.syscall_block[syscall_getid("vfork")] = 1;
214    jopt.syscall_block[syscall_getid("clone")] = 1;
215    jopt.syscall_block[syscall_getid("system")] = 1;
216}
Note: See TracBrowser for help on using the repository browser.