aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLAN-TW <lantw44@gmail.com>2012-09-19 23:24:48 +0800
committerLAN-TW <lantw44@gmail.com>2012-09-19 23:30:22 +0800
commitfae3bd51ccf149bca7beaa81bc63727cf5a46562 (patch)
tree26185b078f9bc55aceb78b6882c06fe0deea9510
parent8f307303f332e9e7695cf512590ca6b7b4af028f (diff)
downloadsctjudge-fae3bd51ccf149bca7beaa81bc63727cf5a46562.tar.gz
sctjudge-fae3bd51ccf149bca7beaa81bc63727cf5a46562.tar.zst
sctjudge-fae3bd51ccf149bca7beaa81bc63727cf5a46562.zip
修改命令列參數格式,並加入 l4basic 作為輔助用函式庫
目前有許多部份尚未配合此次命令列變更,因此程式運作可能不正常!
-rw-r--r--Makefile.am9
-rw-r--r--l4basic/Makefile12
-rw-r--r--l4basic/README13
-rw-r--r--l4basic/VERSION1
-rw-r--r--l4basic/l4arg/Makefile14
-rw-r--r--l4basic/l4arg/l4arg.h28
-rw-r--r--l4basic/l4arg/qarg.c54
-rw-r--r--l4basic/l4arg/toargv.c111
-rw-r--r--l4basic/l4bds/Makefile14
-rw-r--r--l4basic/l4bds/l4bds.h66
-rw-r--r--l4basic/l4bds/list.c235
-rw-r--r--l4basic/l4darr/Makefile14
-rw-r--r--l4basic/l4darr/d1array.c131
-rw-r--r--l4basic/l4darr/d1arrstr.c43
-rw-r--r--l4basic/l4darr/d2array.c26
-rw-r--r--l4basic/l4darr/l4darr.h62
-rw-r--r--src/Makefile.am6
-rw-r--r--src/config2.h3
-rw-r--r--src/core.h6
-rw-r--r--src/main.c297
20 files changed, 989 insertions, 156 deletions
diff --git a/Makefile.am b/Makefile.am
index af437a6..9dbeb56 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1 +1,8 @@
-SUBDIRS = src
+EXTRA_DIST = l4basic
+SUBDIRS = . src
+all-local:
+ cd l4basic/l4darr && $(MAKE) all
+ cd l4basic/l4arg && $(MAKE) all
+clean-local:
+ cd l4basic/l4darr && $(MAKE) clean
+ cd l4basic/l4arg && $(MAKE) clean
diff --git a/l4basic/Makefile b/l4basic/Makefile
new file mode 100644
index 0000000..cc3afdc
--- /dev/null
+++ b/l4basic/Makefile
@@ -0,0 +1,12 @@
+.PHONY: all clean install uninstall
+all:
+ $(MAKE) -C l4darr all
+ $(MAKE) -C l4bds all
+ $(MAKE) -C l4arg all
+clean:
+ $(MAKE) -C l4darr clean
+ $(MAKE) -C l4bds clean
+ $(MAKE) -C l4arg clean
+install:
+ @echo "You should statically link your program against it instead of installing it!"
+
diff --git a/l4basic/README b/l4basic/README
new file mode 100644
index 0000000..fb2344a
--- /dev/null
+++ b/l4basic/README
@@ -0,0 +1,13 @@
+l4arg:
+ (Argument) 解析命令列的常用函式
+l4bds:
+ (Basic Data Structure) 包含 list、stack、queue,其中 stack 和 queue 其實都
+ 是用 list 實作
+l4darr:
+ (Dynamic Array) 包含可動態調整大小的一維陣列(類似 C++ 的 vector),還有透
+ 或一維陣列模擬二維陣列的功能(但不可動態調整大小)
+
+基本上這些函式庫都很小,所以請直接靜態連結到你的程式,不要安裝到系統上!
+同時預設的 Makefile 也不提供建立動態函式庫的功能,有需要請自行處理!
+
+本函式庫使用 Public Domain 釋出,歡迎自行修改以符合需求!
diff --git a/l4basic/VERSION b/l4basic/VERSION
new file mode 100644
index 0000000..3eefcb9
--- /dev/null
+++ b/l4basic/VERSION
@@ -0,0 +1 @@
+1.0.0
diff --git a/l4basic/l4arg/Makefile b/l4basic/l4arg/Makefile
new file mode 100644
index 0000000..8c23687
--- /dev/null
+++ b/l4basic/l4arg/Makefile
@@ -0,0 +1,14 @@
+CC=cc
+AR=ar
+RM=rm
+CFLAGS=-Wall -g -I. -I../l4darr
+OBJ=toargv.o qarg.o
+LIBFILE=libl4arg.a
+
+.PHONY: all clean
+
+all: $(LIBFILE)
+$(LIBFILE): $(OBJ)
+ $(AR) rcs $(LIBFILE) $(OBJ)
+clean:
+ $(RM) -f $(LIBFILE) $(OBJ)
diff --git a/l4basic/l4arg/l4arg.h b/l4basic/l4arg/l4arg.h
new file mode 100644
index 0000000..68352c8
--- /dev/null
+++ b/l4basic/l4arg/l4arg.h
@@ -0,0 +1,28 @@
+#ifndef L4LIB_ARG_PARSER
+#define L4LIB_ARG_PARSER
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+char** l4arg_toargv(const char*, const char*, const char*, const char*);
+void l4arg_toargv_free(char**);
+
+typedef struct l4lib_qarg {
+ char* arg_name;
+ char* arg_value;
+} L4QARG;
+
+L4QARG* l4qarg_parse(const char*);
+void l4qarg_free(L4QARG*);
+#define l4qarg_n(qargitem) ((qargitem).arg_name)
+#define l4qarg_v(qargitem) ((qargitem).arg_value)
+#define l4qarg_hasvalue(qargitem) (((qargitem).arg_value != NULL))
+#define l4qarg_end(qargitem) \
+ ((((qargitem).arg_name) == NULL) && (((qargitem).arg_value) == NULL))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/l4basic/l4arg/qarg.c b/l4basic/l4arg/qarg.c
new file mode 100644
index 0000000..412967c
--- /dev/null
+++ b/l4basic/l4arg/qarg.c
@@ -0,0 +1,54 @@
+#include <stdlib.h>
+#include <string.h>
+#include <l4arg.h>
+
+/* 為什麼叫做 qarg 呢?因為這是用來解析很像 QEMU 命令列參數的參數 */
+
+L4QARG* l4qarg_parse(const char* str){
+ char** pargv = l4arg_toargv(str, ",", "\"\'", "\\");
+ if(pargv == NULL){
+ return NULL;
+ }
+ int i, allc;
+ L4QARG* qargarr;
+ char* pos;
+ for(i=0; pargv[i]!=NULL; i++);
+ allc = i + 1;
+ qargarr = (L4QARG*) malloc(sizeof(L4QARG) * allc);
+ if(qargarr == NULL){
+ l4arg_toargv_free(pargv);
+ return NULL;
+ }
+ for(i=0; pargv[i]!=NULL; i++){
+ pos = strchr(pargv[i], '=');
+ if(pos == NULL){
+ qargarr[i].arg_name = pargv[i];
+ qargarr[i].arg_value = NULL;
+ }else{
+ *pos = '\0';
+ qargarr[i].arg_name = pargv[i];
+ pos++;
+ qargarr[i].arg_value = (char*) malloc(strlen(pos)+1);
+ if(qargarr[i].arg_value == NULL){
+ l4arg_toargv_free(pargv);
+ return NULL;
+ }
+ strcpy(qargarr[i].arg_value, pos);
+ }
+ }
+ free(pargv);
+ qargarr[i].arg_name = NULL;
+ qargarr[i].arg_value = NULL;
+ return qargarr;
+}
+
+void l4qarg_free(L4QARG* qarg){
+ int i;
+ for(i=0; !(qarg[i].arg_name == NULL && qarg[i].arg_value == NULL); i++){
+ free(qarg[i].arg_name);
+ if(qarg[i].arg_value != NULL){
+ free(qarg[i].arg_value);
+ }
+ }
+ free(qarg);
+}
diff --git a/l4basic/l4arg/toargv.c b/l4basic/l4arg/toargv.c
new file mode 100644
index 0000000..433ad1a
--- /dev/null
+++ b/l4basic/l4arg/toargv.c
@@ -0,0 +1,111 @@
+#include <string.h>
+#include <stdlib.h>
+#include <l4arg.h>
+#include <l4darr.h>
+
+/* 基本上優先順序是 escape -> quoting -> delimiter */
+
+#define abort_l4arg_toargv \
+ do{ \
+ l4da_free(parr); \
+ l4da_free(tmpstr); \
+ return NULL; \
+ }while(0)
+
+char** l4arg_toargv(const char* str,
+ const char* delim, const char* quoting, const char* esc){
+ int i;
+ char escaped = 0, quoted = 0, delimed = 0;
+ L4DA* parr;
+ L4DA* tmpstr;
+ char* addstr, tmpchar;
+ char** rval;
+ parr = l4da_create(sizeof(char*), 0);
+ if(parr == NULL){
+ return NULL;
+ }
+ tmpstr = l4da_create(sizeof(char), 0);
+ if(tmpstr == NULL){
+ l4da_free(parr);
+ return NULL;
+ }
+ for(i=0; str[i]!='\0'; i++){
+ if(escaped){
+ if(l4da_pushback(tmpstr, &str[i]) < 0){
+ abort_l4arg_toargv;
+ }
+ escaped = 0;
+ delimed = 0;
+ continue;
+ }
+ if(quoted){
+ if(strchr(quoting, str[i]) != NULL){
+ quoted = 0;
+ continue;
+ }
+ if(l4da_pushback(tmpstr, &str[i]) < 0){
+ abort_l4arg_toargv;
+ }
+ delimed = 0;
+ continue;
+ }
+ if(strchr(esc, str[i]) != NULL){
+ escaped = 1;
+ continue;
+ }
+ if(strchr(quoting, str[i]) != NULL){
+ quoted = 1;
+ continue;
+ }
+ if(strchr(delim, str[i]) != NULL){
+ if(l4da_getlen(tmpstr) > 0){
+ tmpchar = '\0';
+ if(l4da_pushback(tmpstr, &tmpchar) < 0){
+ abort_l4arg_toargv;
+ }
+ addstr = (char*)l4da_drop_struct(tmpstr);
+ if(l4da_pushback(parr, &addstr) < 0){
+ l4da_free(parr);
+ return NULL;
+ }
+ tmpstr = l4da_create(sizeof(char), 0);
+ if(tmpstr == NULL){
+ l4da_free(parr);
+ return NULL;
+ }
+ }
+ delimed = 1;
+ continue;
+ }
+ if(l4da_pushback(tmpstr, &str[i]) < 0){
+ abort_l4arg_toargv;
+ }
+ delimed = 0;
+ }
+ if(!delimed){
+ tmpchar = '\0';
+ if(l4da_pushback(tmpstr, &tmpchar) < 0){
+ abort_l4arg_toargv;
+ }
+ addstr = (char*)l4da_drop_struct(tmpstr);
+ if(l4da_pushback(parr, &addstr) < 0){
+ l4da_free(parr);
+ return NULL;
+ }
+ }
+ addstr = NULL;
+ if(l4da_pushback(parr, &addstr) < 0){
+ l4da_free(parr);
+ return NULL;
+ }
+ rval = (char**)l4da_drop_struct(parr);
+ return rval;
+}
+
+void l4arg_toargv_free(char** pargv){
+ int i;
+ for(i=0; pargv[i]!=NULL; i++){
+ free(pargv[i]);
+ }
+ free(pargv);
+}
diff --git a/l4basic/l4bds/Makefile b/l4basic/l4bds/Makefile
new file mode 100644
index 0000000..1691cee
--- /dev/null
+++ b/l4basic/l4bds/Makefile
@@ -0,0 +1,14 @@
+CC=cc
+AR=ar
+RM=rm
+CFLAGS=-Wall -g -I.
+OBJ=list.o
+LIBFILE=libl4bds.a
+
+.PHONY: all clean
+
+all: $(LIBFILE)
+$(LIBFILE): $(OBJ)
+ $(AR) rcs $(LIBFILE) $(OBJ)
+clean:
+ $(RM) -f $(LIBFILE) $(OBJ)
diff --git a/l4basic/l4bds/l4bds.h b/l4basic/l4bds/l4bds.h
new file mode 100644
index 0000000..2ad7199
--- /dev/null
+++ b/l4basic/l4bds/l4bds.h
@@ -0,0 +1,66 @@
+#ifndef L4LIB_BASIC_DATA_STRUCTURE
+#define L4LIB_BASIC_DATA_STRUCTURE
+
+/*********** list ***********/
+
+typedef struct l4lib_list_node{ /* list 中每一個項目用的資料結構,會有很多個 */
+ struct l4lib_list_node* node_prev;
+ struct l4lib_list_node* node_next;
+ void* node_data;
+ int node_data_size;
+} L4LLNODE;
+
+typedef struct l4lib_list{ /* 管理 list 用的,每個 list 只有一個 */
+ struct l4lib_list_node* list_first;
+ struct l4lib_list_node* list_last;
+ int list_len;
+} L4LL;
+
+L4LL* l4ll_create(void);
+void l4ll_free(L4LL*);
+#define l4ll_prev(node) ((node)->node_prev)
+#define l4ll_next(node) ((node)->node_next)
+#define l4ll_len(list) ((list)->list_len)
+#define l4ll_node_back(list) ((list)->list_last)
+#define l4ll_node_front(list) ((list)->list_first)
+#define l4ll_data(node) ((node)->node_data)
+#define l4ll_datasize(node) ((node)->node_data_size)
+L4LLNODE* l4ll_insert_prev(L4LL*, L4LLNODE*, const void*, int);
+L4LLNODE* l4ll_insert_next(L4LL*, L4LLNODE*, const void*, int);
+void l4ll_remove(L4LL*, L4LLNODE*);
+#define l4ll_pushback(list,data,size) \
+ (l4ll_insert_next((list),(l4ll_node_back(list)),(data),(size)))
+#define l4ll_pushfront(list,data,size) \
+ (l4ll_insert_prev((list),(l4ll_node_front(list)),(data),(size)))
+#define l4ll_popback(list) \
+ (l4ll_remove((list),(l4ll_node_back((list)))))
+#define l4ll_popfront(list) \
+ (l4ll_remove((list),(l4ll_node_front((list)))))
+L4LLNODE* l4ll_goto(L4LLNODE*, int);
+
+/*********** stack ***********/
+
+typedef L4LL L4STACK;
+#define l4stack_create() (l4ll_create())
+#define l4stack_free(list) (l4ll_free(list))
+#define l4stack_push(list,data,size) (l4ll_pushback((list),(data),(size)))
+#define l4stack_pop(list) (l4ll_popback(list))
+#define l4stack_len(list) (l4ll_len(list))
+#define l4stack_data(list) (l4ll_data(l4ll_node_back(list)))
+#define l4stack_datasize(list) (l4ll_datasize(l4ll_node_back(list)))
+
+/*********** queue ***********/
+
+typedef L4LL L4QUEUE;
+#define l4queue_create() (l4ll_create())
+#define l4queue_free(list) (l4ll_free(list))
+#define l4queue_push(list,data,size) (l4ll_pushback((list),(data),(size)))
+#define l4queue_pop(list) (l4ll_popfront(list))
+#define l4queue_len(list) (l4ll_len(list))
+#define l4queue_frontdata(list) (l4ll_data(l4ll_node_front(list)))
+#define l4queue_frontdatasize(list) (l4ll_datasize(l4ll_node_front(list)))
+#define l4queue_backdata(list) (l4ll_data(l4ll_node_back(list)))
+#define l4queue_backdatasize(list) (l4ll_datasize(l4ll_node_back(list)))
+#define l4queue_data(list) (l4queue_frontdata(list))
+#define l4queue_datasize(list) (l4queue_frontdatasize(list))
+#endif
diff --git a/l4basic/l4bds/list.c b/l4basic/l4bds/list.c
new file mode 100644
index 0000000..09ec746
--- /dev/null
+++ b/l4basic/l4bds/list.c
@@ -0,0 +1,235 @@
+#include <stdlib.h>
+#include <string.h>
+#include <l4bds.h>
+
+L4LL* l4ll_create(void){
+ L4LL* newlist = (L4LL*)malloc(sizeof(L4LL));
+ if(newlist == NULL){
+ return NULL;
+ }
+ newlist->list_first = NULL;
+ newlist->list_last = NULL;
+ newlist->list_len = 0;
+ return newlist;
+}
+
+void l4ll_free(L4LL* oldlist){
+ if(oldlist->list_len <= 0){
+ free(oldlist);
+ return;
+ }
+ L4LLNODE* i;
+ L4LLNODE* next;
+ for(i=oldlist->list_first; i!=NULL; i=next){
+ next = i->node_next;
+ if(i->node_data_size){ /* 只要資料大小不為零,就還要釋放資料區 */
+ free(i->node_data);
+ }
+ free(i);
+ }
+ free(oldlist);
+}
+
+static L4LLNODE*
+l4ll_initfirst(L4LL* list, const void* data, int size){
+ /* 插入第一個資料,如果 list 不是空的就別用!
+ * 否則會造成資料結構混亂和 memory leak */
+ L4LLNODE* node = (L4LLNODE*)malloc(sizeof(L4LLNODE));
+ if(node == NULL){
+ return NULL;
+ }
+ void* newdata;
+ if(size != 0){
+ newdata = malloc(size);
+ if(newdata == NULL){
+ free(node);
+ return NULL;
+ }
+ memcpy(newdata, data, size);
+ }
+ list->list_first = node;
+ list->list_last = node;
+ list->list_len = 1;
+ node->node_prev = NULL;
+ node->node_next = NULL;
+ node->node_data = (size != 0) ? newdata : NULL;
+ node->node_data_size = size;
+ return node;
+}
+
+L4LLNODE* l4ll_insert_prev(L4LL* list, L4LLNODE* node,
+ const void* data, int size){
+ /* list 送 NULL 來的我不理它,就自己去 segfault 吧
+ * node 送 NULL 來只能在 list 是空的時候用 */
+ if(list->list_len == 0){
+ return l4ll_initfirst(list, data, size);
+ }
+ L4LLNODE* newnode = (L4LLNODE*)malloc(sizeof(L4LLNODE));
+ if(newnode == NULL){
+ return NULL;
+ }
+ void* newdata;
+ if(size != 0){
+ newdata = malloc(size);
+ if(newdata == NULL){
+ free(newnode);
+ return NULL;
+ }
+ memcpy(newdata, data, size);
+ }
+ list->list_len++;
+ if(list->list_first == node){ /* 如果是第一個,那要修改 list_first */
+ list->list_first = newnode;
+ }
+ L4LLNODE* oldprev = node->node_prev;
+ node->node_prev = newnode;
+ newnode->node_next = node;
+ newnode->node_prev = oldprev;
+ if(oldprev != NULL){
+ oldprev->node_next = newnode;
+ }
+ newnode->node_data = (size != 0) ? newdata : NULL;
+ newnode->node_data_size = size;
+ return newnode;
+}
+
+L4LLNODE* l4ll_insert_next(L4LL* list, L4LLNODE* node,
+ const void* data, int size){
+ /* 基本上同 l4ll_insert_prev */
+ if(list->list_len == 0){
+ return l4ll_initfirst(list, data, size);
+ }
+ L4LLNODE* newnode = (L4LLNODE*)malloc(sizeof(L4LLNODE));
+ if(newnode == NULL){
+ return NULL;
+ }
+ void* newdata;
+ if(size != 0){
+ newdata = malloc(size);
+ if(newdata == NULL){
+ free(newnode);
+ return NULL;
+ }
+ memcpy(newdata, data, size);
+ }
+ list->list_len++;
+ if(list->list_last == node){
+ list->list_last = newnode;
+ }
+ L4LLNODE* oldnext = node->node_next;
+ node->node_next = newnode;
+ newnode->node_prev = node;
+ newnode->node_next = oldnext;
+ if(oldnext != NULL){
+ oldnext->node_prev = newnode;
+ }
+ newnode->node_data = (size != 0) ? newdata : NULL;
+ newnode->node_data_size = size;
+ return newnode;
+}
+
+void l4ll_remove(L4LL* list, L4LLNODE* node){
+ /* 不要在 node 傳 NULL,這一點意義也沒有且我不知道會發生什麼事 */
+ if(list->list_first == node){
+ list->list_first = node->node_next;
+ }
+ if(list->list_last == node){
+ list->list_last = node->node_prev;
+ }
+ list->list_len--; /* 不考慮長度為零的情況,空白是想要刪什麼? */
+ L4LLNODE* oldnext = node->node_next;
+ L4LLNODE* oldprev = node->node_prev;
+ if(node->node_data_size != 0){
+ free(node->node_data);
+ }
+ free(node);
+ if(oldnext != NULL){
+ oldnext->node_prev = oldprev;
+ }
+ if(oldprev != NULL){
+ oldprev->node_next = oldnext;
+ }
+}
+
+L4LLNODE* l4ll_goto(L4LLNODE* node, int count){
+ int i;
+ if(count == 0){
+ return node;
+ }else if(count > 0){
+ for(i=1; i<=count; i++){
+ node = node->node_next;
+ if(node == NULL){
+ return NULL;
+ }
+ }
+ }else{
+ count = -count;
+ for(i=1; i<=count; i++){
+ node = node->node_prev;
+ if(node == NULL){
+ return NULL;
+ }
+ }
+ }
+ return node;
+}
+
+#if 0
+int l4ll_pushback(L4LL* list, void* data, int size){
+ L4LLNODE* cur_save = list->list_current; /* 等一下要把現在位置搬回去 */
+ list->list_current = list->list_last;
+ int result = l4ll_insnext(list, data, size);
+ if(result == 0){ /* 成功 */
+ if(cur_save != NULL){ /* 原先的現在位置若為空就無意義了 */
+ list->list_current = cur_save;
+ }
+ }else{ /* 失敗 */
+ list->list_current = cur_save;
+ }
+ return result;
+}
+
+
+int l4ll_pushfront(L4LL*, void*){ /* 取自 l4ll_pushback */
+ L4LLNODE* cur_save = list->list_current;
+ list->list_current = list->list_front;
+ int result = l4ll_insprev(list, data, size);
+ if(result == 0){
+ if(cur_save != NULL){
+ list->list_current = cur_save;
+ }
+ }else{
+ list->list_current = cur_save;
+ }
+ return result;
+}
+
+int l4ll_popback(L4LL*){
+ L4LLNODE* cur_save = list->list_current;
+ L4LLNODE* last_save = list->list_last
+ list->list_current = last_save;
+ int result = l4ll_remove(list, L4LL_PREV);
+ if(result == 0){
+ if(cur_save != NULL && ){
+ list->list_current = cur_save;
+ }
+ }else{
+ list->list_current = cur_save;
+ }
+ return result;
+}
+
+int l4ll_popfront(L4LL*){
+ L4LLNODE* cur_save = list->list_current;
+ list->list_current = list->list_first;
+ int result = l4ll_remove(list, L4LL_NEXT);
+ if(result == 0){
+ if(cur_save != NULL){
+ list->list_current = cur_save;
+ }
+ }else{
+ list->list_current = cur_save;
+ }
+ return result;
+}
+#endif
diff --git a/l4basic/l4darr/Makefile b/l4basic/l4darr/Makefile
new file mode 100644
index 0000000..3bc40c7
--- /dev/null
+++ b/l4basic/l4darr/Makefile
@@ -0,0 +1,14 @@
+CC=cc
+AR=ar
+RM=rm
+CFLAGS=-Wall -g -I.
+OBJ=d1array.o d1arrstr.o d2array.o
+LIBFILE=libl4darr.a
+
+.PHONY: all clean
+
+all: $(LIBFILE)
+$(LIBFILE): $(OBJ)
+ $(AR) rcs $(LIBFILE) $(OBJ)
+clean:
+ $(RM) -f $(LIBFILE) $(OBJ)
diff --git a/l4basic/l4darr/d1array.c b/l4basic/l4darr/d1array.c
new file mode 100644
index 0000000..4091358
--- /dev/null
+++ b/l4basic/l4darr/d1array.c
@@ -0,0 +1,131 @@
+#include <stdlib.h>
+#include <string.h>
+#include <l4darr.h>
+
+L4DA* l4da_create_setmax(int itemsize, int len, int maxlen){
+ if(itemsize <= 0 || len < 0 || maxlen < len){
+ return NULL;
+ }
+ L4DA* arr = (L4DA*)malloc(sizeof(L4DA));
+ if(arr == NULL){
+ return NULL;
+ }
+ arr->arr_itemsize = itemsize;
+ arr->arr_curlen = len;
+ arr->arr_maxlen = maxlen;
+ if(maxlen != 0){
+ arr->arr_data = malloc(itemsize * maxlen);
+ if(arr->arr_data == NULL){
+ free(arr);
+ return NULL;
+ }
+ }else{
+ arr->arr_data = NULL;
+ }
+ return arr;
+}
+
+L4DA* l4da_create(int itemsize, int len){
+ return l4da_create_setmax(itemsize, len, len);
+}
+
+void l4da_free(L4DA* arr){
+ if(arr->arr_data != NULL){
+ free(arr->arr_data);
+ }
+ free(arr);
+}
+
+int l4da_pushback(L4DA* arr, const void* data){
+ if((arr->arr_maxlen) < (arr->arr_curlen + 1)){
+ if(arr->arr_maxlen != 0){
+ if(l4da_setmax(arr, arr->arr_maxlen*2) < 0){
+ return -1;
+ }
+ }else{
+ if(l4da_setmax(arr, 1) < 0){
+ return -1;
+ }
+ }
+ }
+ memcpy(l4da_vp(arr, arr->arr_curlen), data, arr->arr_itemsize);
+ arr->arr_curlen++;
+ return 0;
+}
+
+int l4da_setlen(L4DA* arr, int len){
+ if(len > (arr->arr_maxlen)){
+ if(l4da_setmax(arr, len) < 0){
+ return -1;
+ }else{
+ arr->arr_curlen = len;
+ }
+ }else{
+ arr->arr_curlen = len;
+ return 0;
+ }
+ return 0;
+}
+
+int l4da_setmax(L4DA* arr, int max){
+ void* newptr;
+ if(arr->arr_data == NULL){
+ newptr = malloc((arr->arr_itemsize)*max);
+ if(newptr == NULL){
+ return -1;
+ }else{
+ arr->arr_maxlen = max;
+ arr->arr_data = newptr;
+ return 0;
+ }
+ }
+ newptr = realloc(arr->arr_data, (arr->arr_itemsize)*max);
+ if(newptr == NULL){
+ return -1;
+ }else{
+ arr->arr_maxlen = max;
+ arr->arr_data = newptr;
+ }
+ return 0;
+}
+
+int l4da_strip(L4DA* arr){
+ if(arr->arr_data == NULL){
+ return 0;
+ }
+ L4DA* newptr;
+ /* 其實縮小空間營該一定會成功才對......
+ * 不過還是保險一點,加個判斷式,別說 memory leak 是我害的
+ * 當然也是避免編譯器一直跳 warning
+ */
+ if((arr->arr_maxlen) > (arr->arr_curlen)){
+ arr->arr_maxlen = arr->arr_curlen;
+ newptr = realloc(arr->arr_data, (arr->arr_curlen)*(arr->arr_itemsize));
+ if(newptr == NULL){
+ return -1;
+ }
+ arr->arr_data = newptr;
+ }
+ return 0;
+}
+
+/* 基本上直接玩 struct 的函式還是少用吧 */
+void* l4da_drop_struct(L4DA* arr){
+ void* toreturn = arr->arr_data;
+ free(arr);
+ return toreturn;
+}
+
+L4DA* l4da_make_struct(void* data, int itemsize, int len, int maxlen){
+ if(itemsize <= 0 || len < 0 || maxlen < len){
+ return NULL;
+ }
+ L4DA* arr = (L4DA*)malloc(sizeof(L4DA));
+ if(arr == NULL){
+ return NULL;
+ }
+ arr->arr_itemsize = itemsize;
+ arr->arr_curlen = len;
+ arr->arr_maxlen = maxlen;
+ return arr;
+}
diff --git a/l4basic/l4darr/d1arrstr.c b/l4basic/l4darr/d1arrstr.c
new file mode 100644
index 0000000..212760e
--- /dev/null
+++ b/l4basic/l4darr/d1arrstr.c
@@ -0,0 +1,43 @@
+#include <string.h>
+#include <l4darr.h>
+
+L4DA* l4da_dup(const L4DA* arr){
+ L4DA* newarr = l4da_create_setmax(
+ l4da_itemsize(arr), l4da_getlen(arr), l4da_getmax(arr));
+ if(newarr == NULL){
+ return NULL;
+ }
+ memcpy(newarr->arr_data, arr->arr_data,
+ l4da_getlen(arr) * l4da_itemsize(arr));
+ return newarr;
+}
+
+int l4da_combine(L4DA* arr, const L4DA* att){
+ if(l4da_itemsize(arr) != l4da_itemsize(att)){
+ return -2;
+ }
+ if(l4da_setlen(arr, l4da_getlen(arr) + l4da_getlen(att)) < 0){
+ return -1;
+ }
+ memcpy(l4da_vp(arr, l4da_getlen(arr)), att->arr_data,
+ l4da_getlen(att) * l4da_itemsize(att));
+ return 0;
+}
+
+L4DA* l4da_filereadline_delim(FILE* infile, int chr){
+ L4DA* newarr = l4da_create(1, 0);
+ if(newarr == NULL){
+ return NULL;
+ }
+ int c;
+ char towrite;
+ do{
+ c = getc(infile);
+ towrite = c;
+ if(l4da_pushback(newarr, (void*)&towrite) < 0){
+ l4da_free(newarr);
+ return NULL;
+ }
+ }while(c != chr);
+ return newarr;
+}
diff --git a/l4basic/l4darr/d2array.c b/l4basic/l4darr/d2array.c
new file mode 100644
index 0000000..c2d6e69
--- /dev/null
+++ b/l4basic/l4darr/d2array.c
@@ -0,0 +1,26 @@
+#include <stdlib.h>
+#include <l4darr.h>
+
+L4DA2* l4da2_create(int itemsize, int lenx, int leny){
+ if(lenx <= 0 || leny <= 0 || itemsize <= 0){
+ return NULL;
+ }
+ L4DA2* arr = (L4DA2*)malloc(sizeof(L4DA2));
+ if(arr == NULL){
+ return NULL;
+ }
+ arr->arr_itemsize = itemsize;
+ arr->arr_lenx = lenx;
+ arr->arr_leny = leny;
+ arr->arr_data = malloc(itemsize*lenx*leny);
+ if(arr->arr_data == NULL){
+ free(arr);
+ return NULL;
+ }
+ return arr;
+}
+
+void l4da2_free(L4DA2* arr){
+ free(arr->arr_data);
+ free(arr);
+}
diff --git a/l4basic/l4darr/l4darr.h b/l4basic/l4darr/l4darr.h
new file mode 100644
index 0000000..d4aab12
--- /dev/null
+++ b/l4basic/l4darr/l4darr.h
@@ -0,0 +1,62 @@
+#ifndef L4LIB_DYNAMIC_ARRAY
+#define L4LIB_DYNAMIC_ARRAY
+
+#include <stdio.h> /* 取得 FILE */
+
+/*********** 一維陣列 ***********/
+
+typedef struct l4lib_dyn_arr{
+ int arr_itemsize; /* 每個項目的大小 */
+ int arr_curlen; /* 陣列總長度 */
+ int arr_maxlen; /* 陣列最大長度 */
+ void* arr_data; /* 資料區 */
+} L4DA ;
+
+L4DA* l4da_create_setmax(int, int, int);
+L4DA* l4da_create(int, int);
+void l4da_free(L4DA*);
+int l4da_pushback(L4DA*, const void*);
+#define l4da_popback(arr) (((arr)->arr_curlen)--)
+#define l4da_getlen(arr) ((arr)->arr_curlen)
+int l4da_setlen(L4DA*, int);
+#define l4da_getmax(arr) ((arr)->arr_maxlen)
+int l4da_setmax(L4DA*, int);
+int l4da_strip(L4DA*);
+#define l4da_itemsize(arr) ((arr)->arr_itemsize)
+#define l4da_v(arr, type, num) \
+ (*(((type*)((arr)->arr_data))+(num)))
+#define l4da_vp(arr, num) \
+ ((void*)(((char*)((arr)->arr_data))+(((arr)->arr_itemsize)*(num))))
+
+#define l4da_readline (l4da_filereadline_delim(stdin, '\n'))
+#define l4da_readline_delim(delim) (l4da_filereadline_delim(stdin, (delim)))
+#define l4da_filereadline(infile) (l4da_filereadline_delim((infile), '\n'))
+L4DA* l4da_filereadline_delim(FILE*, int);
+
+L4DA* l4da_dup(const L4DA*);
+int l4da_combine(L4DA*, const L4DA*);
+
+void* l4da_drop_struct(L4DA*);
+L4DA* l4da_make_struct(void*, int, int, int);
+
+/*********** 二維陣列 (其實是用一維陣列來模擬,功能有限) ***********/
+
+typedef struct l4lib_dyn_2darr{
+ int arr_itemsize; /* 每個項目的大小 */
+ int arr_lenx; /* 陣列 x 方向長度 */
+ int arr_leny; /* 陣列 y 方向長度 */
+ void* arr_data; /* 資料區 */
+} L4DA2 ;
+
+L4DA2* l4da2_create(int, int, int);
+void l4da2_free(L4DA2*);
+#define l4da2_getlenx(arr) ((arr)->arr_lenx)
+#define l4da2_getleny(arr) ((arr)->arr_leny)
+#define l4da2_itemsize(arr) ((arr)->arr_itemsize)
+#define l4da2_v(arr, type, numx, numy) \
+ (*(((type*)((arr)->arr_data))+((numx)*(l4da2_getleny(arr)))+(numy)))
+#define l4da2_vp(arr, numx, numy) \
+ ((void*)(((char*)((arr)->arr_data))+ \
+ ((arr)->arr_itemsize)*((numx)*(l4da2_getleny(arr))+(numy))))
+
+#endif
diff --git a/src/Makefile.am b/src/Makefile.am
index 51ab89a..27daa09 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,7 +1,7 @@
bin_PROGRAMS = sctjudge
-sctjudge_CFLAGS = -Wall -pipe -pthread
-sctjudge_LDFLAGS =
-sctjudge_LDADD =
+sctjudge_CFLAGS = -Wall -pipe -pthread -I../l4basic/l4darr -I../l4basic/l4arg
+sctjudge_LDFLAGS = -L../l4basic/l4darr -L../l4basic/l4arg
+sctjudge_LDADD = -ll4arg -ll4darr
sctjudge_SOURCES = common.c common.h config.h core.h disptime.c checktle.c\
main.c mkchild.c version.h config2.h
diff --git a/src/config2.h b/src/config2.h
index 3f508d5..ba798eb 100644
--- a/src/config2.h
+++ b/src/config2.h
@@ -9,4 +9,5 @@
#define SCTJUDGE_EXIT_SUCCESS 0 /* 當然就是正常結束 */
#define SCTJUDGE_EXIT_SYNTAX 1 /* 命令列語法錯誤 */
#define SCTJUDGE_EXIT_TOOFEW 2 /* 少了一些必須的選項 */
-#define SCTJUDGE_EXIT_THREAD 3 /* pthread_create 以後才發生錯誤 */
+#define SCTJUDGE_EXIT_MALLOC 3 /* 配置記憶體發生錯誤 */
+#define SCTJUDGE_EXIT_THREAD 4 /* pthread_create 以後才發生錯誤 */
diff --git a/src/core.h b/src/core.h
index 94418e5..0778597 100644
--- a/src/core.h
+++ b/src/core.h
@@ -49,8 +49,10 @@ struct makechildopt{
#define SCTMC_NOCOPY 0x00000002
#define SCTMC_SETUID 0x00000004
#define SCTMC_SETGID 0x00000008
-#define SCTMC_VERBOSE 0x00000010
-#define SCTMC_DRYRUN 0x00000020
+#define SCTMC_DRYRUN 0x00000010
+#define SCTMC_FORCE 0x00000020
+#define SCTMC_VERBOSE 0x00000040
+#define SCTMC_DEBUG 0x00000080
/* sctjudge_makechild 的回傳值,main 會接收到 */
struct makechildrval{
diff --git a/src/main.c b/src/main.c
index ef76767..e8782ed 100644
--- a/src/main.c
+++ b/src/main.c
@@ -18,9 +18,39 @@
#include <pthread.h>
#include <semaphore.h>
-#define SCTMAIN_ERRNOARG "%s: 選項「%s」之後需要一個參數"
-#define SCTMAIN_ERRBADARG "%s: 在「%s」之後有個不存在或用"\
- "法不正確的參數「%s」\n"
+#include <l4darr.h>
+#include <l4arg.h>
+
+#define SCTMAIN_ERRNOARG "%s: 選項「%s」之後需要一個參數\n"
+#define SCTMAIN_ERRNOQARG "%s: 在「%s」之後缺少一個值\n"
+#define SCTMAIN_ERREXTRAQARG "%s: 在「%s」之後並不需要參數\n"
+
+#define SCTMAIN_CHECKARGEXIST \
+ do{ \
+ i++; \
+ if(i >= argc){ \
+ fprintf(stderr, SCTMAIN_ERRNOARG, argv[0], argv[i-1]); \
+ exit(SCTJUDGE_EXIT_TOOFEW); \
+ } \
+ }while(0)
+
+#define SCTMAIN_CHECKQARGHAVEVALUE \
+ do{ \
+ if(!l4qarg_hasvalue(qarglist[j])){ \
+ fprintf(stderr, SCTMAIN_ERRNOQARG, \
+ argv[0], qarglist[j].arg_name); \
+ exit(SCTJUDGE_EXIT_TOOFEW); \
+ } \
+ }while(0)
+
+#define SCTMAIN_CHECKQARGNOVALUE \
+ do{ \
+ if(l4qarg_hasvalue(qarglist[j])){ \
+ fprintf(stderr, SCTMAIN_ERREXTRAQARG, \
+ argv[0], qarglist[j].arg_name); \
+ exit(SCTJUDGE_EXIT_SYNTAX); \
+ } \
+ }while(0)
static const char* sctres_text[2][SCTRES_MAX] = {
{"OK", "RE", "TLE", "OLE", "SLE", "AB", "UD"},
@@ -35,72 +65,16 @@ static const char* sctres_text[2][SCTRES_MAX] = {
}
};
-int getargvint(int* ip, int argc, const char* prearg, const char* arg,
- const char* argzero, const char* invalidmsg){
- int toreturn;
- (*ip)++;
- if((*ip) < argc){
- toreturn = atoi(arg);
- if(toreturn <= 0){
- fprintf(stderr, invalidmsg, argzero, arg);
- exit(SCTJUDGE_EXIT_SYNTAX);
- }
- }else{
- fprintf(stderr, SCTMAIN_ERRNOARG, argzero, prearg);
- exit(SCTJUDGE_EXIT_SYNTAX);
- }
- return toreturn;
-}
-
-char* getargvstr(int* ip, int argc, const char* prearg, const char* arg,
- const char* argzero){
- char* toreturn;
- (*ip)++;
- if((*ip) < argc){
- toreturn = (char*)arg;
- }else{
- fprintf(stderr, SCTMAIN_ERRNOARG, argzero, prearg);
- exit(SCTJUDGE_EXIT_SYNTAX);
- }
- return toreturn;
-}
-
-int getargvmulstr(char* arg, char** key, char** value, int* keylen){
- /* 警告;這個函式 thread unsafe */
- static char* prearg = NULL;
- char *tmpstr, *seppos;
- if(prearg != arg){
- tmpstr = strtok(arg, ",");
- }else{
- tmpstr = strtok(NULL, ",");
- }
- prearg = arg;
- if(tmpstr == NULL){
- return -1;
- }else{
- seppos = strchr(tmpstr, '=');
- (*key) = tmpstr;
- if(seppos == NULL){
- (*value) = NULL;
- }else{
- (*keylen) = seppos - tmpstr;
- (*value) = seppos + 1;
- }
- return 0;
- }
- return 0;
-}
-
int main(int argc, char* argv[]){
/* 照理說是 zh_TW.utf8,但考慮作業系統差異還是從環境變數抓
* (反正出錯是使用者的事) */
setlocale(LC_ALL, "");
- int i;
+ int i, j;
struct makechildopt mcopt; /* 送給 sctjudge_makechild 當參數用 */
- char verbose=0, dryrun=0;
- char *mulstr_key, *mulstr_value;
- int mulstr_keylen;
+ char verbose=0; /* 0 是安靜模式(機器模式)、1 是 verbose、2 是 debug */
+ char dryrun=0, force=0;
+ L4QARG* qarglist;
/* 預設值當然都是 0 */
memset(&mcopt, 0 ,sizeof(mcopt));
@@ -118,49 +92,51 @@ int main(int argc, char* argv[]){
"用法:%s [選項]\n"
"選項:\n\n"
" -v/-verbose\n"
- " 顯示詳細執行過程\n\n"
- " -version\n"
+ " 顯示更多訊息(第二個 -v 可以顯示所有重要指令執行過"
+ "程)\n\n"
+ " -V/version\n"
" 顯示版本資訊\n\n"
" -n/-dryrun\n"
" 只列出設定值而不要執行(包含 -v)\n\n"
+ " -f/-force\n"
+ " 忽略警告訊息並強制執行\n\n"
" -t/-time <時間>\n"
" 受測程式時間限制為<時間>毫秒\n\n"
- " -m/-memory <大小>\n"
- " 受測程式記憶體限制<大小>MiB\n\n"
+ " -e/-exec <檔案>\n"
+ " 指定受測程式可執行檔名稱(務必靜態連結!)\n\n"
" -i/-input <檔案>\n"
" 指定要導向至受測程式標準輸入的檔案,若未指定則為 "
NULL_DEVICE"\n\n"
- " -o/-output file=<檔案>[,stderr][,limit=<大小>]\n"
- " 設定受測程式輸出選項:\n\n"
- " file=<檔案>\n"
- " 指定輸出檔案為<檔案>\n\n"
+ " -o/-output <檔案>\n"
+ " 指定要導向至受測程式標準輸出的檔案,若未指定則為 "
+ NULL_DEVICE"\n\n"
+ " -r/-root <目錄>\n"
+ " 受測程式將以<目錄>為根目錄執行,若無此選項則關"
+ "閉 chroot 功能\n\n"
+ " -m/-misc 選項1[=值],選項2[=值],選項3[=值]...\n"
+ " 設定額外參數:\n\n"
+ " mem=<大小>\n"
+ " 設定受測程式記憶體上限為<大小>MiB\n\n"
+ " outlimit=<大小>\n"
+ " 受測程式最多只能輸出<大小>MiB,若未指定則不限制"
+ "\n"
+ " (無限制時請確定有足夠的磁碟空間!)\n\n"
" stderr\n"
" 將受測程式的標準錯誤也導向至輸出檔。若未指定,"
"則只有標準輸\n"
" 出會寫入輸出檔案,標準錯誤則被導向至 "
NULL_DEVICE"\n\n"
- " limit=<大小>\n"
- " 受測程式最多只能輸出<大小>MiB,若未指定則不限制"
- "\n"
- " (無限制時請確定你有足夠的磁碟空間!)\n\n"
- " -e/-exec file=<檔案>[,nocopy]\n"
- " 設定受測程式可執行檔位置:\n\n"
- " file=<檔案>\n"
- " 指定受測程式檔案名稱\n\n"
" nocopy\n"
- " 如果你啟用了 chroot 功能,預設情況下本程式會自"
- "動將檔案複製\n"
+ " 如果啟用了 chroot 功能,預設情況下本程式會自動"
+ "將檔案複製\n"
" 到新的根目錄中,並在結束時自動刪除檔案。\n"
" 使用此選項則取消自動複製的功能,但請注意:此時"
" file 指定的\n"
" 檔案名稱是相對於新的根目錄而不是現在的根目錄!"
"\n\n"
- " -chroot <目錄>\n"
- " 受測程式將以<目錄>為根目錄執行,若無此選項則關"
- "閉 chroot 功能\n\n"
- " -u/-uid <UID>\n"
- " 受測程式將以 UID 為 <UID> 的使用者身份執行\n"
- " -g/-gid <GID>\n"
+ " uid=<UID>\n"
+ " 受測程式將以 UID 為 <UID> 的使用者身份執行\n\n"
+ " gid=<GID>\n"
" 受測程式將以 GID 為 <GID> 的群組身份執行\n"
" 此選項會同時設定 real/effective/supplementary "
"GID(s)\n"
@@ -168,94 +144,117 @@ int main(int argc, char* argv[]){
"定的數值\n\n"
, argv[0]);
return SCTJUDGE_EXIT_SUCCESS;
- }else if(!strcmp(&argv[i][1], "version") ||
+ }else if(!strcmp(&argv[i][1], "V") ||
+ !strcmp(&argv[i][1], "version") ||
!strcmp(&argv[i][1], "-version")){
puts(SCTJUDGE_TITLEBAR);
exit(SCTJUDGE_EXIT_SUCCESS);
}else if(!strcmp(&argv[i][1], "v") ||
!strcmp(&argv[i][1], "verbose")){
- verbose = 1;
+ verbose++;
mcopt.flags |= SCTMC_VERBOSE;
+ if(verbose >= 2){
+ mcopt.flags |= SCTMC_DEBUG;
+ }
}else if(!strcmp(&argv[i][1], "n") ||
!strcmp(&argv[i][1], "dryrun")){
dryrun = 1, verbose = 1;
mcopt.flags |= (SCTMC_DRYRUN | SCTMC_VERBOSE);
+ }else if(!strcmp(&argv[i][1], "f") ||
+ !strcmp(&argv[i][1], "force")){
+ force = 1;
+ mcopt.flags |= (SCTMC_FORCE);
}else if(!strcmp(&argv[i][1], "t") ||
!strcmp(&argv[i][1], "time")){
- mcopt.exectime = getargvint(&i, argc, argv[i], argv[i+1],
- argv[0], "%s: 「%s」不是正確的時間設定值\n");
- }else if(!strcmp(&argv[i][1], "m") ||
- !strcmp(&argv[i][1], "memory")){
- mcopt.memlimit = getargvint(&i, argc, argv[i], argv[i+1],
- argv[0], "%s: 「%s」不是正確的記憶體大小設定\n");
+ SCTMAIN_CHECKARGEXIST;
+ mcopt.exectime = atoi(argv[i]);
+ if(mcopt.exectime <= 0){
+ fprintf(stderr, "%s: 「%s」不是正確的時間設定值\n",
+ argv[0], argv[i]);
+ exit(SCTJUDGE_EXIT_SYNTAX);
+ }
+ }else if(!strcmp(&argv[i][1], "e") ||
+ !strcmp(&argv[i][1], "exec")){
+ SCTMAIN_CHECKARGEXIST;
+ mcopt.executable = argv[i];
}else if(!strcmp(&argv[i][1], "i") ||
+ !strcmp(&argv[i][1], "in") ||
!strcmp(&argv[i][1], "input")){
- mcopt.inputfile = getargvstr(&i, argc, argv[i], argv[i+1],
- argv[0]);
+ SCTMAIN_CHECKARGEXIST;
+ mcopt.inputfile = argv[i];
}else if(!strcmp(&argv[i][1], "o") ||
+ !strcmp(&argv[i][1], "out") ||
!strcmp(&argv[i][1], "output")){
- getargvstr(&i, argc, argv[i], argv[i+1], argv[0]);
- while(getargvmulstr(argv[i], &mulstr_key, &mulstr_value,
- &mulstr_keylen) >= 0){
- if(mulstr_value == NULL){
- if(!strcmp(mulstr_key, "stderr")){
- mcopt.flags |= SCTMC_REDIR_STDERR;
- }else{
- fprintf(stderr, SCTMAIN_ERRBADARG
- , argv[0], argv[i-1], mulstr_key);
+ SCTMAIN_CHECKARGEXIST;
+ mcopt.outputfile = argv[i];
+ }else if(!strcmp(&argv[i][1], "r") ||
+ !strcmp(&argv[i][1], "root") ||
+ !strcmp(&argv[i][1], "chroot")){
+ SCTMAIN_CHECKARGEXIST;
+ mcopt.executable = argv[i];
+ }else if(!strcmp(&argv[i][1], "m") ||
+ !strcmp(&argv[i][1], "misc") ||
+ !strcmp(&argv[i][1], "opt") ||
+ !strcmp(&argv[i][1], "option")){
+ SCTMAIN_CHECKARGEXIST;
+ qarglist = l4qarg_parse(argv[i]);
+ if(qarglist == NULL){
+ fprintf(stderr, "%s: 記憶體配置發生錯誤\n", argv[0]);
+ exit(SCTJUDGE_EXIT_MALLOC);
+ }
+ for(j=0; !l4qarg_end(qarglist[j]); j++){
+ if(!strcmp(qarglist[j].arg_name, "mem") ||
+ !strcmp(qarglist[j].arg_name, "memory")){
+ SCTMAIN_CHECKQARGHAVEVALUE;
+ mcopt.memlimit = atoi(qarglist[j].arg_value);
+ if(mcopt.memlimit <= 0){
+ fprintf(stderr, "%s: 「%s」不是正確的記憶體限制"
+ "設定值\n", argv[0],
+ qarglist[j].arg_value);
exit(SCTJUDGE_EXIT_SYNTAX);
}
- }else{
- if(!strncmp(mulstr_key, "limit", mulstr_keylen)){
- mcopt.outlimit = atoi(mulstr_value);
- if(mcopt.outlimit <= 0){
- fprintf(stderr, "%s: 「%s」不是正確的輸出限制"
- "值\n", argv[0], mulstr_value);
- exit(SCTJUDGE_EXIT_SYNTAX);
- }
- }else if(!strncmp(mulstr_key, "file", mulstr_keylen)){
- mcopt.outputfile = mulstr_value;
- }else{
- fprintf(stderr, SCTMAIN_ERRBADARG
- , argv[0], argv[i-1], mulstr_key);
+ }else if(!strcmp(qarglist[j].arg_name, "outlimit") ||
+ !strcmp(qarglist[j].arg_name, "outlim")){
+ SCTMAIN_CHECKQARGHAVEVALUE;
+ mcopt.outlimit = atoi(qarglist[j].arg_value);
+ if(mcopt.outlimit <= 0){
+ fprintf(stderr, "%s: 「%s」不是正確的輸出限制"
+ "設定\n", argv[0], qarglist[j].arg_value);
exit(SCTJUDGE_EXIT_SYNTAX);
}
- }
- }
- }else if(!strcmp(&argv[i][1], "e") ||
- !strcmp(&argv[i][1], "exec")){
- getargvstr(&i, argc, argv[i], argv[i+1], argv[0]);
- while(getargvmulstr(argv[i], &mulstr_key, &mulstr_value,
- &mulstr_keylen) >= 0){
- if(mulstr_value == NULL){
- if(!strcmp(mulstr_key, "nocopy")){
- mcopt.flags |= SCTMC_NOCOPY;
- }else{
- fprintf(stderr, SCTMAIN_ERRBADARG,
- argv[0], argv[i-1], mulstr_key);
+ }else if(!strcmp(qarglist[j].arg_name, "stderr")){
+ SCTMAIN_CHECKQARGNOVALUE;
+ mcopt.flags |= SCTMC_REDIR_STDERR;
+ }else if(!strcmp(qarglist[j].arg_name, "nocopy")){
+ SCTMAIN_CHECKQARGNOVALUE;
+ mcopt.flags |= SCTMC_NOCOPY;
+ }else if(!strcmp(qarglist[j].arg_name, "uid") ||
+ !strcmp(qarglist[j].arg_name, "user")){
+ SCTMAIN_CHECKQARGHAVEVALUE;
+ mcopt.flags |= SCTMC_SETUID;
+ if(sscanf(qarglist[j].arg_value, "%d", &mcopt.uid)
+ <= 0){
+ fprintf(stderr, "%s: 「%s」並不是整數\n",
+ argv[0], qarglist[j].arg_value);
exit(SCTJUDGE_EXIT_SYNTAX);
}
- }else{
- if(!strncmp(mulstr_key, "file", mulstr_keylen)){
- mcopt.executable = mulstr_value;
- }else{
- fprintf(stderr, SCTMAIN_ERRBADARG
- , argv[0], argv[i-1], mulstr_key);
+ }else if(!strcmp(qarglist[j].arg_name, "gid") ||
+ !strcmp(qarglist[j].arg_name, "group")){
+ SCTMAIN_CHECKQARGHAVEVALUE;
+ mcopt.flags |= SCTMC_SETGID;
+ if(sscanf(qarglist[j].arg_value, "%d", &mcopt.gid)
+ <= 0){
+ fprintf(stderr, "%s: 「%s」並不是整數\n",
+ argv[0], qarglist[j].arg_value);
exit(SCTJUDGE_EXIT_SYNTAX);
}
+ }else{
+ fprintf(stderr, "%s: 「%s」是不明的選項\n", argv[0],
+ qarglist[j].arg_name);
+ exit(SCTJUDGE_EXIT_SYNTAX);
}
}
- }else if(!strcmp(&argv[i][1], "chroot")){
- mcopt.chrootdir = getargvstr(&i, argc, argv[i], argv[i+1],
- argv[0]);
- }else if(!strcmp(&argv[i][1], "u") || !strcmp(&argv[i][1], "uid")){
- mcopt.flags |= SCTMC_SETUID;
- mcopt.uid = getargvint(&i, argc, argv[i], argv[i+1],
- argv[0], "%s: 指定 UID 為「%s」不安全或不合理\n");
- }else if(!strcmp(&argv[i][1], "g") || !strcmp(&argv[i][1], "gid")){
- mcopt.flags |= SCTMC_SETGID;
- mcopt.gid = getargvint(&i, argc, argv[i], argv[i+1],
- argv[0], "%s: 指定 GID 為「%s」不安全或不合理\n");
+ l4qarg_free(qarglist);
}else{
fprintf(stderr, "%s: 不明的選項「%s」\n", argv[0], argv[i]);
return SCTJUDGE_EXIT_SYNTAX;