diff options
author | LAN-TW <lantw44@gmail.com> | 2014-01-12 16:42:19 +0800 |
---|---|---|
committer | LAN-TW <lantw44@gmail.com> | 2014-01-12 16:42:19 +0800 |
commit | 0c1dfc4fcbf9764633aa6cb1798e63d55af66752 (patch) | |
tree | 73eb50e8924c41cc2721c50aa731bec5ca03c196 /hw4 | |
parent | 57ab8916608d8b319a1b522bdb2e549ebcac1072 (diff) | |
download | sp2013-0c1dfc4fcbf9764633aa6cb1798e63d55af66752.tar sp2013-0c1dfc4fcbf9764633aa6cb1798e63d55af66752.tar.gz sp2013-0c1dfc4fcbf9764633aa6cb1798e63d55af66752.tar.bz2 sp2013-0c1dfc4fcbf9764633aa6cb1798e63d55af66752.tar.lz sp2013-0c1dfc4fcbf9764633aa6cb1798e63d55af66752.tar.xz sp2013-0c1dfc4fcbf9764633aa6cb1798e63d55af66752.tar.zst sp2013-0c1dfc4fcbf9764633aa6cb1798e63d55af66752.zip |
HW4: 準備 build system
Diffstat (limited to 'hw4')
-rw-r--r-- | hw4/Makefile.am | 27 | ||||
-rwxr-xr-x | hw4/autogen.sh | 25 | ||||
-rw-r--r-- | hw4/chttpd-log.c | 13 | ||||
-rw-r--r-- | hw4/chttpd-log.h | 28 | ||||
-rw-r--r-- | hw4/chttpd-main.c | 8 | ||||
-rw-r--r-- | hw4/configure.ac | 34 | ||||
-rw-r--r-- | hw4/l4basic.sed | 7 | ||||
-rw-r--r-- | hw4/l4basic/l4common.h | 42 | ||||
-rw-r--r-- | hw4/l4basic/l4list.c | 201 | ||||
-rw-r--r-- | hw4/l4basic/l4list.h | 116 | ||||
-rw-r--r-- | hw4/l4basic/l4posix.c | 333 | ||||
-rw-r--r-- | hw4/l4basic/l4posix.h | 41 | ||||
-rw-r--r-- | hw4/l4basic/l4str.c | 44 | ||||
-rw-r--r-- | hw4/l4basic/l4str.h | 15 | ||||
-rw-r--r-- | hw4/memwrap.c | 67 | ||||
-rw-r--r-- | hw4/memwrap.h | 12 |
16 files changed, 1013 insertions, 0 deletions
diff --git a/hw4/Makefile.am b/hw4/Makefile.am new file mode 100644 index 0000000..6d4fdc1 --- /dev/null +++ b/hw4/Makefile.am @@ -0,0 +1,27 @@ +EXTRA_DIST = +NULL = + +bin_PROGRAMS = cgish-httpd +noinst_LIBRARIES = libl4basic.a + +libl4basic_a_SOURCES = \ + memwrap.h \ + memwrap.c \ + l4basic/l4common.h \ + l4basic/l4list.h \ + l4basic/l4list.c \ + l4basic/l4str.h \ + l4basic/l4str.c \ + l4basic/l4posix.h \ + l4basic/l4posix.c \ + $(NULL) +libl4basic_a_CFLAGS = -pthread -I$(top_srcdir)/l4basic +libl4basic_a_CPPFLAGS = -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 + +cgish_httpd_SOURCES = \ + chttpd-main.c \ + chttpd-log.h \ + chttpd-log.c \ + $(NULL) +cgish_httpd_CFLAGS = -pthread -I$(top_srcdir)/l4basic +cgish_httpd_LDADD = $(top_builddir)/libl4basic.a diff --git a/hw4/autogen.sh b/hw4/autogen.sh new file mode 100755 index 0000000..2f3a1fc --- /dev/null +++ b/hw4/autogen.sh @@ -0,0 +1,25 @@ +#!/bin/sh + +generate_file () +{ + file_src="$1" + file_dest="../l4basic/$1" + + echo "Generating $file_src" + sed -f "$2" "$file_src" > "$file_dest" +} + +autoreconf -iv +[ -z "$1" ] && exit 0 + +mkdir -p "l4basic" +git clone "$1" "l4basic-tmp" +cd "l4basic-tmp" + +for i in l4common.h l4list.[ch] l4posix.[ch] l4str.[ch] +do + generate_file "$i" "../l4basic.sed" +done + +cd ".." +rm -rf "l4basic-tmp" diff --git a/hw4/chttpd-log.c b/hw4/chttpd-log.c new file mode 100644 index 0000000..24dae72 --- /dev/null +++ b/hw4/chttpd-log.c @@ -0,0 +1,13 @@ +/* b01902062 藍挺瑋 */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "chttpd-log.h" +#include <l4list.h> + +#include <string.h> + +ChttpdLog* chttpd_log_new (const char* name, int log_fd) { + return NULL; +} diff --git a/hw4/chttpd-log.h b/hw4/chttpd-log.h new file mode 100644 index 0000000..c29d421 --- /dev/null +++ b/hw4/chttpd-log.h @@ -0,0 +1,28 @@ +#ifndef CHTTPD_LOG_H +#define CHTTPD_LOG_H + +#include <l4list.h> + +#include <pthread.h> +#include <sys/types.h> + +typedef struct { + unsigned ref_count; + char* name; + pid_t pid; + int log_fd; + LbsList* log_data; + pthread_rwlock_t rwlock; +} ChttpdLog; + +ChttpdLog* chttpd_log_new (const char* name, int log_fd); +ChttpdLog* chttpd_log_new_file (const char* name, const char* file); +ChttpdLog* chttpd_log_ref (ChttpdLog* log); +void chttpd_log_unref (ChttpdLog* log); + +int chttpd_log_read_start (ChttpdLog* log); +void chttpd_log_read_stop (ChttpdLog* log); +int chttpd_log_write (ChttpdLog* log, const char* format, ...); +int chttpd_log_write_str (ChttpdLog* log, const char* string); + +#endif /* CHTTPD_LOG_H */ diff --git a/hw4/chttpd-main.c b/hw4/chttpd-main.c new file mode 100644 index 0000000..df27b73 --- /dev/null +++ b/hw4/chttpd-main.c @@ -0,0 +1,8 @@ +/* b01902062 藍挺瑋 */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +int main (int argc, char* argv[]) { + return 0; +} diff --git a/hw4/configure.ac b/hw4/configure.ac new file mode 100644 index 0000000..e57b5bc --- /dev/null +++ b/hw4/configure.ac @@ -0,0 +1,34 @@ +# -*- Autoconf -*- +# Process this file with autoconf to produce a configure script. + +AC_INIT([cgish-httpd], [1]) +AC_CONFIG_SRCDIR([chttpd-main.c]) +AC_CONFIG_HEADERS([config.h]) + +AM_INIT_AUTOMAKE([foreign]) +AM_SILENT_RULES([yes]) + +# Checks for programs. +AC_PROG_CC([clang gcc cl cc]) +AC_PROG_CC_C99 +AC_PROG_RANLIB + +if test x"${ac_cv_prog_cc_c99}" = xno; then + AC_MSG_ERROR([C99 support is required to compile $PACKAGE]) +fi + +# Checks for typedefs, structures, and compiler characteristics. +AC_CHECK_HEADER_STDBOOL +AC_C_INLINE +AC_TYPE_OFF_T +AC_TYPE_PID_T +AC_TYPE_SIZE_T +AC_TYPE_SSIZE_T + +# Checks for library functions. +AC_FUNC_MALLOC +AC_FUNC_REALLOC +AC_FUNC_STRERROR_R + +AC_CONFIG_FILES([Makefile]) +AC_OUTPUT diff --git a/hw4/l4basic.sed b/hw4/l4basic.sed new file mode 100644 index 0000000..74725ca --- /dev/null +++ b/hw4/l4basic.sed @@ -0,0 +1,7 @@ +1i\ +#include "memwrap.h" +1i\ +/* This file is modified by autogen.sh */ +s/malloc/xmalloc/g +s/realloc/xrealloc/g +s/strdup/xstrdup/g diff --git a/hw4/l4basic/l4common.h b/hw4/l4basic/l4common.h new file mode 100644 index 0000000..c41539c --- /dev/null +++ b/hw4/l4basic/l4common.h @@ -0,0 +1,42 @@ +#include "memwrap.h" +/* This file is modified by autogen.sh */ +/* vim: set sw=4 ts=4 sts=4 et: */ +#ifndef LBS_COMMON_H +#define LBS_COMMON_H + +#include <stddef.h> + +#ifdef __STDC_VERSION__ +# include <stdbool.h> +# if __STDC_VERSION__ >= 201112L +# define LBS_COMMON_ISO_C11 +# define LBS_COMMON_CHECK_TYPE(x,type) (_Generic ((x), type: (x))) +# else +# define LBS_COMMON_ISO_C99 +# define LBS_COMMON_CHECK_TYPE(x,type) (x) +# endif +#else +# ifdef __cplusplus +# define LBS_COMMON_CXX +# define LBS_COMMON_CHECK_TYPE(x,type) (x) +# else +# define bool char +# define true 1 +# define false 0 +# define inline +# define LBS_COMMON_ISO_C89 +# define LBS_COMMON_CHECK_TYPE(x,type) (x) +# endif /* __cplusplus */ +#endif /* __STDC_VERSION__ */ + +#define LBS_COMMON_NULL_PTR ((void*)NULL) +#define LBS_COMMON_DEFINE_GETTER(ns,xt,m,mt) \ + static inline mt ns ## _get_ ## m (xt x) { \ + return x->m; \ + } +#define LBS_COMMON_DEFINE_SETTER(ns,xt,m,mt) \ + static inline void ns ## _set_ ## m (xt x, mt v) { \ + x->m = v; \ + } + +#endif /* LBS_COMMON_H */ diff --git a/hw4/l4basic/l4list.c b/hw4/l4basic/l4list.c new file mode 100644 index 0000000..3569b19 --- /dev/null +++ b/hw4/l4basic/l4list.c @@ -0,0 +1,201 @@ +#include "memwrap.h" +/* This file is modified by autogen.sh */ +/* vim: set sw=4 ts=4 sts=4 et: */ +#include "l4list.h" + +#include <stdlib.h> +#include <string.h> + +LbsListMeta* lbs_list_meta_new (void (*free_func) (void*)) { + LbsListMeta* list = xmalloc (sizeof (LbsListMeta)); + if (list == NULL) { + return NULL; + } + + list->first = NULL; + list->last = NULL; + list->len = 0; + list->free_func = free_func; + + return list; +} + +void lbs_list_meta_free (LbsListMeta* list) { + if (list == NULL) { + return; + } + if (list->len <= 0) { + free (list); + return; + } + + LbsList *iter, *next; + for (iter = list->first; iter != NULL; iter = next) { + next = iter->next; + if (iter->free_func != NULL) { + (*(iter->free_func)) (iter->data); + } else if (list->free_func != NULL) { + (*(list->free_func)) (iter->data); + } + free (iter); + } + free (list); +} + +static LbsList* init_first_node (LbsListMeta* list, + void* data, void (*free_func) (void*)) { + + /* Warning: This function assumes the list is empty! */ + LbsList* node = xmalloc (sizeof (LbsList)); + if (node == NULL) { + return NULL; + } + + if (list != NULL) { + list->first = node; + list->last = node; + list->len = 1; + } + + node->prev = NULL; + node->next = NULL; + node->data = data; + node->free_func = free_func; + + return node; +} + +LbsList* lbs_list_insert_prev (LbsListMeta* list, LbsList* node, + void* data, void (*free_func) (void*)) { + + if (list != NULL && list->len <= 0) { + return init_first_node (list, data, free_func); + } + + LbsList* new_node = xmalloc (sizeof (LbsList)); + if (new_node == NULL) { + return NULL; + } + + if (node == NULL) { + new_node->prev = NULL; + new_node->next = NULL; + new_node->data = data; + new_node->free_func = free_func; + return new_node; + } + + if (list != NULL) { + list->len++; + if (list->first == node) { + list->first = new_node; + } + } + + LbsList* old_prev = node->prev; + node->prev = new_node; + new_node->next = node; + new_node->prev = old_prev; + if (old_prev != NULL) { + old_prev->next = new_node; + } + + new_node->data = data; + new_node->free_func = free_func; + return new_node; +} + +LbsList* lbs_list_insert_next (LbsListMeta* list, LbsList* node, + void* data, void (*free_func) (void*)) { + + if (list != NULL && list->len <= 0) { + return init_first_node (list, data, free_func); + } + + LbsList* new_node = xmalloc (sizeof (LbsList)); + if (new_node == NULL) { + return NULL; + } + + if (node == NULL) { + new_node->prev = NULL; + new_node->next = NULL; + new_node->data = data; + new_node->free_func = free_func; + return new_node; + } + + if (list != NULL) { + list->len++; + if(list->last == node){ + list->last = new_node; + } + } + + LbsList* old_next = node->next; + node->next = new_node; + new_node->prev = node; + new_node->next = old_next; + if (old_next != NULL) { + old_next->prev = new_node; + } + + new_node->data = data; + new_node->free_func = free_func; + return new_node; +} + +void lbs_list_remove (LbsListMeta* list, LbsList* node) { + /* node must not be NULL! */ + if (list != NULL) { + if (list->first == node) { + list->first = node->next; + } + if (list->last == node) { + list->last = node->prev; + } + if (list->len > 0) { + list->len--; + } + } + + LbsList* old_next = node->next; + LbsList* old_prev = node->prev; + + if (node->free_func != NULL) { + (*(node->free_func)) (node->data); + } else if (list != NULL && list->free_func != NULL) { + (*(list->free_func)) (node->data); + } + free (node); + + if (old_next != NULL) { + old_next->prev = old_prev; + } + if (old_prev != NULL) { + old_prev->next = old_next; + } +} + +LbsList* lbs_list_goto (LbsList* node, int count) { + int i; + + if (count > 0) { /* positive */ + for (i = 0; i < count; i++) { + node = node->next; + if (node == NULL) { + return NULL; + } + } + } else if (count < 0) { /* negative */ + count = -count; + for (i = 0; i < count; i++) { + node = node->prev; + if (node == NULL) { + return NULL; + } + } + } + + return node; +} diff --git a/hw4/l4basic/l4list.h b/hw4/l4basic/l4list.h new file mode 100644 index 0000000..00dba10 --- /dev/null +++ b/hw4/l4basic/l4list.h @@ -0,0 +1,116 @@ +#include "memwrap.h" +/* This file is modified by autogen.sh */ +/* vim: set sw=4 ts=4 sts=4 et: */ +#ifndef LBS_LIST_H +#define LBS_LIST_H + +#include <l4common.h> + +typedef struct LbsListStruct { /* list node */ + /*< private >*/ + struct LbsListStruct* prev; /* pointer to the previous node */ + struct LbsListStruct* next; /* pointer to the next node */ + + /*< public >*/ + void (*free_func) (void* data); /* function to free the data pointer */ + void* data; /* data pointer */ +} LbsList; + +typedef struct LbsListMetaStruct { /* list wrapper */ + /*< private >*/ + struct LbsListStruct* first; /* pointer to the first node in the list */ + struct LbsListStruct* last; /* pointer to the last node in the list */ + size_t len; /* current length of the list */ + + /*< public >*/ + void (*free_func) (void* data); + /* Function to free the data pointer. This function is used only if + * the free_func field in the node is set to NULL */ +} LbsListMeta; + +#define LBS_LIST(x) ((LbsList*)(x)) +#define LBS_LIST_META(x) ((LbsListMeta*)(x)) + +LbsListMeta* lbs_list_meta_new (void (*free_func) (void*)); +void lbs_list_meta_free (LbsListMeta* list); + +#define lbs_list_meta_get_first(list) \ + (LBS_COMMON_CHECK_TYPE ((list), LbsListMeta*)->first) +#define lbs_list_meta_get_last(list) \ + (LBS_COMMON_CHECK_TYPE ((list), LbsListMeta*)->last) +#define lbs_list_meta_get_len(list) \ + (LBS_COMMON_CHECK_TYPE ((list), LbsListMeta*)->len) +#define lbs_list_meta_get_free_func(list) \ + (LBS_COMMON_CHECK_TYPE ((list), LbsListMeta*)->free_func) + +#define lbs_list_meta_set_free_func(list,value) \ + ((LBS_COMMON_CHECK_TYPE ((list), LbsListMeta*)->free_func) = (value)) + +#define lbs_list_get_prev(node) \ + (LBS_COMMON_CHECK_TYPE ((node), LbsList*)->prev) +#define lbs_list_get_next(node) \ + (LBS_COMMON_CHECK_TYPE ((node), LbsList*)->next) +#define lbs_list_get_data(node) \ + (LBS_COMMON_CHECK_TYPE ((node), LbsList*)->data) +#define lbs_list_get_free_func(node) \ + (LBS_COMMON_CHECK_TYPE ((node), LbsList*)->free_func) + +#define lbs_list_set_data(node,value) \ + ((LBS_COMMON_CHECK_TYPE ((node), LbsList*)->data) = (value)) +#define lbs_list_set_free_func(node,value) \ + ((LBS_COMMON_CHECK_TYPE ((node), LbsList*)->free_func) = (value)) + +LbsList* lbs_list_insert_prev (LbsListMeta* list, LbsList* node, + void* data, void (*free_func) (void*)); +LbsList* lbs_list_insert_next (LbsListMeta* list, LbsList* node, + void* data, void (*free_func) (void*)); +void lbs_list_remove (LbsListMeta* list, LbsList* node); + +#define lbs_list_push_back(list,data,f) \ + (lbs_list_insert_next ((list), (lbs_list_meta_get_last (list)), (data), (f))) +#define lbs_list_push_front(list,data,f) \ + (lbs_list_insert_prev ((list), (lbs_list_meta_get_first (list)), (data), (f))) +#define lbs_list_pop_back(list) \ + (lbs_list_remove ((list), (lbs_list_meta_get_last ((list))))) +#define lbs_list_pop_front(list) \ + (lbs_list_remove ((list), (lbs_list_meta_get_first ((list))))) + +LbsList* lbs_list_goto (LbsList* node, int count); +#define lbs_list_meta_goto(list,count) \ + (lbs_list_goto ((lbs_list_meta_get_first (list)), (count))) + + +#ifndef LBS_LIST_DISABLE_STACK + +typedef LbsListMeta LbsStack; +#define lbs_stack_new(f) (lbs_list_meta_new (f)) +#define lbs_stack_free(stack) (lbs_list_meta_free (stack)) +#define lbs_stack_push(stack,data,f) \ + (lbs_list_push_back ((stack), (data), (f))) +#define lbs_stack_pop(stack) (lbs_list_pop_back (stack)) +#define lbs_stack_get_len(stack) (lbs_list_meta_get_len (stack)) +#define lbs_stack_get_data(stack) \ + (lbs_list_get_data (lbs_list_meta_get_last (stack))) + +#endif /* LBS_LIST_DISABLE_STACK */ + + +#ifndef LBS_LIST_DISABLE_QUEUE + +typedef LbsListMeta LbsQueue; +#define lbs_queue_new(f) (lbs_list_meta_new (f)) +#define lbs_queue_free(queue) (lbs_list_meta_free (queue)) +#define lbs_queue_enqueue(queue,data,f) \ + (lbs_list_push_back ((queue), (data), (f))) +#define lbs_queue_dequeue(queue) (lbs_list_pop_front (queue)) +#define lbs_queue_get_len(queue) (lbs_list_meta_get_len (queue)) +#define lbs_queue_get_front(queue) \ + (lbs_list_get_data (lbs_list_meta_get_first (queue))) +#define lbs_queue_get_back(queue) \ + (lbs_list_get_data (lbs_list_meta_get_last (queue))) +#define lbs_queue_get_data(queue) (lbs_queue_get_front (queue)) + +#endif /* LBS_LIST_DISABLE_QUEUE */ + + +#endif /* LBS_LIST_H */ diff --git a/hw4/l4basic/l4posix.c b/hw4/l4basic/l4posix.c new file mode 100644 index 0000000..82b42a0 --- /dev/null +++ b/hw4/l4basic/l4posix.c @@ -0,0 +1,333 @@ +#include "memwrap.h" +/* This file is modified by autogen.sh */ +/* vim: set sw=4 ts=4 sts=4 et: */ +#define _POSIX_C_SOURCE 200809L +#define _XOPEN_SOURCE 700 +#include "l4posix.h" + +#include <arpa/inet.h> +#include <errno.h> +#include <fcntl.h> +#include <netinet/in.h> +#include <stdarg.h> +#include <stdlib.h> +#include <string.h> +#include <sys/select.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +char* lbs_posix_strcat (const char* str, ...) { + va_list ap; + char* strp; + char* strnow; + char* newstr; + int len = strlen (str); + + va_start (ap, str); + while ((strp = va_arg (ap, char*)) != NULL) { + len += strlen (strp); + } + va_end (ap); + + newstr = xmalloc (len + 1); + + va_start (ap, str); + strnow = stpcpy (newstr, str); + while ((strp = va_arg (ap, char*)) != NULL) { + strnow = stpcpy (strnow, strp); + } + newstr[len] = '\0'; + va_end (ap); + + return newstr; +} + +int lbs_posix_add_fd (int fd, int fdflags) { + int orgfd = fcntl (fd, F_GETFD); + if (orgfd < 0) { + return -1; + } + return fcntl (fd, F_SETFD, orgfd | fdflags); +} + +int lbs_posix_del_fd (int fd, int fdflags) { + int orgfd = fcntl (fd, F_GETFD); + if (orgfd < 0) { + return -1; + } + return fcntl (fd, F_SETFD, orgfd & ~(fdflags)); +} + +int lbs_posix_add_fl (int fd, int flflags) { + int orgfl = fcntl (fd, F_GETFL); + if (orgfl < 0) { + return -1; + } + return fcntl (fd, F_SETFL, orgfl | flflags); +} + +int lbs_posix_del_fl (int fd, int flflags) { + int orgfl = fcntl (fd, F_GETFL); + if (orgfl < 0) { + return -1; + } + return fcntl (fd, F_SETFL, orgfl & ~(flflags)); +} + +char* lbs_posix_readlink (const char* filename) { + struct stat st; + if (lstat (filename, &st) < 0) { + return NULL; + } + size_t bufsize = st.st_size ? st.st_size : 8192; + char* buf = xmalloc (bufsize + 1); + if (buf == NULL) { + return NULL; + } + ssize_t written = readlink (filename, buf, bufsize); + if (written < 0) { + free (buf); + return NULL; + } + buf[written] = '\0'; + return buf; +} + +char* lbs_posix_getcwd (void) { + char *cwd, *result; + size_t size = pathconf (".", _PC_PATH_MAX); + + size = size > 0 ? size : 256; + size = size > 8192 ? 8192 : size; + cwd = xmalloc (sizeof (char) * size); + + while ((result = getcwd (cwd, size)) == NULL && errno == ERANGE) { + size *= 2; + cwd = xrealloc (cwd, size); + } + + return cwd; +} + +size_t lbs_posix_write_all (int fd, const char* str, size_t size) { + ssize_t wtn = 0; + if (size <= 0) { + size = strlen (str); + } + size_t rem = size; + while (rem > 0) { + wtn = write (fd, str, rem); + if (wtn < 0) { + if (errno != EINTR && errno != EAGAIN) { + break; + } + continue; + } + str += wtn; + rem -= wtn; + } + + rem = rem > 0 ? rem : 0; + return size - rem; +} + +void lbs_posix_buffer_init (LbsPosixBuffer* buf) { + buf->buf_start = 0; + buf->buf_len = 0; + buf->buf_line = NULL; + buf->buf_line_len = 0; + buf->buf_error = false; + buf->buf_eof = false; +} + +void lbs_posix_buffer_clear (LbsPosixBuffer* buf, bool initial) { + buf->buf_start = 0; + buf->buf_len = 0; + + if (!initial) { + free (buf->buf_line); + } + buf->buf_line = NULL; + buf->buf_line_len = 0; + buf->buf_error = false; + buf->buf_eof = false; +} + +char* lbs_posix_buffer_getline (int fd, LbsPosixBuffer* buf, int delim) { + if (buf->buf_error || buf->buf_eof) { + return NULL; + } + + if (buf->buf_len == 0) { + int rval = read (fd, buf->buf, LBS_POSIX_BUFFER_SIZE); + if (rval < 0) { + if (errno != EAGAIN && errno != EINTR) { + buf->buf_error = true; + } + return NULL; + } + if (rval == 0) { + buf->buf_eof = true; + return NULL; + } + buf->buf_start = 0; + buf->buf_len = rval; + } + + int i; + for (i = 0; i < buf->buf_len; i++) { + if (buf->buf[buf->buf_start + i] == delim) { + break; + } + } + + int buf_line_start = buf->buf_line_len; + buf->buf_line_len += i; + buf->buf_line = xrealloc (buf->buf_line, buf->buf_line_len + 1); + memcpy (buf->buf_line + buf_line_start, buf->buf + buf->buf_start, i); + buf->buf_line[buf->buf_line_len] = '\0'; + + /* remove CR if delim is LF and delim is found */ + if (i < buf->buf_len && delim == '\n' && buf->buf_line_len - 1 >= 0 && + buf->buf_line[buf->buf_line_len - 1] == '\r') { + buf->buf_line[buf->buf_line_len - 1] = '\0'; + buf->buf_line_len--; + } + + int buf_len_saved = buf->buf_len; + buf->buf_start += i + 1; + buf->buf_len -= i + 1; + if (buf->buf_len <= 0) { + buf->buf_start = 0; + buf->buf_len = 0; + } + + if (i < buf_len_saved) { + /* delim is found */ + char* newstr = buf->buf_line; + buf->buf_line = NULL; + buf->buf_line_len = 0; + memmove (buf->buf, buf->buf + buf->buf_start, buf->buf_len); + buf->buf_start = 0; + return newstr; + } + + return NULL; +} + +#define SOCKADDR(x) ((struct sockaddr*)(x)) +#define SOCKADDR_UN(x) ((struct sockaddr_un*)(x)) +#define SOCKADDR_IN(x) ((struct sockaddr_in*)(x)) +#define SOCKADDR_IN6(x) ((struct sockaddr_in6*)(x)) + +static char* lbs_posix_socket_name ( + int sockfd, int (*getter) (int, struct sockaddr*, socklen_t*)) { + + struct sockaddr_storage sock; + socklen_t socklen = sizeof (sock); + + memset (&sock, 0, socklen); + if ((*getter)(sockfd, SOCKADDR (&sock), &socklen) < 0) { + return xstrdup ("invalid socket"); + } + + int domain = sock.ss_family; + if (domain == AF_UNIX) { + return xstrdup ("local process"); + } + + socklen_t ipstrlen; + void* ipnet; + char* ipstr; + if (domain == AF_INET) { + ipstrlen = INET_ADDRSTRLEN; + ipnet = &(SOCKADDR_IN (&sock)->sin_addr); + } else { + ipstrlen = INET6_ADDRSTRLEN; + ipnet = &(SOCKADDR_IN6 (&sock)->sin6_addr); + } + + ipstr = xmalloc (ipstrlen); + if (inet_ntop (domain, ipnet, ipstr, ipstrlen) == NULL) { + free (ipstr); + return xstrdup ("unknown address"); + } + + return ipstr; +} + +char* lbs_posix_socket_sockname (int sockfd) { + return lbs_posix_socket_name (sockfd, getsockname); +} + +char* lbs_posix_socket_peername (int sockfd) { + return lbs_posix_socket_name (sockfd, getpeername); +} + +void lbs_posix_exchange_data (int fd[2], LbsPosixProgress prog_cb) { + int nfds, active; + fd_set rset, wset; + fd_set rres, wres; + LbsPosixBuffer buf[2]; + + FD_ZERO (&rset); + FD_SET (fd[0], &rset); + FD_SET (fd[1], &rset); + FD_ZERO (&wset); + + active = 2; + nfds = (fd[0] > fd[1] ? fd[0] : fd[1]) + 1; + lbs_posix_buffer_clear (&buf[0], true); + lbs_posix_buffer_clear (&buf[1], true); + + while (active && (*prog_cb) (fd, buf)) { + rres = rset; + wres = wset; + if (select (nfds, &rres, &wres, NULL, NULL) >= 0) { + for (int i = 0; i < 2; i++) { + if (buf[i].buf_len) { + /* read buffer full */ + if (FD_ISSET (fd[!i], &wres)) { + int wb = write (fd[!i], + buf[i].buf + buf[i].buf_start, buf[i].buf_len); + if (wb > 0) { + buf[i].buf_start += wb; + buf[i].buf_len -= wb; + if (!buf[i].buf_len) { + FD_CLR (fd[!i], &wset); + FD_SET (fd[i], &rset); + } + } else { + if (wb < 0 && (errno == EAGAIN || errno == EINTR)) { + continue; + } else { + FD_CLR (fd[!i], &wset); + active = 0; + } + } + } + } else { + /* read buffer empty */ + if (FD_ISSET (fd[i], &rres)) { + int rb = read (fd[i], buf[i].buf, LBS_POSIX_BUFFER_SIZE); + if (rb > 0) { + buf[i].buf_start = 0; + buf[i].buf_len = rb; + FD_CLR (fd[i], &rset); + FD_SET (fd[!i], &wset); + } else { + if (rb < 0 && (errno == EAGAIN || errno == EINTR)) { + continue; + } else{ + FD_CLR (fd[i], &rset); + active = 0; + } + } + } + } + } + } + } +} diff --git a/hw4/l4basic/l4posix.h b/hw4/l4basic/l4posix.h new file mode 100644 index 0000000..a368609 --- /dev/null +++ b/hw4/l4basic/l4posix.h @@ -0,0 +1,41 @@ +#include "memwrap.h" +/* This file is modified by autogen.sh */ +/* vim: set sw=4 ts=4 sts=4 et: */ +#ifndef LBS_POSIX_H +#define LBS_POSIX_H + +#include <l4common.h> +#include <sys/types.h> + +char* lbs_posix_strcat (const char* str, ...); +int lbs_posix_add_fd (int fd, int fdflags); +int lbs_posix_del_fd (int fd, int fdflags); +int lbs_posix_add_fl (int fd, int flflags); +int lbs_posix_del_fl (int fd, int flflags); +char* lbs_posix_readlink (const char* filename); +char* lbs_posix_getcwd (void); +size_t lbs_posix_write_all (int fd, const char* str, size_t size); +char* lbs_posix_socket_sockname (int sockfd); +char* lbs_posix_socket_peername (int sockfd); + + +#define LBS_POSIX_BUFFER_SIZE 4096 + +typedef struct { + char buf[LBS_POSIX_BUFFER_SIZE]; + off_t buf_start; + off_t buf_len; + char* buf_line; + ssize_t buf_line_len; + int buf_error : 1; + int buf_eof : 1; +} LbsPosixBuffer; + +void lbs_posix_buffer_init (LbsPosixBuffer* buf); +void lbs_posix_buffer_clear (LbsPosixBuffer* buf, bool initial); +char* lbs_posix_buffer_getline (int fd, LbsPosixBuffer* buf, int delim); + +typedef int (*LbsPosixProgress) (int fd[2], LbsPosixBuffer buf[2]); +void lbs_posix_exchange_data (int fd[2], LbsPosixProgress prog_cb); + +#endif /* LBS_POSIX_H */ diff --git a/hw4/l4basic/l4str.c b/hw4/l4basic/l4str.c new file mode 100644 index 0000000..fa1d31b --- /dev/null +++ b/hw4/l4basic/l4str.c @@ -0,0 +1,44 @@ +#include "memwrap.h" +/* This file is modified by autogen.sh */ +/* vim: set sw=4 ts=4 sts=4 et: */ + +#include "l4str.h" + +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +bool lbs_str_has_suffix (const char* str, const char* suffix) { + size_t len = strlen (str); + size_t suflen = strlen (suffix); + int i, j; + for (i = len - 1, j = suflen - 1; i >= 0 && j >= 0; i--, j--) { + if (str[i] != suffix[j]) { + return false; + } + } + if (i < 0 && j >= 0) { + return false; + } + return true; +} + +char* lbs_str_printf (const char* format, ...) { + va_list ap; + char* newstr; + int len; + + va_start (ap, format); + len = vsnprintf (NULL, 0, format, ap) + 1; + va_end (ap); + + newstr = xmalloc (len); + + va_start (ap, format); + vsnprintf (newstr, len, format, ap); + va_end (ap); + + return newstr; +} + diff --git a/hw4/l4basic/l4str.h b/hw4/l4basic/l4str.h new file mode 100644 index 0000000..40bb7fe --- /dev/null +++ b/hw4/l4basic/l4str.h @@ -0,0 +1,15 @@ +#include "memwrap.h" +/* This file is modified by autogen.sh */ +/* vim: set sw=4 ts=4 sts=4 et: */ +#ifndef LBS_STR_H +#define LBS_STR_H + +#include <l4common.h> + +#define LBS_STR_STATIC_STRLEN(x) (sizeof(x)/sizeof(char) - 1) +#define LBS_STR_ARRAY_LEN(x,t) (sizeof(x)/sizeof(t)) + +bool lbs_str_has_suffix (const char* str, const char* suffix); +char* lbs_str_printf (const char* format, ...); + +#endif /* LBS_STR_H */ diff --git a/hw4/memwrap.c b/hw4/memwrap.c new file mode 100644 index 0000000..5a09258 --- /dev/null +++ b/hw4/memwrap.c @@ -0,0 +1,67 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "memwrap.h" + +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <time.h> +#include <unistd.h> + +#define RETRY_SEC 0 +#define RETRY_NSEC 250000000 +#define MSG_BUF_LEN 256 + +static void show_errmsg (void) { + int errno_backup = errno; + + const char fail_msg[] = "Fail to allocate memory: "; + const size_t fail_len = LBS_STR_STATIC_STRLEN (fail_msg); + write (STDERR_FILENO, fail_msg, fail_len); + + char err_msg[MSG_BUF_LEN]; + size_t err_len; + if (strerror_r (errno_backup, err_msg, err_len)) { + const char unknown_msg[] = "Unknown error code"; + const size_t unknown_len = LBS_STR_STATIC_STRLEN (unknown_msg); + write (STDERR_FILENO, unknown_msg, unknown_len); + } else { + err_len = strlen (err_msg); + write (STDERR_FILENO, err_msg, err_len); + } + + const char retry_msg[] = ". Retry ...\n"; + const size_t retry_len = LBS_STR_STATIC_STRLEN (retry_msg); + write (STDERR_FILENO, retry_msg, retry_len); + + errno = errno_backup; +} + +void* xmalloc (size_t size) { + void* memptr; + while ((memptr = malloc (size)) == NULL) { + show_errmsg (); + nanosleep (&(struct timespec) { RETRY_SEC, RETRY_NSEC }, NULL); + } + return memptr; +} + +void* xrealloc (void* ptr, size_t size) { + void* newptr; + while ((newptr = realloc (ptr, size)) == NULL) { + show_errmsg (); + nanosleep (&(struct timespec) { RETRY_SEC, RETRY_NSEC }, NULL); + } + return newptr; +} + +char* xstrdup (const char* str) { + char* newstr; + while ((newstr = strdup (str)) == NULL) { + show_errmsg (); + nanosleep (&(struct timespec) { RETRY_SEC, RETRY_NSEC }, NULL); + } + return newstr; +} diff --git a/hw4/memwrap.h b/hw4/memwrap.h new file mode 100644 index 0000000..3d2ad5b --- /dev/null +++ b/hw4/memwrap.h @@ -0,0 +1,12 @@ +#ifndef MEMORY_FUNCTION_WRAPPER +#define MEMORY_FUNCTION_WRAPPER + +#include <l4str.h> + +#include <stddef.h> + +void* xmalloc (size_t size); +void* xrealloc (void* ptr, size_t size); +char* xstrdup (const char* str); + +#endif /* MEMORY_FUNCTION_WRAPPER */ |