diff options
author | ptt <ptt@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> | 2002-10-18 22:43:58 +0800 |
---|---|---|
committer | ptt <ptt@63ad8ddf-47c3-0310-b6dd-a9e9d9715204> | 2002-10-18 22:43:58 +0800 |
commit | 86672771393d552ac6d9c742fa1d80c34cc1cf74 (patch) | |
tree | 559e636d1dca81d54c8d5a7a929bba73a9f62646 | |
parent | d87c20433e1a16e5ec3d31b00c1dd491e995b1ea (diff) | |
download | pttbbs-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
-rw-r--r-- | web/Makefile.old | 120 | ||||
-rw-r--r-- | web/Makefile.tmpl | 16 | ||||
-rw-r--r-- | web/Makefile.tmpl.bak | 17 | ||||
-rwxr-xr-x | web/args.c | 228 | ||||
-rw-r--r-- | web/board.c | 39 | ||||
-rw-r--r-- | web/chmod | 1 | ||||
-rw-r--r-- | web/libptt.a | bin | 0 -> 107932 bytes | |||
-rw-r--r-- | web/mail.c | 6 | ||||
-rw-r--r-- | web/post.c | 6 | ||||
-rwxr-xr-x | web/stuff.c | 269 | ||||
-rw-r--r-- | web/user.c | 6 | ||||
-rwxr-xr-x | web/util_cache.c | 516 | ||||
-rwxr-xr-x | web/util_passwd.c | 141 | ||||
-rwxr-xr-x | web/util_record.c | 245 |
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 Binary files differnew file mode 100644 index 00000000..26c2f527 --- /dev/null +++ b/web/libptt.a 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; +} |