summaryrefslogtreecommitdiffstats
path: root/web
diff options
context:
space:
mode:
authorptt <ptt@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2002-10-18 22:43:58 +0800
committerptt <ptt@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2002-10-18 22:43:58 +0800
commit86672771393d552ac6d9c742fa1d80c34cc1cf74 (patch)
tree559e636d1dca81d54c8d5a7a929bba73a9f62646 /web
parentd87c20433e1a16e5ec3d31b00c1dd491e995b1ea (diff)
downloadpttbbs-86672771393d552ac6d9c742fa1d80c34cc1cf74.tar
pttbbs-86672771393d552ac6d9c742fa1d80c34cc1cf74.tar.gz
pttbbs-86672771393d552ac6d9c742fa1d80c34cc1cf74.tar.bz2
pttbbs-86672771393d552ac6d9c742fa1d80c34cc1cf74.tar.lz
pttbbs-86672771393d552ac6d9c742fa1d80c34cc1cf74.tar.xz
pttbbs-86672771393d552ac6d9c742fa1d80c34cc1cf74.tar.zst
pttbbs-86672771393d552ac6d9c742fa1d80c34cc1cf74.zip
*** empty log message ***
git-svn-id: http://opensvn.csie.org/pttbbs/pttbbs/trunk/pttbbs@539 63ad8ddf-47c3-0310-b6dd-a9e9d9715204
Diffstat (limited to 'web')
-rw-r--r--web/Makefile.old120
-rw-r--r--web/Makefile.tmpl16
-rw-r--r--web/Makefile.tmpl.bak17
-rwxr-xr-xweb/args.c228
-rw-r--r--web/board.c39
-rw-r--r--web/chmod1
-rw-r--r--web/libptt.abin0 -> 107932 bytes
-rw-r--r--web/mail.c6
-rw-r--r--web/post.c6
-rwxr-xr-xweb/stuff.c269
-rw-r--r--web/user.c6
-rwxr-xr-xweb/util_cache.c516
-rwxr-xr-xweb/util_passwd.c141
-rwxr-xr-xweb/util_record.c245
14 files changed, 1610 insertions, 0 deletions
diff --git a/web/Makefile.old b/web/Makefile.old
new file mode 100644
index 00000000..db2735bf
--- /dev/null
+++ b/web/Makefile.old
@@ -0,0 +1,120 @@
+##
+## Apache Makefile, automatically generated by Configure script.
+## Hand-edited changes will be lost if the Configure script is re-run.
+## Sources: - ../../Makefile.config (via Configuration)
+## - ./Makefile.tmpl
+##
+
+##
+## Inherited Makefile options from Configure script
+## (Begin of automatically generated section)
+##
+SRCDIR=../..
+EXTRA_CFLAGS=
+EXTRA_LDFLAGS=
+EXTRA_LIBS=
+EXTRA_INCLUDES=
+EXTRA_DEPS=
+OSDIR=$(SRCDIR)/os/unix
+INCDIR=$(SRCDIR)/include
+INCLUDES0=-I$(OSDIR) -I$(INCDIR) -I../$(INCDIR)
+SHELL=/bin/sh
+OS=FreeBSD 4.6
+CC=gcc
+CPP=gcc -E
+TARGET=httpd
+OPTIM=
+CFLAGS1= -funsigned-char -DUSE_EXPAT -I$(SRCDIR)/lib/expat-lite -DNO_DL_NEEDED
+INCLUDES1=
+LIBS_SHLIB=
+LDFLAGS1=
+MFLAGS_STATIC=
+REGLIB=
+EXPATLIB=lib/expat-lite/libexpat.a
+RANLIB=ranlib
+LIBS1= -lcrypt
+##
+## (End of automatically generated section)
+##
+
+##
+## Default Makefile options from Configure script
+## (Begin of automatically generated section)
+##
+CFLAGS=$(OPTIM) $(CFLAGS1) $(EXTRA_CFLAGS)
+LIBS=$(EXTRA_LIBS) $(LIBS1)
+INCLUDES=$(INCLUDES1) $(INCLUDES0) $(EXTRA_INCLUDES)
+LDFLAGS=$(LDFLAGS1) $(EXTRA_LDFLAGS)
+INCDIR=$(SRCDIR)/include
+OBJS=mod_ptt.o parse_html.o
+BBSLIBS=util_cache.o util_passwd.o util_record.o
+LIB=libptt.a
+SHLIBS=
+OBJS_PIC=
+
+all: lib shlib
+
+lib: $(LIB)
+
+shlib: $(SHLIBS)
+
+dummy $(LIB): $(OBJS)
+ rm -f $@
+ ar cr $@ $(OBJS) $(BBSLIBS)
+ $(RANLIB) $@
+
+.SUFFIXES: .o .so .dll
+
+.c.o:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $<
+
+.c.so:
+ $(CC) -c $(INCLUDES) $(CFLAGS) $(CFLAGS_SHLIB) $< && mv $*.o $*.lo
+ $(LD_SHLIB) $(LDFLAGS_SHLIB) -o $@ $*.lo $(LIBS_SHLIB)
+
+clean:
+ rm -f $(LIB) $(OBJS) $(SHLIBS) $(OBJS_PIC)
+
+distclean: clean
+ rm -f Makefile
+
+# NOT FOR END USERS!
+depend:
+ cp Makefile.tmpl Makefile.tmpl.bak \
+ && sed -ne '1,/^# DO NOT REMOVE/p' Makefile.tmpl > Makefile.new \
+ && gcc -MM $(INCLUDES) $(CFLAGS) *.c >> Makefile.new \
+ && sed -e '1,$$s: $(INCDIR)/: $$(INCDIR)/:g' \
+ -e '1,$$s: $(OSDIR)/: $$(OSDIR)/:g' Makefile.new \
+ > Makefile.tmpl \
+ && rm Makefile.new
+
+##
+## (End of automatically generated section)
+##
+
+#Dependencies
+
+$(OBJS) $(OBJS_PIC): Makefile
+
+# DO NOT REMOVE
+mod_ptt.o: mod_ptt.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_core.h $(INCDIR)/http_log.h \
+ $(INCDIR)/http_main.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/util_script.h \
+ /home/bbs/pttbbs/include/bbs.h
+
+parse_html.o: parse_html.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_core.h $(INCDIR)/http_log.h \
+ $(INCDIR)/http_main.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/util_script.h \
+ /home/bbs/pttbbs/include/bbs.h
diff --git a/web/Makefile.tmpl b/web/Makefile.tmpl
new file mode 100644
index 00000000..83ed1e84
--- /dev/null
+++ b/web/Makefile.tmpl
@@ -0,0 +1,16 @@
+
+#Dependencies
+
+$(OBJS) $(OBJS_PIC): Makefile
+
+BBSLIBS= util_cache.o util_record.o util_passwd.o
+
+# DO NOT REMOVE
+mod_ptt.o: mod_ptt.c $(INCDIR)/httpd.h $(INCDIR)/ap_config.h \
+ $(INCDIR)/ap_mmn.h $(INCDIR)/ap_config_auto.h \
+ $(OSDIR)/os.h $(OSDIR)/os-inline.c $(INCDIR)/ap_ctype.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_core.h $(INCDIR)/http_log.h \
+ $(INCDIR)/http_main.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/util_script.h
diff --git a/web/Makefile.tmpl.bak b/web/Makefile.tmpl.bak
new file mode 100644
index 00000000..e686b7a9
--- /dev/null
+++ b/web/Makefile.tmpl.bak
@@ -0,0 +1,17 @@
+
+#Dependencies
+
+$(OBJS) $(OBJS_PIC): Makefile
+
+BBSLIBS= util_cache.o util_record.o util_passwd.o
+
+# DO NOT REMOVE
+mod_ptt.o: mod_ptt.c $(INCDIR)/httpd.h \
+ $(INCDIR)/ap_config.h $(INCDIR)/ap_mmn.h \
+ $(INCDIR)/ap_config_auto.h $(OSDIR)/os.h \
+ $(INCDIR)/ap_ctype.h $(INCDIR)/hsregex.h \
+ $(INCDIR)/ap_alloc.h $(INCDIR)/buff.h $(INCDIR)/ap.h \
+ $(INCDIR)/util_uri.h $(INCDIR)/http_config.h \
+ $(INCDIR)/http_core.h $(INCDIR)/http_log.h \
+ $(INCDIR)/http_main.h $(INCDIR)/http_protocol.h \
+ $(INCDIR)/util_script.h
diff --git a/web/args.c b/web/args.c
new file mode 100755
index 00000000..02e0fad0
--- /dev/null
+++ b/web/args.c
@@ -0,0 +1,228 @@
+/* 使用方法: 自己先用 r->method_number 判斷是 M_GET 或 M_POST
+ */
+#include "mod_ptt.h"
+
+unsigned char xtoc(char ch1, char ch2) {
+ unsigned char d, up1, up2;
+
+ if (!isxdigit(ch1) || !isxdigit(ch2)) return ' ';
+
+ up1 = toupper(ch1);
+ up2 = toupper(ch2);
+
+ if (up1>='0' && up1<='9') d = up1-'0';
+ else d = up1-'A'+10;
+ d <<= 4;
+ if (up2>='0' && up2<='9') d += up2-'0';
+ else d += up2-'A'+10;
+
+ return d;
+}
+
+char * cstoxs(pool *p, char *str)
+{
+ char * newstr = pstrdup(p,""), *po = str;
+
+ for(po = str; *po; po++)
+ {
+ if(isprint(*po) && *po!=' ') newstr=psprintf(p, "%s%c", newstr,*po);
+ else newstr=psprintf(p, "%s%%%X", newstr, *po& 0xFF);
+ }
+ return newstr;
+}
+
+int // Ptt: 我重寫拿掉mygetchar 並加上fileupload的功能
+inital_postdata(request_rec *r, int *fileupload, char *boundary,
+ char **data)
+{
+ char *buf, *mb;
+ int size, off = 0, len_read;
+ void (*handler)();
+
+ buf = table_get(r->subprocess_env,"CONTENT_TYPE");
+ if(!buf ||
+ (strncasecmp(buf,"application/x-www-form-urlencoded",33) &&
+ strncasecmp(buf,"multipart/form-data",19)))
+ return -1;
+
+ if(!strncasecmp(buf,"multipart/form-data",19)) {
+ if(!fileupload) return -1;
+ *fileupload=1;
+ mb = strchr(buf,'=');
+ if(mb) {
+ strcpy(boundary,mb+1);
+ strtok(boundary, " ;\n");
+ }
+ else return -1;
+ }
+
+ buf = table_get(r->subprocess_env,"CONTENT_LENGTH");
+ if(buf==NULL) return -1;
+
+ size = atoi(buf);
+ mb = (char *)palloc(r->pool,(size+1)*sizeof(char));
+
+ if(!mb ||
+ (setup_client_block(r ,REQUEST_CHUNKED_ERROR) != 0) ||
+ (should_client_block(r) == 0))
+ return -1;
+
+ hard_timeout("args.c copy script args", r);
+ handler = signal(SIGPIPE, SIG_IGN);
+
+ while(size-off > 0 && (len_read = get_client_block
+ (r, mb + off, size - off)) > 0) {
+ off += len_read;
+ }
+
+ signal(SIGPIPE, handler);
+ kill_timeout(r);
+
+ if(len_read < 0) return -1; // 讀的中途有中斷
+ mb[size]=0; // Ptt:截掉不需要吧 因為不是用字串處理方式
+ (*data) = mb;
+ return size;
+}
+
+#define ENCODED_NAME " name=\""
+#define ENCODED_FILENAME " filename=\""
+#define ENCODED_CONTENT "Content-Type: "
+
+//#define FILEDATAFILE DATABASEDIR "/" FDATA
+
+int
+unescape(request_rec *r, char** name, char** value) {
+ static char *sp=NULL, boundary[150];
+ static int fileupload, boundarylen, dsize;
+ pool *p = r->pool;
+ char ch, ch1, *dp, *p0, *p1, *temp_sp, *ftype;
+ int type;
+
+ if (sp==NULL) {
+ fileupload=0;
+ switch (r->method_number) {
+ case M_GET:
+ if (r->args) sp = pstrdup(p, r->args);
+ else {sp=NULL; return -1;}
+ break;
+ case M_POST:
+ if ((dsize =
+ inital_postdata(r, &fileupload, boundary,&sp))<0)
+ {sp=NULL; return -1; }
+ if(fileupload) boundarylen = strlen(boundary);
+ break;
+ default:
+ sp=NULL;
+ return -1;
+ }
+ }
+
+ if(fileupload)
+ {
+ if(dsize >0 && (temp_sp = memstr(sp, boundary, dsize)))
+ {
+ temp_sp += boundarylen;
+ p0 = strstr(temp_sp, "\r\n\r\n");
+ p1 = strstr(temp_sp, "\n\n");
+
+ if(!((*name) = strstr(temp_sp, ENCODED_NAME)))
+ {sp=NULL; return -1; }
+ (*name) += strlen(ENCODED_NAME);
+ strtok((*name) + 1 , "\"");
+ if( (!p0 && p1) || (p0 && p1 && p1<p0))
+ {
+ (*value) = sp = p1 + 2;
+ type = 2;
+ }
+ else if(p0)
+ {
+ (*value) = sp = p0 + 4;
+ type = 4;
+ }
+ else
+ {
+ sp=NULL;
+ return -1;
+ }
+
+ if((p1 = memstr(temp_sp, boundary, dsize - boundarylen)))
+ temp_sp = p1;
+ else
+ temp_sp = sp + dsize;
+
+ *(temp_sp - type) = 0;
+
+ // 檢查是不是file 若是就給fileinfo
+ if((dp=memstr(
+ (*name) + strlen(*name) +1, ENCODED_FILENAME, dsize)) &&
+ dp < *value)
+ {
+ dp += strlen(ENCODED_FILENAME);
+ p0 = strchr(dp,'"');
+ *p0 = 0;
+ if(p0 - dp>3)
+ {
+ fileheader_t *file=(fileheader_t *)pcalloc(p, sizeof(fileheader_t));
+ if((ftype = strstr(p0 + 1, ENCODED_CONTENT)))
+ {
+ ftype += strlen(ENCODED_CONTENT);
+ strtok(ftype, "\r\n");
+ }
+ while(p0 > dp && *p0 !='/' && *p0 !='\\') p0--;
+ strcpy(file->name, p0+1);
+ strcpy(file->content_type, ftype);
+ file->icontent_type = filetype(ftype);
+ // if(file->icontent_type & (FILE_TXT | FILE_HTML))
+ // file->size = strlen(sp);
+ // else
+ file->size = temp_sp - sp - type;
+ file->uploadtime = time(NULL);
+ file->data = (*value);
+ (*value) = (char *)file;
+ }
+ else
+ {
+ (*value) = NULL;
+ }
+ }
+
+ dsize -= (temp_sp - sp);
+ sp = temp_sp;
+ return 1;
+ }
+ else
+ {
+ sp=NULL;
+ return -1;
+ }
+ }
+
+ dp = (*name) = sp;
+ while(1) {
+ ch = *sp++;
+ switch(ch) {
+ case '+':
+ *dp++ = ' ';
+ break;
+ case '=':
+ *dp++ = '\0';
+ (*value) = dp;
+ break;
+ case '&': case '|':
+ *dp++ = '\0';
+ return 1;
+ case '\0': case EOF:
+ *dp = '\0';
+ sp=NULL;
+ return 0;
+ case '%':
+ ch = *sp++; ch1 = *sp++;
+ *dp++ = xtoc(ch, ch1);
+ break;
+ default:
+ *dp++=ch;
+ break;
+ }
+ }
+}
+
diff --git a/web/board.c b/web/board.c
new file mode 100644
index 00000000..43347912
--- /dev/null
+++ b/web/board.c
@@ -0,0 +1,39 @@
+#include "mod_ptt.h"
+
+extern int numboards;
+extern boardheader_t *bcache;
+extern int ptt_handler(request_rec *r, void *args);
+
+int bbs_board(request_rec *r, void *args)
+{
+ int i;
+ r->content_type = "text/xml";
+ ap_send_http_header(r);
+ ap_rputs("<hr> Ptt \n", r);
+return ptt_handler (r,args);
+
+ ap_rprintf(r,"r->filename : %s <br>",r->filename);
+ ap_rprintf(r,"r->request_time : %s <br>",ctime(&r->request_time));
+ ap_rprintf(r,"r->method : %s <br>",r->method);
+ ap_rprintf(r,"r->method_number : %d <br>",r->method_number);
+ ap_rprintf(r,"r->path_info : %s <br>",r->path_info);
+ ap_rprintf(r,"r->args : %s <br>",r->args);
+ ap_rprintf(r,"r->unparsed_uri : %s <br>",r->unparsed_uri);
+ ap_rprintf(r,"r->uri : %s <br>",r->uri);
+ ap_rprintf(r,"r->handler : %s <br>",r->handler);
+ ap_rprintf(r,"r->content_type : %s <br>",r->content_type);
+ ap_rprintf(r, "Server built: \"%s\"\n", ap_get_server_built());
+
+ ap_rputs("<hr> Ptt \n", r);
+
+ ap_rputs("<XML>",r);
+/*
+ for(i = 0; i++ < numboards; i++)
+ {
+ ap_rputs("<board>",r);
+ ap_rputs("</board>",r);
+ }
+*/
+
+ return OK;
+}
diff --git a/web/chmod b/web/chmod
new file mode 100644
index 00000000..a91df6d5
--- /dev/null
+++ b/web/chmod
@@ -0,0 +1 @@
+ftasfdsf
diff --git a/web/libptt.a b/web/libptt.a
new file mode 100644
index 00000000..26c2f527
--- /dev/null
+++ b/web/libptt.a
Binary files differ
diff --git a/web/mail.c b/web/mail.c
new file mode 100644
index 00000000..9f226afe
--- /dev/null
+++ b/web/mail.c
@@ -0,0 +1,6 @@
+#include "mod_ptt.h"
+
+int bbs_mail(request_rec *r, void *args)
+{
+ return OK;
+}
diff --git a/web/post.c b/web/post.c
new file mode 100644
index 00000000..3e67937e
--- /dev/null
+++ b/web/post.c
@@ -0,0 +1,6 @@
+#include "mod_ptt.h"
+
+int bbs_post(request_rec *r, void *args)
+{
+ return OK;
+}
diff --git a/web/stuff.c b/web/stuff.c
new file mode 100755
index 00000000..b02dbb0d
--- /dev/null
+++ b/web/stuff.c
@@ -0,0 +1,269 @@
+/* Ptt : 常用字串函式整理 */
+#include "mod_ptt.h"
+
+// 缺少 escape_url的東西
+
+/*
+ * 檔案判別
+ */
+
+ /* 傳回:路徑大小 */
+
+off_t
+dashs(fname)
+ char *fname;
+{
+ struct stat st;
+
+ if (!stat(fname, &st))
+ return (st.st_size);
+ else
+ return 0; /* 無此檔是 size 0 */
+}
+
+ /* 傳回:路徑時間 */
+long
+dasht(char *fname)
+{
+ struct stat st;
+
+ if (!stat(fname, &st))
+ return (st.st_mtime);
+ else
+ return -1;
+}
+
+ /* 傳回:路徑是否為link檔 */
+int
+dashl(char *fname)
+{
+ struct stat st;
+ return (lstat(fname, &st) == 0 && S_ISLNK(st.st_mode));
+}
+
+ /* 傳回:路徑是否為檔案 */
+dashf(char *fname)
+{
+ struct stat st;
+
+ return (stat(fname, &st) == 0 && S_ISREG(st.st_mode));
+}
+
+/* 字串的小寫 */
+#define char_lower(c) ((c >= 'A' && c <= 'Z') ? c|32 : c)
+
+void
+str_lower(t, s)
+ char *t, *s;
+{
+ register char ch;
+ do
+ {
+ ch = *s++;
+ *t++ = char_lower(ch);
+ } while (ch);
+}
+
+int
+str_ncmp(s1, s2, n)
+ char *s1, *s2;
+ int n;
+{
+ int c1, c2;
+
+ while (n--)
+ {
+ c1 = *s1++;
+ if (c1 >= 'A' && c1 <= 'Z')
+ c1 |= 32;
+
+ c2 = *s2++;
+ if (c2 >= 'A' && c2 <= 'Z')
+ c2 |= 32;
+
+ if (c1 -= c2)
+ return (c1);
+
+ if (!c2)
+ break;
+ }
+ return 0;
+}
+char *
+memstr(char *mem, char *str, int size)
+{
+ char *loc, *ptr=mem, *end=mem+size;
+ int len = strlen(str);
+ while((loc = memchr(ptr, *str, size)))
+ {
+ if(!strncmp(loc, str, len))
+ return loc;
+ ptr = loc +1;
+ size = (end - ptr);
+ if(size <=0 ) return NULL;
+ }
+ return NULL;
+}
+
+/* 傳回: strstr的比較但不計大小寫的結果 */
+/*
+char *
+strcasestr(str, tag)
+ char *str, *tag;
+{
+ char buf[BUFLEN];
+
+ str_lower(buf, str);
+ return strstr(buf, tag);
+}
+*/
+
+/* 傳回: 一個checksum 給字串比較用 */
+
+int str_checksum(char *str)
+{
+ int n=1;
+ if(strlen(str) < 6) return 0;
+ while(*str)
+ n += *str++ ^ n;
+ return n;
+}
+
+int
+not_alpha(ch)
+ register char ch;
+{
+ return (ch < 'A' || (ch > 'Z' && ch < 'a') || ch > 'z');
+}
+
+int
+not_alnum(ch)
+ register char ch;
+{
+ return (ch < '0' || (ch > '9' && ch < 'A') ||
+ (ch > 'Z' && ch < 'a') || ch > 'z');
+}
+
+char
+ch2ph(char ch)
+{
+ static const
+ // a b c d e f g h i j k l m n o
+ char table[]={'2','2','2','3','3','3','4','4','4','5','5','5','6','6','6',
+ // p q r s t u v w x y z
+ '7','1','7','7','8','8','8','9','9','9','1'};
+ static char d;
+ d = char_lower(ch);
+ if(d>='a' && d<='z') d=table[d-'a'];
+ return d;
+}
+
+void
+archiv32(chrono, fname)
+ time_t chrono; /* 32 bits */
+ char *fname; /* 7 chars */
+{
+ char *str;
+ char radix32[32] = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F',
+ 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
+ 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
+ };
+
+ str = fname + 7;
+ *str = '\0';
+ for (;;)
+ {
+ *(--str) = radix32[chrono & 31];
+ if (str == fname)
+ return;
+ chrono >>= 5;
+ }
+}
+
+/* ARPANET時間格式 */
+char *
+Atime(clock)
+ time_t *clock;
+{
+ static char datemsg[40];
+ /* ARPANET format: Thu, 11 Feb 1999 06:00:37 +0800 (CST) */
+ /* strftime(datemsg, 40, "%a, %d %b %Y %T %Z", localtime(clock)); */
+ /* time zone的傳回值不知和ARPANET格式是否一樣,先硬給,同sendmail*/
+ strftime(datemsg, 40, "%a, %d %b %Y %T +0800 (CST)", localtime(clock));
+ return (datemsg);
+}
+
+
+/* userid是否合法 */
+int
+bad_user_id(userid)
+ char *userid;
+{
+ register char ch;
+ if (strlen(userid) < 2)
+ return 1;
+ if (not_alpha(*userid))
+ return 1;
+ if (!strcasecmp(userid, "new") || !strcasecmp(userid, "guest") ||
+ !strcasecmp(userid, "root") || !strcasecmp(userid, "webadm") ||
+ !strncasecmp(userid,"yam",3)
+ )
+ return 1;
+
+ while (ch = *(++userid))
+ {
+ if (not_alnum(ch) || ch == '0')
+ return 1;
+ }
+ return 0;
+}
+
+
+int
+logfile(pool *p, char *filename,char *buf)
+{
+ FILE *fp;
+ time_t now;
+ if( (fp = ap_pfopen(p, filename, "a" )) ) {
+
+ fputs( buf, fp );
+ if(!strchr(buf,'\n'))
+ {
+ now = time(NULL);
+ fputs(ctime(&now), fp);
+ }
+ ap_pfclose(p, fp );
+ return 0;
+ }
+ else{
+ printf("error open file");
+ return -1;
+ }
+}
+
+/* 檢查中文斷字問題 */
+char *strexam(char *s)
+{
+ int i;
+ int odd;
+ for (i = 0, odd = 0; s[i]; i++)
+ if (odd) odd = 0;
+ else if (s[i] & 128) odd = 1;
+ if (odd) s[--i] = 0;
+ return s;
+}
+
+int
+maxline(char *data,char *newline, int max)
+{
+ register int n, nlen=strlen(newline);
+ register char *po;
+
+ for(n=0, po = data; (po = strstr(po, newline)); po+=nlen)
+ {
+ if(++n>=max) {*po=0; return -1;}
+ }
+ return n;
+}
diff --git a/web/user.c b/web/user.c
new file mode 100644
index 00000000..fe5d0696
--- /dev/null
+++ b/web/user.c
@@ -0,0 +1,6 @@
+#include "mod_ptt.h"
+
+int bbs_user(request_rec *r, void *args)
+{
+ return OK;
+}
diff --git a/web/util_cache.c b/web/util_cache.c
new file mode 100755
index 00000000..5178dad5
--- /dev/null
+++ b/web/util_cache.c
@@ -0,0 +1,516 @@
+/* $Id: util_cache.c,v 1.1 2002/10/18 14:43:58 ptt Exp $ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/sem.h>
+
+#ifdef __FreeBSD__
+#include <machine/param.h>
+#endif
+
+#include "config.h"
+#include "pttstruct.h"
+#include "common.h"
+#include "perm.h"
+#include "modes.h"
+#include "proto.h"
+
+/* the reason for "safe_sleep" is that we may call sleep during
+ SIGALRM handler routine, while SIGALRM is blocked.
+ if we use the original sleep, we'll never wake up. */
+unsigned int safe_sleep(unsigned int seconds) {
+ /* jochang sleep有問題時用*/
+ sigset_t set,oldset;
+
+ sigemptyset(&set);
+ sigprocmask(SIG_BLOCK, &set, &oldset);
+ if(sigismember(&oldset, SIGALRM)) {
+ unsigned long retv;
+ sigemptyset(&set);
+ sigaddset(&set,SIGALRM);
+ sigprocmask(SIG_UNBLOCK,&set,NULL);
+ retv=sleep(seconds);
+ sigprocmask(SIG_BLOCK,&set,NULL);
+ return retv;
+ }
+ return sleep(seconds);
+}
+
+void setapath(char *buf, char *boardname) {
+ sprintf(buf, "man/boards/%c/%s", boardname[0], boardname);
+}
+
+static char *str_dotdir = ".DIR";
+
+void setadir(char *buf, char *path) {
+ sprintf(buf, "%s/%s", path, str_dotdir);
+}
+
+static void attach_err(int shmkey, char *name) {
+ fprintf(stderr, "[%s error] key = %x\n", name, shmkey);
+ fprintf(stderr, "errno = %d: %s\n", errno, strerror(errno));
+ exit(1);
+}
+
+void *attach_shm(int shmkey, int shmsize) {
+ void *shmptr;
+ int shmid;
+
+ char *empty_addr;
+ /* set up one page in-accessible -- jochang */
+ {
+ int fd = open("/dev/zero",O_RDONLY);
+ int size = ((shmsize + 4095) / 4096) * 4096;
+
+ munmap(
+ (empty_addr=mmap(0,4096+size,PROT_NONE,MAP_PRIVATE,fd,0))+4096
+ ,size);
+
+ close(fd);
+ }
+
+ shmid = shmget(shmkey, shmsize, 0);
+ if(shmid < 0) {
+ shmid = shmget(shmkey, shmsize, IPC_CREAT | 0600);
+ if(shmid < 0)
+ attach_err(shmkey, "shmget");
+ shmptr = (void *)shmat(shmid, NULL, 0);
+ if(shmptr == (void *)-1)
+ attach_err(shmkey, "shmat");
+ } else {
+ shmptr = (void *)shmat(shmid, NULL, 0);
+ if(shmptr == (void *)-1)
+ attach_err(shmkey, "shmat");
+ }
+
+ /* unmap the page -- jochang */
+ {
+ munmap(empty_addr,4096);
+ }
+ return shmptr;
+}
+
+#ifndef __FreeBSD__
+/* according to X/OPEN we have to define it ourselves */
+union semun {
+ int val; /* value for SETVAL */
+ struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
+ unsigned short int *array; /* array for GETALL, SETALL */
+ struct seminfo *__buf; /* buffer for IPC_INFO */
+};
+#endif
+
+#define SEM_FLG 0600 /* semaphore mode */
+
+/* ----------------------------------------------------- */
+/* semaphore : for critical section */
+/* ----------------------------------------------------- */
+void sem_init(int semkey,int *semid) {
+ union semun s;
+
+ s.val=1;
+ *semid = semget(semkey, 1, 0);
+ if(*semid == -1) {
+ *semid = semget(semkey, 1, IPC_CREAT | SEM_FLG);
+ if(*semid == -1)
+ attach_err(semkey, "semget");
+ semctl(*semid, 0, SETVAL, s);
+ }
+}
+
+void sem_lock(int op,int semid) {
+ struct sembuf sops;
+
+ sops.sem_num = 0;
+ sops.sem_flg = SEM_UNDO;
+ sops.sem_op = op;
+ semop(semid, &sops, 1);
+}
+
+SHM_t *SHM;
+int *GLOBALVAR;
+boardheader_t *bcache;
+int numboards = -1;
+
+void attach_SHM(void)
+{
+ SHM = attach_shm(SHM_KEY, sizeof(SHM_t));
+ if( !SHM->loaded ) /* (uhash) assume fresh shared memory is zeroed */
+ exit(1);
+ if( SHM->Btouchtime == 0 )
+ SHM->Btouchtime = 1;
+ bcache = SHM->bcache;
+
+ GLOBALVAR = SHM->GLOBALVAR;
+ if( SHM->Ptouchtime == 0 )
+ SHM->Ptouchtime = 1;
+
+ if( SHM->Ftouchtime == 0 )
+ SHM->Ftouchtime = 1;
+
+ bcache = SHM->bcache;
+ numboards = SHM->Bnumber;
+}
+
+int setumoney(int uid, int money) {
+ SHM->money[uid-1]=money;
+ passwd_update_money(uid);
+ return SHM->money[uid-1];
+}
+
+int deumoney(int uid, int money) {
+ if(money<0 && SHM->money[uid-1]<-money)
+ return setumoney(uid,0);
+ else
+ return setumoney(uid,SHM->money[uid-1]+money);
+}
+int moneyof(int uid){ /* ptt 改進金錢處理效率 */
+ return SHM->money[uid-1];
+}
+
+static unsigned string_hash(unsigned char *s) {
+ unsigned int v=0;
+ while(*s) {
+ v = (v << 8) | (v >> 24);
+ v ^= toupper(*s++); /* note this is case insensitive */
+ }
+ return (v * 2654435769UL) >> (32 - HASH_BITS);
+}
+
+void add_to_uhash(int n, char *id) {
+ int *p, h = string_hash(id);
+ strcpy(SHM->userid[n], id);
+
+ p = &(SHM->hash_head[h]);
+
+ while(*p != -1)
+ p = &(SHM->next_in_hash[*p]);
+
+ SHM->next_in_hash[*p = n] = -1;
+}
+
+/* note: after remove_from_uhash(), you should add_to_uhash()
+ (likely with a different name) */
+void remove_from_uhash(int n) {
+ int h = string_hash(SHM->userid[n]);
+ int *p = &(SHM->hash_head[h]);
+
+ while(*p != -1 && *p != n)
+ p = &(SHM->next_in_hash[*p]);
+ if(*p == n)
+ *p = SHM->next_in_hash[n];
+}
+
+int searchuser(char *userid) {
+ int h,p;
+
+ if(SHM == NULL)
+ attach_SHM(); /* for sloopy util programs */
+
+ h = string_hash(userid);
+ p = SHM->hash_head[h];
+
+ while(p != -1) {
+ if(strcasecmp(SHM->userid[p],userid) == 0) {
+ strcpy(userid,SHM->userid[p]);
+ return p + 1;
+ }
+ p = SHM->next_in_hash[p];
+ }
+ return 0;
+}
+userec_t xuser;
+
+int getuser(char *userid) {
+ int uid;
+ if((uid = searchuser(userid)))
+ passwd_query(uid, &xuser);
+ return uid;
+}
+
+void setuserid(int num, char *userid) {
+ if(num > 0 && num <= MAX_USERS) {
+ if(num > SHM->number)
+ SHM->number = num;
+ else
+ remove_from_uhash(num-1);
+ add_to_uhash(num-1,userid);
+ }
+}
+
+/*-------------------------------------------------------*/
+/* .UTMP cache */
+/*-------------------------------------------------------*/
+void resolve_utmp() {
+ if(SHM == NULL) {
+ attach_SHM();
+ if(SHM->UTMPuptime == 0)
+ SHM->UTMPuptime = SHM->UTMPnumber = 1;
+ }
+}
+
+userinfo_t *currutmp = NULL;
+
+void getnewutmpent(userinfo_t *up) {
+ extern int errno;
+ register int i;
+ register userinfo_t *uentp;
+
+ resolve_utmp();
+
+ for(i = 0; i < USHM_SIZE; i++) {
+ uentp = &(SHM->uinfo[i]);
+ if(!(uentp->pid)) {
+ memcpy(uentp, up, sizeof(userinfo_t));
+ currutmp = uentp;
+ SHM->number++;
+ return;
+ }
+ }
+ exit(1);
+}
+
+int apply_ulist(int (*fptr)(userinfo_t *)) {
+ register userinfo_t *uentp;
+ register int i, state;
+
+ resolve_utmp();
+ for(i = 0; i < USHM_SIZE; i++) {
+ uentp = &(SHM->uinfo[i]);
+ if(uentp->pid && (PERM_HIDE(currutmp) || !PERM_HIDE(uentp)))
+ if((state = (*fptr) (uentp)))
+ return state;
+ }
+ return 0;
+}
+
+userinfo_t *search_ulist(int uid) {
+ register int i;
+ register userinfo_t *uentp;
+
+ resolve_utmp();
+ for(i = 0; i < USHM_SIZE; i++) {
+ uentp = &(SHM->uinfo[i]);
+ if(uid==uentp->uid)
+ return uentp;
+ }
+ return 0;
+}
+
+/*-------------------------------------------------------*/
+/* .BOARDS cache */
+/*-------------------------------------------------------*/
+char *fn_board=BBSHOME"/"FN_BOARD;
+static void reload_bcache() {
+ if(SHM->Bbusystate) {
+ safe_sleep(1);
+ }
+}
+
+void resolve_boards() {
+ if(SHM == NULL) {
+ attach_SHM();
+ if(SHM->Btouchtime == 0)
+ SHM->Btouchtime = 1;
+ }
+
+ while(SHM->Buptime < SHM->Btouchtime)
+ reload_bcache();
+ numboards = SHM->Bnumber;
+}
+
+void touch_boards() {
+ time(&(SHM->Btouchtime));
+ numboards = -1;
+ resolve_boards();
+}
+void reset_board(int bid)
+{
+ int fd;
+ boardheader_t bh;
+ if(--bid<0)return;
+ if(SHM->Bbusystate==0)
+ {
+ SHM->Bbusystate = 1;
+ if((fd = open(fn_board, O_RDONLY)) > 0) {
+ lseek(fd, (off_t)(bid * sizeof(boardheader_t)), SEEK_SET);
+ read(fd, &bh , sizeof(boardheader_t));
+ close(fd);
+ if(bh.brdname[0] && !strcmp(bh.brdname,bcache[bid].brdname))
+ memcpy(&bcache[bid],&bh, sizeof(boardheader_t));
+ }
+ SHM->Bbusystate = 0;
+ }
+}
+boardheader_t *getbcache(int bid) { /* Ptt改寫 */
+ return bcache + bid - 1;
+}
+
+void touchbtotal(int bid) {
+ SHM->total[bid - 1] = 0;
+ SHM->lastposttime[bid - 1] = 0;
+}
+
+
+int getbnum(char *bname) {
+ register int i;
+ register boardheader_t *bhdr;
+
+ for(i = 0, bhdr = bcache; i++ < numboards; bhdr++)
+ if(
+ !strcasecmp(bname, bhdr->brdname))
+ return i;
+ return 0;
+}
+
+/*-------------------------------------------------------*/
+/* PTT cache */
+/*-------------------------------------------------------*/
+/* cachefor 動態看版 */
+void reload_pttcache(void)
+{
+ if(SHM->Pbusystate)
+ safe_sleep(1);
+ else { /* jochang: temporary workaround */
+ fileheader_t item, subitem;
+ char pbuf[256], buf[256], *chr;
+ FILE *fp, *fp1, *fp2;
+ int id, section = 0;
+
+ SHM->Pbusystate = 1;
+ SHM->max_film = 0;
+ bzero(SHM->notes, sizeof SHM->notes);
+ setapath(pbuf, "Note");
+ setadir(buf, pbuf);
+ id = 0;
+ if((fp = fopen(buf, "r"))) {
+ while(fread(&item, sizeof(item), 1, fp)) {
+ if(item.title[3]=='<' && item.title[8]=='>') {
+ sprintf(buf,"%s/%s", pbuf, item.filename);
+ setadir(buf, buf);
+ if(!(fp1 = fopen(buf, "r")))
+ continue;
+ SHM->next_refresh[section] = SHM->n_notes[section] = id;
+ section ++;
+ while(fread(&subitem, sizeof(subitem), 1, fp1)) {
+ sprintf(buf,"%s/%s/%s", pbuf, item.filename ,
+ subitem.filename);
+ if(!(fp2=fopen(buf,"r")))
+ continue;
+ fread(SHM->notes[id],sizeof(char), 200*11, fp2);
+ SHM->notes[id][200*11 - 1]=0;
+ id++;
+ fclose(fp2);
+ if(id >= MAX_MOVIE)
+ break;
+ }
+ fclose(fp1);
+ if(id >= MAX_MOVIE || section >= MAX_MOVIE_SECTION)
+ break;
+ }
+ }
+ fclose(fp);
+ }
+ SHM->next_refresh[section] = -1;
+ SHM->n_notes[section] = SHM->max_film = id-1;
+ SHM->max_history = SHM->max_film - 2;
+ if(SHM->max_history > MAX_HISTORY - 1)
+ SHM->max_history = MAX_HISTORY - 1;
+ if(SHM->max_history <0) SHM->max_history=0;
+
+ fp = fopen("etc/today_is","r");
+ if(fp) {
+ fgets(SHM->today_is,15,fp);
+ if((chr = strchr(SHM->today_is,'\n')))
+ *chr = 0;
+ SHM->today_is[15] = 0;
+ fclose(fp);
+ }
+
+ /* 等所有資料更新後再設定 uptime */
+
+ SHM->Puptime = SHM->Ptouchtime ;
+ SHM->Pbusystate = 0;
+ }
+}
+
+void resolve_garbage() {
+ int count=0;
+
+ if(SHM == NULL) {
+ attach_SHM();
+ if(SHM->Ptouchtime == 0)
+ SHM->Ptouchtime = 1;
+ }
+ while(SHM->Puptime < SHM->Ptouchtime) { /* 不用while等 */
+ reload_pttcache();
+ if(count ++ > 10 && SHM->Pbusystate) {
+/* Ptt: 這邊會有問題 load超過10 秒會所有進loop的process都讓 busystate = 0
+ 這樣會所有prcosee都會在load 動態看板 會造成load大增
+ 但沒有用這個function的話 萬一load passwd檔的process死了 又沒有人把他
+ 解開 同樣的問題發生在reload passwd
+*/
+ SHM->Pbusystate = 0;
+ }
+ }
+}
+
+/*-------------------------------------------------------*/
+/* PTT's cache */
+/*-------------------------------------------------------*/
+/* cachefor from host 與最多上線人數 */
+static void reload_fcache() {
+ if(SHM->Fbusystate)
+ safe_sleep(1);
+ else {
+ FILE *fp;
+
+ SHM->Fbusystate = 1;
+ bzero(SHM->domain, sizeof SHM->domain);
+ if((fp = fopen("etc/domain_name_query","r"))) {
+ char buf[101],*po;
+
+ SHM->top=0;
+ while(fgets(buf,100,fp)) {
+ if(buf[0] && buf[0] != '#' && buf[0] != ' ' &&
+ buf[0] != '\n') {
+ sscanf(buf,"%s",SHM->domain[SHM->top]);
+ po = buf + strlen(SHM->domain[SHM->top]);
+ while(*po == ' ')
+ po++;
+ strncpy(SHM->replace[SHM->top],po,49);
+ SHM->replace[SHM->top]
+ [strlen(SHM->replace[SHM->top])-1] = 0;
+ (SHM->top)++;
+ }
+ }
+ }
+
+ SHM->max_user=0;
+
+ /* 等所有資料更新後再設定 uptime */
+ SHM->Fuptime = SHM->Ftouchtime;
+ SHM->Fbusystate = 0;
+ }
+}
+
+void resolve_fcache() {
+ if(SHM == NULL) {
+ attach_SHM();
+ if(SHM->Ftouchtime == 0)
+ SHM->Ftouchtime = 1;
+ }
+ while(SHM->Fuptime < SHM->Ftouchtime)
+ reload_fcache();
+}
diff --git a/web/util_passwd.c b/web/util_passwd.c
new file mode 100755
index 00000000..03e90f6c
--- /dev/null
+++ b/web/util_passwd.c
@@ -0,0 +1,141 @@
+/* $Id: util_passwd.c,v 1.1 2002/10/18 14:43:58 ptt Exp $ */
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include "config.h"
+#include "pttstruct.h"
+#include "modes.h"
+#include "common.h"
+#include "proto.h"
+
+#ifndef SEM_R
+#define SEM_R 0400
+#endif
+
+#ifndef SEM_A
+#define SEM_A 0200
+#endif
+
+#ifndef __FreeBSD__
+union semun {
+ int val; /* value for SETVAL */
+ struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */
+ u_short *array; /* array for GETALL & SETALL */
+ struct seminfo *__buf; /* buffer for IPC_INFO */
+};
+#endif
+
+static userec_t *passwd_image = NULL;
+static int passwd_image_size;
+static int semid = -1;
+
+int passwd_mmap() {
+ int fd;
+
+ if(passwd_image!=NULL) return 0;
+ fd = open(FN_PASSWD, O_RDWR);
+ if(fd > 0) {
+ struct stat st;
+
+ fstat(fd, &st);
+ passwd_image_size = st.st_size;
+ passwd_image = mmap(NULL, passwd_image_size,
+ PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if(passwd_image == (userec_t *)-1) {
+ perror("mmap");
+ return -1;
+ }
+ close(fd);
+ semid = semget(PASSWDSEM_KEY, 1, SEM_R | SEM_A | IPC_CREAT | IPC_EXCL);
+ if(semid == -1) {
+ if(errno == EEXIST) {
+ semid = semget(PASSWDSEM_KEY, 1, SEM_R | SEM_A);
+ if(semid == -1) {
+ perror("semget");
+ exit(1);
+ }
+ } else {
+ perror("semget");
+ exit(1);
+ }
+ } else {
+ union semun s;
+
+ s.val = 1;
+ if(semctl(semid, 0, SETVAL, s) == -1) {
+ perror("semctl");
+ exit(1);
+ }
+ }
+ } else {
+ perror(FN_PASSWD);
+ return -1;
+ }
+ return 0;
+}
+int passwd_update_money(int num) {
+ int money;
+ if(num < 1 || num > MAX_USERS)
+ return -1;
+ money = moneyof(num);
+ memcpy(&passwd_image[num - 1].money, &money, sizeof(int));
+ return 0;
+}
+
+int passwd_update(int num, userec_t *buf) {
+ if(num < 1 || num > MAX_USERS)
+ return -1;
+ buf->money = moneyof(num);
+ memcpy(&passwd_image[num - 1], buf, sizeof(userec_t));
+ return 0;
+}
+
+int passwd_query(int num, userec_t *buf) {
+ if(num < 1 || num > MAX_USERS)
+ return -1;
+ memcpy(buf, &passwd_image[num - 1], sizeof(userec_t));
+ return 0;
+}
+
+int passwd_apply(int (*fptr)(userec_t *)) {
+ int i;
+
+ for(i = 0; i < MAX_USERS; i++)
+ if((*fptr)(&passwd_image[i]) == QUIT)
+ return QUIT;
+ return 0;
+}
+
+int passwd_apply2(int (*fptr)(int, userec_t *)) {
+ int i;
+
+ for(i = 0; i < MAX_USERS; i++)
+ if((*fptr)(i, &passwd_image[i]) == QUIT)
+ return QUIT;
+ return 0;
+}
+
+void passwd_lock() {
+ struct sembuf buf = { 0, -1, SEM_UNDO };
+
+ if(semop(semid, &buf, 1)) {
+ perror("semop");
+ exit(1);
+ }
+}
+
+void passwd_unlock() {
+ struct sembuf buf = { 0, 1, SEM_UNDO };
+
+ if(semop(semid, &buf, 1)) {
+ perror("semop");
+ exit(1);
+ }
+}
diff --git a/web/util_record.c b/web/util_record.c
new file mode 100755
index 00000000..bc74d575
--- /dev/null
+++ b/web/util_record.c
@@ -0,0 +1,245 @@
+/* $Id: util_record.c,v 1.1 2002/10/18 14:43:58 ptt Exp $ */
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include "config.h"
+#include "pttstruct.h"
+#include "modes.h"
+#include "proto.h"
+
+#undef HAVE_MMAP
+#define BUFSIZE 512
+
+extern char *str_reply;
+
+static void PttLock(int fd, int size, int mode) {
+ static struct flock lock_it;
+ int ret;
+
+ lock_it.l_whence = SEEK_CUR; /* from current point */
+ lock_it.l_start = 0; /* -"- */
+ lock_it.l_len = size; /* length of data */
+ lock_it.l_type = mode; /* set exclusive/write lock */
+ lock_it.l_pid = 0; /* pid not actually interesting */
+ while((ret = fcntl(fd, F_SETLKW, &lock_it)) < 0 && errno == EINTR);
+}
+
+#define safewrite write
+
+int get_num_records(char *fpath, int size) {
+ struct stat st;
+ if(stat(fpath, &st) == -1)
+ return 0;
+ return st.st_size / size;
+}
+
+int get_sum_records(char* fpath, int size) {
+ struct stat st;
+ long ans = 0;
+ FILE* fp;
+ fileheader_t fhdr;
+ char buf[200], *p;
+
+ if(!(fp = fopen(fpath, "r")))
+ return -1;
+
+ strcpy(buf, fpath);
+ p = strrchr(buf, '/') + 1;
+
+ while(fread(&fhdr, size, 1, fp) == 1) {
+ strcpy(p, fhdr.filename);
+ if(stat(buf, &st) == 0 && S_ISREG(st.st_mode) && st.st_nlink == 1)
+ ans += st.st_size;
+ }
+ fclose(fp);
+ return ans / 1024;
+}
+
+int get_record(char *fpath, void *rptr, int size, int id) {
+ int fd = -1;
+
+ if(id < 1 || (fd = open(fpath, O_RDONLY, 0)) != -1) {
+ if(lseek(fd, (off_t)(size * (id - 1)), SEEK_SET) != -1) {
+ if(read(fd, rptr, size) == size) {
+ close(fd);
+ return 0;
+ }
+ }
+ close(fd);
+ }
+ return -1;
+}
+
+int get_records(char *fpath, void *rptr, int size, int id, int number) {
+ int fd;
+
+ if(id < 1 || (fd = open(fpath, O_RDONLY, 0)) == -1)
+ return -1;
+
+ if(lseek(fd, (off_t)(size * (id - 1)), SEEK_SET) == -1) {
+ close(fd);
+ return 0;
+ }
+ if((id = read(fd, rptr, size * number)) == -1) {
+ close(fd);
+ return -1;
+ }
+ close(fd);
+ return id / size;
+}
+
+int substitute_record(char *fpath, void *rptr, int size, int id) {
+ int fd;
+
+#ifdef POSTBUG
+ if(size == sizeof(fileheader) && (id > 1) && ((id - 1) % 4 == 0))
+ saverecords(fpath, size, id);
+#endif
+
+ if(id < 1 || (fd = open(fpath, O_WRONLY | O_CREAT, 0644)) == -1)
+ return -1;
+
+#ifdef HAVE_REPORT
+ if(lseek(fd, (off_t)(size * (id - 1)), SEEK_SET) == -1)
+ report("substitute_record failed!!! (lseek)");
+ PttLock(fd, size, F_WRLCK);
+ if(safewrite(fd, rptr, size) != size)
+ report("substitute_record failed!!! (safewrite)");
+ PttLock(fd, size, F_UNLCK);
+#else
+ lseek(fd, (off_t) (size * (id - 1)), SEEK_SET);
+ PttLock(fd, size, F_WRLCK);
+ safewrite(fd, rptr, size);
+ PttLock(fd, size, F_UNLCK);
+#endif
+ close(fd);
+
+#ifdef POSTBUG
+ if(size == sizeof(fileheader) && (id > 1) && ((id - 1) % 4 == 0))
+ restorerecords(fpath, size, id);
+#endif
+
+ return 0;
+}
+
+int apply_record(char *fpath, int (*fptr)(), int size) {
+ char abuf[BUFSIZE];
+ FILE* fp;
+
+ if(!(fp = fopen(fpath, "r")))
+ return -1;
+
+ while(fread(abuf, 1, size, fp) == size)
+ if((*fptr) (abuf) == QUIT) {
+ fclose(fp);
+ return QUIT;
+ }
+ fclose(fp);
+ return 0;
+}
+
+/* mail / post 時,依據時間建立檔案,加上郵戳 */
+int stampfile(char *fpath, fileheader_t *fh) {
+ register char *ip = fpath;
+ time_t dtime;
+ struct tm *ptime;
+ int fp = 0;
+
+ if(access(fpath, X_OK | R_OK | W_OK))
+ mkdir(fpath, 0755);
+
+ time(&dtime);
+ while (*(++ip));
+ *ip++ = '/';
+ do {
+ sprintf(ip, "M.%ld.A.%3.3X", ++dtime, rand()&0xfff );
+ if(fp == -1 && errno != EEXIST)
+ return -1;
+ } while((fp = open(fpath, O_CREAT | O_EXCL | O_WRONLY, 0644)) == -1);
+ close(fp);
+ memset(fh, 0, sizeof(fileheader_t));
+ strcpy(fh->filename, ip);
+ ptime = localtime(&dtime);
+ sprintf(fh->date, "%2d/%02d", ptime->tm_mon + 1, ptime->tm_mday);
+ return 0;
+}
+
+void stampdir(char *fpath, fileheader_t *fh) {
+ register char *ip = fpath;
+ time_t dtime;
+ struct tm *ptime;
+
+ if(access(fpath, X_OK | R_OK | W_OK))
+ mkdir(fpath, 0755);
+
+ time(&dtime);
+ while(*(++ip));
+ *ip++ = '/';
+ do {
+ sprintf(ip, "D%lX", ++dtime & 07777);
+ } while(mkdir(fpath, 0755) == -1);
+ memset(fh, 0, sizeof(fileheader_t));
+ strcpy(fh->filename, ip);
+ ptime = localtime(&dtime);
+ sprintf(fh->date, "%2d/%02d", ptime->tm_mon + 1, ptime->tm_mday);
+}
+
+void stamplink(char *fpath, fileheader_t *fh) {
+ register char *ip = fpath;
+ time_t dtime;
+ struct tm *ptime;
+
+ if(access(fpath, X_OK | R_OK | W_OK))
+ mkdir(fpath, 0755);
+
+ time(&dtime);
+ while(*(++ip));
+ *ip++ = '/';
+ do {
+ sprintf(ip, "S%lX", ++dtime );
+ } while(symlink("temp", fpath) == -1);
+ memset(fh, 0, sizeof(fileheader_t));
+ strcpy(fh->filename, ip);
+ ptime = localtime(&dtime);
+ sprintf(fh->date, "%2d/%02d", ptime->tm_mon + 1, ptime->tm_mday);
+}
+
+int do_append(char *fpath, fileheader_t *record, int size) {
+ int fd;
+
+ if((fd = open(fpath, O_WRONLY | O_CREAT, 0644)) == -1) {
+ perror("open");
+ return -1;
+ }
+ flock(fd, LOCK_EX);
+ lseek(fd, 0, SEEK_END);
+
+ safewrite(fd, record, size);
+
+ flock(fd, LOCK_UN);
+ close(fd);
+ return 0;
+}
+
+int append_record(char *fpath, fileheader_t *record, int size) {
+#ifdef POSTBUG
+ int numrecs = (int)get_num_records(fpath, size);
+
+ bug_possible = 1;
+ if(size == sizeof(fileheader) && numrecs && (numrecs % 4 == 0))
+ saverecords(fpath, size, numrecs + 1);
+#endif
+ do_append(fpath,record,size);
+
+#ifdef POSTBUG
+ if(size == sizeof(fileheader) && numrecs && (numrecs % 4 == 0))
+ restorerecords(fpath, size, numrecs + 1);
+ bug_possible = 0;
+#endif
+ return 0;
+}