diff options
author | LAN-TW <lantw44@gmail.com> | 2013-02-20 09:47:22 +0800 |
---|---|---|
committer | LAN-TW <lantw44@gmail.com> | 2013-02-20 09:53:17 +0800 |
commit | 0eefe53e15fddb6a9131222e3d389e73de3c7013 (patch) | |
tree | 37e1f21632b7dbe7849e70b3084cd40c5921ea1b /src/SctCommon.c | |
parent | 2a6d9c778a19a55d8d91c119749d9339165a382f (diff) | |
download | sctjudge-master.tar.gz sctjudge-master.tar.zst sctjudge-master.zip |
關於程式架構,請參考 README 檔案。
目前仍許多功能在舊版已實作,但此版本尚未加入。
Diffstat (limited to 'src/SctCommon.c')
-rw-r--r-- | src/SctCommon.c | 163 |
1 files changed, 163 insertions, 0 deletions
diff --git a/src/SctCommon.c b/src/SctCommon.c new file mode 100644 index 0000000..27019e0 --- /dev/null +++ b/src/SctCommon.c @@ -0,0 +1,163 @@ +#ifdef HAVE_CONFIG_H +# include "SctConfig.h" +#endif + +#include "SctCommon.h" + +#include <time.h> +#include <errno.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> + +#include <pthread.h> + +uid_t procrealuid = 0; +uid_t proceffuid = 0; + +int str_to_u(const char* s, unsigned* u){ + char* p; + unsigned o; + errno = 0; + o = strtoul(s, &p, 0); + if(errno || *p){ + return -1; + } + *u = o; + return 0; +} + +int read_complete(int fd, void* buf, size_t count){ + /* 一定要讀到 count 位元組的資料才會回傳,所以只要回傳 < count + * 就表示已經讀到 EOF 了 */ + char* bufp = (char*)buf; + size_t curcount = 0; + int rval; + do{ + rval = read(fd, bufp, count - curcount); + if(rval < 0){ + return rval; + }else if(rval == 0){ + return curcount; + }else{ + bufp += rval; + curcount += rval; + } + }while(curcount < count); + return count; +} + +int strerror_threadsafe(int errnum, char* buf, size_t buflen){ + static pthread_mutex_t strerror_call_mutex = PTHREAD_MUTEX_INITIALIZER; + char* rval; + int rlen; + pthread_mutex_lock(&strerror_call_mutex); + rval = strerror(errnum); + rlen = strlen(rval); + if(buflen < rlen){ + pthread_mutex_unlock(&strerror_call_mutex ); + return -1; + } + strcpy(buf, rval); + pthread_mutex_unlock(&strerror_call_mutex); + return 0; +} + +int sprintf_malloc(char** strstore, const char* format, ...){ + int len; + char* newstr; + va_list ap; + + va_start(ap, format); + len = vsnprintf(NULL, 0, format, ap) + 1; + va_end(ap); + + newstr = malloc(len); + if(newstr == NULL){ + return -1; + } + + va_start(ap, format); + len = vsnprintf(newstr, len, format, ap); + va_end(ap); + + *strstore = newstr; + return len; +} + +void checktimespec(struct timespec* arg){ + long tominus; + if(arg->tv_nsec >= 1000000000){ + arg->tv_sec += (arg->tv_nsec / 1000000000); + arg->tv_nsec %= 1000000000; + }else if(arg->tv_nsec < 0){ + if((-(arg->tv_nsec)) % 1000000000 == 0){ + arg->tv_sec -= ((-(arg->tv_nsec)) / 1000000000); + arg->tv_nsec = 0; + }else{ + tominus = (((-(arg->tv_nsec)) / 1000000000) + 1); + arg->tv_sec -= tominus; + arg->tv_nsec += tominus * 1000000000; + } + } +} + +void difftimespec(start, end, out) + const struct timespec* start; + const struct timespec* end; + struct timespec* out; +{ + out->tv_sec = end->tv_sec - start->tv_sec; + out->tv_nsec = end->tv_nsec - start->tv_nsec; + if(out->tv_nsec < 0){ + out->tv_nsec += 1000000000; + out->tv_sec--; + } +} + +int comparetimespec(t1, t2) + const struct timespec* t1; + const struct timespec* t2; +{ + if(t1->tv_sec < t2->tv_sec){ + return -1; + }else if(t1->tv_sec > t2->tv_sec){ + return 1; + }else{ + if(t1->tv_nsec < t2->tv_nsec){ + return -1; + }else if(t1->tv_nsec > t2->tv_nsec){ + return 1; + }else{ + return 0; + } + } + return 0; +} + +void save_uids(void){ /* 這個一定要先執行,不然預設 uid 就是 0 */ + procrealuid = getuid(); + proceffuid = geteuid(); +} + +#ifndef HAVE_CONF_CAP + +void disable_setuid(void){ +#ifdef _POSIX_SAVED_IDS + seteuid(procrealuid); +#else + setreuid(proceffuid, procrealuid); +#endif +} + +void enable_setuid(void){ +#ifdef _POSIX_SAVED_IDS + seteuid(proceffuid); +#else + setreuid(procrealuid, proceffuid); +#endif +} + +#endif |