diff options
author | LAN-TW <lantw44@gmail.com> | 2012-09-19 23:24:48 +0800 |
---|---|---|
committer | LAN-TW <lantw44@gmail.com> | 2012-09-19 23:30:22 +0800 |
commit | fae3bd51ccf149bca7beaa81bc63727cf5a46562 (patch) | |
tree | 26185b078f9bc55aceb78b6882c06fe0deea9510 | |
parent | 8f307303f332e9e7695cf512590ca6b7b4af028f (diff) | |
download | sctjudge-fae3bd51ccf149bca7beaa81bc63727cf5a46562.tar.gz sctjudge-fae3bd51ccf149bca7beaa81bc63727cf5a46562.tar.zst sctjudge-fae3bd51ccf149bca7beaa81bc63727cf5a46562.zip |
修改命令列參數格式,並加入 l4basic 作為輔助用函式庫
目前有許多部份尚未配合此次命令列變更,因此程式運作可能不正常!
-rw-r--r-- | Makefile.am | 9 | ||||
-rw-r--r-- | l4basic/Makefile | 12 | ||||
-rw-r--r-- | l4basic/README | 13 | ||||
-rw-r--r-- | l4basic/VERSION | 1 | ||||
-rw-r--r-- | l4basic/l4arg/Makefile | 14 | ||||
-rw-r--r-- | l4basic/l4arg/l4arg.h | 28 | ||||
-rw-r--r-- | l4basic/l4arg/qarg.c | 54 | ||||
-rw-r--r-- | l4basic/l4arg/toargv.c | 111 | ||||
-rw-r--r-- | l4basic/l4bds/Makefile | 14 | ||||
-rw-r--r-- | l4basic/l4bds/l4bds.h | 66 | ||||
-rw-r--r-- | l4basic/l4bds/list.c | 235 | ||||
-rw-r--r-- | l4basic/l4darr/Makefile | 14 | ||||
-rw-r--r-- | l4basic/l4darr/d1array.c | 131 | ||||
-rw-r--r-- | l4basic/l4darr/d1arrstr.c | 43 | ||||
-rw-r--r-- | l4basic/l4darr/d2array.c | 26 | ||||
-rw-r--r-- | l4basic/l4darr/l4darr.h | 62 | ||||
-rw-r--r-- | src/Makefile.am | 6 | ||||
-rw-r--r-- | src/config2.h | 3 | ||||
-rw-r--r-- | src/core.h | 6 | ||||
-rw-r--r-- | src/main.c | 297 |
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 以後才發生錯誤 */ @@ -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{ @@ -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; |