summaryrefslogtreecommitdiffstats
path: root/util
diff options
context:
space:
mode:
authorin2 <in2@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2002-03-07 23:13:44 +0800
committerin2 <in2@63ad8ddf-47c3-0310-b6dd-a9e9d9715204>2002-03-07 23:13:44 +0800
commitae31e19f92e717919ac8e3db9039eb38d2b89aae (patch)
treec70164d6a1852344f44b04a653ae2815043512af /util
downloadpttbbs-ae31e19f92e717919ac8e3db9039eb38d2b89aae.tar
pttbbs-ae31e19f92e717919ac8e3db9039eb38d2b89aae.tar.gz
pttbbs-ae31e19f92e717919ac8e3db9039eb38d2b89aae.tar.bz2
pttbbs-ae31e19f92e717919ac8e3db9039eb38d2b89aae.tar.lz
pttbbs-ae31e19f92e717919ac8e3db9039eb38d2b89aae.tar.xz
pttbbs-ae31e19f92e717919ac8e3db9039eb38d2b89aae.tar.zst
pttbbs-ae31e19f92e717919ac8e3db9039eb38d2b89aae.zip
Initial revision
git-svn-id: http://opensvn.csie.org/pttbbs/pttbbs/trunk/pttbbs@1 63ad8ddf-47c3-0310-b6dd-a9e9d9715204
Diffstat (limited to 'util')
-rw-r--r--util/.cvsignore42
-rw-r--r--util/BM_money.c117
-rw-r--r--util/BM_money.sh5
-rw-r--r--util/BOARDS.bidbin0 -> 1006592 bytes
-rw-r--r--util/DEADJOE9
-rw-r--r--util/LocalVars.pm.sample22
-rw-r--r--util/Makefile167
-rw-r--r--util/Makefile.save152
-rw-r--r--util/a.outbin0 -> 14661 bytes
-rw-r--r--util/account.c414
-rw-r--r--util/antispam.c122
-rw-r--r--util/backpasswd.sh11
-rw-r--r--util/bbsctl.c63
-rw-r--r--util/bbsmail.c239
-rw-r--r--util/bbsrf.c148
-rw-r--r--util/birth.c99
-rw-r--r--util/buildAnnounce.c69
-rw-r--r--util/buildAnnounce.sh5
-rw-r--r--util/buildir.c124
-rw-r--r--util/countalldice.c95
-rw-r--r--util/cpdeadbrd.c41
-rw-r--r--util/dailybackup.pl48
-rw-r--r--util/daymandex.c269
-rw-r--r--util/deluserfile.c147
-rw-r--r--util/descrypt.c616
-rw-r--r--util/expire.c226
-rw-r--r--util/horoscope.c157
-rw-r--r--util/in2outmailbin0 -> 39392 bytes
-rw-r--r--util/in2outmail.c288
-rw-r--r--util/initbbs.c223
-rw-r--r--util/inndBM.c194
-rw-r--r--util/jungo.c202
-rw-r--r--util/kenben.c44
-rw-r--r--util/mailog.sh9
-rw-r--r--util/mandex.c263
-rw-r--r--util/merge_board.c106
-rw-r--r--util/merge_passwd.c106
-rw-r--r--util/opendice.sh10
-rw-r--r--util/openticket.c198
-rw-r--r--util/openticket.sh10
-rw-r--r--util/openvice.c54
-rw-r--r--util/outmail.c274
-rw-r--r--util/parse_news.c78
-rw-r--r--util/post.c61
-rw-r--r--util/poststat.c497
-rw-r--r--util/reaper.c69
-rw-r--r--util/rmuid.c50
-rw-r--r--util/shmsweep.c43
-rw-r--r--util/showboard.c70
-rw-r--r--util/smtest.c296
-rw-r--r--util/smtest.c.save172
-rw-r--r--util/smtest.result1191
-rw-r--r--util/smtest.result23
-rw-r--r--util/smtest.temp231
-rw-r--r--util/stock.perl31
-rw-r--r--util/stock.sh5
-rw-r--r--util/tarqueue.pl75
-rw-r--r--util/testkenben.txt11
-rw-r--r--util/toplazyBBM.c203
-rw-r--r--util/toplazyBBM.sh3
-rw-r--r--util/toplazyBM.c211
-rw-r--r--util/toplazyBM.sh3
-rw-r--r--util/topsong.sh5
-rw-r--r--util/topusr.c205
-rw-r--r--util/tunepasswd.c77
-rw-r--r--util/uhash_loader.c129
-rw-r--r--util/userlist.c48
-rw-r--r--util/util.h31
-rw-r--r--util/util_cache.c518
-rw-r--r--util/util_passwd.c139
-rw-r--r--util/util_record.c245
-rw-r--r--util/waterball.pl149
-rw-r--r--util/weather.perl31
-rw-r--r--util/weather.sh5
-rw-r--r--util/webgrep.c46
-rw-r--r--util/xchatd.c3504
-rw-r--r--util/xchatd.h111
-rw-r--r--util/yearsold.c112
78 files changed, 13046 insertions, 0 deletions
diff --git a/util/.cvsignore b/util/.cvsignore
new file mode 100644
index 00000000..e7408563
--- /dev/null
+++ b/util/.cvsignore
@@ -0,0 +1,42 @@
+bbsmail
+BM_money
+post
+account
+birth
+deluserfile
+expire
+mandex
+horoscope
+openvice
+parse_news
+openticket
+bmda
+uhash_loader
+poststat
+showboard
+topusr
+yearsold
+cutpasswd
+inndBM
+antispam
+countalldice
+webgrep
+bbsrf
+initbbs
+outmail
+xchatd
+userlist
+tunepasswd
+buildir
+reaper
+shmsweep
+merge_passwd
+merge_board
+cpdeadbrd
+rmuid
+buildAnnounce
+toplazyBBM
+toplazyBM
+jungo
+bbsctl
+daymandex
diff --git a/util/BM_money.c b/util/BM_money.c
new file mode 100644
index 00000000..51e24c38
--- /dev/null
+++ b/util/BM_money.c
@@ -0,0 +1,117 @@
+/* $Id: BM_money.c,v 1.1 2002/03/07 15:13:45 in2 Exp $ */
+
+/* µ¹ª©¥D¿úªºµ{¦¡ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include "config.h"
+#include "pttstruct.h"
+#include "util.h"
+#include "common.h"
+
+#define FUNCTION (2100 - c*5)
+
+extern int numboards;
+extern boardheader_t *bcache;
+extern struct UCACHE *uidshm;
+
+int c, n;
+extern userec_t xuser;
+
+
+
+int Link(char *src, char *dst) {
+ char cmd[200];
+
+ if (link(src, dst) == 0)
+ return 0;
+
+ sprintf(cmd, "/bin/cp -R %s %s", src, dst);
+ return system(cmd);
+}
+
+
+int main() {
+ FILE *fp = fopen(BBSHOME "/etc/topboardman", "r");
+ char buf[201], bname[20], BM[90], *ch;
+ boardheader_t *bptr = NULL;
+ int nBM;
+
+ resolve_boards();
+ if(passwd_mmap())
+ exit(1);
+ if (!fp)
+ return 0;
+
+ c = 0;
+ fgets(buf, 200, fp); /* ²Ä¤@¦æ®³±¼ */
+
+ printf(
+ " \033[1;44m ¼úÀyÀu¨}ª©¥D ¨C¶gªáÁ~ ¨ÌºëµØ°Ï±Æ¦W¤À°t \033[m\n\n"
+ "\033[33m (±Æ¦W¤Ó«á­±©Î´X¥G¨S¦³ºëµØ°ÏªÌ¤£¦C¤J)\033[m\n"
+ " ¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w\n"
+ "\n\n");
+
+ while (fgets(buf, 200, fp) != NULL)
+ {
+ buf[24] = 0;
+ sscanf(&buf[9], "%s", bname);
+ for (n = 0; n < numboards; n++)
+ {
+ bptr = &bcache[n];
+ if (!strcmp(bptr->brdname, bname))
+ break;
+ }
+ if (n == numboards)
+ continue;
+ strcpy(BM, bptr->BM);
+ printf(" (%d) %-15.15s %s \n", c + 1, bptr->brdname, bptr->title);
+
+ if (BM[0] == 0 || BM[0] == ' ')
+ continue;
+
+ ch = BM;
+ for (nBM = 1; (ch = strchr(ch, '/')) != NULL; nBM++)
+ {
+ ch++;
+ };
+ ch = BM;
+
+ if (FUNCTION <= 0)
+ break;
+
+ printf(" ¼úª÷ \033[32m%6d \033[m ¤Àµ¹ \033[33m%s\033[m \n",
+ FUNCTION, bptr->BM);
+
+ for (n = 0; n < nBM; n++)
+ {
+ fileheader_t mymail;
+ char *ch1,uid ;
+ if((ch1 = strchr(ch, '/')))
+ *ch1 = 0;
+ if ((uid=getuser(ch))!=0)
+ {
+
+ char genbuf[200];
+ deumoney(uid,FUNCTION / nBM);
+ sprintf(genbuf, BBSHOME "/home/%c/%s", ch[0], ch);
+ stampfile(genbuf, &mymail);
+
+ strcpy(mymail.owner, "[Á~¤ô³U]");
+ sprintf(mymail.title,
+ "\033[32m %s \033[mª©ªºÁ~¤ô ¢C\033[33m%d\033![m", bptr->brdname, FUNCTION / nBM);
+ mymail.savemode = 0;
+ unlink(genbuf);
+ Link(BBSHOME "/etc/BM_money", genbuf);
+ sprintf(genbuf, BBSHOME "/home/%c/%s/.DIR", ch[0], ch);
+ append_record(genbuf, &mymail, sizeof(mymail));
+ }
+ ch = ch1 + 1;
+ }
+ c++;
+ }
+ return 0;
+}
diff --git a/util/BM_money.sh b/util/BM_money.sh
new file mode 100644
index 00000000..8bef4fc9
--- /dev/null
+++ b/util/BM_money.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+# $Id: BM_money.sh,v 1.1 2002/03/07 15:13:45 in2 Exp $
+
+bin/BM_money > etc/BM_money
+bin/post Record ¬P´Á¤­' 'ª©¥DµoÁ~¤é [°]ª÷®ø®§] etc/BM_money
diff --git a/util/BOARDS.bid b/util/BOARDS.bid
new file mode 100644
index 00000000..8d0312e5
--- /dev/null
+++ b/util/BOARDS.bid
Binary files differ
diff --git a/util/DEADJOE b/util/DEADJOE
new file mode 100644
index 00000000..a0793f05
--- /dev/null
+++ b/util/DEADJOE
@@ -0,0 +1,9 @@
+
+*** Modified files in JOE when it aborted on Thu Nov 22 19:30:21 2001
+*** JOE was aborted by signal 1
+
+*** Modified files in JOE when it aborted on Mon Nov 26 09:50:15 2001
+*** JOE was aborted because the terminal closed
+
+*** File '(Unnamed)'
+BBSNAME
diff --git a/util/LocalVars.pm.sample b/util/LocalVars.pm.sample
new file mode 100644
index 00000000..67157009
--- /dev/null
+++ b/util/LocalVars.pm.sample
@@ -0,0 +1,22 @@
+#!/usr/bin/perl
+package LocalVars;
+require Exporter;
+@ISA = qw/Exporter/;
+@EXPORT = qw/
+ $hostname $FQDN $SMTPSERVER
+ $BBSHOME $JOBSPOOL $TMP
+ $TAR/;
+
+# host
+$hostname = 'ptt';
+$FQDN = 'ptt.csie.ntu.edu.tw';
+$SMTPSERVER = 'ptt2.csie.ntu.edu.tw';
+
+# dir
+$BBSHOME = '/home/bbs';
+$JOBSPOOL = "$BBSHOME/jobspool";
+$TMP = '/tmp';
+
+# program
+$TAR = '/bin/tar';
+
diff --git a/util/Makefile b/util/Makefile
new file mode 100644
index 00000000..eeacad38
--- /dev/null
+++ b/util/Makefile
@@ -0,0 +1,167 @@
+# $Id: Makefile,v 1.1 2002/03/07 15:13:45 in2 Exp $
+
+BBSHOME?=$(HOME)
+OSTYPE=linux
+
+# FreeBSD
+CC_FreeBSD= gcc
+CFLAGS_FreeBSD= -pipe -Wall -g -O3 -DHAVE_SETPROCTITLE -DBBSHOME='"$(BBSHOME)"' -I../include
+LIBS_FreeBSD=
+LIBMAIL_FreeBSD=-lutil
+LIBCHAT_FreeBSD=
+
+# Linux
+CC_linux= gcc
+CFLAGS_linux= -pipe -Wall -g -O3 -DHAVE_DES_CRYPT -DBBSHOME='"$(BBSHOME)"' -I../include
+LIBS_linux= -lresolv
+LIBMAIL_linux=
+LIBCHAT_linux= -lcrypt
+
+CC= $(CC_$(OSTYPE))
+CFLAGS= $(CFLAGS_$(OSTYPE))
+LDFLAGS=$(LDFLAGS_$(OSTYPE))
+LIBMAIL=$(LIBMAIL_$(OSTYPE))
+LIBCHAT=$(LIBCHAT_$(OSTYPE))
+
+OBJS= util_cache.o util_record.o util_passwd.o
+
+CPROGS= bbsmail BM_money post account birth deluserfile expire mandex\
+ horoscope openvice parse_news openticket topusr yearsold uhash_loader\
+ poststat showboard antispam countalldice webgrep bbsrf\
+ initbbs outmail xchatd userlist tunepasswd buildir reaper shmsweep\
+ merge_passwd merge_board inndBM buildAnnounce rmuid cpdeadbrd \
+ toplazyBM jungo toplazyBBM daymandex
+
+PROGS= $(CPROGS) BM_money.sh backpasswd.sh mailog.sh opendice.sh\
+ openticket.sh stock.sh topsong.sh weather.sh stock.perl weather.perl\
+ toplazyBM.sh toplazyBBM.sh dailybackup.pl tarqueue.pl waterball.pl
+
+all: $(PROGS)
+
+bbsmail: bbsmail.c $(OBJS)
+ $(CC) $(CFLAGS) -o $@ $@.c $(OBJS)
+
+BM_money: BM_money.c $(OBJS)
+ $(CC) $(CFLAGS) -o $@ $@.c $(OBJS)
+
+post: post.c $(OBJS)
+ $(CC) $(CFLAGS) -o $@ $@.c $(OBJS)
+
+jungo: jungo.c $(OBJS)
+ $(CC) $(CFLAGS) -o $@ $@.c $(OBJS)
+
+account: account.c $(OBJS)
+ $(CC) $(CFLAGS) -o $@ $@.c $(OBJS)
+
+birth: birth.c $(OBJS)
+ $(CC) $(CFLAGS) -o $@ $@.c $(OBJS)
+
+deluserfile: deluserfile.c $(OBJS)
+ $(CC) $(CFLAGS) -o $@ $@.c $(OBJS)
+
+expire: expire.c $(OBJS)
+ $(CC) $(CFLAGS) -o $@ $@.c $(OBJS)
+
+mandex: mandex.c $(OBJS)
+ $(CC) $(CFLAGS) -o $@ $@.c $(OBJS)
+
+daymandex: daymandex.c $(OBJS)
+ $(CC) $(CFLAGS) -o $@ $@.c $(OBJS)
+
+rmuid: rmuid.c $(OBJS)
+ $(CC) $(CFLAGS) -o $@ $@.c $(OBJS)
+
+cpdeadbrd: cpdeadbrd.c $(OBJS)
+ $(CC) $(CFLAGS) -o $@ $@.c $(OBJS)
+
+horoscope: horoscope.c $(OBJS)
+ $(CC) $(CFLAGS) -o $@ $@.c $(OBJS)
+
+openvice: openvice.c $(OBJS)
+ $(CC) $(CFLAGS) -o $@ $@.c $(OBJS)
+
+parse_news: parse_news.c $(OBJS)
+ $(CC) $(CFLAGS) -o $@ $@.c $(OBJS)
+
+openticket: openticket.c $(OBJS)
+ $(CC) $(CFLAGS) -o $@ $@.c $(OBJS)
+
+topusr: topusr.c $(OBJS)
+ $(CC) $(CFLAGS) -o $@ $@.c $(OBJS)
+
+yearsold: yearsold.c $(OBJS)
+ $(CC) $(CFLAGS) -o $@ $@.c $(OBJS)
+
+xchatd: xchatd.c $(OBJS) descrypt.c
+ $(CC) $(CFLAGS) -o $@ $@.c $(OBJS) descrypt.c $(LIBCHAT)
+
+toplazyBM: toplazyBM.c $(OBJS)
+ $(CC) $(CFLAGS) -o $@ $@.c $(OBJS)
+
+toplazyBBM: toplazyBBM.c $(OBJS)
+ $(CC) $(CFLAGS) -o $@ $@.c $(OBJS)
+
+smtest: smtest.c $(OBJS)
+ $(CC) $(CFLAGS) -o $@ $@.c $(OBJS)
+
+reaper: reaper.c $(OBJS)
+ $(CC) $(CFLAGS) -o $@ $@.c $(OBJS)
+
+buildAnnounce: buildAnnounce.c $(OBJS)
+ $(CC) $(CFLAGS) -o $@ $@.c $(OBJS)
+
+inndBM: inndBM.c $(OBJS)
+ $(CC) $(CFLAGS) -o $@ $@.c $(OBJS)
+
+shmsweep: shmsweep.c
+ $(CC) $(CFLAGS) -o $@ $@.c
+
+uhash_loader: uhash_loader.c
+ $(CC) $(CFLAGS) -o $@ $@.c
+
+showboard: showboard.c
+ $(CC) $(CFLAGS) -o $@ $@.c
+
+antispam: antispam.c
+ $(CC) $(CFLAGS) -o $@ $@.c
+
+countalldice: countalldice.c
+ $(CC) $(CFLAGS) -o $@ $@.c
+
+webgrep: webgrep.c
+ $(CC) $(CFLAGS) -o $@ $@.c
+
+bbsrf: bbsrf.c
+ $(CC) $(CFLAGS) -o $@ $@.c
+
+initbbs: initbbs.c
+ $(CC) $(CFLAGS) -o $@ $@.c
+
+outmail: outmail.c
+ $(CC) $(CFLAGS) -o $@ $@.c $(LIBMAIL)
+
+userlist: userlist.c
+ $(CC) $(CFLAGS) -o $@ $@.c
+
+tunepasswd: tunepasswd.c
+ $(CC) $(CFLAGS) -o $@ $@.c
+
+buildir: buildir.c
+ $(CC) $(CFLAGS) -o $@ $@.c
+
+merge_passwd: merge_passwd.c
+ $(CC) $(CFLAGS) -o $@ $@.c
+
+merge_board : merge_board.c
+ $(CC) $(CFLAGS) -o $@ $@.c
+
+bbsctl: bbsctl.c
+ $(CC) $(CFLAGS) -o $@ $@.c
+
+install: $(PROGS)
+ install -d $(BBSHOME)/bin/
+ install -c -m 755 $(PROGS) $(BBSHOME)/bin/
+ chmod 4755 $(BBSHOME)/bin/post
+
+clean:
+ rm -f *.o $(CPROGS)
diff --git a/util/Makefile.save b/util/Makefile.save
new file mode 100644
index 00000000..2d0651b1
--- /dev/null
+++ b/util/Makefile.save
@@ -0,0 +1,152 @@
+# $Id: Makefile.save,v 1.1 2002/03/07 15:13:45 in2 Exp $
+
+BBSHOME?=$(HOME)
+OSTYPE=linux
+
+# FreeBSD
+CC_FreeBSD= gcc
+CFLAGS_FreeBSD= -pipe -Wall -g -O3 -DHAVE_SETPROCTITLE -DBBSHOME='"$(BBSHOME)"' -I../include
+LIBS_FreeBSD=
+LIBMAIL_FreeBSD=-lutil
+LIBCHAT_FreeBSD=
+
+# Linux
+CC_linux= gcc
+CFLAGS_linux= -pipe -Wall -g -O3 -DHAVE_DES_CRYPT -DBBSHOME='"$(BBSHOME)"' -I../include
+LIBS_linux= -lresolv
+LIBMAIL_linux=
+LIBCHAT_linux= -lcrypt
+
+CC= $(CC_$(OSTYPE))
+CFLAGS= $(CFLAGS_$(OSTYPE))
+LDFLAGS=$(LDFLAGS_$(OSTYPE))
+LIBMAIL=$(LIBMAIL_$(OSTYPE))
+LIBCHAT=$(LIBCHAT_$(OSTYPE))
+
+CPROGS= bbsmail BM_money post account birth deluserfile expire mandex\
+ horoscope openvice parse_news openticket topusr yearsold uhash_loader\
+ poststat showboard antispam countalldice webgrep bbsrf\
+ initbbs outmail xchatd userlist tunepasswd buildir reaper shmsweep\
+ merge_passwd merge_board inndBM buildAnnounce cpdeadbrd toplazyBM\
+ jungo
+PROGS= $(CPROGS) BM_money.sh backpasswd.sh mailog.sh opendice.sh\
+ openticket.sh stock.sh topsong.sh weather.sh stock.perl weather.perl\
+ cvslog.sh toplazyBM.sh
+
+all: $(PROGS)
+
+bbsmail: bbsmail.c util_cache.c util_record.c util_passwd.c
+ $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c
+
+BM_money: BM_money.c util_cache.c util_record.c util_passwd.c
+ $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c
+
+post: post.c util_cache.c util_record.c util_passwd.c
+ $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c
+
+account: account.c util_cache.c util_record.c util_passwd.c
+ $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c
+
+birth: birth.c util_cache.c util_record.c util_passwd.c
+ $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c
+
+deluserfile: deluserfile.c util_cache.c util_record.c util_passwd.c
+ $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c
+
+expire: expire.c util_cache.c util_record.c util_passwd.c
+ $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c
+
+mandex: mandex.c util_cache.c util_record.c util_passwd.c
+ $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c
+
+cpdeadbrd: cpdeadbrd.c util_cache.c util_record.c util_passwd.c
+ $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c
+
+horoscope: horoscope.c util_cache.c util_record.c util_passwd.c
+ $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c
+
+openvice: openvice.c util_cache.c util_record.c util_passwd.c
+ $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c
+
+parse_news: parse_news.c util_cache.c util_record.c util_passwd.c
+ $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c
+
+openticket: openticket.c util_cache.c util_record.c util_passwd.c
+ $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c
+
+topusr: topusr.c util_cache.c util_record.c util_passwd.c
+ $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c
+
+yearsold: yearsold.c util_cache.c util_record.c util_passwd.c
+ $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c
+
+xchatd: xchatd.c util_cache.c util_record.c util_passwd.c descrypt.c
+ $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c descrypt.c $(LIBCHAT)
+
+toplazyBM: toplazyBM.c util_cache.c util_record.c util_passwd.c
+ $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c
+
+jungo: jungo.c util_cache.c util_record.c util_passwd.c
+ $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c
+
+smtest: smtest.c util_cache.c util_record.c util_passwd.c
+ $(CC) $(CFLAGS) -o $@ $@.c util_cache.c util_record.c util_passwd.c
+
+reaper: reaper.c util_passwd.c
+ $(CC) $(CFLAGS) -o $@ $@.c util_passwd.c util_cache.c util_passwd.c
+
+buildAnnounce: buildAnnounce.c
+ $(CC) $(CFLAGS) -o $@ $@.c util_record.c util_cache.c util_passwd.c
+
+inndBM: inndBM.c
+ $(CC) $(CFLAGS) -o $@ $@.c util_record.c util_cache.c util_passwd.c
+
+shmsweep: shmsweep.c
+ $(CC) $(CFLAGS) -o $@ $@.c
+
+uhash_loader: uhash_loader.c
+ $(CC) $(CFLAGS) -o $@ $@.c
+
+showboard: showboard.c
+ $(CC) $(CFLAGS) -o $@ $@.c
+
+antispam: antispam.c
+ $(CC) $(CFLAGS) -o $@ $@.c
+
+countalldice: countalldice.c
+ $(CC) $(CFLAGS) -o $@ $@.c
+
+webgrep: webgrep.c
+ $(CC) $(CFLAGS) -o $@ $@.c
+
+bbsrf: bbsrf.c
+ $(CC) $(CFLAGS) -o $@ $@.c
+
+initbbs: initbbs.c
+ $(CC) $(CFLAGS) -o $@ $@.c
+
+outmail: outmail.c
+ $(CC) $(CFLAGS) -o $@ $@.c $(LIBMAIL)
+
+userlist: userlist.c
+ $(CC) $(CFLAGS) -o $@ $@.c
+
+tunepasswd: tunepasswd.c
+ $(CC) $(CFLAGS) -o $@ $@.c
+
+buildir: buildir.c
+ $(CC) $(CFLAGS) -o $@ $@.c
+
+merge_passwd: merge_passwd.c
+ $(CC) $(CFLAGS) -o $@ $@.c
+
+merge_board : merge_board.c
+ $(CC) $(CFLAGS) -o $@ $@.c
+
+install: $(PROGS)
+ install -d $(BBSHOME)/bin/
+ install -c -m 755 $(PROGS) $(BBSHOME)/bin/
+ chmod 4755 $(BBSHOME)/bin/post
+
+clean:
+ rm -f $(CPROGS)
diff --git a/util/a.out b/util/a.out
new file mode 100644
index 00000000..f4032dc4
--- /dev/null
+++ b/util/a.out
Binary files differ
diff --git a/util/account.c b/util/account.c
new file mode 100644
index 00000000..e4166092
--- /dev/null
+++ b/util/account.c
@@ -0,0 +1,414 @@
+/* $Id: account.c,v 1.1 2002/03/07 15:13:45 in2 Exp $ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "config.h"
+#include "pttstruct.h"
+#include "util.h"
+
+#define MAX_LINE 16
+#define ADJUST_M 6 /* adjust back 5 minutes */
+
+extern struct pttcache_t *ptt;
+
+void
+ reset_garbage()
+{
+ if (ptt == NULL)
+ {
+ ptt = attach_shm(PTTSHM_KEY, sizeof(*ptt));
+ if (ptt->touchtime == 0)
+ ptt->touchtime = 1;
+ }
+
+/* ¤£¾ã­Óreload?
+ for(n=0;n<=ptt->max_film;n++)
+ printf("\n**%d**\n %s \n",n,ptt->notes[n]);
+ */
+ ptt->uptime = 0;
+ reload_pttcache();
+
+ printf("\n°ÊºA¬ÝªO¼Æ[%d]\n", ptt->max_film);
+/*
+ for(n=0; n<MAX_MOVIE_SECTION; n++)
+ printf("sec%d=> °_ÂI:%d ¤U¦¸­n´«ªº:%d\n ",n,ptt->n_notes[n],
+ ptt->next_refresh[n]);
+ printf("\n");
+*/
+}
+
+void
+keeplog(fpath, board, title)
+ char *fpath;
+ char *board;
+ char *title;
+{
+ fileheader_t fhdr;
+ int bid;
+ char genbuf[256], buf[256];
+
+ if (!board)
+ board = "Record";
+
+
+ sprintf(genbuf, "boards/%s", board);
+ stampfile(genbuf, &fhdr);
+ sprintf(buf, "mv %s %s", fpath, genbuf);
+ system(buf);
+/*
+ printf("keep record:[%s][%s][%s][%s]\n",fpath, board, title,genbuf);
+*/
+ strcpy(fhdr.title, title);
+ strcpy(fhdr.owner, "[¾ú¥v¦Ñ®v]");
+ sprintf(genbuf, "boards/%s/.DIR", board);
+ append_record(genbuf, &fhdr, sizeof(fhdr));
+ if((bid = getbnum(board)) > 0)touchbtotal(bid);
+
+}
+
+
+static void
+my_outs(fp, buf, mode)
+ FILE *fp;
+ char buf[], mode;
+{
+ static char state = '0';
+
+ if (state != mode)
+ fprintf(fp, "[3%cm", state = mode);
+ if (buf[0])
+ {
+ fprintf(fp, buf);
+ buf[0] = 0;
+ }
+}
+
+
+void gzip(source, target, stamp)
+ char *source, *target, *stamp;
+{
+ char buf[128];
+ sprintf(buf, "gzip -f9n adm/%s%s", target, stamp);
+ rename(source, &buf[14]);
+ system(buf);
+}
+
+extern struct fromcache_t *fcache;
+extern uhash_t *uhash;
+
+int main() {
+ int hour, max, item, total, i, j, mo, da, max_user = 0, max_login = 0,
+ max_reg = 0, mahour = 0, k;
+ char *act_file = ".act";
+ char *log_file = "usies";
+ char buf[256], buf1[256], *p;
+ FILE *fp, *fp1;
+ int act[27]; /* ¦¸¼Æ/²Ö­p®É¶¡/pointer */
+ time_t now;
+ struct tm *ptime;
+
+ now = time(NULL) - ADJUST_M * 60; /* back to ancent */
+ ptime = localtime(&now);
+
+ memset(act, 0, sizeof(act));
+ printf("¦¸¼Æ/²Ö­p®É¶¡\n");
+ if ((ptime->tm_hour != 0) && (fp = fopen(act_file, "r")))
+ {
+ fread(act, sizeof(act), 1, fp);
+ fclose(fp);
+ }
+ if ((fp = fopen(log_file, "r")) == NULL)
+ {
+ printf("cann't open usies\n");
+ return 1;
+ }
+ if (act[26])
+ fseek(fp, act[26], 0);
+ while (fgets(buf, 256, fp))
+ {
+ buf[11+2]=0;
+ hour = atoi(buf + 11);
+ if (hour < 0 || hour > 23)
+ {
+ continue;
+ }
+//"09/06/1999 17:44:58 Mon "
+// 012345678901234567890123
+ if (strstr(buf + 20, "ENTER"))
+ {
+ act[hour]++;
+ continue;
+ }
+ if ((p = (char *) strstr(buf + 40, "Stay:")))
+ {
+ if((hour = atoi(p + 5))) {
+ act[24] += hour;
+ act[25]++;
+ }
+ continue;
+ }
+ }
+ act[26] = ftell(fp);
+ fclose(fp);
+ for (i = max = total = 0; i < 24; i++)
+ {
+ total += act[i];
+ if (act[i] > max)
+ {
+ max_user = max = act[i];
+ mahour = i;
+ }
+ }
+ item = max / MAX_LINE + 1;
+
+ if (!ptime->tm_hour)
+ {
+ keeplog("etc/today", "Record", "¤W¯¸¤H¦¸²Î­p");
+ keeplog("etc/money", "Security", "¥»¤éª÷¿ú©¹¨Ó°O¿ý");
+ keeplog("etc/illegal_money", "Security", "¥»¤é¹HªkÁÈ¿ú°O¿ý");
+ keeplog("etc/chicken", "Record", "Âû³õ³ø§i");
+ }
+
+ printf("¤W¯¸¤H¦¸²Î­p\n");
+ if ((fp = fopen("etc/today", "w")) == NULL)
+ {
+ printf("cann't open etc/today\n");
+ return 1;
+ }
+ fprintf(fp, "\t\t\t ¨C¤p®É¤W¯¸¤H¦¸²Î­p [%02d/%02d/%02d] \n\n", ptime->tm_year % 100, ptime->tm_mon + 1, ptime->tm_mday);
+ for (i = MAX_LINE + 1; i > 0; i--)
+ {
+ strcpy(buf, " ");
+ for (j = 0; j < 24; j++)
+ {
+ max = item * i;
+ hour = act[j];
+ if (hour && (max > hour) && (max - item <= hour))
+ {
+ my_outs(fp, buf, '3');
+ fprintf(fp, "%-3d", hour / 10);
+ }
+ else if (max <= hour)
+ {
+ my_outs(fp, buf, '4');
+ fprintf(fp, "¢i ");
+ }
+ else
+ strcat(buf, " ");
+ }
+ fprintf(fp, "\n");
+ }
+ fprintf(fp, " "
+ "0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23\n\n"
+ "\t ³æ¦ì: 10 ¤H");
+ fprintf(fp, " Á`¦@¤W¯¸¤H¦¸¡G%-7d¥­§¡¨Ï¥Î¤H¼Æ¡G%d\n", total, total / 24);
+ fclose(fp);
+
+ if((fp = fopen(act_file, "w"))) {
+ fwrite(act, sizeof(act), 1, fp);
+ fclose(fp);
+ }
+
+/* -------------------------------------------------------------- */
+
+ sprintf(buf, "-%02d%02d%02d",
+ ptime->tm_year % 100, ptime->tm_mon + 1, ptime->tm_mday);
+
+ now += ADJUST_M * 60; /* back to future */
+
+
+ printf("¾ú¥v¨Æ¥ó³B²z\n");
+/* Ptt ¾ú¥v¨Æ¥ó³B²z */
+ if((fp = fopen("etc/history.data", "r"))) { /*³Ì¦h¦P®É¤W½u */
+ if (fscanf(fp, "%d %d %d %d", &max_login, &max, &max_reg, &k))
+ {
+ int a;
+ resolve_fcache();
+ printf("¦¹®É¬q³Ì¦h¦P®É¤W½u:%d ¹L¥h:%d\n", a = fcache->max_user, k);
+ fclose(fp);
+ if (a > k)
+ {
+ ptime = localtime(&fcache->max_time);
+ if((fp1 = fopen("etc/history", "a")))
+ {
+ fprintf(fp1,
+ "¡· ¡i%02d/%02d/%02d %02d:%02d¡j"
+ "¦P®É¦b§{¤º¤H¼Æ­º¦¸¹F¨ì %d ¤H¦¸\n",
+ ptime->tm_mon + 1, ptime->tm_mday, ptime->tm_year % 100,
+ ptime->tm_hour, ptime->tm_min, a);
+ fclose(fp1);
+ }
+ if((fp = fopen("etc/history.data", "w")))
+ {
+ fprintf(fp, "%d %d %d %d", max_login, max, max_reg, a);
+ fclose(fp);
+ }
+ }
+ }
+ else
+ fclose(fp);
+ }
+ ptime = localtime(&now);
+
+ if (ptime->tm_hour)
+ {
+ /* rotate one line in today_is */
+ puts("¦h­Ó¸`¤é³B²z");
+ if((fp1 = fopen("etc/today_is", "r"))) {
+ char tod[100][20];
+
+ i = 0;
+ while(i < 100 && fgets(tod[i], sizeof(tod[0]), fp1))
+ i++;
+ fclose(fp1);
+
+ fp1 = fopen("etc/today_is", "w");
+ for(j = 0; j < i; j++)
+ fputs(tod[j + 1 < i ? j + 1 : 0], fp1);
+ fclose(fp1);
+ }
+ }
+
+
+ if (!ptime->tm_hour)
+ {
+ keeplog(".note", "Record", "¤ß±¡¯d¨¥ª©");
+ system("/bin/cp etc/today etc/yesterday");
+/* system("rm -f note.dat"); */
+/* Ptt */
+ sprintf(buf1, "[¤½¦w³ø§i] ¨Ï¥ÎªÌ¤W½uºÊ±± [%02d/%02d:%02d]"
+ ,ptime->tm_mon + 1, ptime->tm_mday, ptime->tm_hour);
+ keeplog("usies", "Security", buf1);
+ printf("[¤½¦w³ø§i] ¨Ï¥ÎªÌ¤W½uºÊ±±\n");
+ gzip(log_file, "usies", buf);
+ printf("À£ÁY¨Ï¥ÎªÌ¤W½uºÊ±±\n");
+/* Ptt ¾ú¥v¨Æ¥ó³B²z */
+ now = time(NULL) - ADJUST_M * 60; /* back to ancent */
+ ptime = localtime(&now);
+
+ attach_uhash();
+ if((fp = fopen("etc/history.data", "r")))
+ { /* ³æ¤é³Ì¦h¦¸¤H¦¸,¦P®É¤W½u,µù¥U */
+ if (fscanf(fp, "%d %d %d %d", &max_login, &max, &max_reg, &k))
+ {
+ fp1 = fopen("etc/history", "r+");
+ fseek(fp1, 0, 2);
+ if (max_user > max)
+ {
+ fprintf(fp1, "¡º ¡i%02d/%02d/%02d %02d¡j "
+ "³æ¤@¤p®É¤W½u¤H¦¸­º¦¸¹F¨ì %d ¤H¦¸ \n"
+ ,ptime->tm_mon + 1, ptime->tm_mday, ptime->tm_year % 100, mahour, max_user);
+ max = max_user;
+ }
+ if (total > max_login)
+ {
+ fprintf(fp1, "¡» ¡i%02d/%02d/%02d¡j "
+ "³æ¤é¤W½u¤H¦¸­º¦¸¹F¨ì %d ¤H¦¸ \n"
+ ,ptime->tm_mon + 1, ptime->tm_mday, ptime->tm_year % 100, total);
+ max_login = total;
+ }
+
+ if (uhash->number > max_reg + max_reg / 10)
+ {
+ fprintf(fp1, "¡¹ ¡i%02d/%02d/%02d¡j "
+ "Á`µù¥U¤H¼Æ´£¤É¨ì %d ¤H \n"
+ ,ptime->tm_mon + 1, ptime->tm_mday, ptime->tm_year % 100, uhash->number);
+ max_reg = uhash->number;
+ }
+
+ fclose(fp1);
+ }
+ fclose(fp);
+ fp = fopen("etc/history.data", "w");
+ fprintf(fp, "%d %d %d %d", max_login, max, max_reg, k);
+ fclose(fp);
+ }
+ now += ADJUST_M * 60; /* back to future */
+ ptime = localtime(&now);
+
+ /* Ptt ¸`¤é³B²z */
+ printf("¸`¤é³B²z\n");
+ if((fp1 = fopen("etc/today_is", "w"))) {
+ i = 0;
+ if((fp = fopen("etc/feast", "r"))) {
+ while(fgets(buf1, sizeof(buf1), fp)) {
+ if(buf[0] != '#' &&
+ sscanf(buf1, "%d %d ", &mo, &da) == 2) {
+ if(ptime->tm_mday == da && ptime->tm_mon + 1 == mo) {
+ i = 1;
+ fprintf(fp1, "%-14.14s", &buf1[6]);
+ }
+ }
+ }
+ fclose(fp);
+ }
+ printf("¸`¤é³B²z1\n");
+ if(i == 0) {
+ if((fp = fopen("etc/today_boring", "r"))) {
+ while(fgets(buf1, sizeof(buf1), fp))
+ if(strlen(buf) > 3)
+ fprintf(fp1, "%s", buf1);
+ fclose(fp);
+ } else
+ fprintf(fp1, "¥»¤é¸`¤é¼x¨D¤¤");
+ }
+ fclose(fp1);
+ }
+
+ /* Ptt Åwªïµe­±³B²z */
+ printf("Åwªïµe­±³B²z\n");
+
+ if((fp = fopen("etc/Welcome.date", "r")))
+ {
+ char temp[50];
+ while (fscanf(fp, "%d %d %s\n", &mo, &da, buf1) != EOF)
+ {
+ if (ptime->tm_mday == da && ptime->tm_mon + 1 == mo)
+ {
+ strcpy(temp, buf1);
+ sprintf(buf1, "cp -f etc/Welcomes/%s etc/Welcome", temp);
+ system(buf1);
+ break;
+ }
+ }
+ fclose(fp);
+ }
+ printf("Åwªïµe­±³B²z\n");
+ if (ptime->tm_wday == 0)
+ {
+ keeplog("etc/week", "Record", "¥»¶g¼öªù¸ÜÃD");
+
+ gzip("bbslog", "bntplink", buf);
+ gzip("innd/bbslog", "innbbsd", buf);
+ gzip("etc/mailog", "mailog", buf);
+ }
+
+ if (ptime->tm_mday == 1)
+ keeplog("etc/month", "Record", "¥»¤ë¼öªù¸ÜÃD");
+
+ if (ptime->tm_yday == 1)
+ keeplog("etc/year", "Record", "¦~«×¼öªù¸ÜÃD");
+ }
+ else if (ptime->tm_hour == 3 && ptime->tm_wday == 6)
+ {
+ char *fn1 = "tmp";
+ char *fn2 = "suicide";
+ rename(fn1, fn2);
+ mkdir(fn1, 0755);
+ sprintf(buf, "tar cfz adm/%s-%02d%02d%02d.tgz %s",
+ fn2, ptime->tm_year % 100, ptime->tm_mon + 1, ptime->tm_mday, fn2);
+ system(buf);
+ sprintf(buf, "/bin/rm -fr %s", fn2);
+ system(buf);
+ }
+/* Ptt reset Ptt's share memory */
+ printf("­«³]Pttcache »Pfcache\n");
+
+ fcache->uptime = 0;
+ resolve_fcache();
+ reset_garbage();
+ return 0;
+}
diff --git a/util/antispam.c b/util/antispam.c
new file mode 100644
index 00000000..f7b77569
--- /dev/null
+++ b/util/antispam.c
@@ -0,0 +1,122 @@
+/* $Id: antispam.c,v 1.1 2002/03/07 15:13:45 in2 Exp $ */
+/* §ì¼s§i«Hªºµ{¦¡ */
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include "config.h"
+
+#define WINDOW 100 /* ¤@¦¸window¦h¤Ö­Óserver */
+#define LEVEL 21 /* ­Y´X¦¸­«´_´Nºâ¼s§i«H */
+
+#define mailog BBSHOME "/etc/mailog"
+#define spamlog BBSHOME "/etc/spam"
+
+typedef struct sendinfo
+{
+ char time[18];
+ char from[50];
+ char userid[20];
+ int count;
+}
+sendinfo;
+
+int
+ main()
+{
+ char buf[200], *from, *userid;
+ int num = -1, numb = -1, n, nb;
+ FILE *fp = fopen(mailog, "r"), *fo;
+ sendinfo data[WINDOW];
+ sendinfo bad[WINDOW];
+
+ unlink(spamlog);
+ fo = fopen(spamlog, "a");
+ memset(data, 0, sizeof(data));
+ memset(bad, 0, sizeof(bad));
+
+ if (!fp || !fo)
+ return 0;
+
+ while (fgets(buf, 200, fp))
+ {
+ strtok(buf, "\r\n");
+ from = strchr(buf, '>') + 2;
+ userid = strstr(buf, " =>");
+
+ if (!from || !userid)
+ continue;
+
+ *userid = 0;
+ userid += 4;
+
+ if (strstr(from, "MAILER-DAEMON")
+ || strstr(from, userid))
+ continue; /* °h«H³qª¾¤£ºÞ */
+ /* ¬O§_¤w¬Obadhost */
+
+ for (nb = 0; nb < WINDOW && bad[nb].from[0]; nb++)
+ if (!strcmp(bad[nb].from, from))
+ break;
+
+ if (nb < WINDOW && bad[nb].from[0])
+ {
+ bad[nb].count++;
+ continue;
+ }
+
+ /* ²¬d¹L¥h°O¿ý */
+
+ for (n = 0; n < WINDOW && data[n].from[0]; n++)
+ if (!strcmp(data[n].from, from))
+ break;
+
+ if (n < WINDOW && data[n].from[0])
+ {
+ if (!strncmp(data[n].userid, userid, 20))
+ continue;
+ /* Â൹¦P¤@­Ó¤H´N¤£ºÞ */
+ strncpy(data[n].userid, userid, 20);
+ if (++data[n].count >= LEVEL)
+ {
+ /* Åܦ¨bad ²¾data¨ìbad ªÅ¯Ê¥Ñ«á¤@µ§¸ê®Æ¸É¤W */
+ if (nb >= WINDOW)
+ {
+ numb = (numb + 1) % WINDOW;
+ nb = numb;
+ fprintf(fo, "%s %s ­«ÂбH %d ¦¸\n",
+ bad[nb].time, bad[nb].from, bad[nb].count);
+/* printf(" %s send %d times\n",
+ bad[nb].from, bad[nb].count); */
+ }
+ memcpy(&bad[nb], &data[n], sizeof(sendinfo));
+ memcpy(&data[n], &data[n + 1], sizeof(sendinfo) * (WINDOW - n - 1));
+ if (num > n)
+ num--;
+ }
+ }
+ else
+ {
+ if (n >= WINDOW)
+ {
+ num = (num + 1) % WINDOW;
+ n = num;
+ }
+/* printf("[%s] to [%s]\n", from, userid); */
+ buf[17] = 0;
+ strncpy(data[n].time, buf, 17);
+ strncpy(data[n].from, from, 50);
+ strncpy(data[n].userid, userid, 20);
+ }
+ }
+
+ for (nb = 0; nb < WINDOW && bad[nb].from[0]; nb++)
+ {
+ fprintf(fo, "%s %s ­«ÂбH %d ¦¸\n", bad[nb].time,
+ bad[nb].from, bad[nb].count);
+/* printf(" %s send %d times\n", bad[nb].from, bad[nb].count); */
+ }
+ fclose(fp);
+ fclose(fo);
+ return 0;
+}
diff --git a/util/backpasswd.sh b/util/backpasswd.sh
new file mode 100644
index 00000000..5ec11abd
--- /dev/null
+++ b/util/backpasswd.sh
@@ -0,0 +1,11 @@
+#!/bin/sh
+# $Id: backpasswd.sh,v 1.1 2002/03/07 15:13:45 in2 Exp $
+
+mv PASSWDS.NEW5 PASSWDS.NEW6
+mv PASSWDS.NEW4 PASSWDS.NEW5
+mv PASSWDS.NEW3 PASSWDS.NEW4
+mv PASSWDS.NEW2 PASSWDS.NEW3
+mv PASSWDS.NEW1 PASSWDS.NEW2
+mv PASSWDS.NEW PASSWDS.NEW1
+cp .PASSWDS PASSWDS.NEW
+
diff --git a/util/bbsctl.c b/util/bbsctl.c
new file mode 100644
index 00000000..bf66df35
--- /dev/null
+++ b/util/bbsctl.c
@@ -0,0 +1,63 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/types.h>
+void usage(void)
+{
+ printf("usage: bbsctl [start|stop|restart]\n");
+ exit(0);
+}
+
+void startbbs(void)
+{
+ if( setuid(0) < 0 ){
+ perror("setuid(0)");
+ exit(1);
+ }
+ puts("starting mbbsd: 23"); system("/home/bbs/bin/mbbsd 23");
+ puts("starting mbbsd:3000"); system("/home/bbs/bin/mbbsd 3000");
+ puts("starting mbbsd:3001"); system("/home/bbs/bin/mbbsd 3001");
+ puts("starting mbbsd:3002"); system("/home/bbs/bin/mbbsd 3002");
+ puts("starting mbbsd:3003"); system("/home/bbs/bin/mbbsd 3003");
+ puts("starting mbbsd:3004"); system("/home/bbs/bin/mbbsd 3004");
+ puts("starting mbbsd:3005"); system("/home/bbs/bin/mbbsd 3005");
+ puts("starting mbbsd:3006"); system("/home/bbs/bin/mbbsd 3006");
+ puts("starting mbbsd:3007"); system("/home/bbs/bin/mbbsd 3007");
+ puts("starting mbbsd:3008"); system("/home/bbs/bin/mbbsd 3008");
+ puts("starting mbbsd:3009"); system("/home/bbs/bin/mbbsd 3009");
+ puts("starting mbbsd:3010"); system("/home/bbs/bin/mbbsd 3010");
+}
+
+void stopbbs(void)
+{
+ char buf[1024];
+ int pid;
+ FILE *fp = popen("/bin/ps -ax | /usr/bin/grep mbbsd | "
+ "/usr/bin/grep listen", "r");
+ while( fgets(buf, sizeof(buf), fp) != NULL ){
+ sscanf(buf, "%d", &pid);
+ printf("stopping %d\n", pid);
+ kill(pid, 1);
+ }
+}
+
+void restartbbs(void)
+{
+ stopbbs();
+ startbbs();
+}
+
+int main(int argc, char **argv)
+{
+ if( argc == 1 )
+ usage();
+ if( strcmp(argv[1], "start") == 0 )
+ startbbs();
+ else if( strcmp(argv[1], "stop") == 0 )
+ stopbbs();
+ else if( strcmp(argv[1], "restart") == 0 )
+ restartbbs();
+ return 0;
+}
diff --git a/util/bbsmail.c b/util/bbsmail.c
new file mode 100644
index 00000000..48f74c63
--- /dev/null
+++ b/util/bbsmail.c
@@ -0,0 +1,239 @@
+/* $Id: bbsmail.c,v 1.1 2002/03/07 15:13:45 in2 Exp $ */
+
+#define _BBS_UTIL_C_
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include "config.h"
+#include "pttstruct.h"
+#include "util.h"
+#include "perm.h"
+#include "common.h"
+
+#define LOG_FILE (BBSHOME "/etc/mailog")
+
+#ifdef HMM_USE_ANTI_SPAM
+extern char *notitle[], *nofrom[], *nocont[];
+#endif
+
+extern userec_t xuser;
+
+int mailalertuid(int tuid)
+{
+ userinfo_t *uentp=NULL;
+ if(tuid>0 && (uentp = (userinfo_t *)search_ulist(tuid)) )
+ uentp->mailalert=1;
+ return 0;
+}
+
+void
+mailog(msg)
+ char *msg;
+{
+ FILE *fp;
+
+ if ((fp = fopen(LOG_FILE, "a")))
+ {
+ time_t now;
+ struct tm *p;
+
+ time(&now);
+ p = localtime(&now);
+ fprintf(fp, "%02d/%02d/%02d %02d:%02d:%02d <bbsmail> %s\n",
+ p->tm_year % 100, p->tm_mon + 1, p->tm_mday, p->tm_hour, p->tm_min, p->tm_sec,
+ msg);
+ fclose(fp);
+ }
+}
+
+
+int
+mail2bbs(userid)
+ char *userid;
+{
+ int uid;
+ fileheader_t mymail;
+ char genbuf[256], title[80], sender[80], filename[80], *ip, *ptr;
+ time_t tmp_time;
+ struct stat st;
+ FILE *fout;
+/* check if the userid is in our bbs now */
+ if (!(uid=getuser(userid)) )
+ {
+ sprintf(genbuf, "BBS user <%s> not existed", userid);
+ puts(genbuf);
+ mailog(genbuf);
+ return -1;//EX_NOUSER;
+ }
+
+ if(xuser.userlevel&PERM_NOOUTMAIL)
+ return -1;
+
+ sprintf(filename, BBSHOME "/home/%c/%s", userid[0], userid);
+
+ if (stat(filename, &st) == -1)
+ {
+ if (mkdir(filename, 0755) == -1)
+ {
+ printf("mail box create error %s \n", filename);
+ return -1;
+ }
+ }
+ else if (!(st.st_mode & S_IFDIR))
+ {
+ printf("mail box error\n");
+ return -1;
+ }
+
+ // printf("dir: %s\n", filename);
+
+/* allocate a file for the new mail */
+
+ stampfile(filename, &mymail);
+ // printf("file: %s\n", filename);
+
+/* copy the stdin to the specified file */
+
+/* parse header */
+
+ while (fgets(genbuf, 255, stdin))
+ {
+ if (!strncmp(genbuf, "From", 4))
+ {
+ if ((ip = strchr(genbuf, '<')) && (ptr = strrchr(ip, '>')))
+ {
+ *ptr = '\0';
+ if (ip[-1] == ' ')
+ ip[-1] = '\0';
+ ptr = (char *) strchr(genbuf, ' ');
+ while (*ptr == ' ') ptr++;
+ sprintf(sender, "%s (%s)", ip + 1, ptr);
+ }
+ else
+ {
+ strtok(genbuf, " \t\n\r");
+ ptr= strtok(NULL, " \t\n\r");
+ if(ptr)
+ strcpy(sender, ptr);
+ }
+ continue;
+ }
+ if (!strncmp(genbuf, "Subject: ", 9))
+ {
+ strcpy(title, genbuf + 9);
+ continue;
+ }
+ if (genbuf[0] == '\n')
+ break;
+ }
+
+ if ((ptr = strchr(sender, '\n')))
+ *ptr = '\0';
+
+ if ((ptr = strchr(title, '\n')))
+ *ptr = '\0';
+
+ if (strchr(sender, '@') == NULL) /* ¥Ñ local host ±H«H */
+ {
+ strcat(sender, "@" MYHOSTNAME);
+ }
+
+ time(&tmp_time);
+
+#ifdef HMM_USE_ANTI_SPAM
+ for (n = 0; notitle[n]; n++)
+ if (strstr(title, notitle[n]))
+ {
+ sprintf(genbuf, "Title <%s> not accepted", title);
+ puts(genbuf);
+ mailog(genbuf);
+ return -1;
+ }
+ for (n = 0; nofrom[n]; n++)
+ if (strstr(sender, nofrom[n]))
+ {
+ sprintf(genbuf, "From <%s> not accepted", sender);
+ puts(genbuf);
+ mailog(genbuf);
+ return -1;
+ }
+#endif
+
+ if ((fout = fopen(filename, "w")) == NULL)
+ {
+ printf("Cannot open %s\n", filename);
+ return -1;
+ }
+
+ if (!title[0])
+ sprintf(title, "¨Ó¦Û %.64s", sender);
+ title[TTLEN] = 0;
+ fprintf(fout, "§@ªÌ: %s\n¼ÐÃD: %s\n®É¶¡: %s\n",
+ sender, title, ctime(&tmp_time));
+
+ while (fgets(genbuf, 255, stdin))
+ {
+#ifdef HMM_USE_ANTI_SPAM
+ for (n = 0; nocont[n]; n++)
+ if (strstr(genbuf, nocont[n]))
+ {
+ fclose(fout);
+ unlink(filename);
+ sprintf(genbuf, "Content <%s> not accepted", nocont[n]);
+ puts(genbuf);
+ mailog(genbuf);
+ return -1;
+ }
+#endif
+ fputs(genbuf, fout);
+ }
+ fclose(fout);
+
+ sprintf(genbuf, "%s => %s", sender, userid);
+ mailog(genbuf);
+
+/* append the record to the MAIL control file */
+
+ strcpy(mymail.title, title);
+
+ if (strtok(sender, " .@\t\n\r"))
+ strcat(sender, ".");
+ sender[IDLEN + 1] = '\0';
+ strcpy(mymail.owner, sender);
+
+ sprintf(genbuf, BBSHOME "/home/%c/%s/.DIR", userid[0], userid);
+ mailalertuid(uid);
+ return append_record(genbuf, &mymail, sizeof(mymail));
+}
+
+
+int
+main(int argc, char* argv[])
+{
+ char receiver[256];
+
+/* argv[1] is userid in bbs */
+
+ if (argc < 2)
+ {
+ printf("Usage:\t%s <bbs_uid>\n", argv[0]);
+ exit(-1);
+ }
+ (void) setgid(BBSGID);
+ (void) setuid(BBSUID);
+
+ if(passwd_mmap()) exit(-1);
+ strcpy(receiver, argv[1]);
+
+ strtok(receiver,".");
+ if (mail2bbs(receiver))
+ {
+ /* eat mail queue */
+ while (fgets(receiver, sizeof(receiver), stdin)) ;
+ }
+ return 0;
+}
diff --git a/util/bbsrf.c b/util/bbsrf.c
new file mode 100644
index 00000000..66f6cee0
--- /dev/null
+++ b/util/bbsrf.c
@@ -0,0 +1,148 @@
+/* $Id: bbsrf.c,v 1.1 2002/03/07 15:13:45 in2 Exp $ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <utmp.h>
+#include <pwd.h>
+#include <syslog.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include "config.h"
+
+/* fill the hid with from hostname */
+void gethid(char *hid, char *tty)
+{
+ int fd;
+ char *tp;
+ struct utmp data;
+
+ gethostname(hid, MAXHOSTNAMELEN);
+ hid[MAXHOSTNAMELEN] = '\0';
+ tp = strrchr(tty, '/') + 1;
+ if (tp && strlen(tp) == 5)
+ {
+ fd = open(_PATH_UTMP, O_RDONLY);
+ if (fd < 0)
+ syslog(LOG_ERR, "%s: %m", _PATH_UTMP);
+ else
+ {
+ while (read(fd, &data, sizeof(data)) == sizeof(data))
+ if (strcmp(data.ut_line, tp) == 0)
+ {
+ if (data.ut_host[0]) {
+#if MAXHOSTNAMELEN < UT_HOSTSIZE
+ strncpy(hid, data.ut_host, MAXHOSTNAMELEN);
+ hid[MAXHOSTNAMELEN] = '\0';
+#else
+ strncpy(hid, data.ut_host, UT_HOSTSIZE);
+ hid[UT_HOSTSIZE] = '\0';
+#endif
+ }
+ break;
+ }
+ close(fd);
+ }
+ }
+}
+
+/*
+ get system load averages
+ return 0 if success; otherwise, return -1.
+ */
+int getload(double load[3])
+{
+ int rtv = -1;
+#if defined(linux)
+ FILE *fp;
+
+ fp = fopen(LOAD_FILE, "r");
+ if (fp)
+ {
+ if (fscanf(fp, "%lf %lf %lf", &load[0], &load[1], &load[2]) == 3)
+ rtv = 0;
+ fclose(fp);
+ }
+#elif defined(__FreeBSD__)
+ if (getloadavg(load, 3) == 3)
+ rtv = 0;
+#endif
+ return rtv;
+}
+
+/*
+ show ban file
+ if filename exist, print it out, sleep 1 second, and return 0;
+ otherwise, return -1.
+ */
+int showbanfile(char *filename)
+{
+ FILE *fp;
+ char buf[256];
+
+ fp = fopen(filename, "r");
+ if (fp)
+ {
+ while (fgets(buf, sizeof(buf), fp))
+ fputs(buf, stdout);
+ printf("\n============================="
+ "=============================\n");
+ fclose(fp);
+ sleep(1);
+ }
+ return fp ? 0 : -1;
+}
+
+int main(void)
+{
+ int uid, rtv = 0;
+ char *tty, ttybuf[32], hid[MAXHOSTNAMELEN + 1];
+
+ openlog("bbsrf", LOG_PID | LOG_PERROR, LOG_USER);
+ chdir(BBSHOME);
+ uid = getuid();
+
+ while (1)
+ {
+ if (!showbanfile(BAN_FILE))
+ {
+ rtv = 1;
+ break;
+ }
+ else if (uid != BBSUID)
+ {
+ syslog(LOG_ERR, "UID DOES NOT MATCH");
+ rtv = -1;
+ break;
+ }
+ else if (!getpwuid(uid))
+ {
+ syslog(LOG_ERR, "YOU DONT EXIST");
+ rtv = -1;
+ break;
+ }
+ else
+ {
+ tty = ttyname(0);
+ if (tty)
+ {
+ strcpy(ttybuf, tty);
+ gethid(hid, ttybuf);
+ }
+ else
+ {
+ strcpy(ttybuf, "notty");
+ strcpy(hid, "unknown");
+ }
+ execl(BBSPROG, "mbbsd", hid, ttybuf, NULL);
+ syslog(LOG_ERR, "execl(): %m");
+ rtv = -1;
+ }
+ break;
+ }
+ return rtv;
+}
diff --git a/util/birth.c b/util/birth.c
new file mode 100644
index 00000000..899bf9ee
--- /dev/null
+++ b/util/birth.c
@@ -0,0 +1,99 @@
+/* ¹Ø¬Pµ{¦¡ 96 10/11 */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <time.h>
+#include "config.h"
+#include "pttstruct.h"
+#include "util.h"
+#include "common.h"
+
+#define OUTFILE BBSHOME "/etc/birth.today"
+
+struct userec_t cuser;
+
+int bad_user_id() {
+ register char ch;
+ int j;
+ if (strlen(cuser.userid) < 2 || !isalpha(cuser.userid[0]))
+ return 1;
+ if (cuser.numlogins == 0 || cuser.numlogins > 15000)
+ return 1;
+ if (cuser.numposts > 15000)
+ return 1;
+ for (j = 1; (ch = cuser.userid[j]); j++)
+ {
+ if (!isalnum(ch))
+ return 1;
+ }
+ return 0;
+}
+
+int Link(char *src, char *dst) {
+ char cmd[200];
+
+ if (link(src, dst) == 0)
+ return 0;
+
+ sprintf(cmd, "/bin/cp -R %s %s", src, dst);
+ return system(cmd);
+}
+
+int main(argc, argv)
+ int argc;
+ char **argv;
+{
+ FILE *fp1;
+ fileheader_t mymail;
+ int i, day = 0;
+ time_t now;
+ struct tm *ptime;
+ int j;
+
+ now = time(NULL); /* back to ancent */
+ ptime = localtime(&now);
+
+ if(passwd_mmap())
+ exit(1);
+
+ printf("*»sªí\n");
+ fp1 = fopen(OUTFILE, "w");
+
+ fprintf(fp1, "\n "
+ "¡¹¡¹¡¹¡¹¡¹¡¹ ¹Ø¬P¤jÆ[ "
+ "¡¹¡¹¡¹¡¹¡¹¡¹ \n\n");
+ fprintf(fp1, "¡i¥»¤é¹Ø¬P¡j \n");
+ for(j = 1; j <= MAX_USERS; j++) {
+ passwd_query(j, &cuser);
+ if (bad_user_id())
+ continue;
+ if (cuser.month == ptime->tm_mon + 1)
+ {
+ if (cuser.day == ptime->tm_mday)
+ {
+ char genbuf[200];
+ sprintf(genbuf, BBSHOME "/home/%c/%s", cuser.userid[0], cuser.userid);
+ stampfile(genbuf, &mymail);
+ strcpy(mymail.owner, BBSNAME);
+ strcpy(mymail.title, "!! ¥Í¤é§Ö¼Ö !!");
+ mymail.savemode = 0;
+ unlink(genbuf);
+ Link(BBSHOME "/etc/Welcome_birth", genbuf);
+ sprintf(genbuf, BBSHOME "/home/%c/%s/.DIR", cuser.userid[0], cuser.userid);
+ append_record(genbuf, &mymail, sizeof(mymail));
+ if ((cuser.numlogins + cuser.numposts) < 20)
+ continue;
+
+ fprintf(fp1,
+ " [%2d/%-2d] %-14s %-24s login:%-5d post:%-5d\n",
+ ptime->tm_mon + 1, ptime->tm_mday, cuser.userid,
+ cuser.username, cuser.numlogins, cuser.numposts);
+ }
+ }
+ }
+ fclose(fp1);
+ return 0;
+}
diff --git a/util/buildAnnounce.c b/util/buildAnnounce.c
new file mode 100644
index 00000000..0e754f22
--- /dev/null
+++ b/util/buildAnnounce.c
@@ -0,0 +1,69 @@
+/* «Ø¥ß©Ò¦³¬ÝªOºëµØ°Ïªº³sµ² */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include "config.h"
+#include "pttstruct.h"
+#define GROUPROOT BBSHOME"/man/group"
+
+extern bcache_t *brdshm;
+extern boardheader_t *bcache;
+extern void resolve_boards();
+
+void buildchilds(int level,char *path,boardheader_t *bptr)
+{
+ char newpath[512];
+ boardheader_t *ptr;
+ fileheader_t item;
+
+ if(bptr->firstchild[1]==(boardheader_t*)~0 || bptr->firstchild[1]==NULL)
+ return;
+ for(ptr =(void*) bptr->firstchild[1];
+ ptr!=(boardheader_t*)~0 ;ptr=ptr->next[1])
+ {
+
+ if(
+ (ptr->brdattr&(BRD_BAD | BRD_GROUPBOARD | BRD_NOCOUNT | BRD_HIDE))!=0
+ ||
+ (ptr->level && !(ptr->brdattr & BRD_POSTMASK))) continue;
+ printf("%*.*s+-%-14s %-s \n",level*2,level*2,"| | | | | | | | |",
+ ptr->brdname, ptr->title);
+ if(ptr->brdattr & BRD_GROUPBOARD)
+ {
+ sprintf(newpath,"%s/%s",path,ptr->brdname);
+ mkdir(newpath,0766);
+ buildchilds(level+1,newpath,ptr);
+ }
+ else
+ {
+ printf("%s4\n",ptr->brdname);
+ sprintf(newpath,"/bin/ln -s "BBSHOME"/man/boards/%s %s/%s",
+ ptr->brdname,path,ptr->brdname);
+ system(newpath);
+ }
+ printf("%s5\n",ptr->brdname);
+ sprintf(newpath,"%s/.DIR",path);
+ strcpy(item.owner,ptr->BM);
+ strtok(item.owner,"/");
+ strcpy(item.title,ptr->title+7);
+ item.savemode = 'D';
+ sprintf(item.filename,ptr->brdname);
+ append_record(newpath, &item, sizeof(item));
+ }
+}
+
+
+int main()
+{
+ char path[512];
+ setsid();
+ strcpy(path,GROUPROOT);
+ system("rm -rf "GROUPROOT);
+ mkdir(GROUPROOT,0766);
+ resolve_boards();
+ buildchilds(0,path,&bcache[0]);
+ return 0;
+}
diff --git a/util/buildAnnounce.sh b/util/buildAnnounce.sh
new file mode 100644
index 00000000..d43f420b
--- /dev/null
+++ b/util/buildAnnounce.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+# $Id: buildAnnounce.sh,v 1.1 2002/03/07 15:13:45 in2 Exp $
+#
+bin/buildAnnounce > etc/ALLBRDLIST
+bin/post Record ¥þ¯¸¬ÝªO¦Cªí [¦Û°Ê¯¸ªø] etc/ALLBRDLIST
diff --git a/util/buildir.c b/util/buildir.c
new file mode 100644
index 00000000..381a657d
--- /dev/null
+++ b/util/buildir.c
@@ -0,0 +1,124 @@
+/* $Id: buildir.c,v 1.1 2002/03/07 15:13:45 in2 Exp $ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <dirent.h>
+#include <fcntl.h>
+#include <time.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "config.h"
+#include "pttstruct.h"
+
+int dirselect(struct dirent *dir) {
+ return strchr("MDSGH", dir->d_name[0]) && dir->d_name[1] == '.';
+}
+
+int mysort(const struct dirent **a,const struct dirent **b)
+{
+ return atoi(((*a)->d_name+2))-atoi(((*b)->d_name+2));
+}
+
+int main(int argc, char **argv) {
+ int k;
+
+ if(argc < 2) {
+ fprintf(stderr, "Usage: %s <path1> [<path2> ...]\n", argv[0]);
+ return 1;
+ }
+
+ for(k = 1; k < argc; k++) {
+ int fdir, count, total;
+ char *ptr, path[MAXPATHLEN];
+ struct dirent **dirlist;
+
+ sprintf(path, "%s/.DIR", argv[k]);
+ if((fdir = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644)) == -1) {
+ perror(path);
+ continue;
+ }
+
+ if((total = scandir(argv[k], &dirlist, dirselect, mysort)) == -1) {
+ fprintf(stderr, "scandir failed!\n");
+ close(fdir);
+ continue;
+ }
+
+ ptr = strrchr(path, '.');
+ for(count = 0; count < total; count++) {
+ FILE *fp;
+ struct stat st;
+
+ strcpy(ptr, dirlist[count]->d_name);
+ if(stat(path, &st) == 0 && st.st_size > 0 &&
+ (fp = fopen(path, "r")) != NULL) {
+ char buf[512];
+ time_t filetime;
+ fileheader_t fhdr;
+
+ memset(&fhdr, 0, sizeof(fhdr));
+ /* set file name */
+ strcpy(fhdr.filename, dirlist[count]->d_name);
+
+ /* set file time */
+ filetime = atoi(dirlist[count]->d_name + 2);
+ if(filetime > 740000000) {
+ struct tm *ptime = localtime(&filetime);
+ sprintf(fhdr.date, "%2d/%02d", ptime->tm_mon + 1,
+ ptime->tm_mday);
+ } else
+ strcpy(fhdr.date, " ");
+
+ /* set file mode */
+ fhdr.filemode = FILE_READ;
+
+ /* set article owner */
+ fgets(buf, sizeof(buf), fp);
+ if(strncmp(buf, "§@ªÌ: ", 6) == 0 ||
+ strncmp(buf, "µo«H¤H: ", 8) == 0) {
+ int i, j;
+
+ for(i = 5; buf[i] != ' '; i++);
+ for(; buf[i] == ' '; i++);
+ for(j = i + 1; buf[j] != ' '; j++);
+ j -= i;
+ if(j > IDLEN + 1)
+ j = IDLEN + 1;
+ strncpy(fhdr.owner, buf + i, j);
+ fhdr.owner[IDLEN + 1] = '\0';
+ strtok(fhdr.owner, " .@\t\n\r");
+ if(strtok(NULL, " .@\t\n\r"))
+ strcat(fhdr.owner, ".");
+
+ /* set article title */
+ while(fgets(buf, sizeof(buf), fp))
+ if(strncmp(buf, "¼ÐÃD: ", 6) == 0 ||
+ strncmp(buf, "¼Ð ÃD: ", 8) == 0) {
+ for(i = 5; buf[i] != ' '; i++);
+ for(; buf[i] == ' '; i++);
+ strtok(buf + i-1, "\n");
+ strncpy(fhdr.title, buf + i, TTLEN);
+ fhdr.title[TTLEN] = '\0';
+ break;
+ }
+ } else if(strncmp(buf, "¡ó Åwªï¥úÁ{", 11) == 0) {
+ strcpy(fhdr.title, "·|ij°O¿ý");
+ } else if(strncmp(buf, "\33[1;33;46m¡¹", 12) == 0||
+ strncmp(buf, "To", 2) == 0) {
+ strcpy(fhdr.title, "¼ö½u°O¿ý");
+ }
+// if(!fhdr.title[0])
+// strcpy(fhdr.title, dirlist[count]->d_name);
+ fclose(fp);
+ write(fdir, &fhdr, sizeof(fhdr));
+ }
+ }
+ close(fdir);
+ for(total--; total >= 0; total--)
+ free(dirlist[total]);
+ free(dirlist);
+ }
+ return 0;
+}
diff --git a/util/countalldice.c b/util/countalldice.c
new file mode 100644
index 00000000..badd4bad
--- /dev/null
+++ b/util/countalldice.c
@@ -0,0 +1,95 @@
+/* $Id: countalldice.c,v 1.1 2002/03/07 15:13:45 in2 Exp $ */
+
+/**********************************************/
+/*³o­Óµ{¦¡¬O¥Î¨Ó­pºâ½ä»ë¤lÁȱo¿ú¸ò½ßªº¿úªºµ{¦¡ */
+/*¥Îªk´N¬Oª½±µ¥´ countalldice ´N¥i¥H°w¹ï©Ò¦³¤H */
+/*¨Ó­pºâ¥LÁ`¦@ÁȤF¦h¤Ö ½ß¤F¦h¤Ö............... */
+/*§@ªÌ:Heat ©ó1997/10/2 */
+/**********************************************/
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include "config.h"
+
+#define DICE_WIN BBSHOME "/etc/windice.log"
+#define DICE_LOST BBSHOME "/etc/lostdice.log"
+
+int total = 0;
+
+typedef struct dice
+{
+ char id[14];
+ int win;
+ int lost;
+}
+dice;
+
+dice table[1024];
+
+int find(char *name)
+{
+ int i = 0;
+ if (total == 0)
+ {
+ total++;
+ return 0;
+ }
+ for (i = 0; i < total; i++)
+ if (!strcmp(name, table[i].id))
+ return i;
+ memset(&table[total++], 0, sizeof(dice));
+ return total - 1;
+}
+
+int main() {
+ int index, win = 0, lost = 0;
+ FILE *fpwin, *fplost;
+ char buf[256], *ptr, buf0[256], *name = (char *) malloc(15), *mon = (char *) malloc(5);
+
+ fpwin = fopen(DICE_WIN, "r");
+ fplost = fopen(DICE_LOST, "r");
+
+ if (!fpwin || !fplost)
+ perror("error open file");
+
+ while (fgets(buf, 255, fpwin))
+ {
+ strcpy(buf0, buf);
+ name = strtok(buf, " ");
+ mon = strstr(buf0, "²bÁÈ:");
+ if ((ptr = strchr(mon, '\n')))
+ *ptr = 0;
+ index = find(name);
+ strcpy(table[index].id, name);
+ table[index].win += atoi(mon + 5);
+ }
+ fclose(fpwin);
+
+ while (fgets(buf, 255, fplost))
+ {
+ strcpy(buf0, buf);
+ name = strtok(buf, " ");
+ mon = strstr(buf0, "¿é¤F ");
+ if ((ptr = strchr(mon, '\n')))
+ *ptr = 0;
+ if ((index = find(name)) == total - 1)
+ strcpy(table[index].id, name);
+ table[index].lost += atoi(mon + 5);
+ }
+
+ for (index = 0; index < total; index++)
+ {
+ printf("%-15s ŤF %-8d ¶ô¿ú¡A ¿é±¼ %-8d ¶ô¿ú\n", table[index].id
+ ,table[index].win, table[index].lost);
+ win += table[index].win;
+ lost += table[index].lost;
+ }
+ index = win + lost;
+ printf("\n¤H¼Æ: %d\nÁ`Ĺ¿ú=%d Á`¿é¿ú=%d Á`ª÷ÃB:%d\n", total, win, lost, index);
+ printf("Ĺªº¤ñ¨Ò:%f ¿éªº¤ñ¨Ò:%f\n", (float) win / index, (float) lost / index);
+ printf("\n³Æµù¡G¿éŬO¥H¨Ï¥ÎªÌªºÆ[ÂI¨Ó¬Ý\n");
+ fclose(fplost);
+ return 0;
+}
diff --git a/util/cpdeadbrd.c b/util/cpdeadbrd.c
new file mode 100644
index 00000000..12c5827e
--- /dev/null
+++ b/util/cpdeadbrd.c
@@ -0,0 +1,41 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include "config.h"
+#include "pttstruct.h"
+#include "util.h"
+
+extern int numboards;
+extern boardheader_t *bcache;
+int main(int argc, char* argv[]){
+struct stat st;
+boardheader_t *bptr;
+ int n;
+ char pathname[1024];
+
+ resolve_boards();
+ for (n=numboards-1;n>0;n--)
+ {
+
+ bptr = &bcache[n];
+ if(!strcmp(bptr->brdname,"ck53rd316"))continue;
+ sprintf(pathname,"/home/bbs/boards/%s/.DIR",bptr->brdname);
+ if(stat(pathname, &st) == -1)
+ {
+ printf("%s is dead\n",pathname);
+ sprintf (pathname,"cp -R /mnt/bbs/boards/%s /home/bbs/boards/%s",bptr->brdname,bptr->brdname);
+ }
+ }
+}
+
+
+
+
+
+
+
diff --git a/util/dailybackup.pl b/util/dailybackup.pl
new file mode 100644
index 00000000..76943887
--- /dev/null
+++ b/util/dailybackup.pl
@@ -0,0 +1,48 @@
+#!/usr/bin/perl
+use lib '/home/bbs/bin/';
+use LocalVars;
+use strict;
+use vars qw/$BACKHOME $MANROOT $HOMEROOT $BOARDROOT/;
+
+$BACKHOME = "$BBSHOME/backup";
+$MANROOT = "man/boards";
+$HOMEROOT = "home";
+$BOARDROOT= "boards";
+
+chdir $BBSHOME;
+my @baktable = (['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'],
+ ['I', 'J', 'K', 'L', 'M', 'N', 'O', 'P'],
+ ['Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X'],
+ ['Y', 'Z', 'a', 'b', 'c', 'd', 'e'],
+ ['f', 'g', 'h', 'i', 'j', 'k', 'l'],
+ ['m', 'n', 'o', 'p', 'q', 'r', 's'],
+ ['t', 'u', 'v', 'w', 'x', 'y', 'z']);
+my (undef,undef,undef,undef,undef,undef,$wday) = localtime(time);
+my $week = defined($ARGV[0]) ? $ARGV[0] : $wday;
+
+no strict 'subs';
+setpriority(PRIO_PROCESS, $$, 20);
+use strict subs;
+
+my($orig, $to);
+foreach $orig ( <$BACKHOME/*new*> ){
+ $to = $orig;
+ $to =~ s/\.new//g;
+ docmd("mv $orig $to");
+}
+
+foreach( @{$baktable[$week]} ){
+ docmd("$TAR zcf $BACKHOME/man.$_.new.tgz $MANROOT/$_*");
+ docmd("$TAR zcf $BACKHOME/home.$_.new.tgz $HOMEROOT/$_/*");
+ docmd("$TAR zcf $BACKHOME/board.$_.new.tgz $BOARDROOT/$_*");
+}
+
+if( $week == 0 ){
+ docmd("$TAR zcf $BACKHOME/general.new.tgz .act .crontab .note .polling .post bin cron etc innd note.ans note.dat out out.going pttbbs pttbbs.conf upgrade.sh usies ussong");
+}
+
+sub docmd
+{
+ print "@_\n";
+ `@_`;
+}
diff --git a/util/daymandex.c b/util/daymandex.c
new file mode 100644
index 00000000..d2921d07
--- /dev/null
+++ b/util/daymandex.c
@@ -0,0 +1,269 @@
+/* $Id: daymandex.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */
+
+/*
+ target : ºëµØ°Ï¯Á¤Þµ{¦¡ (man index)
+
+ syntax : mandex [board]
+ [board] ¦³­È ==> ¥u¶]¸Ó board
+ ªÅªº ==> ©Ò¦³ªº boards ³£¶]
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "config.h"
+#include "pttstruct.h"
+#include "util.h"
+
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 1024
+#endif
+
+extern int numboards;
+extern boardheader_t *bcache;
+
+char color[4][10] =
+{"", "", "", ""};
+char fn_index[] = ".index";
+char fn_new[] = ".index.new";
+char index_title[] = "¡· ºëµØ°Ï¥Ø¿ý¯Á¤Þ";
+FILE *fndx;
+int ndir;
+int nfile;
+int index_pos;
+char topdir[128], pgem[512], pndx[512];
+
+int nb = 0; /* board ¼Æ */
+
+struct boardinfo
+{
+ char bname[40];
+ int ndir;
+ int nfile;
+ int k;
+};
+typedef struct boardinfo boardinfo;
+
+boardinfo
+board[MAX_BOARD];
+
+int k_cmp(b, a)
+ boardinfo *b, *a;
+{
+ return ((a->k / 100 + a->ndir + a->nfile) - (b->k / 100 + b->ndir + b->nfile));
+}
+
+int dashd(fname)
+ char *fname;
+{
+ struct stat st;
+
+ return (stat(fname, &st) == 0 && S_ISDIR(st.st_mode));
+}
+
+
+/* visit the hierarchy recursively */
+
+void
+mandex(level, num_header, fpath)
+ int level;
+ char *fpath, *num_header;
+{
+ FILE *fgem;
+ char *fname, buf[256];
+ struct stat st;
+ int count;
+ fileheader_t fhdr;
+
+ fgem = fopen(fpath, "r+");
+ if (fgem == NULL)
+ return;
+
+ fname = strrchr(fpath, '.');
+ if (!level)
+ {
+
+ printf("%s\r\n",fpath);
+ strcpy(pgem, fpath);
+
+ strcpy(fname, fn_new);
+ fndx = fopen(fpath, "w");
+ if (fndx == NULL)
+ {
+ fclose(fgem);
+ return;
+ }
+ fprintf(fndx, "§Ç¸¹\t\t\tºëµØ°Ï¥DÃD\n"
+ "¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w\n");
+ strcpy(pndx, fpath);
+ ndir = nfile = 0;
+ index_pos = -1;
+ }
+
+ count = 0;
+ while (fread(&fhdr, sizeof(fhdr), 1, fgem) == 1)
+ {
+ strcpy(fname, fhdr.filename);
+ if (!fname[0]) continue;
+ if (!level && !strncmp(fhdr.title, index_title, strlen(index_title))
+ && index_pos < 0)
+ {
+ index_pos = count;
+ unlink(fpath);
+ }
+ st.st_size = 0;
+ stat(fpath, &st);
+
+ sprintf(buf, "%.*s%s%3d. %s \n",
+
+ 11 * level, num_header, color[level % 4], ++count, fhdr.title); /* Ptt */
+ fputs(buf, fndx);
+ if (dashd(fpath))
+ {
+ ++ndir;
+ if (*fhdr.title != '#' && level < 10)
+ {
+ strcat(fpath, "/.DIR");
+ mandex(level + 1, buf, fpath);
+ }
+ }
+ else
+ ++nfile;
+ }
+
+ if (!level)
+ {
+ char lpath[MAXPATHLEN];
+
+ fclose(fndx);
+ strcpy(fname, fn_index);
+ rename(pndx, fpath);
+ strcpy(pndx, fpath);
+
+ sprintf(buf, "%s.new", pgem);
+ if (index_pos >= 0 || (fndx = fopen(buf, "w")))
+ {
+ fname[-1] = 0;
+ stamplink(fpath, &fhdr);
+ unlink(fpath);
+ strcpy(fhdr.owner, "¨C¤Ñ¦Û°Ê§ó·s");
+ sprintf(lpath, "%s/%s", topdir, pndx);
+ st.st_size = 0;
+ stat(lpath, &st);
+ sprintf(fhdr.title, "%s (%.1fk)", index_title, st.st_size / 1024.);
+ board[nb].k = st.st_size; /* Ptt */
+ printf("(%d)[%dK]", nb, board[nb].k);
+ symlink(lpath, fpath);
+ if (index_pos < 0)
+ {
+ fwrite(&fhdr, sizeof(fhdr), 1, fndx);
+ rewind(fgem);
+ while (fread(&fhdr, sizeof(fhdr), 1, fgem) == 1)
+ fwrite(&fhdr, sizeof(fhdr), 1, fndx);
+ fclose(fndx);
+ fclose(fgem);
+ rename(buf, pgem);
+ }
+ else
+ {
+ fseek(fgem, index_pos * sizeof(fhdr), 0);
+ fwrite(&fhdr, sizeof(fhdr), 1, fgem);
+ fclose(fgem);
+ }
+ return;
+ }
+ }
+ fclose(fgem);
+}
+
+
+int main(int argc, char* argv[]){
+ boardheader_t *bptr;
+ DIR *dirp;
+ struct dirent *de;
+ int ch, n;
+ int place = 0;
+ char *fname, fpath[MAXPATHLEN];
+
+ resolve_boards();
+ nb = 0;
+ if(argc == 1){
+ puts("Creating the whole index...");
+ chdir(strcpy(topdir, BBSHOME));
+ strcpy(fpath, "man/.DIR");
+ mandex(0, "", fpath);
+ }
+
+
+ chdir(strcpy(topdir, BBSHOME "/man/boards"));
+
+ if(argc > 1) {
+ sprintf(fpath, "%s/.DIR", argv[1]);
+ mandex(0, "", fpath);
+ exit(0);
+ }
+
+ /* process all boards */
+
+ if(!(dirp = opendir(topdir))) {
+ printf("## unable to enter [man/boards]\n");
+ exit(-1);
+ }
+
+ while((de = readdir(dirp))){
+ fname = de->d_name;
+ ch = fname[0];
+ if (ch != '.'){
+ board[nb].k = 0;
+ strcpy(board[nb].bname, fname);
+ sprintf(fpath, "%s/.rebuild", fname);
+ if( access(fpath, 0) >= 0 ){
+ unlink(fpath);
+
+ sprintf(fpath, "%s/.DIR", fname);
+ mandex(0, "", fpath);
+ printf("%-14sd: %d\tf: %d\n", fname, ndir, nfile);
+ /* report */
+ board[nb].ndir = ndir;
+ board[nb].nfile = nfile;
+ if (board[nb].k)
+ nb++;
+ }
+ }
+ }
+ closedir(dirp);
+
+ qsort(board, nb, sizeof(boardinfo), k_cmp);
+
+ if (!(fndx = fopen(BBSHOME "/etc/topboardman", "w")))
+ exit(0);
+
+ fprintf(fndx, "±Æ¦W ¬Ý ª© ¥Ø¿ý¼Æ ÀÉ®×¼Æ"
+ " byte¼Æ  Á` ¤À ª© ¥D \n");
+
+ for (ch = 0; ch < nb; ch++){
+ for (n = 0; n < numboards; n++){
+ bptr = &bcache[n];
+ if (!strcmp(bptr->brdname, board[ch].bname))
+ break;
+ }
+ if (n >= numboards ||
+ (bptr->brdattr & (BRD_BAD | BRD_NOCOUNT | BRD_HIDE)))
+ continue;
+ if (board[ch].ndir + board[ch].nfile < 5)
+ break;
+ fprintf(fndx, "%3d.%15s %5d %7d %10d %6d %-24.24s\n",
+ ++place,
+ board[ch].bname,
+ board[ch].ndir, board[ch].nfile, board[ch].k
+ ,board[ch].k / 100 + board[ch].nfile + board[ch].ndir
+ ,bptr->BM);
+ }
+ fclose(fndx);
+ exit(0);
+}
diff --git a/util/deluserfile.c b/util/deluserfile.c
new file mode 100644
index 00000000..63cfefba
--- /dev/null
+++ b/util/deluserfile.c
@@ -0,0 +1,147 @@
+/* $Id: deluserfile.c,v 1.1 2002/03/07 15:13:45 in2 Exp $ */
+/* ¦Û°Ê¬åuser¥Ø¿ýÀÉ®×µ{¦¡ */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include "config.h"
+#include "pttstruct.h"
+#include "util.h"
+
+#define HOLDWRITELOG
+#define DELZEROFILE
+#define USERHOME BBSHOME "/home"
+
+int bad_user_id(char *userid)
+{
+ register char ch;
+
+ if (strlen(userid) < 2)
+ return 1;
+
+ if (!isalpha(*userid))
+ return 1;
+
+ if (!strcasecmp(userid, "new"))
+ return 1;
+
+ while ((ch = *(++userid)))
+ if (!isalnum(ch))
+ return 1;
+ return 0;
+}
+
+void del_file(char *userid)
+{
+ char buf[200], buf1[200];
+ struct dirent *de;
+ DIR *dirp;
+ char *ptr;
+
+ sprintf(buf, BBSHOME "/home/%c/%s", userid[0], userid);
+
+ if (chdir(buf) == -1)
+ return;
+
+ if (!(dirp = opendir(buf)))
+ return;
+
+ while ((de = readdir(dirp)))
+ {
+ ptr = de->d_name;
+ if (ptr[0] > ' ' && ptr[0] != '.')
+ {
+ if (strstr(ptr, "writelog"))
+#ifdef HOLDWRITELOG
+ {
+ fileheader_t mymail;
+
+ stampfile(buf, &mymail);
+ mymail.savemode = 'H'; /* hold-mail flag */
+ mymail.filemode = FILE_READ;
+ strcpy(mymail.owner, userid);
+ strcpy(mymail.title, "¼ö½u°O¿ý");
+ sprintf(buf1, BBSHOME "/home/%c/%s/writelog",
+ userid[0], userid);
+ rename(buf1, buf);
+ sprintf(buf1, BBSHOME "/home/%c/%s/.DIR", userid[0], userid);
+ append_record(buf1, &mymail, sizeof(mymail));
+ }
+#else
+ unlink(ptr);
+#endif
+ else if (strstr(ptr, "chat_"))
+ unlink(ptr);
+ else if (strstr(ptr, "ve_"))
+ unlink(ptr);
+ else if (strstr(ptr, "SR."))
+ unlink(ptr);
+ else if (strstr(ptr, ".old"))
+ unlink(ptr);
+ else if (strstr(ptr, "talk_"))
+ unlink(ptr);
+ }
+ }
+ closedir(dirp);
+}
+
+void mv_user_home(char *ptr)
+{
+ char buf[200];
+
+ printf("move user %s to tmp\n", ptr);
+ sprintf(buf, "cp -R " BBSHOME "/home/%c/%s " BBSHOME "/tmp", ptr[0], ptr);
+// sprintf(buf,"rm -rf " BBSHOME "/home/%c/%s",ptr[0],ptr);
+ if (!system(buf))
+ { //Copy success
+
+ sprintf(buf, "rm -rf " BBSHOME "/home/%c/%s", ptr[0], ptr);
+ system(buf);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ struct dirent *de;
+ DIR *dirp;
+ char *ptr, buf[200], ch;
+ int count = 0;
+/* visit all users */
+
+ printf("new version, deleting\n");
+
+ for (ch = 'A'; ch <= 'z'; ch++)
+ {
+ if(ch > 'Z' && ch < 'a')
+ continue;
+ printf("Cleaning %c\n", ch);
+ sprintf(buf, USERHOME "/%c", ch);
+ if (!(dirp = opendir(buf)))
+ {
+ printf("unable to open %s\n", buf);
+ continue;
+ }
+
+ while ((de = readdir(dirp)))
+ {
+ ptr = de->d_name;
+
+ /* ¹w¨¾¿ù»~ */
+ if (!bad_user_id(ptr))
+ {
+ if (!(count++ % 300))
+ printf(".\n");
+ if (!searchuser(ptr))
+ mv_user_home(ptr);
+ else
+ del_file(ptr);
+ }
+ }
+ closedir(dirp);
+ }
+ return 0;
+}
diff --git a/util/descrypt.c b/util/descrypt.c
new file mode 100644
index 00000000..97475c1a
--- /dev/null
+++ b/util/descrypt.c
@@ -0,0 +1,616 @@
+/* $Id: descrypt.c,v 1.1 2002/03/07 15:13:45 in2 Exp $ */
+
+/*
+ * FreeSec: libcrypt for NetBSD
+ *
+ * Copyright (c) 1994 David Burren
+ * All rights reserved.
+ *
+ * Adapted for FreeBSD-2.0 by Geoffrey M. Rehmet
+ * crypt.c should now *only* export crypt(), in order to make
+ * binaries of libcrypt exportable from the USA
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the author nor the names of other contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD: src/secure/lib/libcrypt/crypt.c,v 1.11 1999/08/28 01:30:24 peter Exp $
+ *
+ * This is an original implementation of the DES and the crypt(3) interfaces
+ * by David Burren <davidb@werj.com.au>.
+ *
+ * An excellent reference on the underlying algorithm (and related
+ * algorithms) is:
+ *
+ * B. Schneier, Applied Cryptography: protocols, algorithms,
+ * and source code in C, John Wiley & Sons, 1994.
+ *
+ * Note that in that book's description of DES the lookups for the initial,
+ * pbox, and final permutations are inverted (this has been brought to the
+ * attention of the author). A list of errata for this book has been
+ * posted to the sci.crypt newsgroup by the author and is available for FTP.
+ *
+ * ARCHITECTURE ASSUMPTIONS:
+ * This code assumes that u_longs are 32 bits. It will probably not
+ * operate on 64-bit machines without modifications.
+ * It is assumed that the 8-byte arrays passed by reference can be
+ * addressed as arrays of u_longs (ie. the CPU is not picky about
+ * alignment).
+ */
+
+#ifndef HAVE_DES_CRYPT
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <pwd.h>
+#include <string.h>
+
+static unsigned char IP[64] = {
+ 58, 50, 42, 34, 26, 18, 10, 2, 60, 52, 44, 36, 28, 20, 12, 4,
+ 62, 54, 46, 38, 30, 22, 14, 6, 64, 56, 48, 40, 32, 24, 16, 8,
+ 57, 49, 41, 33, 25, 17, 9, 1, 59, 51, 43, 35, 27, 19, 11, 3,
+ 61, 53, 45, 37, 29, 21, 13, 5, 63, 55, 47, 39, 31, 23, 15, 7
+};
+
+static unsigned char inv_key_perm[64];
+static unsigned char u_key_perm[56];
+static unsigned char key_perm[56] = {
+ 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18,
+ 10, 2, 59, 51, 43, 35, 27, 19, 11, 3, 60, 52, 44, 36,
+ 63, 55, 47, 39, 31, 23, 15, 7, 62, 54, 46, 38, 30, 22,
+ 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 28, 20, 12, 4
+};
+
+static unsigned char key_shifts[16] = {
+ 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
+};
+
+static unsigned char inv_comp_perm[56];
+static unsigned char comp_perm[48] = {
+ 14, 17, 11, 24, 1, 5, 3, 28, 15, 6, 21, 10,
+ 23, 19, 12, 4, 26, 8, 16, 7, 27, 20, 13, 2,
+ 41, 52, 31, 37, 47, 55, 30, 40, 51, 45, 33, 48,
+ 44, 49, 39, 56, 34, 53, 46, 42, 50, 36, 29, 32
+};
+
+/*
+ * No E box is used, as it's replaced by some ANDs, shifts, and ORs.
+ */
+
+static unsigned char u_sbox[8][64];
+static unsigned char sbox[8][64] = {
+ {
+ 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
+ 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
+ 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
+ 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13
+ },
+ {
+ 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
+ 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
+ 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
+ 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9
+ },
+ {
+ 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
+ 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
+ 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
+ 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12
+ },
+ {
+ 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
+ 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
+ 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
+ 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14
+ },
+ {
+ 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
+ 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
+ 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
+ 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3
+ },
+ {
+ 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
+ 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
+ 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
+ 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13
+ },
+ {
+ 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
+ 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
+ 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
+ 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12
+ },
+ {
+ 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
+ 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
+ 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
+ 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
+ }
+};
+
+static unsigned char un_pbox[32];
+static unsigned char pbox[32] = {
+ 16, 7, 20, 21, 29, 12, 28, 17, 1, 15, 23, 26, 5, 18, 31, 10,
+ 2, 8, 24, 14, 32, 27, 3, 9, 19, 13, 30, 6, 22, 11, 4, 25
+};
+
+static unsigned long bits32[32] = {
+ 0x80000000, 0x40000000, 0x20000000, 0x10000000,
+ 0x08000000, 0x04000000, 0x02000000, 0x01000000,
+ 0x00800000, 0x00400000, 0x00200000, 0x00100000,
+ 0x00080000, 0x00040000, 0x00020000, 0x00010000,
+ 0x00008000, 0x00004000, 0x00002000, 0x00001000,
+ 0x00000800, 0x00000400, 0x00000200, 0x00000100,
+ 0x00000080, 0x00000040, 0x00000020, 0x00000010,
+ 0x00000008, 0x00000004, 0x00000002, 0x00000001
+};
+
+static unsigned char bits8[8] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
+
+static unsigned long saltbits;
+static long old_salt;
+static unsigned long *bits28, *bits24;
+static unsigned char init_perm[64], final_perm[64];
+static unsigned long en_keysl[16], en_keysr[16];
+static unsigned long de_keysl[16], de_keysr[16];
+static int des_initialised = 0;
+static unsigned char m_sbox[4][4096];
+static unsigned long psbox[4][256];
+static unsigned long ip_maskl[8][256], ip_maskr[8][256];
+static unsigned long fp_maskl[8][256], fp_maskr[8][256];
+static unsigned long key_perm_maskl[8][128], key_perm_maskr[8][128];
+static unsigned long comp_maskl[8][128], comp_maskr[8][128];
+static unsigned long old_rawkey0, old_rawkey1;
+
+static unsigned char ascii64[] =
+"./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+/* 0000000000111111111122222222223333333333444444444455555555556666 */
+/* 0123456789012345678901234567890123456789012345678901234567890123 */
+
+static int ascii_to_bin(char ch) {
+ if(ch > 'z')
+ return 0;
+ if(ch >= 'a')
+ return ch - 'a' + 38;
+ if(ch > 'Z')
+ return 0;
+ if(ch >= 'A')
+ return ch - 'A' + 12;
+ if(ch > '9')
+ return 0;
+ if(ch >= '.')
+ return ch - '.';
+ return 0;
+}
+
+static void des_init() {
+ int i, j, b, k, inbit, obit;
+ unsigned long *p, *il, *ir, *fl, *fr;
+
+ old_rawkey0 = old_rawkey1 = 0L;
+ saltbits = 0L;
+ old_salt = 0L;
+ bits24 = (bits28 = bits32 + 4) + 4;
+
+ /*
+ * Invert the S-boxes, reordering the input bits.
+ */
+ for(i = 0; i < 8; i++)
+ for(j = 0; j < 64; j++) {
+ b = (j & 0x20) | ((j & 1) << 4) | ((j >> 1) & 0xf);
+ u_sbox[i][j] = sbox[i][b];
+ }
+
+ /*
+ * Convert the inverted S-boxes into 4 arrays of 8 bits.
+ * Each will handle 12 bits of the S-box input.
+ */
+ for(b = 0; b < 4; b++)
+ for(i = 0; i < 64; i++)
+ for(j = 0; j < 64; j++)
+ m_sbox[b][(i << 6) | j] =
+ (u_sbox[(b << 1)][i] << 4) |
+ u_sbox[(b << 1) + 1][j];
+
+ /*
+ * Set up the initial & final permutations into a useful form, and
+ * initialise the inverted key permutation.
+ */
+ for(i = 0; i < 64; i++) {
+ init_perm[final_perm[i] = IP[i] - 1] = i;
+ inv_key_perm[i] = 255;
+ }
+
+ /*
+ * Invert the key permutation and initialise the inverted key
+ * compression permutation.
+ */
+ for(i = 0; i < 56; i++) {
+ u_key_perm[i] = key_perm[i] - 1;
+ inv_key_perm[key_perm[i] - 1] = i;
+ inv_comp_perm[i] = 255;
+ }
+
+ /*
+ * Invert the key compression permutation.
+ */
+ for(i = 0; i < 48; i++) {
+ inv_comp_perm[comp_perm[i] - 1] = i;
+ }
+
+ /*
+ * Set up the OR-mask arrays for the initial and final permutations,
+ * and for the key initial and compression permutations.
+ */
+ for(k = 0; k < 8; k++) {
+ for(i = 0; i < 256; i++) {
+ *(il = &ip_maskl[k][i]) = 0L;
+ *(ir = &ip_maskr[k][i]) = 0L;
+ *(fl = &fp_maskl[k][i]) = 0L;
+ *(fr = &fp_maskr[k][i]) = 0L;
+ for(j = 0; j < 8; j++) {
+ inbit = 8 * k + j;
+ if(i & bits8[j]) {
+ if((obit = init_perm[inbit]) < 32)
+ *il |= bits32[obit];
+ else
+ *ir |= bits32[obit-32];
+ if ((obit = final_perm[inbit]) < 32)
+ *fl |= bits32[obit];
+ else
+ *fr |= bits32[obit - 32];
+ }
+ }
+ }
+ for(i = 0; i < 128; i++) {
+ *(il = &key_perm_maskl[k][i]) = 0L;
+ *(ir = &key_perm_maskr[k][i]) = 0L;
+ for(j = 0; j < 7; j++) {
+ inbit = 8 * k + j;
+ if(i & bits8[j + 1]) {
+ if((obit = inv_key_perm[inbit]) == 255)
+ continue;
+ if(obit < 28)
+ *il |= bits28[obit];
+ else
+ *ir |= bits28[obit - 28];
+ }
+ }
+ *(il = &comp_maskl[k][i]) = 0L;
+ *(ir = &comp_maskr[k][i]) = 0L;
+ for(j = 0; j < 7; j++) {
+ inbit = 7 * k + j;
+ if(i & bits8[j + 1]) {
+ if((obit=inv_comp_perm[inbit]) == 255)
+ continue;
+ if(obit < 24)
+ *il |= bits24[obit];
+ else
+ *ir |= bits24[obit - 24];
+ }
+ }
+ }
+ }
+
+ /*
+ * Invert the P-box permutation, and convert into OR-masks for
+ * handling the output of the S-box arrays setup above.
+ */
+ for(i = 0; i < 32; i++)
+ un_pbox[pbox[i] - 1] = i;
+
+ for(b = 0; b < 4; b++)
+ for(i = 0; i < 256; i++) {
+ *(p = &psbox[b][i]) = 0L;
+ for (j = 0; j < 8; j++) {
+ if (i & bits8[j])
+ *p |= bits32[un_pbox[8 * b + j]];
+ }
+ }
+
+ des_initialised = 1;
+}
+
+static void setup_salt(long salt) {
+ unsigned long obit, saltbit;
+ int i;
+
+ if (salt == old_salt)
+ return;
+ old_salt = salt;
+
+ saltbits = 0L;
+ saltbit = 1;
+ obit = 0x800000;
+ for (i = 0; i < 24; i++) {
+ if (salt & saltbit)
+ saltbits |= obit;
+ saltbit <<= 1;
+ obit >>= 1;
+ }
+}
+
+static int des_setkey(const char *key) {
+ unsigned long k0, k1, rawkey0, rawkey1;
+ int shifts, round;
+
+ if(!des_initialised)
+ des_init();
+
+ rawkey0 = ntohl(*(unsigned long *) key);
+ rawkey1 = ntohl(*(unsigned long *) (key + 4));
+
+ if((rawkey0 | rawkey1)
+ && rawkey0 == old_rawkey0
+ && rawkey1 == old_rawkey1) {
+ /*
+ * Already setup for this key.
+ * This optimisation fails on a zero key (which is weak and
+ * has bad parity anyway) in order to simplify the starting
+ * conditions.
+ */
+ return 0;
+ }
+ old_rawkey0 = rawkey0;
+ old_rawkey1 = rawkey1;
+
+ /*
+ * Do key permutation and split into two 28-bit subkeys.
+ */
+ k0 = key_perm_maskl[0][rawkey0 >> 25]
+ | key_perm_maskl[1][(rawkey0 >> 17) & 0x7f]
+ | key_perm_maskl[2][(rawkey0 >> 9) & 0x7f]
+ | key_perm_maskl[3][(rawkey0 >> 1) & 0x7f]
+ | key_perm_maskl[4][rawkey1 >> 25]
+ | key_perm_maskl[5][(rawkey1 >> 17) & 0x7f]
+ | key_perm_maskl[6][(rawkey1 >> 9) & 0x7f]
+ | key_perm_maskl[7][(rawkey1 >> 1) & 0x7f];
+ k1 = key_perm_maskr[0][rawkey0 >> 25]
+ | key_perm_maskr[1][(rawkey0 >> 17) & 0x7f]
+ | key_perm_maskr[2][(rawkey0 >> 9) & 0x7f]
+ | key_perm_maskr[3][(rawkey0 >> 1) & 0x7f]
+ | key_perm_maskr[4][rawkey1 >> 25]
+ | key_perm_maskr[5][(rawkey1 >> 17) & 0x7f]
+ | key_perm_maskr[6][(rawkey1 >> 9) & 0x7f]
+ | key_perm_maskr[7][(rawkey1 >> 1) & 0x7f];
+ /*
+ * Rotate subkeys and do compression permutation.
+ */
+ shifts = 0;
+ for(round = 0; round < 16; round++) {
+ unsigned long t0, t1;
+
+ shifts += key_shifts[round];
+
+ t0 = (k0 << shifts) | (k0 >> (28 - shifts));
+ t1 = (k1 << shifts) | (k1 >> (28 - shifts));
+
+ de_keysl[15 - round] =
+ en_keysl[round] = comp_maskl[0][(t0 >> 21) & 0x7f]
+ | comp_maskl[1][(t0 >> 14) & 0x7f]
+ | comp_maskl[2][(t0 >> 7) & 0x7f]
+ | comp_maskl[3][t0 & 0x7f]
+ | comp_maskl[4][(t1 >> 21) & 0x7f]
+ | comp_maskl[5][(t1 >> 14) & 0x7f]
+ | comp_maskl[6][(t1 >> 7) & 0x7f]
+ | comp_maskl[7][t1 & 0x7f];
+
+ de_keysr[15 - round] = en_keysr[round] =
+ comp_maskr[0][(t0 >> 21) & 0x7f]
+ | comp_maskr[1][(t0 >> 14) & 0x7f]
+ | comp_maskr[2][(t0 >> 7) & 0x7f]
+ | comp_maskr[3][t0 & 0x7f]
+ | comp_maskr[4][(t1 >> 21) & 0x7f]
+ | comp_maskr[5][(t1 >> 14) & 0x7f]
+ | comp_maskr[6][(t1 >> 7) & 0x7f]
+ | comp_maskr[7][t1 & 0x7f];
+ }
+ return 0;
+}
+
+static int do_des(unsigned long l_in, unsigned long r_in, unsigned long *l_out,
+ unsigned long *r_out, int count) {
+ /*
+ * l_in, r_in, l_out, and r_out are in pseudo-"big-endian" format.
+ */
+ unsigned long l, r, *kl, *kr, *kl1, *kr1;
+ unsigned long f, r48l, r48r;
+ int round;
+
+ if(count == 0) {
+ return 1;
+ } else if(count > 0) {
+ /*
+ * Encrypting
+ */
+ kl1 = en_keysl;
+ kr1 = en_keysr;
+ } else {
+ /*
+ * Decrypting
+ */
+ count = -count;
+ kl1 = de_keysl;
+ kr1 = de_keysr;
+ }
+
+ /*
+ * Do initial permutation (IP).
+ */
+ l = ip_maskl[0][l_in >> 24]
+ | ip_maskl[1][(l_in >> 16) & 0xff]
+ | ip_maskl[2][(l_in >> 8) & 0xff]
+ | ip_maskl[3][l_in & 0xff]
+ | ip_maskl[4][r_in >> 24]
+ | ip_maskl[5][(r_in >> 16) & 0xff]
+ | ip_maskl[6][(r_in >> 8) & 0xff]
+ | ip_maskl[7][r_in & 0xff];
+ r = ip_maskr[0][l_in >> 24]
+ | ip_maskr[1][(l_in >> 16) & 0xff]
+ | ip_maskr[2][(l_in >> 8) & 0xff]
+ | ip_maskr[3][l_in & 0xff]
+ | ip_maskr[4][r_in >> 24]
+ | ip_maskr[5][(r_in >> 16) & 0xff]
+ | ip_maskr[6][(r_in >> 8) & 0xff]
+ | ip_maskr[7][r_in & 0xff];
+
+ while(count--) {
+ /*
+ * Do each round.
+ */
+ kl = kl1;
+ kr = kr1;
+ round = 16;
+ while(round--) {
+ /*
+ * Expand R to 48 bits (simulate the E-box).
+ */
+ r48l = ((r & 0x00000001) << 23)
+ | ((r & 0xf8000000) >> 9)
+ | ((r & 0x1f800000) >> 11)
+ | ((r & 0x01f80000) >> 13)
+ | ((r & 0x001f8000) >> 15);
+
+ r48r = ((r & 0x0001f800) << 7)
+ | ((r & 0x00001f80) << 5)
+ | ((r & 0x000001f8) << 3)
+ | ((r & 0x0000001f) << 1)
+ | ((r & 0x80000000) >> 31);
+ /*
+ * Do salting for crypt() and friends, and
+ * XOR with the permuted key.
+ */
+ f = (r48l ^ r48r) & saltbits;
+ r48l ^= f ^ *kl++;
+ r48r ^= f ^ *kr++;
+ /*
+ * Do sbox lookups (which shrink it back to 32 bits)
+ * and do the pbox permutation at the same time.
+ */
+ f = psbox[0][m_sbox[0][r48l >> 12]]
+ | psbox[1][m_sbox[1][r48l & 0xfff]]
+ | psbox[2][m_sbox[2][r48r >> 12]]
+ | psbox[3][m_sbox[3][r48r & 0xfff]];
+ /*
+ * Now that we've permuted things, complete f().
+ */
+ f ^= l;
+ l = r;
+ r = f;
+ }
+ r = l;
+ l = f;
+ }
+ /*
+ * Do final permutation (inverse of IP).
+ */
+ *l_out = fp_maskl[0][l >> 24]
+ | fp_maskl[1][(l >> 16) & 0xff]
+ | fp_maskl[2][(l >> 8) & 0xff]
+ | fp_maskl[3][l & 0xff]
+ | fp_maskl[4][r >> 24]
+ | fp_maskl[5][(r >> 16) & 0xff]
+ | fp_maskl[6][(r >> 8) & 0xff]
+ | fp_maskl[7][r & 0xff];
+ *r_out = fp_maskr[0][l >> 24]
+ | fp_maskr[1][(l >> 16) & 0xff]
+ | fp_maskr[2][(l >> 8) & 0xff]
+ | fp_maskr[3][l & 0xff]
+ | fp_maskr[4][r >> 24]
+ | fp_maskr[5][(r >> 16) & 0xff]
+ | fp_maskr[6][(r >> 8) & 0xff]
+ | fp_maskr[7][r & 0xff];
+ return 0;
+}
+
+char *crypt(char *key, char *setting) {
+ unsigned long count, salt, l, r0, r1, keybuf[2];
+ unsigned char *p, *q;
+ static unsigned char output[21];
+
+ if(!des_initialised)
+ des_init();
+ /*
+ * Copy the key, shifting each character up by one bit
+ * and padding with zeros.
+ */
+ q = (unsigned char *)keybuf;
+ while(q - (unsigned char *)keybuf - 8) {
+ if((*q++ = *key << 1))
+ key++;
+ }
+ if(des_setkey((unsigned char *)keybuf))
+ return NULL;
+
+ /*
+ * "old"-style:
+ * setting - 2 bytes of salt
+ * key - up to 8 characters
+ */
+ count = 25;
+
+ salt = (ascii_to_bin(setting[1]) << 6)
+ | ascii_to_bin(setting[0]);
+
+ output[0] = setting[0];
+ /*
+ * If the encrypted password that the salt was extracted from
+ * is only 1 character long, the salt will be corrupted. We
+ * need to ensure that the output string doesn't have an extra
+ * NUL in it!
+ */
+ output[1] = setting[1] ? setting[1] : output[0];
+
+ p = output + 2;
+
+ setup_salt(salt);
+ /*
+ * Do it.
+ */
+ if(do_des(0L, 0L, &r0, &r1, count))
+ return NULL;
+ /*
+ * Now encode the result...
+ */
+ l = (r0 >> 8);
+ *p++ = ascii64[(l >> 18) & 0x3f];
+ *p++ = ascii64[(l >> 12) & 0x3f];
+ *p++ = ascii64[(l >> 6) & 0x3f];
+ *p++ = ascii64[l & 0x3f];
+
+ l = (r0 << 16) | ((r1 >> 16) & 0xffff);
+ *p++ = ascii64[(l >> 18) & 0x3f];
+ *p++ = ascii64[(l >> 12) & 0x3f];
+ *p++ = ascii64[(l >> 6) & 0x3f];
+ *p++ = ascii64[l & 0x3f];
+
+ l = r1 << 2;
+ *p++ = ascii64[(l >> 12) & 0x3f];
+ *p++ = ascii64[(l >> 6) & 0x3f];
+ *p++ = ascii64[l & 0x3f];
+ *p = 0;
+
+ return output;
+}
+#endif
diff --git a/util/expire.c b/util/expire.c
new file mode 100644
index 00000000..d6f3e2b9
--- /dev/null
+++ b/util/expire.c
@@ -0,0 +1,226 @@
+/* $Id: expire.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */
+/* ¦Û°Ê¬å«H¤u¨ãµ{¦¡ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <dirent.h>
+#include <fcntl.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 "util.h"
+
+#define QCAST int (*)(const void *, const void *)
+
+#define DEF_DAYS 50
+#define DEF_MAXP 2000
+#define DEF_MINP 300
+
+#define EXPIRE_CONF BBSHOME "/etc/expire.conf"
+extern boardheader_t *bcache;
+char *bpath = BBSHOME "/boards";
+
+struct life
+{
+ char bname[16]; /* board ID */
+ int days; /* expired days */
+ int maxp; /* max post */
+ int minp; /* min post */
+};
+typedef struct life life;
+
+
+void
+ expire(brd)
+life *brd;
+{
+ fileheader_t head;
+ struct stat state;
+ char lockfile[128], tmpfile[128], bakfile[128];
+ char fpath[128], index[128], *fname;
+ int total, bid;
+ int fd, fdr, fdw, done, keep;
+ int duetime, ftime;
+
+ printf("%s\n", brd->bname);
+ if((bid = getbnum(brd->bname)) == 0 ||
+ strcmp(brd->bname, bcache[bid-1].brdname))
+ {
+ printf("no such board?: %s\n", brd->bname);
+ return;
+ }
+#ifdef VERBOSE
+ if (brd->days < 1)
+ {
+ printf(":Err: expire time must more than 1 day.\n");
+ return;
+ }
+ else if (brd->maxp < 100)
+ {
+ printf(":Err: maxmum posts number must more than 100.\n");
+ return;
+ }
+#endif
+
+ sprintf(index, "%s/%s/.DIR", bpath, brd->bname);
+ sprintf(lockfile, "%s.lock", index);
+ if ((fd = open(lockfile, O_RDWR | O_CREAT | O_APPEND, 0644)) == -1)
+ return;
+ flock(fd, LOCK_EX);
+
+ strcpy(fpath, index);
+ fname = (char *) strrchr(fpath, '.');
+
+ duetime = time(NULL) - brd->days * 24 * 60 * 60;
+ done = 0;
+ if ((fdr = open(index, O_RDONLY, 0)) > 0)
+ {
+ fstat(fdr, &state);
+ total = state.st_size / sizeof(head);
+ sprintf(tmpfile, "%s.new", index);
+ unlink(tmpfile);
+ if ((fdw = open(tmpfile, O_WRONLY | O_CREAT | O_EXCL, 0644)) > 0)
+ {
+ while (read(fdr, &head, sizeof head) == sizeof head)
+ {
+ done = 1;
+ ftime = atoi(head.filename + 2);
+ if (head.owner[0] == '-')
+ keep = 0;
+ else if (head.filemode & FILE_MARKED || total <= brd->minp)
+ keep = 1;
+ else if (ftime < duetime || total > brd->maxp)
+ keep = 0;
+ else
+ keep = 1;
+
+ if (keep)
+ {
+ if (write(fdw, (char *)&head, sizeof head) == -1)
+ {
+ done = 0;
+ break;
+ }
+ }
+ else
+ {
+ strcpy(fname, head.filename);
+ unlink(fpath);
+ printf("\t%s\n", fname);
+ total--;
+ }
+ }
+ close(fdw);
+ }
+ close(fdr);
+ }
+
+ if (done)
+ {
+ sprintf(bakfile, "%s.old", index);
+ if (rename(index, bakfile) != -1)
+ {
+ rename(tmpfile, index);
+ touchbtotal(bid);
+ }
+ }
+ flock(fd, LOCK_UN);
+ close(fd);
+}
+
+
+int main(argc, argv)
+char *argv[];
+{
+ FILE *fin;
+ int number, count;
+ life db, table[MAX_BOARD], *key;
+ struct dirent *de;
+ DIR *dirp;
+ char *ptr, *bname, buf[256];
+
+ resolve_boards();
+ db.days = ((argc > 1) && (number = atoi(argv[1])) > 0) ? number : DEF_DAYS;
+ db.maxp = ((argc > 2) && (number = atoi(argv[2])) > 0) ? number : DEF_MAXP;
+ db.minp = ((argc > 3) && (number = atoi(argv[3])) > 0) ? number : DEF_MINP;
+
+/* --------------- */
+/* load expire.ctl */
+/* --------------- */
+
+ count = 0;
+ if((fin = fopen(EXPIRE_CONF, "r")))
+ {
+ while (fgets(buf, 256, fin))
+ {
+ if (buf[0] == '#')
+ continue;
+
+ bname = (char *) strtok(buf, " \t\r\n");
+ if (bname && *bname)
+ {
+ ptr = (char *) strtok(NULL, " \t\r\n");
+ if (ptr && (number = atoi(ptr)) > 0)
+ {
+ key = &(table[count++]);
+ strcpy(key->bname, bname);
+ key->days = number;
+ key->maxp = db.maxp;
+ key->minp = db.minp;
+
+ ptr = (char *) strtok(NULL, " \t\r\n");
+ if (ptr && (number = atoi(ptr)) > 0)
+ {
+ key->maxp = number;
+
+ ptr = (char *) strtok(NULL, " \t\r\n");
+ if (ptr && (number = atoi(ptr)) > 0)
+ {
+ key->minp = number;
+ }
+ }
+ }
+ }
+ }
+ fclose(fin);
+ }
+
+ if (count > 1)
+ {
+ qsort(table, count, sizeof(life), (QCAST)strcasecmp);
+ }
+
+/* ---------------- */
+/* visit all boards */
+/* ---------------- */
+
+ if (!(dirp = opendir(bpath)))
+ {
+ printf(":Err: unable to open %s\n", bpath);
+ return -1;
+ }
+
+ while((de = readdir(dirp)))
+ {
+ ptr = de->d_name;
+ if (ptr[0] > ' ' && ptr[0] != '.')
+ {
+ if (count)
+ key = (life *) bsearch(ptr, table, count, sizeof(life), (QCAST)strcasecmp);
+ else
+ key = NULL;
+ if (!key)
+ key = &db;
+ strcpy(key->bname, ptr);
+ expire(key);
+ }
+ }
+ closedir(dirp);
+ return 0;
+}
diff --git a/util/horoscope.c b/util/horoscope.c
new file mode 100644
index 00000000..c91db7cd
--- /dev/null
+++ b/util/horoscope.c
@@ -0,0 +1,157 @@
+/* $Id: horoscope.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */
+#include <stdio.h>
+#include <sys/types.h>
+#include "config.h"
+#include "pttstruct.h"
+#include "util.h"
+#include "common.h"
+
+struct userec_t cuser;
+
+int main() {
+ int i, j, k;
+ FILE *fp;
+ int max, item, maxhoroscope;
+
+ int act[12];
+
+ char *name[13] =
+ {"¨d¦Ï",
+ "ª÷¤û",
+ "Âù¤l",
+ "¥¨ÃÉ",
+ "·à¤l",
+ "³B¤k",
+ "¤Ñ¯¯",
+ "¤ÑÃÈ",
+ "®g¤â",
+ "¼¯½~",
+ "¤ô²~",
+ "Âù³½",
+ ""
+ };
+ char *blk[10] =
+ {
+ " ", "¢j", "¢k", "¢l", "¢m",
+ "¢n", "¢o", "¢p", "¢i", "¢i",
+ };
+
+ memset(act, 0, sizeof(act));
+ if(passwd_mmap())
+ exit(1);
+ for(k = 1; k <= MAX_USERS; k++) {
+ passwd_query(k, &cuser);
+ if(!cuser.userid[0])
+ continue;
+ switch (cuser.month)
+ {
+ case 1:
+ if (cuser.day <= 19)
+ act[9]++;
+ else
+ act[10]++;
+ break;
+ case 2:
+ if (cuser.day <= 18)
+ act[10]++;
+ else
+ act[11]++;
+ break;
+ case 3:
+ if (cuser.day <= 20)
+ act[11]++;
+ else
+ act[0]++;
+ break;
+ case 4:
+ if (cuser.day <= 19)
+ act[0]++;
+ else
+ act[1]++;
+ break;
+ case 5:
+ if (cuser.day <= 20)
+ act[1]++;
+ else
+ act[2]++;
+ break;
+ case 6:
+ if (cuser.day <= 21)
+ act[2]++;
+ else
+ act[3]++;
+ break;
+ case 7:
+ if (cuser.day <= 22)
+ act[3]++;
+ else
+ act[4]++;
+ break;
+ case 8:
+ if (cuser.day <= 22)
+ act[4]++;
+ else
+ act[5]++;
+ break;
+ case 9:
+ if (cuser.day <= 22)
+ act[5]++;
+ else
+ act[6]++;
+ break;
+ case 10:
+ if (cuser.day <= 23)
+ act[6]++;
+ else
+ act[7]++;
+ break;
+ case 11:
+ if (cuser.day <= 22)
+ act[7]++;
+ else
+ act[8]++;
+ break;
+ case 12:
+ if (cuser.day <= 21)
+ act[8]++;
+ else
+ act[9]++;
+ break;
+ }
+ }
+
+ for (i = max = maxhoroscope = 0; i < 12; i++)
+ {
+ if (act[i] > max)
+ {
+ max = act[i];
+ maxhoroscope = i;
+ }
+ }
+
+ item = max / 30 + 1;
+
+ if ((fp = fopen(BBSHOME"/etc/horoscope", "w")) == NULL)
+ {
+ printf("cann't open etc/horoscope\n");
+ return 1;
+ }
+
+ for (i = 0; i < 12; i++)
+ {
+ fprintf(fp, " %s®y ", name[i]);
+ for (j = 0; j < act[i] / item; j++)
+ {
+ fprintf(fp, "%2s", blk[9]);
+ }
+ /* ¬°¤F­è¦n¤@­¶ */
+ if (i != 11)
+ fprintf(fp, "%2s %d\n\n", blk[(act[i] % item) * 10 / item],
+ act[i]);
+ else
+ fprintf(fp, "%2s %d\n", blk[(act[i] % item) * 10 / item],
+ act[i]);
+ }
+ fclose(fp);
+ return 0;
+}
diff --git a/util/in2outmail b/util/in2outmail
new file mode 100644
index 00000000..686944c1
--- /dev/null
+++ b/util/in2outmail
Binary files differ
diff --git a/util/in2outmail.c b/util/in2outmail.c
new file mode 100644
index 00000000..fce9cc59
--- /dev/null
+++ b/util/in2outmail.c
@@ -0,0 +1,288 @@
+/* $Id: in2outmail.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include "config.h"
+#include "pttstruct.h"
+
+
+#ifdef HAVE_SETPROCTITLE
+
+#include <sys/types.h>
+#include <libutil.h>
+
+void initsetproctitle(int argc, char **argv, char **envp) {
+}
+
+#else
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+char **Argv = NULL; /* pointer to argument vector */
+char *LastArgv = NULL; /* end of argv */
+extern char **environ;
+
+void initsetproctitle(int argc, char **argv, char **envp) {
+ register int i;
+
+ /* Move the environment so setproctitle can use the space at
+ the top of memory. */
+ for(i = 0; envp[i]; i++);
+ environ = malloc(sizeof(char *) * (i + 1));
+ for(i = 0; envp[i]; i++)
+ environ[i] = strdup(envp[i]);
+ environ[i] = NULL;
+
+ /* Save start and extent of argv for setproctitle. */
+ Argv = argv;
+ if(i > 0)
+ LastArgv = envp[i - 1] + strlen(envp[i - 1]);
+ else
+ LastArgv = argv[argc - 1] + strlen(argv[argc - 1]);
+}
+
+static void do_setproctitle(const char *cmdline) {
+ char buf[256], *p;
+ int i;
+
+ strncpy(buf, cmdline, 256);
+ buf[255] = '\0';
+ i = strlen(buf);
+ if(i > LastArgv - Argv[0] - 2) {
+ i = LastArgv - Argv[0] - 2;
+ }
+ strcpy(Argv[0], buf);
+ p = &Argv[0][i];
+ while(p < LastArgv)
+ *p++='\0';
+ Argv[1] = NULL;
+}
+
+void setproctitle(const char* format, ...) {
+ char buf[256];
+
+ va_list args;
+ va_start(args, format);
+ vsprintf(buf, format,args);
+ do_setproctitle(buf);
+ va_end(args);
+}
+#endif
+
+
+
+
+
+#define SPOOL BBSHOME "/out"
+#define INDEX SPOOL "/.DIR"
+#define NEWINDEX SPOOL "/.DIR.sending"
+#define FROM ".bbs@" MYHOSTNAME
+#define SMTPPORT 25
+
+int waitReply(int sock) {
+ char buf[256];
+
+ if(read(sock, buf, sizeof(buf)) <= 0)
+ return -1;
+ else
+ return buf[0] - '0';
+}
+
+int sendRequest(int sock, char *request) {
+ return write(sock, request, strlen(request)) < 0 ? -1 : 0;
+}
+
+int connectMailServer(char *host) {
+ int sock;
+ struct sockaddr_in addr;
+
+ if((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
+ perror("socket");
+ return -1;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+#ifdef FreeBSD
+ addr.sin_len = sizeof(addr);
+#endif
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(SMTPPORT);
+ addr.sin_addr.s_addr = inet_addr(host);
+
+ if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ perror(RELAY_SERVER_IP);
+ close(sock);
+ return -1;
+ }
+
+ if(waitReply(sock) != 2) {
+ close(sock);
+ return -1;
+ }
+
+ if(sendRequest(sock, "helo " MYHOSTNAME "\n") || waitReply(sock) != 2) {
+ close(sock);
+ return -1;
+ } else
+ return sock;
+}
+
+void disconnectMailServer(int sock) {
+ sendRequest(sock, "quit\n");
+ /* drop the reply :p */
+ close(sock);
+}
+
+void doSendBody(int sock, FILE *fp, char *from, char *to, char *subject) {
+ int n;
+ char buf[2048];
+
+ n = snprintf(buf, sizeof(buf), "From: %s\nTo: %s\nSubject: %s\n\n",
+ from, to, subject);
+ write(sock, buf, n);
+
+ while(fgets(buf, sizeof(buf), fp)) {
+ if(buf[0] == '.' && buf[1] == '\n')
+ strcpy(buf, "..\n");
+ write(sock, buf, strlen(buf));
+ }
+}
+
+void doSendMail(int sock, FILE *fp, char *from, char *to, char *subject) {
+ char buf[256];
+
+ snprintf(buf, sizeof(buf), "mail from: %s\n", from);
+ if(sendRequest(sock, buf) || waitReply(sock) != 2)
+ return;
+
+ snprintf(buf, sizeof(buf), "rcpt to: %s\n", to);
+ if(sendRequest(sock, buf) || waitReply(sock) != 2)
+ return;
+
+ if(sendRequest(sock, "data\n") || waitReply(sock) != 3)
+ return;
+
+ doSendBody(sock, fp, from, to, subject);
+
+ if(sendRequest(sock, "\n.\n") || waitReply(sock) != 2)
+ return;
+}
+
+void sendMail() {
+ int fd, sockPTT2, sockHinet;
+ MailQueue mq;
+
+ if(access(NEWINDEX, R_OK | W_OK)) {
+ if(link(INDEX, NEWINDEX) || unlink(INDEX))
+ /* nothing to do */
+ return;
+ }
+
+ if( (sockPTT2 = connectMailServer("140.112.30.143")) < 0 ){
+ fprintf(stderr, "connect server failed...\n");
+ return;
+ }
+ sockHinet = connectMailServer("61.218.59.183");
+
+ fd = open(NEWINDEX, O_RDONLY);
+ flock(fd, LOCK_EX);
+ while(read(fd, &mq, sizeof(mq)) > 0) {
+ FILE *fp;
+ char buf[256];
+
+ snprintf(buf, sizeof(buf), "%s%s", mq.sender, FROM);
+ if((fp = fopen(mq.filepath, "r"))) {
+ setproctitle("outmail: sending %s", mq.filepath);
+ if( strstr(mq.rcpt, ".edu.tw") ||
+ strstr(mq.rcpt, ".twbbs.org") ||
+ strstr(mq.rcpt, "ptt.cc") ||
+ strstr(mq.rcpt, "ptt2.cc") ){
+ printf("relay server: ptt2, to %s\n", mq.rcpt);
+ doSendMail(sockPTT2, fp, buf, mq.rcpt, mq.subject);
+ }
+ else{
+ printf("relay server: ezmain, to %s\n", mq.rcpt);
+ doSendMail( (sockHinet > 0) ? sockHinet : sockPTT2,
+ fp, buf, mq.rcpt, mq.subject);
+ }
+ fclose(fp);
+ unlink(mq.filepath);
+ } else {
+ perror(mq.filepath);
+ }
+ }
+ flock(fd, LOCK_UN);
+ close(fd);
+ unlink(NEWINDEX);
+
+ if( sockHinet > 0 )
+ disconnectMailServer(sockHinet);
+ disconnectMailServer(sockPTT2);
+}
+
+void listQueue() {
+ int fd;
+
+ if((fd = open(INDEX, O_RDONLY)) >= 0) {
+ int counter = 0;
+ MailQueue mq;
+
+ flock(fd, LOCK_EX);
+ while(read(fd, &mq, sizeof(mq)) > 0) {
+ printf("%s:%s -> %s:%s\n", mq.filepath, mq.username, mq.rcpt,
+ mq.subject);
+ counter++;
+ }
+ flock(fd, LOCK_UN);
+ close(fd);
+ printf("\nTotal: %d mails in queue\n", counter);
+ } else {
+ perror(INDEX);
+ }
+}
+
+void usage() {
+ fprintf(stderr, "usage: outmail [-qh]\n");
+}
+
+void wakeup(int s) {
+}
+
+int main(int argc, char **argv, char **envp) {
+ int ch;
+
+ signal(SIGHUP, wakeup);
+ initsetproctitle(argc, argv, envp);
+
+ if(chdir(BBSHOME))
+ return 1;
+ while((ch = getopt(argc, argv, "qh")) != -1) {
+ switch(ch) {
+ case 'q':
+ listQueue();
+ return 0;
+ default:
+ usage();
+ return 0;
+ }
+ }
+ for(;;) {
+ sendMail();
+ setproctitle("outmail: sleeping");
+ sleep(60 * 3); /* send mail every 3 minute */
+ }
+ return 0;
+}
diff --git a/util/initbbs.c b/util/initbbs.c
new file mode 100644
index 00000000..ce6c4361
--- /dev/null
+++ b/util/initbbs.c
@@ -0,0 +1,223 @@
+/* $Id: initbbs.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "config.h"
+#include "pttstruct.h"
+#include "perm.h"
+
+static void initDir() {
+ mkdir("adm", 0755);
+ mkdir("boards", 0755);
+ mkdir("etc", 0755);
+ mkdir("man", 0755);
+ mkdir("man/boards", 0755);
+ mkdir("out", 0755);
+ mkdir("tmp", 0755);
+}
+
+static void initHome() {
+ int i;
+ char buf[256];
+
+ mkdir("home", 0755);
+ strcpy(buf, "home/?");
+ for(i = 0; i < 26; i++) {
+ buf[5] = 'A' + i;
+ mkdir(buf, 0755);
+ buf[5] = 'a' + i;
+ mkdir(buf, 0755);
+ }
+}
+
+static void initPasswds() {
+ int i;
+ userec_t u;
+ FILE *fp = fopen(".PASSWDS", "w");
+
+ memset(&u, 0, sizeof(u));
+ if(fp) {
+ for(i = 0; i < MAX_USERS; i++)
+ fwrite(&u, sizeof(u), 1, fp);
+ fclose(fp);
+ }
+}
+
+static void newboard(FILE *fp, boardheader_t *b) {
+ char buf[256];
+
+ fwrite(b, sizeof(boardheader_t), 1, fp);
+ sprintf(buf, "boards/%s", b->brdname);
+ mkdir(buf, 0755);
+ sprintf(buf, "man/boards/%s", b->brdname);
+ mkdir(buf, 0755);
+}
+
+static void initBoards() {
+ FILE *fp = fopen(".BOARDS", "w");
+ boardheader_t b;
+
+ if(fp) {
+ memset(&b, 0, sizeof(b));
+
+ strcpy(b.brdname, "SYSOP");
+ strcpy(b.title, "¼T­ù ¡·¯¸ªø¦n!");
+ b.brdattr = BRD_POSTMASK | BRD_NOTRAN | BRD_NOZAP;
+ b.level = 0;
+ b.gid = 2;
+
+ newboard(fp, &b);
+ strcpy(b.brdname, "1...........");
+ strcpy(b.title, ".... £U¤¤¥¡¬F©² ¡m°ªÀ£¦MÀI,«D¤H¥i¼Ä¡n");
+ b.brdattr = BRD_GROUPBOARD;
+ b.level = PERM_SYSOP;
+ b.gid = 1;
+ newboard(fp, &b);
+
+ strcpy(b.brdname, "junk");
+ strcpy(b.title, "µo¹q ¡·Âø¤CÂø¤Kªº©U§£");
+ b.brdattr = BRD_NOTRAN;
+ b.level = PERM_SYSOP;
+ b.gid = 2;
+ newboard(fp, &b);
+
+ strcpy(b.brdname, "Security");
+ strcpy(b.title, "µo¹q ¡·¯¸¤º¨t²Î¦w¥þ");
+ b.brdattr = BRD_NOTRAN;
+ b.level = PERM_SYSOP;
+ b.gid = 2;
+ newboard(fp, &b);
+
+ strcpy(b.brdname, "2...........");
+ strcpy(b.title, ".... £U¥«¥Á¼s³õ ³ø§i ¯¸ªø £­¡I");
+ b.brdattr = BRD_GROUPBOARD;
+ b.level = 0;
+ b.gid = 1;
+ newboard(fp, &b);
+
+ strcpy(b.brdname, "ALLPOST");
+ strcpy(b.title, "¼T­ù ¡·¸óªO¦¡LOCAL·s¤å³¹");
+ b.brdattr = BRD_POSTMASK | BRD_NOTRAN;
+ b.level = PERM_SYSOP;
+ b.gid = 5;
+ newboard(fp, &b);
+
+ strcpy(b.brdname, "deleted");
+ strcpy(b.title, "¼T­ù ¡·¸ê·½¦^¦¬µ©");
+ b.brdattr = BRD_NOTRAN;
+ b.level = PERM_BM;
+ b.gid = 5;
+ newboard(fp, &b);
+
+ strcpy(b.brdname, "Note");
+ strcpy(b.title, "¼T­ù ¡·°ÊºA¬ÝªO¤Îºq¦±§ë½Z");
+ b.brdattr = BRD_NOTRAN;
+ b.level = 0;
+ b.gid = 5;
+ newboard(fp, &b);
+
+ strcpy(b.brdname, "Record");
+ strcpy(b.title, "¼T­ù ¡·§Ú­Ìªº¦¨ªG");
+ b.brdattr = BRD_NOTRAN | BRD_POSTMASK;
+ b.level = 0;
+ b.gid = 5;
+ newboard(fp, &b);
+
+
+ strcpy(b.brdname, "WhoAmI");
+ strcpy(b.title, "¼T­ù ¡·¨þ¨þ¡A²q²q§Ú¬O½Ö¡I");
+ b.brdattr = BRD_NOTRAN;
+ b.level = 0;
+ b.gid = 5;
+ newboard(fp, &b);
+
+ strcpy(b.brdname, "EditExp");
+ strcpy(b.title, "¼T­ù ¡·½d¥»ºëÆF§ë½Z°Ï");
+ b.brdattr = BRD_NOTRAN;
+ b.level = 0;
+ b.gid = 5;
+ newboard(fp, &b);
+
+ fclose(fp);
+ }
+}
+
+static void initMan() {
+ FILE *fp;
+ fileheader_t f;
+ time_t t = time(NULL);
+ struct tm *tm = localtime(&t);
+
+ memset(&f, 0, sizeof(f));
+ f.savemode = 0;
+ strcpy(f.owner, "SYSOP");
+ sprintf(f.date, "%2d/%02d", tm->tm_mon + 1, tm->tm_mday);
+ f.money = 0;
+ f.filemode = 0;
+
+ if((fp = fopen("man/boards/Note/.DIR", "w"))) {
+ strcpy(f.filename, "SONGBOOK");
+ strcpy(f.title, "¡» ¡iÂI ºq ºq ¥»¡j");
+ fwrite(&f, sizeof(f), 1, fp);
+ mkdir("man/boards/Note/SONGBOOK", 0755);
+
+ strcpy(f.filename, "SONGO");
+ strcpy(f.title, "¡» <ÂIºq> °ÊºA¬ÝªO");
+ fwrite(&f, sizeof(f), 1, fp);
+ mkdir("man/boards/Note/SONGO", 0755);
+
+ strcpy(f.filename, "SYS");
+ strcpy(f.title, "¡» <¨t²Î> °ÊºA¬ÝªO");
+ fwrite(&f, sizeof(f), 1, fp);
+ mkdir("man/boards/Note/SYS", 0755);
+
+ strcpy(f.filename, "AD");
+ strcpy(f.title, "¡» <¼s§i> °ÊºA¬ÝªO");
+ fwrite(&f, sizeof(f), 1, fp);
+ mkdir("man/boards/Note/AD", 0755);
+
+ strcpy(f.filename, "NEWS");
+ strcpy(f.title, "¡» <·s»D> °ÊºA¬ÝªO");
+ fwrite(&f, sizeof(f), 1, fp);
+ mkdir("man/boards/Note/NEWS", 0755);
+
+ fclose(fp);
+ }
+
+}
+
+static void initSymLink() {
+ symlink(BBSHOME "/man/boards/Note/SONGBOOK", BBSHOME "/etc/SONGBOOK");
+ symlink(BBSHOME "/man/boards/Note/SONGO", BBSHOME "/etc/SONGO");
+ symlink(BBSHOME "/man/boards/EditExp", BBSHOME "/etc/editexp");
+}
+
+static void initHistory() {
+ FILE *fp = fopen("etc/history.data", "w");
+
+ if(fp) {
+ fprintf(fp, "0 0 0 0");
+ fclose(fp);
+ }
+}
+
+int main() {
+ if(chdir(BBSHOME)) {
+ perror(BBSHOME);
+ exit(1);
+ }
+
+ initDir();
+ initHome();
+ initPasswds();
+ initBoards();
+ initMan();
+ initSymLink();
+ initHistory();
+
+ return 0;
+}
diff --git a/util/inndBM.c b/util/inndBM.c
new file mode 100644
index 00000000..426fa6f5
--- /dev/null
+++ b/util/inndBM.c
@@ -0,0 +1,194 @@
+/* ¨Ì¾Ú .BOARDÀÉ & newsfeeds.bbs ¦C¥X°Ñ»PÂà«Hªº©Ò¦³ªO¸ê®Æ */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include "config.h"
+#include "pttstruct.h"
+#define INNDHOME BBSHOME"/innd"
+
+#define INND_NEWSFEED INNDHOME "/newsfeeds.bbs"
+#define INND_NODELIST INNDHOME "/nodelist.bbs"
+#define INND_SCRIPT INNDHOME "/bbsnnrpall.auto.sh"
+
+extern bcache_t *brdshm;
+extern boardheader_t *bcache;
+extern int numboards;
+int istran[MAX_BOARD];
+
+typedef
+struct newssvr_t
+{
+ char name[30];
+ char address[256];
+ char type[10];
+}newssvr_t;
+
+typedef
+struct newsfeed_t
+{
+ char group[128];
+ char board[15];
+ char server[30];
+}newsfeed_t;
+
+newssvr_t server[128];
+newsfeed_t feedline[MAX_BOARD];
+int servercount;
+int feedcount;
+
+int newsfeed_cmp(newsfeed_t *a,newsfeed_t *b)
+{
+ int i;
+ i=strcasecmp(a->server,b->server);
+ if(i) return i;
+ return strcasecmp(a->board,b->board);
+}
+
+int get_server(char *name)
+{
+ int i;
+ for(i=0;i<servercount;i++)
+ if(!strcasecmp(server[i].name,name))
+ {return i;}
+ return -1;
+}
+
+int load_server()
+{
+ FILE *fp;
+ char str[128];
+
+ if (!(fp = fopen(INND_NODELIST, "r")))
+ {
+ return 0;
+ }
+
+ for(servercount=0; fgets(str, 128, fp); servercount++)
+ {
+ if(str[0]=='#') continue;
+ sscanf(str,"%s %s %s",server[servercount].name,
+ server[servercount].address,
+ server[servercount].type);
+ }
+ fclose(fp);
+ return servercount;
+}
+
+int load_newsfeeds()
+{
+ int bid;
+ FILE *fp;
+ char str[128];
+ if (!(fp = fopen(INND_NEWSFEED, "r")))
+ {
+ return 0;
+ }
+
+ for(feedcount=0; fgets(str, 128, fp); feedcount++)
+ {
+ if(str[0]=='#') continue;
+ sscanf(str,"%s %s %s",
+ feedline[feedcount].group,feedline[feedcount].board,
+ feedline[feedcount].server);
+ bid=getbnum(feedline[feedcount].board);
+ if(!bid) {feedcount--;continue; /*²¾°£¨S¦³ªº¬ÝªOi*/}
+ strcpy(feedline[feedcount].board,bcache[bid-1].brdname);
+ /*®Õ¥¿¤j¤p¼g */
+
+ istran[bid-1]=1;
+
+ }
+ fclose(fp);
+ qsort(feedline, feedcount, sizeof(newsfeed_t), newsfeed_cmp);
+ return feedcount;
+}
+int dobbsnnrp(char *serverstr, int serverid,FILE *fpscript)
+{
+ char buf[256];
+ printf("set %s\r\n",serverstr);
+ strtok(serverstr,";\r\n");
+ strtok(server[serverid].address,";\r\n"); //¨¾hack
+ sprintf(buf,INNDHOME"/bbsnnrp -c %s "
+ INNDHOME"/active/%s.auto.active >>"
+ INNDHOME"/log/inndBM.log 2>>"
+ INNDHOME"/log/inndBM.log.err &\r\n",
+ server[serverid].address,
+ serverstr);
+ system(buf);
+ if(fpscript)
+ fprintf(fpscript,INNDHOME"/bbsnnrp %s "
+ INNDHOME"/active/%s.auto.active >>"
+ INNDHOME"/log/inndBM.log 2>>"
+ INNDHOME"/log/inndBM.log.err &\r\n",
+ server[serverid].address,serverstr);
+ return 0;
+}
+int main()
+{
+ int i,serverid=0;
+ FILE *fp=NULL,*fpscript=fopen(INND_SCRIPT,"w");
+ char buf[256],serverstr[30]="";
+ resolve_boards();
+ memset(istran,0,sizeof(int)*MAX_BOARD);
+ load_server();
+ load_newsfeeds();
+
+ for(i=0;i<feedcount;i++)
+ {
+ if(strcasecmp(serverstr,feedline[i].server))
+ {
+ if(get_server(feedline[i].server)==-1) continue;
+ if(fp) {
+ fclose(fp);
+ dobbsnnrp(serverstr,serverid,fpscript);
+ }
+ strcpy(serverstr,feedline[i].server);
+ serverid=get_server(feedline[i].server);
+ sprintf(buf,INNDHOME"/active/%s.auto.active",serverstr);
+ fp=fopen(buf,"w");
+ }
+ if(fp)
+ fprintf(fp,"%-35s 0000000000 0000000000 y\r\n",feedline[i].group);
+ }
+ if(fp)
+ {
+ dobbsnnrp(serverstr,serverid,fpscript);
+ fclose(fp);
+ }
+ if(fpscript)
+ {
+ fclose(fpscript);
+ chmod(INND_SCRIPT,0700);
+ }
+
+ // ­«³]Âà«H»P¤£Âà«Hª©¼Ð°O
+ for(i=0;i<numboards;i++)
+ {
+ if(bcache[i].brdname[0]=='\0' ||
+ (bcache[i].brdattr & BRD_GROUPBOARD) ) continue;
+ if((bcache[i].brdattr & BRD_NOTRAN )&& istran[i])
+ {
+ while(brdshm->busystate) {safe_sleep(1);}
+ brdshm->busystate = 1;
+ bcache[i].brdattr = bcache[i].brdattr & ~BRD_NOTRAN;
+ strncpy(bcache[i].title + 5, "¡´", 2);
+ brdshm->busystate = 0;
+
+ substitute_record(BBSHOME"/.BOARDS", &bcache[i],sizeof(boardheader_t),i+1);
+ }
+ else if(!(bcache[i].brdattr & BRD_NOTRAN) && !istran[i])
+ {
+ while(brdshm->busystate) {safe_sleep(1);}
+ brdshm->busystate = 1;
+ bcache[i].brdattr = bcache[i].brdattr | BRD_NOTRAN;
+ strncpy(bcache[i].title + 5, "¡·", 2);
+ brdshm->busystate = 0;
+ substitute_record(BBSHOME"/.BOARDS", &bcache[i],sizeof(boardheader_t),i+1);
+ }
+
+ }
+ return 0;
+}
diff --git a/util/jungo.c b/util/jungo.c
new file mode 100644
index 00000000..15096b30
--- /dev/null
+++ b/util/jungo.c
@@ -0,0 +1,202 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <ctype.h>
+#include "config.h"
+#include "pttstruct.h"
+#include "util.h"
+#include "perm.h"
+#include "common.h"
+
+#define OUTFILE BBSHOME "/etc/toplazyBBM"
+#define FIREFILE BBSHOME "/etc/topfireBBM"
+
+extern boardheader_t *bcache;
+extern int numboards;
+
+boardheader_t allbrd[MAX_BOARD];
+extern userec_t xuser;
+typedef struct lostbm {
+ char *bmname;
+ char *title;
+ char *ctitle;
+ int lostdays;
+} lostbm;
+lostbm lostbms[MAX_BOARD];
+
+typedef struct BMarray{
+ char *bmname;
+ int flag;
+} BMArray;
+BMArray bms[3];
+
+int bmlostdays_cmp(const void *va, const void *vb)
+{
+ lostbm *a=(lostbm *)va, *b=(lostbm *)vb;
+ if (a->lostdays > b->lostdays) return -1;
+ else if (a->lostdays == b->lostdays) return 0;
+ else return 1;
+}
+
+int LINK(char* src, char* dst){
+ char cmd[200];
+ if(symlink(src,dst) == -1)
+ {
+ sprintf(cmd, "/bin/cp -R %s %s", src, dst);
+ return system(cmd);
+ }
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ int bmid, i, j=0;
+ FILE *inf, *firef;
+
+ resolve_boards();
+
+ if(passwd_mmap())
+ exit(1);
+
+ memcpy(allbrd,bcache,numboards*sizeof(boardheader_t));
+
+ /* write out the target file */
+
+ inf = fopen(OUTFILE, "w+");
+ if(inf == NULL){
+ printf("open file error : %s\n", OUTFILE);
+ exit(1);
+ }
+ firef = fopen(FIREFILE, "w+");
+ if(firef == NULL){
+ printf("open file error : %s\n", FIREFILE);
+ fclose(inf);
+ exit(1);
+ }
+
+ fprintf(inf, "ĵ§i: ¤p²Õªø­Y©ó¤@­Ó¤ë¥¼¤W¯¸,±N¤©©ó§K¾\n");
+ fprintf(inf,
+ "¬ÝªO¦WºÙ "
+ " ¤p²Õªø ´X¤Ñ¨S¨Ó°Õ\n"
+ "---------------------------------------------------"
+ "-------------------\n");
+
+ fprintf(firef, "§K¾¤p²Õªø\n");
+ fprintf(firef,
+ "¬ÝªO¦WºÙ "
+ " ¤p²Õªø ´X¤Ñ¨S¨Ó°Õ\n"
+ "---------------------------------------------------"
+ "-------------------\n");
+
+
+ j = 0 ;
+ for (i = 0; i < numboards; i++) {
+ char *p, bmbuf[IDLEN * 3 + 3];
+ int index = 0, flag = 0, k, n;
+ p=strtok(allbrd[i].BM,"/ ");
+ if(p)
+ do
+ {
+ if(allbrd[i].brdname[0] == '\0' || (allbrd[i].brdattr & BRD_GROUPBOARD) ==0 ) continue;
+ if (*p == '[' ){p[strlen(p)-1]='\0'; p++;}
+ bmid=getuser(p);
+ bms[index].bmname = p;
+ bms[index].flag = 0;
+ if (((((int)time(NULL)-(int)xuser.lastlogin)/(60*60*24))>=7)
+ //&& isalpha(allbrd[i].brdname[0])
+ && isalpha(allbrd[i].BM[0])
+ && !(xuser.userlevel & PERM_SYSOP))
+ {
+ lostbms[j].bmname = p;
+ lostbms[j].title = allbrd[i].brdname;
+ lostbms[j].ctitle = allbrd[i].title;
+ lostbms[j].lostdays =
+ ((int)time(NULL)-(int)xuser.lastlogin)/(60*60*24);
+
+ printf("%s\n", lostbms[j].title);
+ //¶W¹L¤»¤Q¤Ñ §K¾
+ if(lostbms[j].lostdays > 30){
+ xuser.userlevel &= ~PERM_BM;
+ bms[index].flag = 1;
+ flag = 1;
+ }
+ j++;
+ }
+ index++;
+ } while((p=strtok(NULL,"/ "))!=NULL);
+
+ //±qª©¥D¦W³æ®³±¼¦W¦r
+
+ if(flag == 1){
+ bmbuf[0] = '\0';
+ for(k = 0 , n = 0; k < index; k++){
+ if(!bms[k].flag){
+ if( n++ != 0) strcat(bmbuf, "/");
+ strcat(bmbuf, bms[k].bmname);
+ }
+ }
+ strcpy(bcache[i].BM, bmbuf);
+ }
+
+ }
+ qsort(lostbms, j, sizeof(lostbm), bmlostdays_cmp);
+
+ //write to the etc/toplazyBBM
+ for ( i=0; i<j; i++)
+ {
+ if( lostbms[i].lostdays > 7){
+ fprintf(firef, "%-*.*s%-*.*s%-*.*s%3d¤Ñ¨S¤W¯¸\n", IDLEN, IDLEN, lostbms[i].title,
+ BTLEN-10, BTLEN-10, lostbms[i].ctitle, IDLEN,IDLEN,
+ lostbms[i].bmname,lostbms[i].lostdays);
+ }else{
+ fprintf(inf, "%-*.*s%-*.*s%-*.*s%3d¤Ñ¨S¤W¯¸\n", IDLEN, IDLEN, lostbms[i].title,
+ BTLEN-10, BTLEN-10, lostbms[i].ctitle, IDLEN,IDLEN,
+ lostbms[i].bmname,lostbms[i].lostdays);
+ }
+ }
+ fclose(inf);
+ fclose(firef);
+
+ //printf("Total %d boards.\n", count);
+
+ //mail to the users
+ for( i=0; i<j; i++)
+ {
+ fileheader_t mymail;
+ char genbuf[200];
+ int lostdays;
+
+ lostdays = lostbms[i].lostdays;
+
+ if( (lostdays != 14) || (lostdays != 21) ) // 14 21 ¤Ñ¤£µo«H
+ continue;
+
+ sprintf(genbuf, BBSHOME "/home/%c/%s", lostbms[i].bmname[0], lostbms[i].bmname);
+ stampfile(genbuf, &mymail);
+
+ strcpy(mymail.owner, "[PTTĵ¹î§½]");
+
+ if(lostdays <= 60){
+ sprintf(mymail.title,
+ "\033[32m [¤p²Õªø§K¾ĵ§i³qª¾] \033[m %s BM %s", lostbms[i].title, lostbms[i].bmname);
+ }else{
+ sprintf(mymail.title,
+ "\033[32m [¤p²Õªø§K¾³qª¾] \033[m %s BM %s", lostbms[i].title, lostbms[i].bmname);
+ }
+ mymail.savemode = 0 ;
+ unlink(genbuf);
+ if(lostdays <= 60){
+ LINK(OUTFILE, genbuf);
+ }else{
+ LINK(FIREFILE, genbuf);
+ }
+
+ sprintf(genbuf, BBSHOME "/home/%c/%s/.DIR", lostbms[i].bmname[0], lostbms[i].bmname);
+ append_record(genbuf, &mymail, sizeof(mymail));
+ }
+
+ return 0;
+}
diff --git a/util/kenben.c b/util/kenben.c
new file mode 100644
index 00000000..5733f4da
--- /dev/null
+++ b/util/kenben.c
@@ -0,0 +1,44 @@
+#include <stdio.h>
+
+
+void main()
+{
+ FILE * fin, * fout;
+ char line[255], line2[255];
+ int i;
+ char genbuf[255], tok[20];
+ fin = fopen("M.1006277896.A","r");
+ while(!feof(fin))
+ {
+ fgets(line,255,fin);
+ line[12] = '\0';
+
+ sprintf(genbuf, "cd ~/boards/%s;grep "
+ "¶W¹L¤@­Ó¤ëµL¼s§i¥H¥~ªº¥»¯¸¤å³¹µoªí¡C"
+ " *.A > ~/pttbbs/util/kenken.txt",line);
+ system(genbuf);
+
+ fout = fopen("kenken.txt","r");
+ while(!feof(fout))
+ {
+ line2[0] = '\0';
+ fgets(line2,255,fout);
+ if(strlen(line2) <= 10) break;
+ sscanf(line2,"%s:",tok);
+ for(i = 0; i < 20;i++)
+ {
+ if(tok[i] == ':')
+ {
+ tok[i] = '\0';
+ break;
+ }
+ }
+ sprintf(genbuf, "cd ~/boards/%s;rm %s",line, tok);
+// printf("%s \n", genbuf);
+ system(genbuf);
+ }
+ }
+
+ fclose(fin);
+
+}
diff --git a/util/mailog.sh b/util/mailog.sh
new file mode 100644
index 00000000..da89ae3d
--- /dev/null
+++ b/util/mailog.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+# $Id: mailog.sh,v 1.1 2002/03/07 15:13:46 in2 Exp $
+#
+# ¾ã²z¥X¼s§i«H¦W³æ
+
+bin/antispam
+bin/post Record ¤µ¤é¹Hªk¼s§i«H¦W³æ [Pttĵ¹î§½] etc/spam
+bin/post Security ¯¸¥~¨Ó«H¬ö¿ýmailog [¨t²Î¦w¥þ§½] etc/mailog
+rm etc/mailog
diff --git a/util/mandex.c b/util/mandex.c
new file mode 100644
index 00000000..9373f814
--- /dev/null
+++ b/util/mandex.c
@@ -0,0 +1,263 @@
+/* $Id: mandex.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */
+
+/*
+ target : ºëµØ°Ï¯Á¤Þµ{¦¡ (man index)
+
+ syntax : mandex [board]
+ [board] ¦³­È ==> ¥u¶]¸Ó board
+ ªÅªº ==> ©Ò¦³ªº boards ³£¶]
+*/
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "config.h"
+#include "pttstruct.h"
+#include "util.h"
+
+#ifndef MAXPATHLEN
+#define MAXPATHLEN 1024
+#endif
+
+extern int numboards;
+extern boardheader_t *bcache;
+
+char color[4][10] =
+{"", "", "", ""};
+char fn_index[] = ".index";
+char fn_new[] = ".index.new";
+char index_title[] = "¡· ºëµØ°Ï¥Ø¿ý¯Á¤Þ";
+FILE *fndx;
+int ndir;
+int nfile;
+int index_pos;
+char topdir[128], pgem[512], pndx[512];
+
+int nb = 0; /* board ¼Æ */
+
+struct boardinfo
+{
+ char bname[40];
+ int ndir;
+ int nfile;
+ int k;
+};
+typedef struct boardinfo boardinfo;
+
+boardinfo
+board[MAX_BOARD];
+
+int k_cmp(b, a)
+ boardinfo *b, *a;
+{
+ return ((a->k / 100 + a->ndir + a->nfile) - (b->k / 100 + b->ndir + b->nfile));
+}
+
+int dashd(fname)
+ char *fname;
+{
+ struct stat st;
+
+ return (stat(fname, &st) == 0 && S_ISDIR(st.st_mode));
+}
+
+
+/* visit the hierarchy recursively */
+
+void
+mandex(level, num_header, fpath)
+ int level;
+ char *fpath, *num_header;
+{
+ FILE *fgem;
+ char *fname, buf[256];
+ struct stat st;
+ int count;
+ fileheader_t fhdr;
+
+ fgem = fopen(fpath, "r+");
+ if (fgem == NULL)
+ return;
+
+ fname = strrchr(fpath, '.');
+ if (!level)
+ {
+
+ printf("%s\r\n",fpath);
+ strcpy(pgem, fpath);
+
+ strcpy(fname, fn_new);
+ fndx = fopen(fpath, "w");
+ if (fndx == NULL)
+ {
+ fclose(fgem);
+ return;
+ }
+ fprintf(fndx, "§Ç¸¹\t\t\tºëµØ°Ï¥DÃD\n"
+ "¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w\n");
+ strcpy(pndx, fpath);
+ ndir = nfile = 0;
+ index_pos = -1;
+ }
+
+ count = 0;
+ while (fread(&fhdr, sizeof(fhdr), 1, fgem) == 1)
+ {
+ strcpy(fname, fhdr.filename);
+ if (!fname[0]) continue;
+ if (!level && !strncmp(fhdr.title, index_title, strlen(index_title))
+ && index_pos < 0)
+ {
+ index_pos = count;
+ unlink(fpath);
+ }
+ st.st_size = 0;
+ stat(fpath, &st);
+
+ sprintf(buf, "%.*s%s%3d. %s \n",
+
+ 11 * level, num_header, color[level % 4], ++count, fhdr.title); /* Ptt */
+ fputs(buf, fndx);
+ if (dashd(fpath))
+ {
+ ++ndir;
+ if (*fhdr.title != '#' && level < 10)
+ {
+ strcat(fpath, "/.DIR");
+ mandex(level + 1, buf, fpath);
+ }
+ }
+ else
+ ++nfile;
+ }
+
+ if (!level)
+ {
+ char lpath[MAXPATHLEN];
+
+ fclose(fndx);
+ strcpy(fname, fn_index);
+ rename(pndx, fpath);
+ strcpy(pndx, fpath);
+
+ sprintf(buf, "%s.new", pgem);
+ if (index_pos >= 0 || (fndx = fopen(buf, "w")))
+ {
+ fname[-1] = 0;
+ stamplink(fpath, &fhdr);
+ unlink(fpath);
+ strcpy(fhdr.owner, "¨C¤Ñ¦Û°Ê§ó·s");
+ sprintf(lpath, "%s/%s", topdir, pndx);
+ st.st_size = 0;
+ stat(lpath, &st);
+ sprintf(fhdr.title, "%s (%.1fk)", index_title, st.st_size / 1024.);
+ board[nb].k = st.st_size; /* Ptt */
+ printf("(%d)[%dK]", nb, board[nb].k);
+ symlink(lpath, fpath);
+ if (index_pos < 0)
+ {
+ fwrite(&fhdr, sizeof(fhdr), 1, fndx);
+ rewind(fgem);
+ while (fread(&fhdr, sizeof(fhdr), 1, fgem) == 1)
+ fwrite(&fhdr, sizeof(fhdr), 1, fndx);
+ fclose(fndx);
+ fclose(fgem);
+ rename(buf, pgem);
+ }
+ else
+ {
+ fseek(fgem, index_pos * sizeof(fhdr), 0);
+ fwrite(&fhdr, sizeof(fhdr), 1, fgem);
+ fclose(fgem);
+ }
+ return;
+ }
+ }
+ fclose(fgem);
+}
+
+
+int main(int argc, char* argv[]){
+ boardheader_t *bptr;
+ DIR *dirp;
+ struct dirent *de;
+ int ch, n;
+ int place = 0;
+ char *fname, fpath[MAXPATHLEN];
+
+ resolve_boards();
+ nb = 0;
+ if(argc == 1){
+ puts("Creating the whole index...");
+ chdir(strcpy(topdir, BBSHOME));
+ strcpy(fpath, "man/.DIR");
+ mandex(0, "", fpath);
+ }
+
+
+ chdir(strcpy(topdir, BBSHOME "/man/boards"));
+
+ if(argc > 1) {
+ sprintf(fpath, "%s/.DIR", argv[1]);
+ mandex(0, "", fpath);
+ exit(0);
+ }
+
+ /* process all boards */
+
+ if(!(dirp = opendir(topdir))) {
+ printf("## unable to enter [man/boards]\n");
+ exit(-1);
+ }
+
+ while((de = readdir(dirp))){
+ fname = de->d_name;
+ ch = fname[0];
+ if (ch != '.'){
+ board[nb].k = 0;
+ strcpy(board[nb].bname, fname);
+ sprintf(fpath, "%s/.DIR", fname);
+ mandex(0, "", fpath);
+ printf("%-14sd: %d\tf: %d\n", fname, ndir, nfile); /* report */
+ board[nb].ndir = ndir;
+ board[nb].nfile = nfile;
+ if (board[nb].k)
+ nb++;
+ }
+ }
+ closedir(dirp);
+
+ qsort(board, nb, sizeof(boardinfo), k_cmp);
+
+ if (!(fndx = fopen(BBSHOME "/etc/topboardman", "w")))
+ exit(0);
+
+ fprintf(fndx, "±Æ¦W ¬Ý ª© ¥Ø¿ý¼Æ ÀÉ®×¼Æ"
+ " byte¼Æ  Á` ¤À ª© ¥D \n");
+
+ for (ch = 0; ch < nb; ch++){
+ for (n = 0; n < numboards; n++){
+ bptr = &bcache[n];
+ if (!strcmp(bptr->brdname, board[ch].bname))
+ break;
+ }
+ if (n >= numboards ||
+ (bptr->brdattr & (BRD_BAD | BRD_NOCOUNT | BRD_HIDE)))
+ continue;
+ if (board[ch].ndir + board[ch].nfile < 5)
+ break;
+ fprintf(fndx, "%3d.%15s %5d %7d %10d %6d %-24.24s\n",
+ ++place,
+ board[ch].bname,
+ board[ch].ndir, board[ch].nfile, board[ch].k
+ ,board[ch].k / 100 + board[ch].nfile + board[ch].ndir
+ ,bptr->BM);
+ }
+ fclose(fndx);
+ exit(0);
+}
diff --git a/util/merge_board.c b/util/merge_board.c
new file mode 100644
index 00000000..743ffc14
--- /dev/null
+++ b/util/merge_board.c
@@ -0,0 +1,106 @@
+/* $Id: merge_board.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <sys/types.h>
+#include "config.h"
+#include "pttstruct.h"
+
+typedef struct hash_t {
+ char *brdname;
+ struct hash_t *next;
+} hash_t;
+
+FILE *fout;
+hash_t *hash_tbl[65536];
+int counter;
+
+void usage() {
+ fprintf(stderr, "Usage:\n\n"
+ "merge_board <output file> [input file1] [input file2] ...\n");
+}
+
+unsigned int 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 - 16);
+}
+
+int is_exist(char *brdname) {
+ int i;
+ hash_t *n;
+
+ i = string_hash(brdname);
+ for(n = hash_tbl[i]; n != NULL; n = n->next)
+ if(strcasecmp(brdname, n->brdname) == 0)
+ return 1;
+ return 0;
+}
+
+void add_hash(char *brdname) {
+ int i;
+ hash_t *n;
+
+ i = string_hash(brdname);
+
+ n = malloc(sizeof(*n));
+ n->brdname = strdup(brdname);
+ n->next = hash_tbl[i];
+ hash_tbl[i] = n;
+}
+
+void merge_board(boardheader_t *b) {
+ if(!is_exist(b->brdname)) {
+ fwrite(b, sizeof(*b), 1, fout);
+ add_hash(b->brdname);
+ ++counter;
+ }
+}
+
+void merge_file(char *fname) {
+ FILE *fin;
+ boardheader_t b;
+
+ if((fin = fopen(fname, "r")) == NULL) {
+ perror(fname);
+ return;
+ }
+
+ counter = 0;
+ while(fread(&b, sizeof(b), 1, fin) == 1)
+ if(b.brdname[0])
+ merge_board(&b);
+
+ printf("merge from %s: %d boards\n", fname, counter);
+
+ fclose(fin);
+}
+
+int main(int argc, char **argv) {
+ int i;
+
+ if(argc < 2) {
+ usage();
+ return 1;
+ }
+
+ bzero(hash_tbl, sizeof(hash_tbl));
+
+ if((fout = fopen(argv[1], "w")) == NULL) {
+ perror(argv[1]);
+ return 2;
+ }
+
+ for(i = 2; i < argc; ++i)
+ merge_file(argv[i]);
+
+ fclose(fout);
+ printf("Done\n");
+
+ return 0;
+}
diff --git a/util/merge_passwd.c b/util/merge_passwd.c
new file mode 100644
index 00000000..d27c473b
--- /dev/null
+++ b/util/merge_passwd.c
@@ -0,0 +1,106 @@
+/* $Id: merge_passwd.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <sys/types.h>
+#include "config.h"
+#include "pttstruct.h"
+
+typedef struct hash_t {
+ char *userid;
+ struct hash_t *next;
+} hash_t;
+
+FILE *fout;
+hash_t *hash_tbl[65536];
+int counter;
+
+void usage() {
+ fprintf(stderr, "Usage:\n\n"
+ "merge_passwd <output file> [input file1] [input file2] ...\n");
+}
+
+unsigned int 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 - 16);
+}
+
+int is_exist(char *userid) {
+ int i;
+ hash_t *n;
+
+ i = string_hash(userid);
+ for(n = hash_tbl[i]; n != NULL; n = n->next)
+ if(strcasecmp(userid, n->userid) == 0)
+ return 1;
+ return 0;
+}
+
+void add_hash(char *userid) {
+ int i;
+ hash_t *n;
+
+ i = string_hash(userid);
+
+ n = malloc(sizeof(*n));
+ n->userid = strdup(userid);
+ n->next = hash_tbl[i];
+ hash_tbl[i] = n;
+}
+
+void merge_user(userec_t *u) {
+ if(!is_exist(u->userid)) {
+ fwrite(u, sizeof(*u), 1, fout);
+ add_hash(u->userid);
+ ++counter;
+ }
+}
+
+void merge_file(char *fname) {
+ FILE *fin;
+ userec_t u;
+
+ if((fin = fopen(fname, "r")) == NULL) {
+ perror(fname);
+ return;
+ }
+
+ counter = 0;
+ while(fread(&u, sizeof(u), 1, fin) == 1)
+ if(u.userid[0])
+ merge_user(&u);
+
+ printf("merge from %s: %d users\n", fname, counter);
+
+ fclose(fin);
+}
+
+int main(int argc, char **argv) {
+ int i;
+
+ if(argc < 2) {
+ usage();
+ return 1;
+ }
+
+ bzero(hash_tbl, sizeof(hash_tbl));
+
+ if((fout = fopen(argv[1], "w")) == NULL) {
+ perror(argv[1]);
+ return 2;
+ }
+
+ for(i = 2; i < argc; ++i)
+ merge_file(argv[i]);
+
+ fclose(fout);
+ printf("Done\n");
+
+ return 0;
+}
diff --git a/util/opendice.sh b/util/opendice.sh
new file mode 100644
index 00000000..767e213a
--- /dev/null
+++ b/util/opendice.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+# $Id: opendice.sh,v 1.1 2002/03/07 15:13:46 in2 Exp $
+
+bin/countalldice > etc/dice.dis
+bin/post Record "»ë¤l¤¤¼ú¦W³æ" "[»ë¤l³ø§i]" etc/windice.log
+bin/post Security "»ë¤l¥¢±Ñ¦W³æ" "[»ë¤l³ø§i]" etc/lostdice.log
+bin/post Security "»ë¤l´Á±æ­È" "[»ë¤l³ø§i]" etc/dice.dis
+rm -f etc/windice.log
+rm -f etc/lostdice.log
+rm -f etc/dice.dis
diff --git a/util/openticket.c b/util/openticket.c
new file mode 100644
index 00000000..69b9ab2a
--- /dev/null
+++ b/util/openticket.c
@@ -0,0 +1,198 @@
+/* $Id: openticket.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */
+/* ¶}¼úªº utility */
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <sys/types.h>
+#include "config.h"
+#include "pttstruct.h"
+#include "common.h"
+#include "util.h"
+
+
+static char *betname[8] = {"Ptt", "Jaky", "Action", "Heat",
+ "DUNK", "Jungo", "waiting", "wofe"};
+
+#define MAX_DES 7 /* ³Ì¤j«O¯d¼ú¼Æ */
+
+extern userec_t xuser;
+
+int Link(char *src, char *dst)
+{
+ char cmd[200];
+
+ if (link(src, dst) == 0)
+ return 0;
+
+ sprintf(cmd, "/bin/cp -R %s %s", src, dst);
+ return system(cmd);
+}
+
+char *
+ Cdatelite(clock)
+time_t *clock;
+{
+ static char foo[18];
+ struct tm *mytm = localtime(clock);
+
+ strftime(foo, 18, "%D %T", mytm);
+ return (foo);
+}
+
+
+int main()
+{
+ int money, bet, n, total = 0, ticket[8] =
+ {0, 0, 0, 0, 0, 0, 0, 0};
+ FILE *fp;
+ time_t now = time(NULL);
+ char des[MAX_DES][200] =
+ {"", "", "", ""};
+ extern struct utmpfile_t *utmpshm;
+
+ if(passwd_mmap())
+ exit(1);
+
+ rename(BBSHOME "/etc/" FN_TICKET_RECORD,
+ BBSHOME "/etc/" FN_TICKET_RECORD ".tmp");
+ rename(BBSHOME "/etc/" FN_TICKET_USER,
+ BBSHOME "/etc/" FN_TICKET_USER ".tmp");
+
+ if (!(fp = fopen(BBSHOME "/etc/"FN_TICKET_RECORD ".tmp", "r")))
+ return 0;
+ fscanf(fp, "%9d %9d %9d %9d %9d %9d %9d %9d\n",
+ &ticket[0], &ticket[1], &ticket[2], &ticket[3],
+ &ticket[4], &ticket[5], &ticket[6], &ticket[7]);
+ for (n = 0; n < 8; n++)
+ total += ticket[n];
+ fclose(fp);
+
+ if (!total)
+ return 0;
+
+ if((fp = fopen(BBSHOME "/etc/" FN_TICKET , "r")))
+ {
+ for (n = 0; n < MAX_DES && fgets(des[n], 200, fp); n++) ;
+ fclose(fp);
+ }
+
+/*
+ *srandom(33); // ©T©w¤@­Ó seed ¦ýºÉ¶q­nÁקK¸ò§O¤Hªºseed¦P
+ *
+ *for( n = (now / (60*60*3)) - 62820; n >0; n--) random();
+ */
+
+/*
+ * ¥¿½Tªºrandom number generatorªº¥Îªk
+ * ¬O¥Î¦P¤@­Ó seed«á¨ú ²Ä¤@­Ó ²Ä¤G­Ó ¦a¤T­Ó.... ¼Æ
+ * srand() ³]§¹seed«á
+ * ¨C©I¥s¤@¦¸rand()´N¨ú¤U¤@­Ó¼Æ
+ *
+ * ¦ý¦]¬°§Ú­Ì¨S¦³°O¿ý¤W¦¸¨ú¨ì²Ä´X­Ó
+ * ©Ò¥H¥Î¨C¼W¥|¤p®É()´N¦h¨ú¤@¦¸ => now / (60*60*4) (¨C¤­¤p®É¶}¤@¦¸¼ú)
+ * (´î 61820 ¬O´î¤Ö loop ¼Æ)
+ *
+ * ¥»¨Ó¬O¥Îsrand(time(0)) ¤£¬O¥¿½Tªº¥Îªk
+ * ¦]¬°¶}¼ú®É¶¡¦³³W²v ©Ò¥H·|³Q§ä¥X³W«ß
+ *
+ * ~Ptt
+ */
+/*
+ *bet=random() % 8;
+ */
+
+ resolve_utmp();
+ bet = utmpshm->number % 8;
+
+/*
+
+ * ¦bC¤¤ srand ¸ò srandom ¤@¼Ë rand ¸ò random ¤@¼Ë
+ * ¤£¦Pªº¬O rand ¬O¶Ç¦^¤@­Ó double µ¹«D¾ã¼Æªº¶Ã¼Æ¥Î
+ * random ¬O¶Ç¦^¤@­Ó int µ¹¾ã¼Æªº¶Ã¼Æ¥Î
+ *
+ * ­Y­n¥Hrand inplement ¾ã¼Æªº¶Ã¼Æ ­nª`·N¥H¤U (man page¤¤¦³)
+ *
+ * In Numerical Recipes in C: The Art of Scientific Computing
+ * (William H. Press, Brian P. Flannery, Saul A. Teukolsky,
+ * William T. Vetterling; New York: Cambridge University
+ * Press, 1990 (1st ed, p. 207)), the following comments are
+ * made:
+ * "If you want to generate a random integer between 1
+ * and 10, you should always do it by
+ *
+ * j=1+(int) (10.0*rand()/(RAND_MAX+1.0));
+ *
+ * and never by anything resembling
+ *
+ * j=1+((int) (1000000.0*rand()) % 10);
+ *
+ * (which uses lower-order bits)."
+ *
+ * Random-number generation is a complex topic. The Numeri-
+ * cal Recipes in C book (see reference above) provides an
+ * excellent discussion of practical random-number generation
+ * issues in Chapter 7 (Random Numbers).
+ * ~ Ptt
+ */
+
+
+ money = ticket[bet] ? total * 95 / ticket[bet] : 9999999;
+
+ if((fp = fopen(BBSHOME "/etc/" FN_TICKET, "w")))
+ {
+ if (des[MAX_DES - 1][0])
+ n = 1;
+ else
+ n = 0;
+
+ for (; n < MAX_DES && des[n][0] != 0; n++)
+ {
+ fprintf(fp, des[n]);
+ }
+
+ printf("\n\n¶}¼ú®É¶¡¡G %s \n\n"
+ "¶}¼úµ²ªG¡G %s \n\n"
+ "¤Uª`Á`ª÷ÃB¡G %d00 ¤¸ \n"
+ "¤¤¼ú¤ñ¨Ò¡G %d±i/%d±i (%f)\n"
+ "¨C±i¤¤¼ú±m²¼¥i±o %d ªT¢Þ¹ô \n\n",
+ Cdatelite(&now), betname[bet], total, ticket[bet], total,
+ (float) ticket[bet] / total, money);
+
+ fprintf(fp, "%s ½ä½L¶}¥X:%s Á`ª÷ÃB:%d00 ¤¸ ¼úª÷/±i:%d ¤¸ ¾÷²v:%1.2f\n",
+ Cdatelite(&now), betname[bet], total, money,
+ (float) ticket[bet] / total);
+ fclose(fp);
+
+ }
+
+ if (ticket[bet] && (fp = fopen(BBSHOME "/etc/" FN_TICKET_USER ".tmp", "r")))
+ {
+ int mybet, num, uid;
+ char userid[20], genbuf[200];
+ fileheader_t mymail;
+
+ while (fscanf(fp, "%s %d %d\n", userid, &mybet, &num) != EOF)
+ {
+ if (mybet == bet)
+ {
+ printf("®¥³ß %-15s¶R¤F%9d ±i %s, Àò±o %d ªT¢Þ¹ô\n"
+ ,userid, num, betname[mybet], money * num);
+ if((uid=getuser(userid))==0) continue;
+ deumoney(uid, money * num);
+ sprintf(genbuf, BBSHOME "/home/%c/%s", userid[0], userid);
+ stampfile(genbuf, &mymail);
+ strcpy(mymail.owner, BBSNAME);
+ sprintf(mymail.title, "[%s] ¤¤¼úÅo! $ %d", Cdatelite(&now), money * num);
+ mymail.savemode = 0;
+ unlink(genbuf);
+ Link(BBSHOME "/etc/ticket", genbuf);
+ sprintf(genbuf, BBSHOME "/home/%c/%s/.DIR", userid[0], userid);
+ append_record(genbuf, &mymail, sizeof(mymail));
+ }
+ }
+ }
+ unlink(BBSHOME "/etc/" FN_TICKET_RECORD ".tmp");
+ unlink(BBSHOME "/etc/" FN_TICKET_USER ".tmp");
+ return 0;
+}
diff --git a/util/openticket.sh b/util/openticket.sh
new file mode 100644
index 00000000..8274e5c3
--- /dev/null
+++ b/util/openticket.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+# $Id: openticket.sh,v 1.1 2002/03/07 15:13:46 in2 Exp $
+
+bin/openticket > etc/jackpot
+bin/post Record "±m¨é¤¤¼ú¦W³æ" "[½ä³õ³ø§i]" etc/jackpot
+bin/post Record "²q¼Æ¦r¤¤¼ú¦W³æ" "[²q¼Æ¦r³ø§i]" etc/winguess.log
+bin/post Record "¶Â¥Õ´Ñ¹ï¾Ô°O¿ý" "[²q¼Æ¦r³ø§i]" etc/othello.log
+rm -f etc/winguess.log
+rm -f etc/loseguess.log
+rm -f etc/othello.log
diff --git a/util/openvice.c b/util/openvice.c
new file mode 100644
index 00000000..9b5e438f
--- /dev/null
+++ b/util/openvice.c
@@ -0,0 +1,54 @@
+/* $Id: openvice.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */
+/* µo²¼¶}¼ú¤pµ{¦¡ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include "config.h"
+#include "pttstruct.h"
+#include "util.h"
+
+#define VICE_SHOW BBSHOME "/etc/vice.show1"
+#define VICE_BINGO BBSHOME "/etc/vice.bingo"
+#define VICE_NEW "vice.new"
+#define VICE_DATA "vice.data"
+#define MAX_BINGO 99999999
+
+int main()
+{
+ char TABLE[5][3] =
+ {"¤@", "¤G", "¤T", "¥|", "¤­"};
+
+ int i = 0, bingo, base = 0;
+
+
+ FILE *fp = fopen(VICE_SHOW, "w"), *fb = fopen(VICE_BINGO, "w");
+
+ extern struct utmpfile_t *utmpshm;
+ resolve_utmp();
+
+ srand(utmpshm->number);
+
+ if (!fp || !fb )
+ perror("error open file");
+
+
+ bingo = rand() % MAX_BINGO;
+ fprintf(fp, "%1c²Î¤@µo²¼¤¤¼ú¸¹½X\n", ' ');
+ fprintf(fp, "%1c================\n", ' ');
+ fprintf(fp, "%1c¯S§O¼ú: %08d\n\n", ' ', bingo);
+ fprintf(fb, "%d\n", bingo);
+
+ while (i < 5)
+ {
+ bingo = (base + rand()) % MAX_BINGO;
+ fprintf(fp, "%1c²Ä%s¼ú: %08d\n", ' ', TABLE[i], bingo);
+ fprintf(fb, "%08d\n", bingo);
+ i++;
+ }
+ fclose(fp);
+ fclose(fb);
+ return 0;
+}
diff --git a/util/outmail.c b/util/outmail.c
new file mode 100644
index 00000000..d6b19bb4
--- /dev/null
+++ b/util/outmail.c
@@ -0,0 +1,274 @@
+/* $Id: outmail.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/file.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include "config.h"
+#include "pttstruct.h"
+
+
+#ifdef HAVE_SETPROCTITLE
+
+#include <sys/types.h>
+#include <libutil.h>
+
+void initsetproctitle(int argc, char **argv, char **envp) {
+}
+
+#else
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+char **Argv = NULL; /* pointer to argument vector */
+char *LastArgv = NULL; /* end of argv */
+extern char **environ;
+
+void initsetproctitle(int argc, char **argv, char **envp) {
+ register int i;
+
+ /* Move the environment so setproctitle can use the space at
+ the top of memory. */
+ for(i = 0; envp[i]; i++);
+ environ = malloc(sizeof(char *) * (i + 1));
+ for(i = 0; envp[i]; i++)
+ environ[i] = strdup(envp[i]);
+ environ[i] = NULL;
+
+ /* Save start and extent of argv for setproctitle. */
+ Argv = argv;
+ if(i > 0)
+ LastArgv = envp[i - 1] + strlen(envp[i - 1]);
+ else
+ LastArgv = argv[argc - 1] + strlen(argv[argc - 1]);
+}
+
+static void do_setproctitle(const char *cmdline) {
+ char buf[256], *p;
+ int i;
+
+ strncpy(buf, cmdline, 256);
+ buf[255] = '\0';
+ i = strlen(buf);
+ if(i > LastArgv - Argv[0] - 2) {
+ i = LastArgv - Argv[0] - 2;
+ }
+ strcpy(Argv[0], buf);
+ p = &Argv[0][i];
+ while(p < LastArgv)
+ *p++='\0';
+ Argv[1] = NULL;
+}
+
+void setproctitle(const char* format, ...) {
+ char buf[256];
+
+ va_list args;
+ va_start(args, format);
+ vsprintf(buf, format,args);
+ do_setproctitle(buf);
+ va_end(args);
+}
+#endif
+
+
+
+
+
+#define SPOOL BBSHOME "/out"
+#define INDEX SPOOL "/.DIR"
+#define NEWINDEX SPOOL "/.DIR.sending"
+#define FROM ".bbs@" MYHOSTNAME
+#define SMTPPORT 25
+
+int waitReply(int sock) {
+ char buf[256];
+
+ if(read(sock, buf, sizeof(buf)) <= 0)
+ return -1;
+ else
+ return buf[0] - '0';
+}
+
+int sendRequest(int sock, char *request) {
+ return write(sock, request, strlen(request)) < 0 ? -1 : 0;
+}
+
+int connectMailServer() {
+ int sock;
+ struct sockaddr_in addr;
+
+ if((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
+ perror("socket");
+ return -1;
+ }
+
+ memset(&addr, 0, sizeof(addr));
+#ifdef FreeBSD
+ addr.sin_len = sizeof(addr);
+#endif
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(SMTPPORT);
+ addr.sin_addr.s_addr = inet_addr(RELAY_SERVER_IP);
+
+ if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ perror(RELAY_SERVER_IP);
+ close(sock);
+ return -1;
+ }
+
+ if(waitReply(sock) != 2) {
+ close(sock);
+ return -1;
+ }
+
+ if(sendRequest(sock, "helo " MYHOSTNAME "\n") || waitReply(sock) != 2) {
+ close(sock);
+ return -1;
+ } else
+ return sock;
+}
+
+void disconnectMailServer(int sock) {
+ sendRequest(sock, "quit\n");
+ /* drop the reply :p */
+ close(sock);
+}
+
+void doSendBody(int sock, FILE *fp, char *from, char *to, char *subject) {
+ int n;
+ char buf[2048];
+
+ n = snprintf(buf, sizeof(buf), "From: %s\nTo: %s\nSubject: %s\n\n",
+ from, to, subject);
+ write(sock, buf, n);
+
+ while(fgets(buf, sizeof(buf), fp)) {
+ if(buf[0] == '.' && buf[1] == '\n')
+ strcpy(buf, "..\n");
+ write(sock, buf, strlen(buf));
+ }
+}
+
+void doSendMail(int sock, FILE *fp, char *from, char *to, char *subject) {
+ char buf[256];
+
+ snprintf(buf, sizeof(buf), "mail from: %s\n", from);
+ if(sendRequest(sock, buf) || waitReply(sock) != 2)
+ return;
+
+ snprintf(buf, sizeof(buf), "rcpt to: %s\n", to);
+ if(sendRequest(sock, buf) || waitReply(sock) != 2)
+ return;
+
+ if(sendRequest(sock, "data\n") || waitReply(sock) != 3)
+ return;
+
+ doSendBody(sock, fp, from, to, subject);
+
+ if(sendRequest(sock, "\n.\n") || waitReply(sock) != 2)
+ return;
+}
+
+void sendMail() {
+ int fd, sock;
+ MailQueue mq;
+
+ if(access(NEWINDEX, R_OK | W_OK)) {
+ if(link(INDEX, NEWINDEX) || unlink(INDEX))
+ /* nothing to do */
+ return;
+ }
+
+ if((sock = connectMailServer()) < 0) {
+ fprintf(stderr, "connect server failed...\n");
+ return;
+ }
+
+ fd = open(NEWINDEX, O_RDONLY);
+ flock(fd, LOCK_EX);
+ while(read(fd, &mq, sizeof(mq)) > 0) {
+ FILE *fp;
+ char buf[256];
+
+ snprintf(buf, sizeof(buf), "%s%s", mq.sender, FROM);
+ if((fp = fopen(mq.filepath, "r"))) {
+ setproctitle("outmail: sending %s", mq.filepath);
+ doSendMail(sock, fp, buf, mq.rcpt, mq.subject);
+ fclose(fp);
+ unlink(mq.filepath);
+ } else {
+ perror(mq.filepath);
+ }
+ }
+ flock(fd, LOCK_UN);
+ close(fd);
+ unlink(NEWINDEX);
+
+ disconnectMailServer(sock);
+}
+
+void listQueue() {
+ int fd;
+
+ if((fd = open(INDEX, O_RDONLY)) >= 0) {
+ int counter = 0;
+ MailQueue mq;
+
+ flock(fd, LOCK_EX);
+ while(read(fd, &mq, sizeof(mq)) > 0) {
+ printf("%s:%s -> %s:%s\n", mq.filepath, mq.username, mq.rcpt,
+ mq.subject);
+ counter++;
+ }
+ flock(fd, LOCK_UN);
+ close(fd);
+ printf("\nTotal: %d mails in queue\n", counter);
+ } else {
+ perror(INDEX);
+ }
+}
+
+void usage() {
+ fprintf(stderr, "usage: outmail [-qh]\n");
+}
+
+void wakeup(int s) {
+}
+
+int main(int argc, char **argv, char **envp) {
+ int ch;
+
+ signal(SIGHUP, wakeup);
+ initsetproctitle(argc, argv, envp);
+
+ if(chdir(BBSHOME))
+ return 1;
+ while((ch = getopt(argc, argv, "qh")) != -1) {
+ switch(ch) {
+ case 'q':
+ listQueue();
+ return 0;
+ default:
+ usage();
+ return 0;
+ }
+ }
+ for(;;) {
+ sendMail();
+ setproctitle("outmail: sleeping");
+ sleep(60 * 3); /* send mail every 3 minute */
+ }
+ return 0;
+}
diff --git a/util/parse_news.c b/util/parse_news.c
new file mode 100644
index 00000000..bebed3f4
--- /dev/null
+++ b/util/parse_news.c
@@ -0,0 +1,78 @@
+/* $Id: parse_news.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "config.h"
+#include "pttstruct.h"
+#include "util.h"
+
+#define NEWSDIRECT BBSHOME "/boards/newspaper"
+#define MOVIEDIRECT BBSHOME "/etc/NEWS"
+
+int main() {
+ int fd;
+ fileheader_t fh, news;
+ struct stat st;
+ register int numfiles, n;
+ FILE *fp = NULL;
+ char buf[200];
+
+ if (stat(NEWSDIRECT "/.DIR", &st) < 0)
+ return 0;
+
+ system("rm -f " MOVIEDIRECT "/*");
+ system("rm -f " MOVIEDIRECT "/.DIR");
+
+ numfiles = st.st_size / sizeof(fileheader_t);
+ n = 0;
+ if ((fd = open(NEWSDIRECT "/.DIR", O_RDONLY)) > 0)
+ {
+ lseek(fd, st.st_size - sizeof(fileheader_t), SEEK_SET);
+ while (numfiles-- && n < 100)
+ {
+ read(fd, &fh, sizeof(fileheader_t));
+ if (!strcmp(fh.owner, "CNA-News."))
+ {
+ if (!strstr(fh.title, "¬¡°Ê¹w§i") && !strstr(fh.title, "¤¤¥¡®ð¶H§½")
+ && !strstr(fh.title, "¾ú¥v¤Wªº¤µ¤Ñ") && !strstr(fh.title, "ÀY±ø·s»D¼ÐÃD")
+ && !strstr(fh.title, "Summary") && !strstr(fh.title, "¥þ²y®ð¶H¤@Äý")
+ && !strstr(fh.title, "®Õ¥¿¤½¹q"))
+ {
+ if (!(n % 10))
+ {
+ if (n)
+ {
+ fclose(fp);
+ append_record(MOVIEDIRECT "/.DIR", &news, sizeof(news));
+ }
+ strcpy(buf, MOVIEDIRECT);
+ stampfile(buf, &news);
+ sprintf(news.title, "¤¤¥¡ªÀ§Y®É·s»D %s", fh.date);
+ strcpy(news.owner, "CNA-News.");
+ news.savemode = 0;
+ if (!(fp = fopen(buf, "w")))
+ return (0);
+ fprintf(fp, " ¢w¢w¢w¢w¢w¢w¢w¢w¢w ¤¤¥¡ªÀ§Y®É·s»D (%s)¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w\n",
+ fh.date);
+ }
+ fprintf(fp, " ¢w¢w¢w¢w¢w¡º [1;3%dm%s %.*s\n",
+ (n % 6 + 4) % 7 + 1, fh.title,
+ (int)(46 - strlen(fh.title)),
+ "¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w¢w");
+ n++;
+ printf("[%d]\n", n);
+
+ }
+ }
+ lseek(fd, -(off_t) 2 * sizeof(fileheader_t), SEEK_CUR);
+ }
+ close(fd);
+ fclose(fp);
+ append_record(MOVIEDIRECT "/.DIR", &news, sizeof(news));
+ }
+ return 0;
+}
diff --git a/util/post.c b/util/post.c
new file mode 100644
index 00000000..efec797f
--- /dev/null
+++ b/util/post.c
@@ -0,0 +1,61 @@
+/* $Id: post.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <time.h>
+#include "config.h"
+#include "pttstruct.h"
+#include "util.h"
+
+void keeplog(FILE *fin, char *fpath, char *board, char *title, char *owner) {
+ fileheader_t fhdr;
+ char genbuf[256], buf[512];
+ FILE *fout;
+ int bid;
+
+ sprintf(genbuf, BBSHOME "/boards/%s", board);
+ stampfile(genbuf, &fhdr);
+
+ if(!(fout = fopen(genbuf, "w"))) {
+ perror(genbuf);
+ return;
+ }
+
+ while(fgets(buf, 512, fin))
+ fputs(buf, fout);
+
+ fclose(fin);
+ fclose(fout);
+
+ strncpy(fhdr.title, title, sizeof(fhdr.title) - 1);
+ fhdr.title[sizeof(fhdr.title) - 1] = '\0';
+
+ strcpy(fhdr.owner, owner);
+ sprintf(genbuf, BBSHOME "/boards/%s/.DIR", board);
+ append_record(genbuf, &fhdr, sizeof(fhdr));
+ if((bid = getbnum(board)) > 0)
+ touchbtotal(bid);
+
+}
+
+int main(int argc, char **argv) {
+ FILE *fp;
+
+ resolve_boards();
+ if(argc != 5) {
+ printf("usage: %s <board name> <title> <owner> <file>\n", argv[0]);
+ return 0;
+ }
+
+ if(strcmp(argv[4], "-") == 0)
+ fp = stdin;
+ else {
+ fp = fopen(argv[4], "r");
+ if(!fp) {
+ perror(argv[4]);
+ return 1;
+ }
+ }
+ keeplog(fp, argv[4], argv[1], argv[2], argv[3]);
+ return 0;
+}
diff --git a/util/poststat.c b/util/poststat.c
new file mode 100644
index 00000000..3aa3cc94
--- /dev/null
+++ b/util/poststat.c
@@ -0,0 +1,497 @@
+/* $Id: poststat.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */
+/* ²Î­p¤µ¤é¡B¶g¡B¤ë¡B¦~¼öªù¸ÜÃD */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+#ifdef __FreeBSD__
+#include <machine/param.h>
+#endif
+
+#include "config.h"
+#include "pttstruct.h"
+
+char *myfile[] =
+{"day", "week", "month", "year"};
+int mycount[4] =
+{7, 4, 12};
+int mytop[] =
+{10, 50, 100, 100};
+char *mytitle[] =
+{"¤é¤Q", "¶g¤­¤Q", "¤ë¦Ê", "¦~«×¦Ê"};
+
+
+#define HASHSIZE 1024
+#define TOPCOUNT 200
+
+
+struct postrec
+{
+ char author[13]; /* author name */
+ char board[13]; /* board name */
+ char title[66]; /* title name */
+ time_t date; /* last post's date */
+ int number; /* post number */
+ struct postrec *next; /* next rec */
+}
+*bucket[HASHSIZE];
+
+
+/* 100 bytes */
+struct posttop
+{
+ char author[13]; /* author name */
+ char board[13]; /* board name */
+ char title[66]; /* title name */
+ time_t date; /* last post's date */
+ int number; /* post number */
+}
+top[TOPCOUNT], *tp;
+
+
+
+/*
+ woju
+ Cross-fs rename()
+ */
+
+int Rename(char *src, char *dst)
+{
+
+ if (rename(src, dst) == 0)
+ return 0;
+/*
+ sprintf(cmd, "/bin/mv %s %s", src, dst);
+ return system(cmd);
+*/
+ return 0;
+}
+
+
+
+/*-------------------------------------------------------*/
+/* .BOARDS cache */
+/*-------------------------------------------------------*/
+
+struct bcache_t *brdshm;
+boardheader_t *bcache;
+int numboards = -1;
+
+
+static void
+attach_err(shmkey, name)
+ int shmkey;
+ char *name;
+{
+ fprintf(stderr, "[%s error] key = %x\n", name, shmkey);
+ exit(1);
+}
+
+
+static void *
+attach_shm(shmkey, shmsize)
+ int shmkey, shmsize;
+{
+ void *shmptr;
+ int shmid;
+
+ 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");
+ memset(shmptr, 0, shmsize);
+ }
+ else
+ {
+ shmptr = (void *) shmat(shmid, NULL, 0);
+ if (shmptr == (void *) -1)
+ attach_err(shmkey, "shmat");
+ }
+ return shmptr;
+}
+
+
+
+void
+resolve_boards()
+{
+ if (brdshm == NULL)
+ {
+ brdshm = attach_shm(BRDSHM_KEY, sizeof(*brdshm));
+ if (brdshm->touchtime == 0)
+ brdshm->touchtime = 1;
+ bcache = brdshm->bcache;
+ }
+
+ while (brdshm->uptime < brdshm->touchtime)
+ {
+ if (brdshm->busystate)
+ {
+ sleep(1);
+ }
+ else
+ {
+ int fd;
+
+ brdshm->busystate = 1;
+
+ if ((fd = open(".BOARDS", O_RDONLY)) > 0)
+ {
+ brdshm->number = read(fd, bcache, MAX_BOARD * sizeof(boardheader_t))
+ / sizeof(boardheader_t);
+ close(fd);
+ }
+
+ /* µ¥©Ò¦³ boards ¸ê®Æ§ó·s«á¦A³]©w uptime */
+
+ brdshm->uptime = brdshm->touchtime;
+ brdshm->busystate = 0;
+ }
+ }
+ numboards = brdshm->number;
+}
+
+
+int
+ci_strcmp(s1, s2)
+ register char *s1, *s2;
+{
+ register int c1, c2, diff;
+
+ do
+ {
+ c1 = *s1++;
+ c2 = *s2++;
+ if (c1 >= 'A' && c1 <= 'Z')
+ c1 |= 32;
+ if (c2 >= 'A' && c2 <= 'Z')
+ c2 |= 32;
+ if((diff = c1 - c2))
+ return (diff);
+ }
+ while (c1);
+ return 0;
+}
+
+int
+get_record(fpath, rptr, size, id)
+ char *fpath;
+ char *rptr;
+ int size, id;
+{
+ int fd;
+
+ if ((fd = open(fpath, O_RDONLY, 0)) != -1)
+ {
+ if (lseek(fd, size * (id - 1), SEEK_SET) != -1)
+ {
+ if (read(fd, rptr, size) == size)
+ {
+ close(fd);
+ return 0;
+ }
+ }
+ close(fd);
+ }
+ return -1;
+}
+
+
+int
+getbnum(bname)
+ char *bname;
+{
+ register int i;
+ register boardheader_t *bhdr;
+
+ resolve_boards();
+ for (i = 0, bhdr = bcache; i++ < numboards; bhdr++)
+ /* if (Ben_Perm(bhdr)) */
+ if (!ci_strcmp(bname, bhdr->brdname))
+ return i;
+ return 0;
+}
+
+
+int
+hash(key)
+ char *key;
+{
+ int i, value = 0;
+
+ for (i = 0; key[i] && i < 80; i++)
+ value += key[i] < 0 ? -key[i] : key[i];
+
+ value = value % HASHSIZE;
+ return value;
+}
+
+
+/* ---------------------------------- */
+/* hash structure : array + link list */
+/* ---------------------------------- */
+
+
+void
+search(t)
+ struct posttop *t;
+{
+ struct postrec *p, *q, *s;
+ int i, found = 0;
+
+ i = hash(t->title);
+ q = NULL;
+ p = bucket[i];
+ while (p && (!found))
+ {
+ if (!strcmp(p->title, t->title) && !strcmp(p->board, t->board))
+ found = 1;
+ else
+ {
+ q = p;
+ p = p->next;
+ }
+ }
+ if (found)
+ {
+ p->number += t->number;
+ if (p->date < t->date) /* ¨ú¸ûªñ¤é´Á */
+ p->date = t->date;
+ }
+ else
+ {
+ s = (struct postrec *) malloc(sizeof(struct postrec));
+ memcpy(s, t, sizeof(struct posttop));
+ s->next = NULL;
+ if (q == NULL)
+ bucket[i] = s;
+ else
+ q->next = s;
+ }
+}
+
+
+int
+sort(pp, count)
+ struct postrec *pp;
+{
+ int i, j;
+
+ for (i = 0; i <= count; i++)
+ {
+ if (pp->number > top[i].number)
+ {
+ if (count < TOPCOUNT - 1)
+ count++;
+ for (j = count - 1; j >= i; j--)
+ memcpy(&top[j + 1], &top[j], sizeof(struct posttop));
+
+ memcpy(&top[i], pp, sizeof(struct posttop));
+ break;
+ }
+ }
+ return count;
+}
+
+
+void
+load_stat(fname)
+ char *fname;
+{
+ FILE *fp;
+
+ if((fp = fopen(fname, "r")))
+ {
+ int count = fread(top, sizeof(struct posttop), TOPCOUNT, fp);
+ fclose(fp);
+ while (count)
+ search(&top[--count]);
+ }
+}
+
+
+int
+filter(board)
+ char *board;
+{
+ boardheader_t bh;
+ int bid;
+
+ bid = getbnum(board);
+ if (get_record(".BOARDS", &bh, sizeof(bh), bid) == -1)
+ return 1;
+ if (bh.brdattr & BRD_NOCOUNT)
+ return 1;
+/*
+ if (bh.brdattr & BRD_POSTMASK)
+ return 0;
+ return (bh.brdattr & ~BRD_POSTMASK) ||
+ >= 32;
+*/
+ return 0;
+}
+
+
+void
+poststat(mytype)
+ int mytype;
+{
+ static char *logfile = ".post";
+ static char *oldfile = ".post.old";
+
+ FILE *fp;
+ char buf[40], curfile[40] = "etc/day.0", *p;
+ struct postrec *pp;
+ int i, j;
+
+ if (mytype < 0)
+ {
+ /* --------------------------------------- */
+ /* load .post and statictic processing */
+ /* --------------------------------------- */
+
+ remove(oldfile);
+ Rename(logfile, oldfile);
+ if ((fp = fopen(oldfile, "r")) == NULL)
+ return;
+ mytype = 0;
+ load_stat(curfile);
+
+ while (fread(top, sizeof(struct posttop), 1, fp))
+ search(top);
+ fclose(fp);
+ }
+ else
+ {
+ /* ---------------------------------------------- */
+ /* load previous results and statictic processing */
+ /* ---------------------------------------------- */
+
+ i = mycount[mytype];
+ p = myfile[mytype];
+ while (i)
+ {
+ sprintf(buf, "etc/%s.%d", p, i);
+ sprintf(curfile, "etc/%s.%d", p, --i);
+ load_stat(curfile);
+ Rename(curfile, buf);
+ }
+ mytype++;
+ }
+
+/* ---------------------------------------------- */
+/* sort top 100 issue and save results */
+/* ---------------------------------------------- */
+
+ memset(top, 0, sizeof(top));
+ for (i = j = 0; i < HASHSIZE; i++)
+ {
+ for (pp = bucket[i]; pp; pp = pp->next)
+ {
+#ifdef DEBUG
+ printf("Title : %s, Board: %s\nPostNo : %d, Author: %s\n"
+ ,pp->title
+ ,pp->board
+ ,pp->number
+ ,pp->author);
+#endif
+
+ j = sort(pp, j);
+ }
+ }
+
+ p = myfile[mytype];
+ sprintf(curfile, "etc/%s.0", p);
+ if((fp = fopen(curfile, "w")))
+ {
+ fwrite(top, sizeof(struct posttop), j, fp);
+ fclose(fp);
+ }
+
+ sprintf(curfile, "etc/%s", p);
+ if((fp = fopen(curfile, "w")))
+ {
+ int max, cnt;
+
+ fprintf(fp, "\t\t-----===== ¥»%s¤j¼öªù¸ÜÃD =====-----\n\n", mytitle[mytype]);
+
+ max = mytop[mytype];
+ p = buf + 4;
+ for (i = cnt = 0; (cnt < max) && (i < j); i++)
+ {
+ tp = &top[i];
+ if (filter(tp->board))
+ continue;
+
+ strcpy(buf, ctime(&(tp->date)));
+ buf[20] = 0;
+ fprintf(fp,
+ "%3d. ¬ÝªO : %-16s¡m %s¡n%4d ½g%16s\n"
+ " ¼ÐÃD : %-60.60s\n"
+ ,++cnt, tp->board, p, tp->number, tp->author, tp->title);
+ }
+ fclose(fp);
+ }
+
+/* free statistics */
+
+ for (i = 0; i < HASHSIZE; i++)
+ {
+ struct postrec *pp0;
+
+ pp = bucket[i];
+ while (pp)
+ {
+ pp0 = pp;
+ pp = pp->next;
+ free(pp0);
+ }
+
+ bucket[i] = NULL;
+ }
+}
+
+
+int main(argc, argv)
+ char *argv[];
+{
+ time_t now;
+ struct tm *ptime;
+
+ if (argc < 2)
+ {
+ printf("Usage:\t%s bbshome [day]\n", argv[0]);
+ return (-1);
+ }
+ chdir(argv[1]);
+
+ if (argc == 3)
+ {
+ poststat(atoi(argv[2]));
+ return (0);
+ }
+ time(&now);
+ ptime = localtime(&now);
+ if (ptime->tm_hour == 0)
+ {
+ if (ptime->tm_mday == 1)
+ poststat(2);
+
+ if (ptime->tm_wday == 0)
+ poststat(1);
+ poststat(0);
+ }
+ poststat(-1);
+ return 0;
+}
diff --git a/util/reaper.c b/util/reaper.c
new file mode 100644
index 00000000..925ea11b
--- /dev/null
+++ b/util/reaper.c
@@ -0,0 +1,69 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <time.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include "config.h"
+#include "pttstruct.h"
+#include "perm.h"
+#include "util.h"
+
+time_t now;
+
+int invalid(char *userid) {
+ int i;
+
+ if(!isalpha(userid[0]))
+ return 1;
+
+ for(i = 1; i < IDLEN && userid[i]; i++)
+ if(!isalpha(userid[i]) && !isdigit(userid[i]))
+ return 1;
+ return 0;
+}
+
+int check(int n, userec_t *u) {
+ time_t d;
+ char buf[256];
+
+ if(u->userid[0] != '\0') {
+ if(invalid(u->userid)) {
+ syslog(LOG_ERR, "bad userid(%d): %s", n, u->userid);
+ u->userid[0] = '\0';
+ } else {
+ d = now - u->lastlogin;
+ if((d > MAX_GUEST_LIFE && (u->userlevel & PERM_LOGINOK) == 0) ||
+ (d > MAX_LIFE && (u->userlevel & PERM_XEMPT) == 0)) {
+ /* expired */
+ int unum;
+
+ unum = searchuser(u->userid);
+ strcpy(buf, ctime(&u->lastlogin));
+ strtok(buf, "\n");
+ syslog(LOG_NOTICE, "kill user(%d): %s %s", unum, u->userid, buf);
+ sprintf(buf, "mv home/%c/%s tmp/", u->userid[0], u->userid);
+ if(system(buf))
+ syslog(LOG_ERR, "can't move user home: %s", u->userid);
+ u->userid[0] = '\0';
+ setuserid(unum, u->userid);
+ }
+ }
+ }
+ return 0;
+}
+
+int main() {
+ now = time(NULL);
+ openlog("reaper", LOG_PID | LOG_PERROR, SYSLOG_FACILITY);
+ chdir(BBSHOME);
+
+ if(passwd_mmap())
+ exit(1);
+ passwd_apply2(check);
+
+ return 0;
+}
diff --git a/util/rmuid.c b/util/rmuid.c
new file mode 100644
index 00000000..cc6e12cb
--- /dev/null
+++ b/util/rmuid.c
@@ -0,0 +1,50 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include "config.h"
+#include "pttstruct.h"
+#include "util.h"
+
+extern int numboards;
+extern boardheader_t *bcache;
+
+int getbidofuid(int uid)
+{
+ register int n; boardheader_t *bh;
+ if(!uid) return 1;
+ for (n=0;n<numboards;n++)
+ {
+ bh = &bcache[n];
+ if(bh->unused == uid)
+ return n+1;
+ }
+ return 1;
+}
+
+int main(int argc, char* argv[]){
+struct stat st;
+ int n;
+ boardheader_t bh;
+ char pathname[1024];
+
+ resolve_boards();
+ for (n=0;n<numboards;n++)
+ {
+ memcpy( &bh, &bcache[n], sizeof(bh));
+ bh.gid=getbidofuid(bh.gid);
+ //printf("%14.14s%14.14s \r\n",bh.brdname, bh.title);
+ substitute_record("BOARDS.bid", &bh, sizeof(bh), n+1);
+ }
+}
+
+
+
+
+
+
+
diff --git a/util/shmsweep.c b/util/shmsweep.c
new file mode 100644
index 00000000..01acb26b
--- /dev/null
+++ b/util/shmsweep.c
@@ -0,0 +1,43 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/stat.h>
+#include "config.h"
+#include "pttstruct.h"
+
+int main() {
+ int i, shm, counter;
+ struct utmpfile_t *utmpshm;
+
+
+ shm = shmget(UTMPSHM_KEY, USHM_SIZE, SHM_R | SHM_W);
+ if(shm == -1) {
+ perror("shmget");
+ exit(0);
+ }
+
+ utmpshm = shmat(shm, NULL, 0);
+ if(utmpshm == (struct utmpfile_t *)-1) {
+ perror("shmat");
+ exit(0);
+ }
+
+ for(i = counter = 0; i < USHM_SIZE; i++)
+ if(utmpshm->uinfo[i].pid) {
+ char buf[256];
+ userinfo_t *f;
+ struct stat sb;
+
+ f = &utmpshm->uinfo[i];
+ sprintf(buf, "/proc/%d", f->pid);
+ if(stat(buf, &sb)) {
+ f->pid = 0;
+ utmpshm->number--;
+ counter++;
+ }
+ }
+ printf("clear %d slots\n", counter);
+ return 0;
+}
diff --git a/util/showboard.c b/util/showboard.c
new file mode 100644
index 00000000..3801dbb1
--- /dev/null
+++ b/util/showboard.c
@@ -0,0 +1,70 @@
+/* $Id: showboard.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */
+/* ¬ÝªO¤@Äýªí(sorted) */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include "config.h"
+#include "pttstruct.h"
+
+boardheader_t allbrd[MAX_BOARD];
+
+int
+board_cmp(a, b)
+ boardheader_t *a, *b;
+{
+ return (strcasecmp(a->brdname, b->brdname));
+}
+
+
+int main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ int inf, i, count;
+
+ if (argc < 2)
+ {
+ printf("Usage:\t%s .BOARDS [MAXUSERS]\n", argv[0]);
+ exit(1);
+ }
+
+
+ inf = open(argv[1], O_RDONLY);
+ if (inf == -1)
+ {
+ printf("error open file\n");
+ exit(1);
+ }
+
+/* read in all boards */
+
+ i = 0;
+ memset(allbrd, 0, MAX_BOARD * sizeof(boardheader_t));
+ while (read(inf, &allbrd[i], sizeof(boardheader_t)) == sizeof(boardheader_t))
+ {
+ if (allbrd[i].brdname[0] )
+ {
+ i++;
+ }
+ }
+ close(inf);
+
+/* sort them by name */
+ count = i;
+ qsort(allbrd, count, sizeof(boardheader_t), board_cmp);
+
+/* write out the target file */
+
+ printf(
+ "¬ÝªO¦WºÙ ªO¥D Ãþ§O ¤¤¤å±Ô­z\n"
+ "----------------------------------------------------------------------\n");
+ for (i = 0; i < count; i++)
+ {
+ printf("%-13s%-25.25s%s\n", allbrd[i].brdname, allbrd[i].BM, allbrd[i].title);
+ }
+ return 0;
+}
diff --git a/util/smtest.c b/util/smtest.c
new file mode 100644
index 00000000..16a2360d
--- /dev/null
+++ b/util/smtest.c
@@ -0,0 +1,296 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <ctype.h>
+#include "config.h"
+#include "pttstruct.h"
+#include "util.h"
+#include "perm.h"
+#include "common.h"
+#include "proto.h"
+
+#define WARNFILE BBSHOME "/etc/DeleteBoard.warn"
+#define EXECFILE BBSHOME"/etc/DeleteBoard.exec"
+#define WARNLIST BBSHOME"/etc/DeleteBoardList.warn"
+#define EXECLIST BBSHOME"/etc/DeleteBoardList.exec"
+
+extern boardheader_t *bcache;
+extern int numboards;
+
+boardheader_t allbrd[MAX_BOARD];
+extern userec_t xuser;
+
+
+int LINK(char* src, char* dst){
+ char cmd[200];
+
+ if( link(src, dst) == 0){
+ return 0;
+ }
+
+ sprintf(cmd, "/bin/cp -R %s %s", src, dst);
+ return system(cmd);
+}
+
+int outofdate(char *hdrdate, char thedate[], int *zf)
+{
+ int k = 0;
+ char *dd;
+ char latestdate[6];
+ int date1[2], date2[2],datetemp;
+ *zf = 0;
+
+ strcpy(latestdate, thedate);
+
+ dd = strtok(hdrdate,"/");
+ if(dd == NULL) return 2;
+ if(dd)
+ k = 0;
+ do{
+ if (*dd == '[' ){dd[strlen(dd)-1]='\0'; dd++;}
+ date1[k] = atoi(dd);
+ k++;
+ } while((dd=strtok(NULL,"/ "))!=NULL);
+
+ dd = strtok(latestdate,"/");
+ if(dd)
+ k = 0;
+ do{
+ if (*dd == '[' ){dd[strlen(dd)-1]='\0'; dd++;}
+ date2[k] = atoi(dd);
+ k++;
+ } while((dd=strtok(NULL,"/ "))!=NULL);
+
+ if(date2[0] == date1[0] && date2[1] >= date1[1])
+ return 0;
+
+ datetemp = date2[0];
+
+ for(k = 1;k <= 5;k++)
+ {
+ datetemp -= 1;
+ if((datetemp) <= 0){
+ datetemp = 12;
+ }
+ if(k < 3 && datetemp == date1[0]) return 0;
+ if(k == 3 && datetemp == date1[0] && date2[1] <= date1[1]) return 0;
+ if(k == 3 && datetemp == date1[0] && date2[1] > date1[1]) return 1;
+ if(k == 4 && datetemp == date1[0] && date2[1] > date1[1]) return 1;
+ }
+ *zf = 1;
+ return 1;
+}
+
+void mailtouser(char *bmname, char *bname, int zf)
+{
+ fileheader_t mymail;
+ char genbuf[200];
+
+ sprintf(genbuf, BBSHOME "/home/%c/%s", bmname[0], bmname);
+ stampfile(genbuf, &mymail);
+ strcpy(mymail.owner, "[PTTĵ¹î§½]");
+
+ if(zf == 0){
+ sprintf(mymail.title,"\033[32m [¼oª©Äµ§i³qª¾]"
+ "\033[m %sª©(BM:%s)",bname, bmname);
+ }else{
+ sprintf(mymail.title,"\033[32m [¼oª©³qª¾] "
+ "\033[m %sª©(BM:%s)",bname, bmname);
+ }
+ mymail.savemode = 0 ;
+ unlink(genbuf);
+ if(zf == 0){
+ LINK(WARNFILE, genbuf);
+ }else{
+ LINK(EXECFILE, genbuf);
+ }
+
+ sprintf(genbuf, BBSHOME "/home/%c/%s/.DIR", bmname[0], bmname);
+ append_record(genbuf, &mymail, sizeof(mymail));
+}
+
+int main()
+{
+ int bmid, i, j, k, rd, ood, flag, zapflag = 0,warncount = 0,execcount = 0;
+ char *p, *bmsname[3], fname[256], hdrdatetemp[6],thedate[6];
+ char bname[32],genbuf[200];
+ fileheader_t hdr;
+ FILE *inf, *def;
+
+ ///// set date //////
+ time_t t = time(NULL);
+ struct tm *tm = localtime(&t);
+ sprintf(thedate, "%2d/%02d", tm->tm_mon + 1, tm->tm_mday);
+
+ ////// board //////
+
+ resolve_boards();
+ if(passwd_mmap())
+ exit(1);
+ memcpy(allbrd,bcache,numboards*sizeof(boardheader_t));
+
+ ////// write out the target file //////
+ inf = fopen(WARNLIST, "w+");
+ if(inf == NULL){
+ printf("open file error : %s\n", WARNLIST);
+ exit(1);
+ }
+
+ def = fopen(EXECLIST, "w+");
+ if(def == NULL)
+ {
+ printf("open file error : %s\n", EXECLIST);
+ exit(1);
+ }
+
+ ////// fprint table title /////
+ fprintf(inf,"\n[¼oª©Äµ§i]§Y¤é°_¤@­Ó¤ë¤º­Y¬ÝªO"
+ "¨Ï¥Î²v¤´µM¹L§C¡A«h¤©¥H¼o°£¡C\n\n"
+ "­^¤åª©¦W Ãþ§O ¤¤¤åª©¦W ¤é´Á "
+ " ª©¥D¦W³æ\n\n");
+
+ fprintf(def,"\n[¼oª©¤½§i]¤U¦C¬ÝªO¦]¨Ï¥Î²v¤´µM¹L§C¡A¬G¤©¥H¼o°£¡C\n\n"
+ "­^¤åª©¦W Ãþ§O ¤¤¤åª©¦W ¤é´Á "
+ " ª©¥D¦W³æ\n\n");
+
+ ////// start process /////
+ j = 0 ;
+ for (i = 0; i < numboards; i++) {
+ rd = 0;
+ if(allbrd[i].brdname[0] == '\0') continue;
+ if((allbrd[i].brdattr & BRD_NOZAP) ||
+ (allbrd[i].brdattr & BRD_GROUPBOARD) ||
+ (allbrd[i].brdattr & BRD_WARNDEL) ||
+ (allbrd[i].brdattr & BRD_HIDE) ||
+ (allbrd[i].brdattr & BRD_POSTMASK) ||
+ (allbrd[i].brdattr & BRD_VOTEBOARD) ||
+ (allbrd[i].brdattr & BRD_BAD) ||
+ (allbrd[i].level != 0)) continue;
+
+ sprintf(fname, BBSHOME "/boards/%s/.DIR",allbrd[i].brdname);
+
+ /* get date to choose junk board */
+ /* exception when ood == 2 */
+ flag = 30;
+ rd = get_num_records(fname, sizeof(fileheader_t));
+ if(rd <= 30)
+ {
+ get_record(fname, &hdr, sizeof (hdr), 1);
+ strcpy(hdrdatetemp, hdr.date);
+ ood = outofdate(hdrdatetemp,thedate, &zapflag);
+ }
+ else
+ {
+ do{
+ if(rd == 0)
+ {
+ ood = 0;
+ break;
+ }
+ get_record(fname, &hdr, sizeof (hdr), rd - flag);
+ strcpy(hdrdatetemp, hdr.date);
+ ood = outofdate(hdrdatetemp,thedate, &zapflag);
+ flag += 5;
+ }while(ood == 2 && flag < 60);
+ }
+ if(ood == 0) continue;
+
+ warncount++;
+ /* print to file */
+ fprintf(inf,"%-*.*s%-*.*s %-*.*s%-*.*s\n", IDLEN, IDLEN,
+ allbrd[i].brdname, BTLEN-26, BTLEN-26, allbrd[i].title,
+ IDLEN - 5, IDLEN-5,hdr.date, IDLEN * 3, IDLEN * 3, allbrd[i].BM);
+
+ /* post warn file to each board */
+ sprintf(genbuf,"~/bin/post %s [¼oª©Äµ§i³qª¾]"
+ " [PTTĵ¹î§½] %s",allbrd[i].brdname,WARNFILE);
+ system(genbuf);
+
+ /* user extract to mail */
+ p=strtok(allbrd[i].BM,"/ ");
+ if(p){
+ k = 0;
+ do
+ {
+ if (*p == '[' ){p[strlen(p)-1]='\0'; p++;}
+ bmid=getuser(p);
+ bmsname[k] = p;
+ if(isalpha(allbrd[i].BM[0])&& !(xuser.userlevel &PERM_SYSOP))
+ {
+ mailtouser(bmsname[k],allbrd[i].title, zapflag);
+ }
+ k++;
+ } while((p=strtok(NULL,"/ "))!=NULL);
+ }
+ /* set attribute of DeleteBoardWarn Flag */
+ bcache[i].brdattr = allbrd[i].brdattr | BRD_WARNDEL;
+
+ /* zap boards */
+ if (zapflag == 1)
+ {
+ execcount++;
+ /* print to file */
+ fprintf(def,"%-*.*s%-*.*s %-*.*s%-*.*s\n", IDLEN, IDLEN,
+ allbrd[i].brdname, BTLEN-26, BTLEN-26, allbrd[i].title,
+ IDLEN - 5, IDLEN-5,hdr.date, IDLEN * 3, IDLEN * 3, allbrd[i].BM);
+
+// strcpy(bname, allbrd[i].brdname);
+// sprintf(genbuf,
+// "/bin/tar zcvf ~/tmp/board_%s.tgz boards/%s man/%s>/dev/null 2>&1;"
+// "/bin/rm -fr ~/boards/%s man/%s",bname, bname, bname, bname,bname);
+// system(genbuf);
+
+// memset(&allbrd[i], 0, sizeof(allbrd[i]));
+// sprintf(allbrd[i].title, "[%s] deleted by System", bname);
+// substitute_record(fn_board, &bh, sizeof(allbrd[i]), bid);
+// reset_board(bid);
+ }
+
+ }
+
+ /* post to Record, ViolateLaw */
+ if(warncount > 0){
+ sprintf(genbuf,"~/bin/post Record [¼oª©Äµ§i³qª¾]"
+ " [PTTĵ¹î§½] %s",WARNLIST);
+ system(genbuf);
+ sprintf(genbuf,"~/bin/post ViolateLaw [¼oª©Äµ§i³qª¾]"
+ " [PTTĵ¹î§½] %s",WARNLIST);
+ system(genbuf);
+ }
+ if(execcount > 0){
+ sprintf(genbuf,"~/bin/post Record [¼oª©¤½§i]"
+ " [PTTĵ¹î§½] %s",EXECLIST);
+ system(genbuf);
+ sprintf(genbuf,"~/bin/post ViolateLaw [¼oª©¤½§i]"
+ " [PTTĵ¹î§½] %s",EXECLIST);
+ system(genbuf);
+ }
+
+
+/* Below is for test only */
+/*
+ mailtouser("Smile","test", 1);
+ mailtouser("Smile","test", 0);
+
+ strcpy(bname, "Test");
+ sprintf(genbuf,"~/bin/post %s test Smile ~/etc/test.fileaaa",bname);
+ system(genbuf);
+
+
+ bid = getbnum(bname);
+ strcpy(bname,"jourslamdunk");
+ sprintf(genbuf,
+ "/bin/tar zcvf ~/tmp/board_%s.tgz boards/%s man/%s>/dev/null 2>&1;"
+ "/bin/rm -fr ~/boards/%s man/%s",bname, bname, bname,bname,bname);
+ system(genbuf);
+
+ memset(&bh, 0, sizeof(bh));
+ sprintf(bh.title, "[%s] deleted by %s", bname,cuser.userid);
+ substitute_record(fn_board, &bh, sizeof(bh), bid);
+ reset_board(bid);
+*/
+ return 0;
+}
diff --git a/util/smtest.c.save b/util/smtest.c.save
new file mode 100644
index 00000000..7e678881
--- /dev/null
+++ b/util/smtest.c.save
@@ -0,0 +1,172 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <ctype.h>
+#include "config.h"
+#include "pttstruct.h"
+#include "util.h"
+#include "perm.h"
+#include "common.h"
+#include "proto.h"
+
+#define OUTFILE BBSHOME "/pttbbs/util/smtest.result1"
+#define FIREFILE BBSHOME "/pttbbs/util/smtest.result2"
+
+extern boardheader_t *bcache;
+extern int numboards;
+
+boardheader_t allbrd[MAX_BOARD];
+struct userec_t xuser;
+
+int getuser(char *userid) {
+ int uid;
+ if((uid = searchuser(userid)))
+ passwd_query(uid, &xuser);
+ return uid;
+}
+
+int LINK(char* src, char* dst){
+ char cmd[200];
+
+ if( link(src, dst) == 0){
+ return 0;
+ }
+
+ sprintf(cmd, "/bin/cp -R %s %s", src, dst);
+ return system(cmd);
+}
+
+int main()
+{
+ int bmid, i, j, k, rd;
+ char *p, *bmsname[3], bmbuf[IDLEN * 3 + 3], fname[256];
+ fileheader_t hdr;
+ FILE *inf;
+
+ resolve_boards();
+ if(passwd_mmap())
+ exit(1);
+ memcpy(allbrd,bcache,numboards*sizeof(boardheader_t));
+
+ /* write out the target file */
+ inf = fopen(OUTFILE, "w+");
+ if(inf == NULL){
+ printf("open file error : %s\n", OUTFILE);
+ exit(1);
+ }
+
+ /*the ouput table title*/
+ fprintf(inf,"­^¤åª©¦W Ãþ§O ¤¤¤åª©¦W ª©¥D¦W³æ"
+ " ¤é´Á ³Æµù \n");
+
+ j = 0 ;
+ for (i = 0; i < 30; i++) {
+ rd = 0;
+ if(allbrd[i].brdname[0] == '\0') continue;
+
+ sprintf(fname, BBSHOME "/boards/%s/.DIR",allbrd[i].brdname);
+
+ rd = get_num_records(fname, sizeof(fileheader_t));
+ get_record(fname, &hdr, sizeof (hdr), rd - 30);
+// printf(" %s %s\n",hdr.title,hdr.date);
+
+ printf("%-*.*s%-*s%s", IDLEN, IDLEN, allbrd[i].brdname, BTLEN,
+ allbrd[i].title,allbrd[i].BM);
+
+ p=strtok(allbrd[i].BM,"/ ");
+ if(p){
+ int k = 0;
+ do
+ {
+ if (*p == '[' ){p[strlen(p)-1]='\0'; p++;}
+ bmid=getuser(p);
+ bmsname[k] = p;
+ if(isalpha(allbrd[i].BM[0])&& !(xuser.userlevel &PERM_SYSOP))
+ {
+ // printf("%s", bmsname[k]);
+ }
+ k++;
+ } while((p=strtok(NULL,"/ "))!=NULL);
+ }
+
+ printf("\n");
+
+}
+
+
+/*
+
+
+
+ if(flag == 1){
+ bmbuf[0] = '\0';
+ for(k = 0 , n = 0; k < index; k++){
+ if(!bms[k].flag){
+ if( n++ != 0) strcat(bmbuf, "/");
+ strcat(bmbuf, bms[k].bmname);
+ }
+ }
+ strcpy(bcache[i].BM, bmbuf);
+ }
+ }
+ qsort(lostbms, j, sizeof(lostbm), bmlostdays_cmp);
+
+ //write to the etc/toplazyBM
+ for ( i=0; i<j; i++)
+ {
+ if( lostbms[i].lostdays > 60){
+ fprintf(firef, "%-*.*s%-*.*s%-*.*s%3d¤Ñ¨S¤W¯¸\n", IDLEN, IDLEN,
+ lostbms[i].title, BTLEN-10, BTLEN-10, lostbms[i].ctitle, IDLEN,IDLEN,
+ lostbms[i].bmname,lostbms[i].lostdays);
+ }else{
+ fprintf(inf, "%-*.*s%-*.*s%-*.*s%3d¤Ñ¨S¤W¯¸\n", IDLEN, IDLEN, lostbms[i].title,
+ BTLEN-10, BTLEN-10, lostbms[i].ctitle, IDLEN,IDLEN,
+ lostbms[i].bmname,lostbms[i].lostdays);
+ }
+ }
+ fclose(inf);
+ fclose(firef);
+
+ //printf("Total %d boards.\n", count);
+
+ //mail to the users
+ for( i=0; i<j; i++)
+ {
+ fileheader_t mymail;
+ char genbuf[200];
+ int lostdays;
+
+ lostdays = lostbms[i].lostdays;
+
+ if( (lostdays != 30) && (lostdays != 45) && (lostdays <= 60))
+ continue;
+
+ sprintf(genbuf, BBSHOME "/home/%c/%s", lostbms[i].bmname[0], lostbms[i].bmname);
+ stampfile(genbuf, &mymail);
+
+ strcpy(mymail.owner, "[PTTĵ¹î§½]");
+
+ if(lostdays <= 60){
+ sprintf(mymail.title,
+ "\033[32m [ª©¥D§K¾ĵ§i³qª¾] \033[m %s BM %s", lostbms[i].title, lostbms[i].bmname);
+ }else{
+ sprintf(mymail.title,
+ "\033[32m [ª©¥D§K¾³qª¾] \033[m %s BM %s", lostbms[i].title, lostbms[i].bmname);
+ }
+ mymail.savemode = 0 ;
+ unlink(genbuf);
+ if(lostdays <= 60){
+ LINK(OUTFILE, genbuf);
+ }else{
+ LINK(FIREFILE, genbuf);
+ }
+
+ sprintf(genbuf, BBSHOME "/home/%c/%s/.DIR", lostbms[i].bmname[0], lostbms[i].bmname);
+ append_record(genbuf, &mymail, sizeof(mymail));
+ }
+*/
+ return 0;
+}
diff --git a/util/smtest.result1 b/util/smtest.result1
new file mode 100644
index 00000000..6dee45ff
--- /dev/null
+++ b/util/smtest.result1
@@ -0,0 +1,191 @@
+­^¤åª©¦W Ãþ§O ¤¤¤åª©¦W ¤é´Á ª©¥D¦W³æ
+ck48th301 «Ø¤¤ ¡·¤jºjÀ°¤§§Ö¼Ö¤Ñ° 3/21 ching/carl/Prosecuted
+Bowling ¹B°Ê ¡´¨«¹L2000,ÁÚ¦V30 7/18 Genson/chiche
+NTUCH-89 ¤Æ¾Ç ¡·²¦·~°Õ¡I¡I 7/10 badora/furtwangler
+SetupBBS BBS ¡·TEST://140.112. 8/08 Libra
+Fei-cat ¹Ï¤å ¡·23:56 ·L»Ä¨ý 8/07 tears
+CKAWE «Ø¤¤ ¡´«Ø¤¤®Õ¤ÍºÞ¼Ö¹Îª 7/04 ckb/papl/trumpet
+jourslamdunk«Ý¼o ¡·¬F¤j·s»D¨tÄx²y¶ 7/04 ¼x¨D¤¤
+ck48th308 «Ø¤¤ ¡·¤S­n²¦·~¤F¡I 7/15 honest
+CS84Her ¤¤¤s ¡·¦U©bªF¦è ¤]­n©M 7/20
+VM ¬P°¨ ¡´¯k¥ú¨}«~«aªº³d¥ 7/20 zoo
+E-Diagrams ®Õ¶é ¡·¤@°_¤K¨ö¤­¤d¦~. 6/29 Benjamin
+ck48th313 «Ø¤¤ ¡´ª©¥D¤£ºÞ¤F,¨ÓÄé 6/08 fantastic
+ck48th324 «Ø¤¤ ¡·«¢«¢«¢... 7/10
+B853023XX ¬Fªv ¡·¤½¦æ·s¥@¬ö 8/15 FireKing
+ck48th303 «Ø¤¤ ¡·§Lªº¥@¬É 6/05 Roses999/henrry/flyingdog
+CS85ee ¤¤¤s ¡·¤j®a¸q°_©¯ºÖ 8/08 admin/MVPgirl
+CS85simple ¤¤¤s ¡·Â²¯Z¤H-¤£Â²³æ 3/29 bbeellaa
+TFG95TRUE ¥_¤@ ¡·¯u¯ZªGµæ¶é 3/29 deceanna
+ck46th318 «Ø¤¤ ¡· ¯¬ ºÖ ¤j ® 3/16 FengX/barkjor
+PTGS50th301 ¤¤¤k ¡·¤Ñ¤U²Ä¤@¯Z--¤¤¤ 8/09 cocoduck/youki
+CS85ming ¤¤¤s ¡·"©ú"¤ß¤p¶é 8/08 shan/lovehook/JWR
+ck47th333 «Ø¤¤ ¡·³o¼Ë·|¤£·|¼oª©? 7/17 diezoo/Express
+TFG97SHOT ¥_¤@ ¡·¦Ì¨º®á¡@¾¾¥Ì°_¤ 8/07 chili/atlantis
+Taichung ªA°È ¡·³Ì³Ì²M·s¥i·R°·± 8/09 Jahon
+southdoor «nªù ¡·«nªù¤»¥Òªºµ£¨¥µ 8/09 happyjoy
+ck47th301 «Ø¤¤ ¡·ÁٳѽְڡH¡H 5/22 huskie/flutii
+hsntu ªþ¤¤ ¡´¥x¤jªþ¤Í·| ¨Ó 11/29 koku/Crony
+JH23th301 °ê¤¤ ¡·§AÁÙ¬¡µÛ¶Ü? 7/25 momi/mvpman
+money ¾Ç³N ¡´Show me the 5/02 kagh
+HSNU_807 ªþ¤¤ ¡·®Ã¨Õ¹s¬m¯Z 7/16 yijean/joj
+ntubbsops µo¹q ¡´¥x¤j³s½u¯¸°ÈªO 3/23 Ptt
+ntuACCT90 ·|­p ¡´³o¬O¥Ã»·ªº¥x¤j· 7/19 blackman/aathena
+geography90 ¦a²z ¡· 5/23 cog/uray
+TFG97Juang ¥_¤@ ¡·§Ú­Ì·|¤£·|ª½¨ì± 8/09 seabreeze/notorious/Ving
+JHArt10th °ê¤¤ ¡·¶Â¦âªº©ñ®ö­x 8/14 sadness/noyes
+ChanAn26-303ªø¦w ¡·¥s§Ú²Ä¤@¦W 8/07 HunterX
+FashionClub ¶h½ì ¡´¶W«lÃz¤§--¥x¤j¦ 1/17 demure/Woodywang/wiki
+TFG97KIND ¥_¤@ ¡·³o¸Ì¥i¬O¤¯¶¡¤Ñ° 1/17 Channy
+AADIA ¥xÆW ¡·¿Nºuºuªº³Ì¨Î¨kº 8/13 CATHYSHU/dyw
+Sunrise12 ¹ÎÅé ¡·´Â¶§¦P¾Ç·|¤Q¤G© 8/14 waiting/doggy
+cksh75th09 ¦¨¥\ ¡·¤Í½Ë¾ú"¤E"¤@¼Ë¿ 8/08 chiahei/WeThree/berserk
+Evangelion ¤é¥» ¡´¸Û¼xª©¥D:) 6/15 ¼x¨D¤¤
+NTUba87 ¤uºÞ ¡·¤uºÞ¤@¥X ½Ö»P 8/09 ukj/littlewin
+ck49th109 «Ø¤¤ ¡·ª©¥D­n¤W¤s«ô®v¥ 3/24 edvi
+CS86Honest ¤¤¤s ¡·³o¸Ì¬O¸Û¯Z¡I¸Û¯ 5/24 Nakai/vicke
+YP86-307 ©µ¥­ ¡·¨È¬w²Ä¤@°Õ! 8/08 DRAGONS/longman
+jackstudio ­µ¼Ö ¡·ªN§J·nºu­µ¼Ö¾Ç­ 8/13 gigimusic
+CS85MadWiser¤¤¤s ¡··¬¨g´¼¼z¤H 12/06 NED
+LiZin ¸É²ß ¡·¥ß¤H¸É²ß¯Z 6/10 success/adket/foster
+HP_86_310 ©M¥­ ¡·©M¥­°ª¤¤²Ä¤@©¡ 11/26 beautyegg/oops/kyte
+Terry ¥xÆW ¡·ªL§Ó¬¯¡uÀ¿Án¦Ó¹ 8/10 jane
+Julia ¥xÆW ¡· ¤@¥Í³Ì·Rªº´^¨Î 8/07 esa
+PTGS50th305 ¤¤¤k ¡·¦³¹Ú¦³ªB¤Í---¤¤ 8/07 gm
+ck49th111 «Ø¤¤ ¡´¥´À»§Å±C¯S§ð¶¤ 3/15 ERWILSON/firebat
+ck49th131 «Ø¤¤ ¡·§Ú­Ì¤S²¦·~¤F... 12/26 lanzi/Cliche
+Wallace ­»´ä ¡·¤p¤Ó¶§Áéº~¨}--¥ 8/07 karencc
+KJ25MC ¥ú¤¯ ¡·¥ú¤¯«lÃz¬ü¤kª© 7/09 pm
+ADS ¨ä¥L ¡´¼s§i¯S°Ï 7/09 chwang/sourit/elixirs
+TFSHS57th310¤@¤¤ ¡´§Ú­Ì¤@®a³£¬O¤H 7/09 difficult/lpp/juwu
+B84305XXX ªÀ·| ¡·84¯ÅªÀ·|¤H 7/12 ridley
+Jeff ¥xÆW ¡·¤Q¤G¤ëªì--±¡ºq¤ 7/24 MisaTanaca/gambol
+EricMoo ¬P°¨ ¡·§Å±Ò½åªº·P°Ê 11/27 piercec
+NTUIB-PHD °ê¥ø ¡·¥x¤j°ê¥ø©Ò³Õ¤h¯ 5/22 yi03
+cksh75th19 ¦¨¥\ ¡·¤µ¤Ñªº§A,¹L±o¦n 8/17 shiii/eegg
+MINGDAO ©ú¹D ¡·ªï±µ·s¥@¬öªº¨ì¨ 3/10 apache/kaening
+NTUMBA-87 °Ó¬ã ¡·¥ø·~®aªººÛ 8/13 jonah
+ck49th324 «Ø¤¤ ¡´¤@©u®L©]ªº¤ß°Ê 4/03 jase/uuuuuu/brita
+TFG96Chung ¥_¤@ ¡·²{¦bµ²±B«Ü¤£¦Eº 8/12 astroboy
+Kinmen ÒO¤Í ¡·¥x¤jÒO¤Í·| 4/26 spurs
+BANYAN ¥_ªù ¡·¥_ªù°ª¤¤46TH 30 7/09 lusa/wangstar
+BADTWINS ¤¤¤Í ¡·¤j¼w°ê¤¤ 7/16 Chilong/ggn/xlight
+TFG96WILL ¥_¤@ ¡·¼Ý°ê­·±¡ 8/17 because/Galong
+HSNU_924 ªþ¤¤ ¡´ºÆ¨g´c¶Õ¤O 7/16 Dukedream
+Cyndi ¥xÆW ¡·¨S¦³"¾ÖµØ"¡A´N¥ 1/11 Melinda
+test2
+CS86Smile ¤¤¤s ¡´¯º¶Æ¤¤¤s 12/20 HsinYu/sunspring
+JI3thN3-3 ¥¿¸q ¡·¥¿¸q°ª¤¤´¶¤T¤T 7/13 screamer/stingypig
+CS87KUNG ¤¤¤s ¡·¤½¤§­·¶³ 8/12 hayashi/yjiou
+NTUBA-837011¥øºÞ ¡·ª©½Þ¬O°¦¤jÃi½Þ 3/10 eemil
+TW-explorer ¼v¶° ¡·¤p¤ß³QÅQ¤ýÀs«r³ 8/06 honu
+NTUIMA ªZ³N ¡·¤º®a®±ªÀ ³¯¤ó¤Ó 8/16 shadowpen/fu6xjp6
+NthuPhi ­õ¾Ç ¡·®µ²ø©P¥H¾C¹C 8/07 cerberus
+FreeNight ¥xÆW ¡·TROUBLE ±i¾_À® 5/24 gonna/holybell
+GlobalECON «Ý¼o ¡·¬F¸g¤K¦Ê(°]¸g°Ý 12/12 ali8/martinboy
+cvslog µo¹q ¡·cvs commit mess 4/16
+Momentum «Ý¼o ¡·°Ê¶q¥\³õ¤u§@«Ç 12/03 adnova/chestnut
+chess ®T¼Ö ¡·¤]¹ï ³£¬O³s±N 2/01 miserable
+ChthoniC ¥xÆW ¡´°{ÆF¼Ö¹Îª© 8/07 Iverigma
+shisong304 ¦èªQ ¡·¦èªQ304 5/15 JawTing/JSmoltz
+NCCU97_MAT ·|¬ã ¡·¨Ó§a.....¦P¾Ç·| 5/15 kemling/A1997
+ck49th331 «Ø¤¤ ¡·¨g¨F³¥±æ¡C 7/12 MDP/den
+HCGH-306 ¦Ë¤k ¡·¦³¤K¨ö¡I¡I¡I 4/19 jennywen/molly
+Foolshome ¹ÎÅé ¡·­C­C­C~~~¤dÁH¦~ 1/06 truth/citizen/nathon
+MARIAH ¬ü°ê ¡· ¡¹¡¹DON'T STOP 8/11 woowa
+KHCHS-87-306·s²ø ¡·³£¶]¨ì­þ¸Ì¥h¤F­ 6/10
+Delphi µ{³] ¡·Delphi¨g·Q¦± 2/13 cying
+ciacia_Her ¥xÆW ¡·ciacia¥Î¤å¦r¬D³ 7/26 sherbet
+KS86-323 ¶¯¤¤ ¡´§Ú­Ì¬O¥Ã»·ªºªüµ 7/05 fayemimi/hanawa
+test2
+KS86-322 ¶¯¤¤ ¡·¤j®a¦^¨ÓÄé¤ô§a¡ 8/10 Vygotsky/SpermTiger
+35WHOteam ¹ÎÅé ¡·ÂåÀø¥~¥æÀç¤T¤­¤ 5/12 winonamars
+test2
+ck49th306 «Ø¤¤ ¡·ernesto¡G 306ª 7/18 pongo/dearyou
+WuLing40-301«Ý¼o ¡·¦³¹Ú¦³ªB¤Í 10/ 8/11 quert
+NTUACCT88 ·|­p ¡·¤Ñ ¹D ¹S ¶Ô 6/12 Abbado/yenjui
+NTUDRC ¬ã¨s ¡·©Î³\©p¬O¹ïªº 8/10 Kymco/plockock/Jimmyplus
+NTUWRC ³°¤W ¡·¥x¤jºL¨¤¬ã¨sªÀ 8/07 BigRed
+TFSHS59th318¤@¤¤ ¡´¹L¤F¤@¤Ñ¤S¤@¤Ñ 8/07 prodigy/kinoo/frisk
+86literarts ¤å¾Ç ¡·86®v¤j¤åÃÀÀç 8/07 stupidbear/bengthek
+NTPU-SOC87 ªÀ·| ¡·«z«¨...·sª©¦¨¥ß 8/12 nettaigyo
+NTU94FLLD ¥~¤å ¡·B83102's Wonder 3/27 poppet
+ToriAmos ¬ü°ê ¡·SLG¼ö½æ¤¤ 8/14 CornflakeBoy
+Bjork ¬ü°ê ¡·¤å³¹³£¤£¨£¤F § 8/09 lunaticlace/sjon
+SCU-BM-87C Æ[¹î ¡· ¤Í½Ë¾ú¤[¤@¼Ë¿@ 4/17 joeyoung/linging/YADY
+CC-304 ¤¤¥¿ ¡·¤¤¥¿¶W´Î 304 8/14 betty0804/daystar
+Robin-Willia«Ý¼o ¡·¥Ã»·¤£¦ÑªºÃ¹»«« 8/09 ¼x¨D¤¤
+NTUEEice ¹ÎÅé ¡·­á -- µ² 8/10 hiei81/shouhou
+tu-tuoz ¹ÎÅé ¡·¦R¼Ñ°ê¥Á¤p¾Ç 8/10 galilei/seethesky
+WesleyS3H-32½Ã²z ¡·³Ì«á¤@­Ó´»°²°Õ¡ 8/15 esm
+Romi ¥xÆW ¡·§Qºö¡ã¡ãÅé¶K 8/16 flyawayhome/holina
+EEacademic ¹q¾÷ ¡´­n´Á¤¤¦ÒÅo¡I¡I 5/11 ccchen
+ck-newboard ¥Ó½Ð ¡·«Ø¤¤²Õ±M¥Î³s¸pª 2/09 Pets
+NTUspecial µLê ¡·¡¸¥xÆW¤j¾ÇµL»Ùà 4/28 t6768
+chienchen §@®a ¡·¤å¦rºëÆF¡X¡XÂ²Ø 8/09 curioussoul/ECOSEED
+test2
+test2
+test2
+NTUmed-SC Âå¾Ç ¡·¡¸¤È¶¡­µ¼Ö·|µ¥§ 8/13 Evan/boo24
+Visual_Basicµ{³] ¡·«z«z..§A¤£¯à¦Û¤ 8/14 glans
+test2
+test2
+AngelicaLee ¬P°¨ ¡·¶W¥i·R§õ¤ß¼ä *^ 8/11 CaptainL
+Jackie_Lui ­»´ä ¡´«L°©¤¯¤ß--§f¹|½ 8/14 pipo/YCJ
+HSNU_888 ªþ¤¤ ¡´888¬¾¨ß²Ä¤G¸] 8/10 Viggeran/cidi
+ClassicMusic­µ¼Ö ¡´§Ú­Ì£x°ê¼Ö 8/13 kuger/mml
+CM34th03 ´º¬ü ¡·:) 8/13 Snorkel
+CS88Jang ¤¤¤s ¡·§Ú­Ì³£¬O¥¿ÂI¬ü¤ 8/08 YANIYANI/cfchien
+TFG99JUANG ¥_¤@ ¡·µM«á¤S¬O¬î¤Ñ°Õ. 8/11 yumeko
+SrcDiscuss ¯¸ªø ¡·PTT ¥¼¨Óµ{¦¡µo® 5/13 CharlieL/DavidYu
+WL-AFFAIRS ¨Æ°È ¡·½Ð¦UªO¥Dª`·N¸s² 6/09 PaiBingTran
+SMGJS-80-302¾å©ú ¡·¥Ã»·ªºªì¤T¤A 8/09 chifang
+ck51st332 «Ø¤¤ ¡·±¥ Â÷§Ú­Ì¦Ó¥hªº 8/13 JeffreyS/jimmycat/Kampuchea/JIROO
+HORT-90 ¶éÃÀ ¡´²¦·~¤F... 8/16 sorng
+NCHUPPSB ¨tÂS ¡·«s«s«s «áÄ~µL¤H 4/14 LCUTE/AMDKX
+TAE ®õ°ê ¡·¦A¨£,¥[¦{®üÅy 4/14 TulipChiu
+LePoete ¥xÆW ¡·¥Ð¶é¸Ö¤H³¯©ú³¹( 4/14 doomcat
+NTUPOD ¬ã¨s ¡· 8/16 Galong
+ck53rd211 «Ø¤¤ ¡·´«­Ó¦W¦r§a.. 8/07 shanvic/BBD
+NCHU-SES ¤gÀô ¡·¤j®a¨Óªï·s³á~~ 4/18 yenjan
+Tin-Tin ¥xÆW ¡´´@´@·Rªº³Ó§Q 8/09 shinoo
+PTGS48th318 ¤¤¤k ¡·ºñ¦âÁ­½¸ºÛ 8/15 yungfang
+KF302 ¥ú´_ ¡·¶ë¨®¤¤ 8/15 ingela/cadillac
+HuangLei ¤j³° ¡·¶À½U¤å¾Ç­µ¼Ö¤jº 8/09 ssr
+NCCU99_EDU «Ý¼o ¡·~±Ð¨|Ä_Ä_ªº­_§§ 8/14 ¼x¨D¤¤
+NCHU_zoo °Êª« ¡´¤£¨}¤û¤H¤ñ¸û¦h 4/24 sengir/GENETICS/velella
+Bull ¾´Î ¡´¤G¤Q¤@¥@¬ö³Ì«i² 4/24 Nicky41/georgey
+KS88-309 ¶¯¤¤ ¡´°¸§i¶D§A...§Ú§@ 4/24 daviy
+cksh77th20 ¦¨¥\ ¡·§A§Ú³£¬O·Ï¤õ¤¤ª 8/06 bergee
+TFG99Dance ¥_¤@ ¡·µL­­¬×Jazz«a­x 8/07 Tinabear/hee
+TFG99Love ¥_¤@ ¡· ¨ä ¹ê 8/07 kelala/SpiceB
+Nedio ´CÅé ¡·§Ö¤Whttp://nedi 8/08 SpiceB/Sophia33
+TYHS88-306 ¥ªÀç ¡´¤T¤Ñ¤T©]¨ì¤T§ó¥ 8/09 niniway/Jey
+BCT-88 ¬ì§Þ ¡·¤@¸s¦b¥Íª«§Þ³N¤ 8/15 physik/avkao
+CARNEGIE0917¹ÎÅé ¡·***ªï±µ°{«Gªº21 8/07 blackmail/mistletoe/tsg
+NCCU_PT ªÀ¹Î ¡·¨S¦³¬¡°Êªº«Ì¤Í· 8/11 mib345/randying
+NCHU-SKATING·È¦B ¡·¨Ó¥h...¨Ó¥h...¤ 3/18 kaoasaki/littlehome
+Tun-Hua-Elem´°¤Æ ¡·TunHua_²Ä32©¡_6 8/07 pup
+CS88jing ¤¤¤s ¡·§Ö²¦·~¤F­C ·Q 8/08 yianne
+LeneMarlin ¬ü°ê ¡·­µ¼ÖºëÆF--µY®¦º 8/08 janetwang
+KS88-304 ¶¯¤¤ ¡·¤j®a¨ÓÄé¤ô³á~ 8/12 ahwa/oldya/BabyHam
+Summer ¥xÆW ¡·§â¼v¤l¯d¤U¡A¦b® 8/08 powerpeople/FINNCHE
+Slayers ¤é¥» ¡·¨q³rÅ]¾É¤h ²ú® 8/07 Zelgandes/marcal/Naga
+NTU-SwimCamp¤ô¤W ¡·¥x¤j´åªaÀç 6/22 sunnyl
+red-sun ªÀ¹Î ¡·¸¨¥Û¨ÓÅo 8/09 renaissance
+1995-JH-325 ª÷µØ ¡·ª÷µØ°ê¤¤¤T¦~¤G¤ 8/13 ThisWayIn/Raistlin/ifq
+X-game ¹B°Ê ¡··¥­­¹B°Ê 8/08 rbaggio
+88leadercamp¹ÎÅé ¡´ ²×©ó¶}ª©ªº88ªÀ 8/12 elbert/aaati
+Curse ¥xÆW ¡·¶A©G¼Ö¹Î(¤Q¤K¤~ 8/07 anticrist
+Joi ¬P°¨ ¡·²E²b¨Î­µ 8/08 leon19/crazykiller
+SHENA-RINGO ¤é¥» ¡·´Õ¦WªLìþ ³Ó¶Dªº 8/08 MayMV
+CCJH-FS-27th¤¤¥¿ ¡·£¯ §N²M²M..... 8/12 Ariyari/YehMay
+PH-Service ¤½½Ã ¡·¥ÃÄò¸gÀ窺¤½½Ãª 8/07 piayyc/yuskay
+1995-JH-309 «Ý¼o ¡·ª÷µØ309°ê¤¤¦P¾Ç 2/11 ¼x¨D¤¤
+Peter ¥xÆW ¡·¨C¦¸·Q¨ì"¦ó¼íªF 3/05 Haas
+IPIS µá°ê ¡·Á­½¸-§Ñ¤F§Ú¬O½Ö 5/30
+cksh76th22 ¦¨¥\ ¡·¦a²y«Ü¦MÀIªº!©p 8/15 lunasoul
+Stella ¬P°¨ ¡·­µ¼Ö²¢¤ß-¶À´ð©É 7/12 gutai309/crazykiller
+Law-Skate ªk«ß ¡·ªk­bª½±Æ½üªÀ ·È 6/12 Rainsalt/gwenlin
+cksh78th08 ¦¨¥\ ¡·¤»¦rÀY 308 3/17 smilefacer
+ntucomga ºÞ·| ¡·ºÞ°|¬ã¨s¥Í¾Ç¥Í· 5/08 handsome
diff --git a/util/smtest.result2 b/util/smtest.result2
new file mode 100644
index 00000000..b84133c2
--- /dev/null
+++ b/util/smtest.result2
@@ -0,0 +1,3 @@
+§K¾ª©¥D
+¬ÝªO¦WºÙ ªO¥D ´X¤Ñ¨S¨Ó°Õ
+----------------------------------------------------------------------
diff --git a/util/smtest.temp b/util/smtest.temp
new file mode 100644
index 00000000..7daa12ce
--- /dev/null
+++ b/util/smtest.temp
@@ -0,0 +1,231 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <ctype.h>
+#include "config.h"
+#include "pttstruct.h"
+#include "util.h"
+#include "perm.h"
+#include "common.h"
+#include "proto.h"
+
+#define OUTFILE BBSHOME "/pttbbs/util/smtest.result1"
+#define FIREFILE BBSHOME "/pttbbs/util/smtest.result2"
+
+extern boardheader_t *bcache;
+extern int numboards;
+
+boardheader_t allbrd[MAX_BOARD];
+struct userec_t xuser;
+
+int getuser(char *userid) {
+ int uid;
+ if((uid = searchuser(userid)))
+ passwd_query(uid, &xuser);
+ return uid;
+}
+
+int LINK(char* src, char* dst){
+ char cmd[200];
+
+ if( link(src, dst) == 0){
+ return 0;
+ }
+
+ sprintf(cmd, "/bin/cp -R %s %s", src, dst);
+ return system(cmd);
+}
+
+int outofdate(char *hdrdate, char latestdate[])
+{
+ int k,rr;
+ char *dd;
+
+ dd = strtok(hdrdate,"/");
+
+ if(dd){
+ k = 0;
+ do
+ {
+ if (*dd == '[' ){dd[strlen(dd)-1]='\0'; dd++;}
+ rr = atoi(dd);
+ printf("%d/", rr);
+ } while((dd = strtok(NULL,"/")) != NULL);
+ }
+
+ printf("\n");
+
+ if(1)
+ return 1;
+ else
+ return 0;
+}
+
+int main()
+{
+ int bmid, i, j, k, rd,rr;
+ char *p, *bmsname[3], fname[256], *dd;
+ fileheader_t hdr;
+ FILE *inf;
+
+ /* set date */
+ char thedate[5];
+ time_t t = time(NULL);
+ struct tm *tm = localtime(&t);
+
+ sprintf(thedate, "%2d/%02d", tm->tm_mon + 1, tm->tm_mday);
+
+ resolve_boards();
+ if(passwd_mmap())
+ exit(1);
+ memcpy(allbrd,bcache,numboards*sizeof(boardheader_t));
+ /* write out the target file */
+ inf = fopen(OUTFILE, "w+");
+ if(inf == NULL){
+ printf("open file error : %s\n", OUTFILE);
+ exit(1);
+ }
+
+ /*the ouput table title*/
+ fprintf(inf,"­^¤åª©¦W Ãþ§O ¤¤¤åª©¦W ª©¥D¦W³æ"
+ " ¤é´Á ³Æµù \n");
+
+ j = 0 ;
+ for (i = 0; i < 30; i++) {
+ rd = 0;
+ if(allbrd[i].brdname[0] == '\0') continue;
+ if((allbrd[i].brdattr & BRD_NOZAP) == 1) continue;
+
+ sprintf(fname, BBSHOME "/boards/%s/.DIR",allbrd[i].brdname);
+
+ /* get date to choose junk board */
+
+ rd = get_num_records(fname, sizeof(fileheader_t));
+ get_record(fname, &hdr, sizeof (hdr), rd - 30);
+
+
+ if(outofdate(hdr.date,thedate)) printf("yest\n");
+
+/*
+ dd = strtok(hdr.date,"/");
+
+ if(dd){
+ k = 0;
+ do
+ {
+ if (*dd == '[' ){dd[strlen(dd)-1]='\0'; dd++;}
+ rr = atoi(dd);
+ printf("%d/", rr);
+
+ } while((dd = strtok(NULL,"/")) != NULL);
+ }
+ printf("\n");
+*/
+ /* print to file */
+ printf("%-*.*s%-*.*s%-*.*s%-*.*s", IDLEN, IDLEN, allbrd[i].brdname,
+ BTLEN-24, BTLEN-26, allbrd[i].title, IDLEN - 5, IDLEN-5,hdr.date,
+ IDLEN * 3, IDLEN * 3, allbrd[i].BM);
+
+ /* post to board */
+
+
+
+ /* user extract to mail */
+
+ p=strtok(allbrd[i].BM,"/ ");
+ if(p){
+ k = 0;
+ do
+ {
+ if (*p == '[' ){p[strlen(p)-1]='\0'; p++;}
+ bmid=getuser(p);
+ bmsname[k] = p;
+ if(isalpha(allbrd[i].BM[0])&& !(xuser.userlevel &PERM_SYSOP))
+ {
+ // printf("%s", bmsname[k]);
+ }
+ k++;
+ } while((p=strtok(NULL,"/ "))!=NULL);
+ }
+
+ printf("\n");
+
+}
+
+
+/*
+
+
+
+ if(flag == 1){
+ bmbuf[0] = '\0';
+ for(k = 0 , n = 0; k < index; k++){
+ if(!bms[k].flag){
+ if( n++ != 0) strcat(bmbuf, "/");
+ strcat(bmbuf, bms[k].bmname);
+ }
+ }
+ strcpy(bcache[i].BM, bmbuf);
+ }
+ }
+ qsort(lostbms, j, sizeof(lostbm), bmlostdays_cmp);
+
+ //write to the etc/toplazyBM
+ for ( i=0; i<j; i++)
+ {
+ if( lostbms[i].lostdays > 60){
+ fprintf(firef, "%-*.*s%-*.*s%-*.*s%3d¤Ñ¨S¤W¯¸\n", IDLEN, IDLEN, lostbms[i].title,
+ BTLEN-10, BTLEN-10, lostbms[i].ctitle, IDLEN,IDLEN,
+ lostbms[i].bmname,lostbms[i].lostdays);
+ }else{
+ fprintf(inf, "%-*.*s%-*.*s%-*.*s%3d¤Ñ¨S¤W¯¸\n", IDLEN, IDLEN, lostbms[i].title,
+ BTLEN-10, BTLEN-10, lostbms[i].ctitle, IDLEN,IDLEN,
+ lostbms[i].bmname,lostbms[i].lostdays);
+ }
+ }
+ fclose(inf);
+ fclose(firef);
+
+ //printf("Total %d boards.\n", count);
+
+ //mail to the users
+ for( i=0; i<j; i++)
+ {
+ fileheader_t mymail;
+ char genbuf[200];
+ int lostdays;
+
+ lostdays = lostbms[i].lostdays;
+
+ if( (lostdays != 30) && (lostdays != 45) && (lostdays <= 60))
+ continue;
+
+ sprintf(genbuf, BBSHOME "/home/%c/%s", lostbms[i].bmname[0], lostbms[i].bmname);
+ stampfile(genbuf, &mymail);
+
+ strcpy(mymail.owner, "[PTTĵ¹î§½]");
+
+ if(lostdays <= 60){
+ sprintf(mymail.title,
+ "\033[32m [ª©¥D§K¾ĵ§i³qª¾] \033[m %s BM %s", lostbms[i].title, lostbms[i].bmname);
+ }else{
+ sprintf(mymail.title,
+ "\033[32m [ª©¥D§K¾³qª¾] \033[m %s BM %s", lostbms[i].title, lostbms[i].bmname);
+ }
+ mymail.savemode = 0 ;
+ unlink(genbuf);
+ if(lostdays <= 60){
+ LINK(OUTFILE, genbuf);
+ }else{
+ LINK(FIREFILE, genbuf);
+ }
+
+ sprintf(genbuf, BBSHOME "/home/%c/%s/.DIR", lostbms[i].bmname[0], lostbms[i].bmname);
+ append_record(genbuf, &mymail, sizeof(mymail));
+ }
+*/
+ return 0;
+}
diff --git a/util/stock.perl b/util/stock.perl
new file mode 100644
index 00000000..568c2d86
--- /dev/null
+++ b/util/stock.perl
@@ -0,0 +1,31 @@
+#!/usr/bin/perl
+# $Id: stock.perl,v 1.1 2002/03/07 15:13:46 in2 Exp $
+#
+# ¤£¯à¶]ªº¸Ü¡A¬Ý¬Ý bbspost ªº¸ô®|¬O§_¥¿½T¡C
+# ¦pªGµo¥Xªº post ¨S¦³®ð¶H³ø§i¦Ó¬O»¡ URL §ä¤£¨ì¡A«h½T©w¤@¤U¯à¤£¯à¬Ý¨ì
+# ¤¤¥¡®ð¶H§½ªº WWW ¤Î URL ¬O§_¥¿½T¡C
+# ²z½×¤W¾A¥Î©Ò¦³ Eagle BBS ¨t¦C¡C
+# -- Beagle Apr 13 1997
+open(BBSPOST, "| bin/webgrep >etc/stock.tmp");
+# ¤é´Á
+open(DATE, "date +'%a %b %d %T %Y' |");
+$date = <DATE>;
+chop $date;
+close DATE;
+
+# Header
+# ¤º®e
+#open(WEATHER, "/usr/local/bin/lynx -dump http://www.dashin.com.tw/bulletin_board/today_stock_price.htm |"); while (<WEATHER>) {
+open(WEATHER, "/usr/bin/lynx -dump http://quotecenter.jpc.com.tw/today_stock_price.htm |"); while(<WEATHER>) {
+ print BBSPOST if ($_ ne "\n");
+}
+close WEATHER;
+
+# ñ¦WÀÉ
+print BBSPOST "\n--\n";
+print BBSPOST "§Ú¬Obeagle©Ò¦³¥i·Rªº¤p»æ°®...¸ó®ü¬°PttªA°È\n";
+print BBSPOST "--\n";
+print BBSPOST "¡¸ [Origin: ¡·ªGÂæ¤p¯¸¡·] [From: [ÂŲùÃP»æ«Î] ] ";
+
+close BBSPOST;
+
diff --git a/util/stock.sh b/util/stock.sh
new file mode 100644
index 00000000..907ddb73
--- /dev/null
+++ b/util/stock.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+# $Id: stock.sh,v 1.1 2002/03/07 15:13:46 in2 Exp $
+#
+bin/stock.perl
+bin/post Record ¤µ¤éªÑ²¼¦¬½L»ù [ªÑ¥«¤p©j] etc/stock.tmp
diff --git a/util/tarqueue.pl b/util/tarqueue.pl
new file mode 100644
index 00000000..20bda9f1
--- /dev/null
+++ b/util/tarqueue.pl
@@ -0,0 +1,75 @@
+#!/usr/bin/perl
+use lib '/home/bbs/bin/';
+use LocalVars;
+use strict;
+use Mail::Sender;
+use POSIX;
+
+no strict 'subs';
+setpriority(PRIO_PROCESS, $$, 20);
+use strict subs;
+chdir $BBSHOME;
+open LOG, ">> log/tarqueue.log";
+
+foreach my $board ( <$JOBSPOOL/tarqueue.*> ){
+ $board =~ s/.*tarqueue\.//;
+ ProcessBoard($board);
+ unlink "$JOBSPOOL/tarqueue.$board";
+}
+close DIR;
+close LOG;
+
+sub ProcessBoard
+{
+ my($board)= @_;
+ my($cmd, $owner, $email, $bakboard, $bakman, $now);
+
+ $now = substr(POSIX::ctime(time()), 0, -1);
+ open FH, "< $JOBSPOOL/tarqueue.$board";
+ chomp($owner = <FH>);
+ chomp($email = <FH>);
+ chomp(($bakboard, $bakman) = split(/,/, <FH>));
+ close FH;
+
+ print LOG sprintf("%-28s %-12s %-12s %d %d %s\n",
+ $now, $owner, $board, $bakboard, $bakman, $email);
+
+ MakeMail({tartarget => "$TMP/$board.tgz",
+ tarsource => "boards/$board/* boards/$board/.DIR",
+ mailto => "$boardªºª©¥D$owner <$email>",
+ subject => "$boardªº¬Ýª©³Æ¥÷",
+ body =>
+ "\n\n\t $owner ±z¦n¡A¦¬¨ì³o«Ê«H¡Aªí¥Ü±z¤w¸g¦¬¨ì¬ÝªO³Æ¥÷¡C\n\n".
+ "\tÁÂÁ±zªº­@¤ßµ¥«Ý¡A¥H¤Î¨Ï¥Î $hostnameªº¬ÝªO³Æ¥÷¨t²Î¡A\n\n".
+ "\t¦p¦³¥ô¦óºÃ°Ý¡AÅwªï±H«Hµ¹¯¸ªø¡A§Ú­Ì·|«Ü¼Ö©óµ¹¤©¨ó§U¡C\n\n\n".
+ "\t³Ì«á¡A¯¬ $owner ¥­¦w§Ö¼Ö¡I ^_^\n\n\n".
+ "\t $hostname¯¸ªø¸s. \n\t$now"
+ }) if( $bakboard );
+
+ MakeMail({tartarget => "$TMP/man.$board.tgz",
+ tarsource => "man/boards/$board/* man/boards/$board/.DIR",
+ mailto => "$boardªºª©¥D$owner <$email>",
+ subject => "$boardªººëµØ°Ï³Æ¥÷",
+ body =>
+ "\n\n\t $owner ±z¦n¡A¦¬¨ì³o«Ê«H¡Aªí¥Ü±z¤w¸g¦¬¨ìºëµØ°Ï³Æ¥÷¡C\n\n".
+ "\tÁÂÁ±zªº­@¤ßµ¥«Ý¡A¥H¤Î¨Ï¥Î $hostnameªº¬ÝªO³Æ¥÷¨t²Î¡A\n\n".
+ "\t¦p¦³¥ô¦óºÃ°Ý¡AÅwªï±H«Hµ¹¯¸ªø¡A§Ú­Ì·|«Ü¼Ö©óµ¹¤©¨ó§U¡C\n\n\n".
+ "\t³Ì«á¡A¯¬ $owner ¥­¦w§Ö¼Ö¡I ^_^\n\n\n".
+ "\t $hostname¯¸ªø¸s. \n\t$now"
+ }) if( $bakman );
+
+}
+
+sub MakeMail
+{
+ my($arg) = @_;
+ my $sender;
+ `$TAR zcf $arg->{tartarget} $arg->{tarsource}`;
+ $sender = new Mail::Sender{smtp => $SMTPSERVER,
+ from => 'pttadmin <in2@ptt2.csie.ntu.edu.tw>'};
+ $sender->MailFile({to => $arg->{mailto},
+ subject => $arg->{subject},
+ msg => $arg->{body},
+ file => $arg->{tartarget}});
+ unlink $arg->{tartarget};
+}
diff --git a/util/testkenben.txt b/util/testkenben.txt
new file mode 100644
index 00000000..df3893d3
--- /dev/null
+++ b/util/testkenben.txt
@@ -0,0 +1,11 @@
+HCGH-306 ¦Ë¤k ¡·¦³¤K¨ö¡I¡I¡I 7/24 jennywen/molly
+Foolshome ¹ÎÅé ¡·­C­C­C~~~¤dÁH¦~ 1/14 truth/citizen/nathon
+KHCHS-87-306·s²ø ¡·³£¶]¨ì­þ¸Ì¥h¤F­ 6/12
+TGHS8714 «n¤k ¡·²z©Ê¤Ñ®ð¡F·P©Ê¥ 8/07 grassflying/EPOCH
+PttDoc ¼T­ù ¡·Ptt Document Pr 8/07
+Delphi µ{³] ¡·Delphi¨g·Q¦± 3/09 cying
+ciacia_Her ¥xÆW ¡·ciacia¥Î¤å¦r¬D³ 8/16 sherbet
+CS87Love ¤¤¤s ¡··R©O! 8/08 sylna/fancydream
+Wanfang ¥xÆW ¡·´N­È±o¤F·R¸UªÚ 8/07 zkkk
+KS87-308 ¶¯¤¤ ¡´¶¯¤¤¤K±¾¯Z¡m¤@¤ 8/07 SBT/shouhou
+
diff --git a/util/toplazyBBM.c b/util/toplazyBBM.c
new file mode 100644
index 00000000..08c07448
--- /dev/null
+++ b/util/toplazyBBM.c
@@ -0,0 +1,203 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <ctype.h>
+#include "config.h"
+#include "pttstruct.h"
+#include "util.h"
+#include "perm.h"
+#include "common.h"
+
+#define OUTFILE BBSHOME "/etc/toplazyBBM"
+#define FIREFILE BBSHOME "/etc/topfireBBM"
+
+extern boardheader_t *bcache;
+extern int numboards;
+
+boardheader_t allbrd[MAX_BOARD];
+extern userec_t xuser;
+typedef struct lostbm {
+ char *bmname;
+ char *title;
+ char *ctitle;
+ int lostdays;
+} lostbm;
+lostbm lostbms[MAX_BOARD];
+
+typedef struct BMarray{
+ char *bmname;
+ int flag;
+} BMArray;
+BMArray bms[3];
+
+int bmlostdays_cmp(const void *va, const void *vb)
+{
+ lostbm *a=(lostbm *)va, *b=(lostbm *)vb;
+ if (a->lostdays > b->lostdays) return -1;
+ else if (a->lostdays == b->lostdays) return 0;
+ else return 1;
+}
+
+
+int LINK(char* src, char* dst){
+ char cmd[200];
+ if(symlink(src,dst) == -1)
+ {
+ sprintf(cmd, "/bin/cp -R %s %s", src, dst);
+ return system(cmd);
+ }
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ int bmid, i, j=0;
+ FILE *inf, *firef;
+
+ resolve_boards();
+
+ if(passwd_mmap())
+ exit(1);
+
+ memcpy(allbrd,bcache,numboards*sizeof(boardheader_t));
+
+ /* write out the target file */
+ printf("Starting Checking\n");
+ inf = fopen(OUTFILE, "w+");
+ if(inf == NULL){
+ printf("open file error : %s\n", OUTFILE);
+ exit(1);
+ }
+ firef = fopen(FIREFILE, "w+");
+ if(firef == NULL){
+ printf("open file error : %s\n", FIREFILE);
+ exit(1);
+ }
+
+ fprintf(inf, "ĵ§i: ª©¥D­Y©ó¨â­Ó¤ë¥¼¤W¯¸,±N¤©©ó§K¾\n");
+ fprintf(inf,
+ "¬ÝªO¦WºÙ "
+ " ªO¥D ´X¤Ñ¨S¨Ó°Õ\n"
+ "---------------------------------------------------"
+ "-------------------\n");
+
+ fprintf(firef, "§K¾ª©¥D\n");
+ fprintf(firef,
+ "¬ÝªO¦WºÙ "
+ " ªO¥D ´X¤Ñ¨S¨Ó°Õ\n"
+ "---------------------------------------------------"
+ "-------------------\n");
+
+
+ j = 0 ;
+ for (i = 0; i < numboards; i++) {
+ char *p, bmbuf[IDLEN * 3 + 3];
+ int index = 0, flag = 0, k, n;
+ p=strtok(allbrd[i].BM,"/ ");
+ if(p)
+ do
+ {
+ if(allbrd[i].brdname[0] == '\0' || (allbrd[i].brdattr & BRD_GROUPBOARD) ==0 ) continue;
+ if (*p == '[' ){p[strlen(p)-1]='\0'; p++;}
+ bmid=getuser(p);
+ bms[index].bmname = p;
+ bms[index].flag = 0;
+ if (((((int)time(NULL)-(int)xuser.lastlogin)/(60*60*24))>=7)
+ //&& isalpha(allbrd[i].brdname[0])
+ //&& isalpha(allbrd[i].BM[0])
+ && !(xuser.userlevel & PERM_SYSOP))
+ {
+ lostbms[j].bmname = p;
+ lostbms[j].title = allbrd[i].brdname;
+ lostbms[j].ctitle = allbrd[i].title;
+ lostbms[j].lostdays =
+ ((int)time(NULL)-(int)xuser.lastlogin)/(60*60*24);
+
+ printf("%s\n", lostbms[j].title);
+ //¶W¹L¤»¤Q¤Ñ §K¾
+ if(lostbms[j].lostdays > 30){
+ xuser.userlevel &= ~PERM_BM;
+ bms[index].flag = 1;
+ flag = 1;
+ }
+ j++;
+ }
+ index++;
+ } while((p=strtok(NULL,"/ "))!=NULL);
+
+ //±qª©¥D¦W³æ®³±¼¦W¦r
+
+ if(flag == 1){
+ bmbuf[0] = '\0';
+ for(k = 0 , n = 0; k < index; k++){
+ if(!bms[k].flag){
+ if( n++ != 0) strcat(bmbuf, "/");
+ strcat(bmbuf, bms[k].bmname);
+ }
+ }
+ strcpy(allbrd[i].BM, bmbuf);
+ }
+
+ }
+ qsort(lostbms, j, sizeof(lostbm), bmlostdays_cmp);
+
+ printf("Starting to mail\n");
+ //write to the etc/toplazyBBM
+ for ( i=0; i<j; i++)
+ {
+ if( lostbms[i].lostdays > 30){
+ fprintf(firef, "%-*.*s%-*.*s%-*.*s%3d¤Ñ¨S¤W¯¸\n", IDLEN, IDLEN, lostbms[i].title,
+ BTLEN-10, BTLEN-10, lostbms[i].ctitle, IDLEN,IDLEN,
+ lostbms[i].bmname,lostbms[i].lostdays);
+ }else{
+ fprintf(inf, "%-*.*s%-*.*s%-*.*s%3d¤Ñ¨S¤W¯¸\n", IDLEN, IDLEN, lostbms[i].title,
+ BTLEN-10, BTLEN-10, lostbms[i].ctitle, IDLEN,IDLEN,
+ lostbms[i].bmname,lostbms[i].lostdays);
+ }
+ }
+ fclose(inf);
+ fclose(firef);
+
+ printf("Total %d boards.\n", j);
+
+ //mail to the users
+ for( i=0; i<j; i++)
+ {
+ fileheader_t mymail;
+ char genbuf[200];
+ int lostdays;
+
+ lostdays = lostbms[i].lostdays;
+
+ if( (lostdays != 14) || (lostdays != 21) ) // 14 21 ¤Ñ¤£µo«H
+ continue;
+
+ sprintf(genbuf, BBSHOME "/home/%c/%s", lostbms[i].bmname[0], lostbms[i].bmname);
+ stampfile(genbuf, &mymail);
+
+ strcpy(mymail.owner, "[PTTĵ¹î§½]");
+
+ if(lostdays <= 30){
+ sprintf(mymail.title,
+ "\033[32m [¤p²Õªø§K¾ĵ§i³qª¾] \033[m %s BM %s", lostbms[i].title, lostbms[i].bmname);
+ }else{
+ sprintf(mymail.title,
+ "\033[32m [¤p²Õªø§K¾³qª¾] \033[m %s BM %s", lostbms[i].title, lostbms[i].bmname);
+ }
+ mymail.savemode = 0 ;
+ unlink(genbuf);
+ if(lostdays <= 30){
+ LINK(OUTFILE, genbuf);
+ }else{
+ LINK(FIREFILE, genbuf);
+ }
+
+ sprintf(genbuf, BBSHOME "/home/%c/%s/.DIR", lostbms[i].bmname[0], lostbms[i].bmname);
+ append_record(genbuf, &mymail, sizeof(mymail));
+ }
+
+ return 0;
+}
diff --git a/util/toplazyBBM.sh b/util/toplazyBBM.sh
new file mode 100644
index 00000000..d1d94229
--- /dev/null
+++ b/util/toplazyBBM.sh
@@ -0,0 +1,3 @@
+bin/toplazyBBM
+bin/post Record Ãi´k¤p²Õªø±Æ¦æº] [Pttĵ¹î§½] etc/toplazyBBM
+bin/post ViolateLaw ¤µ¤é§K¾¤p²Õªø [Pttªk°|] etc/firelazyBBM
diff --git a/util/toplazyBM.c b/util/toplazyBM.c
new file mode 100644
index 00000000..ec9319c2
--- /dev/null
+++ b/util/toplazyBM.c
@@ -0,0 +1,211 @@
+#include <stdio.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <ctype.h>
+#include "config.h"
+#include "pttstruct.h"
+#include "util.h"
+#include "perm.h"
+#include "common.h"
+#include "proto.h"
+#include "modes.h"
+
+
+#define OUTFILE BBSHOME "/etc/toplazyBM"
+#define FIREFILE BBSHOME "/etc/firelazyBM"
+
+extern boardheader_t *bcache;
+extern int numboards;
+
+boardheader_t allbrd[MAX_BOARD];
+extern userec_t xuser;
+typedef struct lostbm {
+ char *bmname;
+ char *title;
+ char *ctitle;
+ int lostdays;
+} lostbm;
+lostbm lostbms[MAX_BOARD];
+
+typedef struct BMarray{
+ char *bmname;
+ int flag;
+} BMArray;
+BMArray bms[3];
+
+
+int bmlostdays_cmp(const void *va, const void *vb)
+{
+ lostbm *a=(lostbm *)va, *b=(lostbm *)vb;
+ if (a->lostdays > b->lostdays) return -1;
+ else if (a->lostdays == b->lostdays) return 0;
+ else return 1;
+}
+
+int LINK(char* src, char* dst){
+ char cmd[200];
+ if(symlink(src,dst) == -1)
+ {
+ sprintf(cmd, "/bin/cp -R %s %s", src, dst);
+ return system(cmd);
+ }
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ int bmid, i, j=0;
+ FILE *inf, *firef;
+
+ resolve_boards();
+
+ if(passwd_mmap())
+ exit(1);
+
+ memcpy(allbrd,bcache,numboards*sizeof(boardheader_t));
+
+ /* write out the target file */
+ inf = fopen(OUTFILE, "w+");
+ if(inf == NULL){
+ printf("open file error : %s\n", OUTFILE);
+ exit(1);
+ }
+
+ firef = fopen(FIREFILE, "w+");
+ if(firef == NULL){
+ printf("open file error : %s\n", FIREFILE);
+ exit(1);
+ }
+
+ fprintf(inf, "ĵ§i: ª©¥D­Y©ó¨â­Ó¤ë¥¼¤W¯¸,±N¤©©ó§K¾\n");
+ fprintf(inf,
+ "¬ÝªO¦WºÙ "
+ " ªO¥D ´X¤Ñ¨S¨Ó°Õ\n"
+ "---------------------------------------------------"
+ "-------------------\n");
+
+ fprintf(firef, "§K¾ª©¥D\n");
+ fprintf(firef,
+ "¬ÝªO¦WºÙ "
+ " ªO¥D ´X¤Ñ¨S¨Ó°Õ\n"
+ "---------------------------------------------------"
+ "-------------------\n");
+
+
+ j = 0 ;
+ for (i = 0; i < numboards; i++) {
+ char *p, bmbuf[IDLEN * 3 + 3];
+ int index = 0, flag = 0, k, n;
+ p=strtok(allbrd[i].BM,"/ ");
+ if(p)
+ do
+ {
+ if(allbrd[i].brdname[0] == '\0') continue;
+ if (*p == '[' ){p[strlen(p)-1]='\0'; p++;}
+ bmid=getuser(p);
+ bms[index].bmname = p;
+ bms[index].flag = 0;
+ if (((((int)time(NULL)-(int)xuser.lastlogin)/(60*60*24))>=31)
+ && isalpha(allbrd[i].brdname[0])
+ && isalpha(allbrd[i].BM[0])
+ && !(xuser.userlevel & PERM_SYSOP))
+ {
+ lostbms[j].bmname = p;
+ lostbms[j].title = allbrd[i].brdname;
+ lostbms[j].ctitle = allbrd[i].title;
+ lostbms[j].lostdays =
+ ((int)time(NULL)-(int)xuser.lastlogin)/(60*60*24);
+
+
+ //¶W¹L¤»¤Q¤Ñ §K¾
+ if(lostbms[j].lostdays > 60){
+ xuser.userlevel &= ~PERM_BM;
+ bms[index].flag = 1;
+ flag = 1;
+ passwd_update(bmid, &xuser);
+ }
+ j++;
+ }
+ index++;
+ } while((p=strtok(NULL,"/ "))!=NULL);
+
+ if(flag == 1){
+ boardheader_t *fhp = 0;
+ printf("%s %s\n", lostbms[j-1].title, lostbms[j-1].bmname);
+ bmbuf[0] = '\0';
+ for(k = 0 , n = 0; k < index; k++){
+ if(!bms[k].flag){
+ if( n++ != 0) strcat(bmbuf, "/");
+ strcat(bmbuf, bms[k].bmname);
+ }
+ }
+
+ strcpy(allbrd[i].BM, bmbuf);
+ if( substitute_record(FN_BOARD, &allbrd[i], sizeof(boardheader_t), i) == -1){
+ printf("Update Board Faile : %s\n", allbrd[i].brdname);
+ }
+ reset_board(i);
+ }
+ }
+
+ qsort(lostbms, j, sizeof(lostbm), bmlostdays_cmp);
+
+ //write to the etc/toplazyBM
+ for ( i=0; i<j; i++)
+ {
+ if( lostbms[i].lostdays > 60){
+ fprintf(firef, "%-*.*s%-*.*s%-*.*s%3d¤Ñ¨S¤W¯¸\n", IDLEN, IDLEN, lostbms[i].title,
+ BTLEN-10, BTLEN-10, lostbms[i].ctitle, IDLEN,IDLEN,
+ lostbms[i].bmname,lostbms[i].lostdays);
+ }else{
+ fprintf(inf, "%-*.*s%-*.*s%-*.*s%3d¤Ñ¨S¤W¯¸\n", IDLEN, IDLEN, lostbms[i].title,
+ BTLEN-10, BTLEN-10, lostbms[i].ctitle, IDLEN,IDLEN,
+ lostbms[i].bmname,lostbms[i].lostdays);
+ }
+ }
+ fclose(inf);
+ fclose(firef);
+
+ //printf("Total %d boards.\n", count);
+
+ //mail to the users
+ for( i=0; i<j; i++)
+ {
+ fileheader_t mymail;
+ char genbuf[200];
+ int lostdays;
+
+ lostdays = lostbms[i].lostdays;
+
+ if( (lostdays != 30) && (lostdays != 45) && (lostdays <= 60))
+ continue;
+
+ sprintf(genbuf, BBSHOME "/home/%c/%s", lostbms[i].bmname[0], lostbms[i].bmname);
+ stampfile(genbuf, &mymail);
+
+ strcpy(mymail.owner, "[PTTĵ¹î§½]");
+
+ if(lostdays <= 60){
+ sprintf(mymail.title,
+ "\033[32m [ª©¥D§K¾ĵ§i³qª¾] \033[m %s BM %s", lostbms[i].title, lostbms[i].bmname);
+ }else{
+ sprintf(mymail.title,
+ "\033[32m [ª©¥D§K¾³qª¾] \033[m %s BM %s", lostbms[i].title, lostbms[i].bmname);
+ }
+ mymail.savemode = 0 ;
+ unlink(genbuf);
+ if(lostdays <= 60){
+ LINK(OUTFILE, genbuf);
+ }else{
+ LINK(FIREFILE, genbuf);
+ }
+
+ sprintf(genbuf, BBSHOME "/home/%c/%s/.DIR", lostbms[i].bmname[0], lostbms[i].bmname);
+ append_record(genbuf, &mymail, sizeof(mymail));
+ }
+
+ return 0;
+}
diff --git a/util/toplazyBM.sh b/util/toplazyBM.sh
new file mode 100644
index 00000000..033e545f
--- /dev/null
+++ b/util/toplazyBM.sh
@@ -0,0 +1,3 @@
+bin/toplazyBM
+bin/post Record Ãi´kª©¥D±Æ¦æº] [Pttĵ¹î§½] etc/toplazyBM
+bin/post ViolateLaw ¤µ¤é§K¾ª©¥D [Pttªk°'|'] etc/firelazyBM
diff --git a/util/topsong.sh b/util/topsong.sh
new file mode 100644
index 00000000..19e9663a
--- /dev/null
+++ b/util/topsong.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+# $Id: topsong.sh,v 1.1 2002/03/07 15:13:46 in2 Exp $
+#
+bin/post Record "¤W¥b­Ó¤ëÂIºq±Æ¦æº]" "[Ptt¬y¦æºô]" etc/topsong
+mv ussong tmp
diff --git a/util/topusr.c b/util/topusr.c
new file mode 100644
index 00000000..22b95e94
--- /dev/null
+++ b/util/topusr.c
@@ -0,0 +1,205 @@
+/* $Id: topusr.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */
+/* ¨Ï¥ÎªÌ ¤W¯¸°O¿ý/¤å³¹½g¼Æ ±Æ¦æº] */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+#include "config.h"
+#include "pttstruct.h"
+#include "perm.h"
+#include "common.h"
+#include "util.h"
+
+#define REAL_INFO
+struct manrec
+{
+ char userid[IDLEN + 1];
+ char username[23];
+ int values[3];
+};
+typedef struct manrec manrec;
+struct manrec *allman[3];
+
+userec_t aman;
+manrec theman;
+int num;
+FILE *fp;
+
+#define TYPE_POST 0
+#define TYPE_LOGIN 1
+#define TYPE_MONEY 2
+
+
+void
+ top(type)
+{
+ static char *str_type[3] =
+ {"µoªí¦¸¼Æ", "¶i¯¸¦¸¼Æ", " ¤j´I¯Î "};
+ int i, j, rows = (num + 1) / 2;
+ char buf1[80], buf2[80];
+
+ if (type != 2)
+ fprintf(fp, "\n\n");
+
+ fprintf(fp, "\
+ ¢~¢w¢w¢w¢w¢w¢¡ [%dm %8.8s±Æ¦æº]  ¢~¢w¢w¢w¢w¢w¢¡\n\
+ ¦W¦¸¢w¥N¸¹¢w¢w¢w¼ÊºÙ¢w¢w¢w¢w¢w¢w¼Æ¥Ø¢w¢w¦W¦¸¢w¥N¸¹¢w¢w¢w¼ÊºÙ¢w¢w¢w¢w¢w¢w¼Æ¥Ø\
+", type + 44, str_type[type]);
+ for (i = 0; i < rows; i++)
+ {
+ char ch=' ';
+ int value;
+
+ if(allman[type][i].values[type] > 1000000000)
+ { value=allman[type][i].values[type]/1000000; ch='M';}
+ else if(allman[type][i].values[type] > 1000000)
+ { value=allman[type][i].values[type]/1000; ch='K';}
+ else {value=allman[type][i].values[type]; ch=' ';}
+ sprintf(buf1, "[%2d] %-11.11s%-16.16s%5d%c",
+ i + 1, allman[type][i].userid, allman[type][i].username,
+ value, ch);
+ j = i + rows;
+ if(allman[type][j].values[type] > 1000000000)
+ { value=allman[type][j].values[type]/1000000; ch='M';}
+ else if(allman[type][j].values[type] > 1000000)
+ { value=allman[type][j].values[type]/1000; ch='K';}
+ else {value=allman[type][j].values[type]; ch=' ';}
+
+ sprintf(buf2, "[%2d] %-11.11s%-16.16s%4d%c",
+ j + 1, allman[type][j].userid, allman[type][j].username,
+ value, ch);
+ if (i < 3)
+ fprintf(fp, "\n [1;%dm%-40s%s", 31 + i, buf1, buf2);
+ else
+ fprintf(fp, "\n %-40s%s", buf1, buf2);
+ }
+}
+
+
+#ifdef HAVE_TIN
+int
+ post_in_tin(char *name)
+{
+ char buf[256];
+ FILE *fh;
+ int counter = 0;
+
+ sprintf(buf, "%s/home/%c/%s/.tin/posted", home_path, name[0], name);
+ fh = fopen(buf, "r");
+ if (fh == NULL)
+ return 0;
+ else
+ {
+ while (fgets(buf, 255, fh) != NULL)
+ counter++;
+ fclose(fh);
+ return counter;
+ }
+}
+#endif /* HAVE_TIN */
+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');
+}
+
+int
+ bad_user_id(userid)
+char *userid;
+{
+ register char ch;
+ if (strlen(userid) < 2)
+ return 1;
+ if (not_alpha(*userid))
+ return 1;
+ while((ch = *(++userid)))
+ {
+ if (not_alnum(ch))
+ return 1;
+ }
+ return 0;
+}
+
+int main(argc, argv)
+int argc;
+char **argv;
+{
+ int i, j;
+
+ if (argc < 3)
+ {
+ printf("Usage: %s <num_top> <out-file>\n", argv[0]);
+ exit(1);
+ }
+
+ num = atoi(argv[1]);
+ if (num == 0)
+ num = 30;
+
+ if(passwd_mmap())
+ {
+ printf("Sorry, the data is not ready.\n");
+ exit(0);
+ }
+ for(i=0; i<3; i++)
+ {
+ allman[i]=malloc(sizeof(manrec) * num);
+ memset(allman[i],0,sizeof(manrec) * num);
+ }
+ for(j = 1; j <= MAX_USERS; j++) {
+ passwd_query(j, &aman);
+ aman.userid[IDLEN]=0;
+ aman.username[22]=0;
+ if((aman.userlevel & PERM_NOTOP) || !aman.userid[0] ||
+ bad_user_id(aman.userid) ||
+ strchr(aman.userid, '.'))
+ {
+ continue;
+ }
+ else {
+ strcpy(theman.userid, aman.userid);
+ strcpy(theman.username, aman.username);
+ theman.values[TYPE_LOGIN] = aman.numlogins;
+ theman.values[TYPE_POST] = aman.numposts;
+ theman.values[TYPE_MONEY] = aman.money;
+ for(i=0; i<3; i++)
+ {
+ int k,l;
+ for(k=num-1; k>=0 && allman[i][k].values[i]<theman.values[i];
+ k--);
+ k++;
+ if(k<num)
+ {
+ for(l=num-1; l>k; l--)
+ memcpy(&allman[i][l], &allman[i][l-1],
+ sizeof(manrec));
+ memcpy(&allman[i][k], &theman, sizeof(manrec));
+ }
+ }
+ }
+ }
+
+
+ if ((fp = fopen(argv[2], "w")) == NULL)
+ {
+ printf("cann't open topusr\n");
+ return 0;
+ }
+
+ top(TYPE_MONEY);
+ top(TYPE_POST);
+ top(TYPE_LOGIN);
+
+ fclose(fp);
+ return 0;
+}
diff --git a/util/tunepasswd.c b/util/tunepasswd.c
new file mode 100644
index 00000000..15a3fe1f
--- /dev/null
+++ b/util/tunepasswd.c
@@ -0,0 +1,77 @@
+/* $Id: tunepasswd.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include "config.h"
+#include "pttstruct.h"
+#include "common.h"
+
+int tune(int num) {
+ int i, j, fin, fout;
+ userec_t u;
+
+ if((fin = open(FN_PASSWD, O_RDONLY)) == -1) {
+ perror(FN_PASSWD);
+ return 1;
+ }
+ if(flock(fin, LOCK_EX)) {
+ printf("Lock failed!\n");
+ return 1;
+ }
+ if((fout = open(FN_PASSWD ".tune" , O_WRONLY | O_CREAT, 0600)) == -1) {
+ perror(FN_PASSWD ".tune");
+ flock(fin, LOCK_UN);
+ close(fin);
+ return 1;
+ }
+
+ for(i = j = 0; i < num; i++) {
+ read(fin, &u, sizeof(u));
+ if(u.userid[0]) {
+ if(j == MAX_USERS) {
+ printf("MAX_USERS is too small!\n");
+ close(fout);
+ unlink(FN_PASSWD ".tune");
+ flock(fin, LOCK_UN);
+ close(fin);
+ return 1;
+ }
+ write(fout, &u, sizeof(u));
+ j++;
+ }
+ }
+ for(memset(&u, 0, sizeof(u)); j < MAX_USERS; j++) {
+ write(fout, &u, sizeof(u));
+ }
+ close(fout);
+
+ /* backup */
+ unlink(FN_PASSWD "~");
+ link(FN_PASSWD, FN_PASSWD "~");
+ unlink(FN_PASSWD);
+ link(FN_PASSWD ".tune", FN_PASSWD);
+ unlink(FN_PASSWD ".tune");
+
+ flock(fin, LOCK_UN);
+ close(fin);
+ return 0;
+}
+
+int main() {
+ struct stat sb;
+
+ if(stat(FN_PASSWD, &sb)) {
+ perror("stat");
+ return 1;
+ }
+ if(sb.st_size != sizeof(userec_t) * MAX_USERS) {
+ printf("size and MAX_USERS do not match!\n");
+ if(tune(sb.st_size / sizeof(userec_t)) == 0)
+ printf(FN_PASSWD " has been tuned successfully!\n");
+ } else
+ printf("Nothing to do.\n");
+ return 0;
+}
diff --git a/util/uhash_loader.c b/util/uhash_loader.c
new file mode 100644
index 00000000..2d88dd06
--- /dev/null
+++ b/util/uhash_loader.c
@@ -0,0 +1,129 @@
+/* $Id: uhash_loader.c,v 1.1 2002/03/07 15:13:47 in2 Exp $ */
+/* standalone uhash loader -- jochang */
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+
+#ifdef __FreeBSD__
+#include <machine/param.h>
+#endif
+
+#include "config.h"
+#include "pttstruct.h"
+#include "common.h"
+
+unsigned string_hash(unsigned char *s);
+void add_to_uhash(int n, userec_t *id);
+void fill_uhash(void);
+void load_uhash(void);
+
+uhash_t *uhash;
+
+int main() {
+ setgid(BBSGID);
+ setuid(BBSUID);
+ chdir(BBSHOME);
+ load_uhash();
+ return 0;
+}
+
+void load_uhash(void) {
+ int shmid;
+ shmid = shmget(UHASH_KEY, sizeof(uhash_t), IPC_CREAT | 0600);
+/* note we didn't use IPC_EXCL here.
+ so if the loading fails,
+ (like .PASSWD doesn't exist)
+ we may try again later.
+*/
+ if (shmid < 0)
+ {
+ perror("shmget");
+ exit(1);
+ }
+
+ uhash = (void *) shmat(shmid, NULL, 0);
+ if (uhash == (void *) -1)
+ {
+ perror("shmat");
+ exit(1);
+ }
+
+/* in case it's not assumed zero, this becomes a race... */
+ uhash->loaded = 0;
+
+ fill_uhash();
+
+/* ok... */
+ uhash->loaded = 1;
+}
+
+void fill_uhash(void)
+{
+ int fd, usernumber;
+ usernumber = 0;
+
+ for (fd = 0; fd < (1 << HASH_BITS); fd++)
+ uhash->hash_head[fd] = -1;
+
+ if ((fd = open(FN_PASSWD, O_RDONLY)) > 0)
+ {
+ struct stat stbuf;
+ caddr_t fimage, mimage;
+
+ fstat(fd, &stbuf);
+ fimage = mmap(NULL, stbuf.st_size, PROT_READ, MAP_SHARED, fd, 0);
+ if (fimage == (char *) -1)
+ {
+ perror("mmap");
+ exit(1);
+ }
+ close(fd);
+ fd = stbuf.st_size / sizeof(userec_t);
+ if (fd > MAX_USERS)
+ fd = MAX_USERS;
+
+ for (mimage = fimage; usernumber < fd; mimage += sizeof(userec_t))
+ {
+ add_to_uhash(usernumber, mimage);
+ usernumber++;
+ }
+ munmap(fimage, stbuf.st_size);
+ }
+ else
+ {
+ perror("open");
+ exit(1);
+ }
+ uhash->number = usernumber;
+ printf("total %d names loaded.\n", usernumber);
+}
+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, userec_t *user)
+{
+ int *p, h = string_hash(user->userid);
+ strcpy(uhash->userid[n], user->userid);
+ uhash->money[n] = user->money;
+ p = &(uhash->hash_head[h]);
+
+ while (*p != -1)
+ p = &(uhash->next_in_hash[*p]);
+
+ uhash->next_in_hash[*p = n] = -1;
+}
diff --git a/util/userlist.c b/util/userlist.c
new file mode 100644
index 00000000..9a142926
--- /dev/null
+++ b/util/userlist.c
@@ -0,0 +1,48 @@
+/* $id:$ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include "config.h"
+#include "pttstruct.h"
+
+struct utmpfile_t *u;
+
+int main(int argc, char **argv) {
+ int i, shm, counter;
+
+ shm = shmget(UTMPSHM_KEY, USHM_SIZE, SHM_R | SHM_W);
+ if(shm == -1) {
+ perror("shmget");
+ exit(0);
+ }
+
+ u = shmat(shm, NULL, 0);
+ if(u == (struct utmpfile_t *)-1) {
+ perror("shmat");
+ exit(0);
+ }
+
+ if(argc > 1) {
+ for(i = 1; i < argc; i++)
+ u->uinfo[atoi(argv[i])].pid = 0;
+ } else {
+ for(i = counter = 0; i < USHM_SIZE; i++)
+ if(u->uinfo[i].pid) {
+ userinfo_t *f;
+
+ f = &u->uinfo[i];
+ printf(
+ "%4d(%d) p[%d] i[%d] u[%s] n[%s] f[%s] m[%d] d[%d] t[%ld]\n",
+ ++counter, i, f->pager, f->invisible, f->userid,
+ f->username, f->from, f->mode, f->mind, f->lastact);
+ }
+ printf("\nTotal: %d(%d)\n", counter, u->number);
+ if(counter != u->number) {
+ u->number = counter;
+ printf("adjust user number!\n");
+ }
+ }
+ return 0;
+}
diff --git a/util/util.h b/util/util.h
new file mode 100644
index 00000000..9128e575
--- /dev/null
+++ b/util/util.h
@@ -0,0 +1,31 @@
+/* $Id: util.h,v 1.1 2002/03/07 15:13:46 in2 Exp $ */
+#ifndef INCLUDE_UTIL_H
+#define INCLUDE_UTIL_H
+
+int searchuser(char *userid);
+int stampfile(char *fpath, fileheader_t *fh);
+int append_record(char *fpath, fileheader_t *record, int size);
+int get_record(char *fpath, void *rptr, int size, int id);
+int substitute_record(char *fpath, void *rptr, int size, int id);
+void resolve_boards();
+int getbnum(char *bname);
+void inbtotal(int bid, int add);
+void *attach_shm(int shmkey, int shmsize);
+void reload_pttcache();
+void resolve_fcache();
+void attach_uhash();
+void stamplink(char *fpath, fileheader_t *fh);
+void resolve_utmp();
+void remove_from_uhash(int n);
+void setuserid(int num, char *userid);
+
+int passwd_mmap();
+int passwd_update(int num, userec_t *buf);
+int passwd_query(int num, userec_t *buf);
+int passwd_apply(int (*fptr)(userec_t *));
+int passwd_apply2(int (*fptr)(int, userec_t *));
+void passwd_lock();
+void passwd_unlock();
+
+#endif
+
diff --git a/util/util_cache.c b/util/util_cache.c
new file mode 100644
index 00000000..12a01994
--- /dev/null
+++ b/util/util_cache.c
@@ -0,0 +1,518 @@
+/* $Id: util_cache.c,v 1.1 2002/03/07 15:13:46 in2 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"
+
+int fcache_semid;
+
+/* 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¦³°ÝÃD®É¥Î*/
+ 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/%s", 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);
+}
+
+/* uhash *******************************************/
+/* the design is this:
+ we use another stand-alone program to create and load data into the hash.
+ (that program could be run in rc-scripts or something like that)
+ after loading completes, the stand-alone program sets loaded to 1 and exits.
+
+ the bbs exits if it can't attach to the shared memory or
+ the hash is not loaded yet.
+*/
+uhash_t *uhash;
+
+int setumoney(int uid, int money) {
+ uhash->money[uid-1]=money;
+ passwd_update_money(uid);
+ return uhash->money[uid-1];
+}
+
+int deumoney(int uid, int money) {
+ if(money<0 && uhash->money[uid-1]<-money)
+ return setumoney(uid,0);
+ else
+ return setumoney(uid,uhash->money[uid-1]+money);
+}
+int moneyof(int uid){ /* ptt §ï¶iª÷¿ú³B²z®Ä²v */
+ return uhash->money[uid-1];
+}
+/* attach_uhash should be called before using uhash */
+void attach_uhash() {
+ uhash = attach_shm(UHASH_KEY, sizeof(*uhash));
+ if(!uhash->loaded) /* assume fresh shared memory is zeroed */
+ exit(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(uhash->userid[n], id);
+
+ p = &(uhash->hash_head[h]);
+
+ while(*p != -1)
+ p = &(uhash->next_in_hash[*p]);
+
+ uhash->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(uhash->userid[n]);
+ int *p = &(uhash->hash_head[h]);
+
+ while(*p != -1 && *p != n)
+ p = &(uhash->next_in_hash[*p]);
+ if(*p == n)
+ *p = uhash->next_in_hash[n];
+}
+
+int searchuser(char *userid) {
+ int h,p;
+
+ if(uhash == NULL)
+ attach_uhash(); /* for sloopy util programs */
+
+ h = string_hash(userid);
+ p = uhash->hash_head[h];
+
+ while(p != -1) {
+ if(strcasecmp(uhash->userid[p],userid) == 0) {
+ strcpy(userid,uhash->userid[p]);
+ return p + 1;
+ }
+ p = uhash->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 > uhash->number)
+ uhash->number = num;
+ else
+ remove_from_uhash(num-1);
+ add_to_uhash(num-1,userid);
+ }
+}
+
+/*-------------------------------------------------------*/
+/* .UTMP cache */
+/*-------------------------------------------------------*/
+struct utmpfile_t *utmpshm=NULL;
+
+void resolve_utmp() {
+ if(utmpshm == NULL) {
+ utmpshm = attach_shm(UTMPSHM_KEY, sizeof(*utmpshm));
+ if(utmpshm->uptime == 0)
+ utmpshm->uptime = utmpshm->number = 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 = &(utmpshm->uinfo[i]);
+ if(!(uentp->pid)) {
+ memcpy(uentp, up, sizeof(userinfo_t));
+ currutmp = uentp;
+ utmpshm->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 = &(utmpshm->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 = &(utmpshm->uinfo[i]);
+ if(uid==uentp->uid)
+ return uentp;
+ }
+ return 0;
+}
+
+/*-------------------------------------------------------*/
+/* .BOARDS cache */
+/*-------------------------------------------------------*/
+char *fn_board=FN_BOARD;
+bcache_t *brdshm;
+boardheader_t *bcache;
+
+static void reload_bcache() {
+ if(brdshm->busystate) {
+ safe_sleep(1);
+ }
+}
+
+int numboards = -1;
+
+void resolve_boards() {
+ if(brdshm == NULL) {
+ brdshm = attach_shm(BRDSHM_KEY, sizeof(*brdshm));
+ if(brdshm->touchtime == 0)
+ brdshm->touchtime = 1;
+ bcache = brdshm->bcache;
+ }
+
+ while(brdshm->uptime < brdshm->touchtime)
+ reload_bcache();
+ numboards = brdshm->number;
+}
+
+void touch_boards() {
+ time(&(brdshm->touchtime));
+ numboards = -1;
+ resolve_boards();
+}
+void reset_board(int bid)
+{
+ int fd;
+ if(--bid<0)return;
+ if(brdshm->busystate==0)
+ {
+ brdshm->busystate = 1;
+ if((fd = open(fn_board, O_RDONLY)) > 0) {
+ lseek(fd, (off_t)(bid * sizeof(boardheader_t)), SEEK_SET);
+ read(fd, &bcache[bid], sizeof(boardheader_t));
+ close(fd);
+ }
+ brdshm->busystate = 0;
+ }
+}
+boardheader_t *getbcache(int bid) { /* Ptt§ï¼g */
+ return bcache + bid - 1;
+}
+
+void touchbtotal(int bid) {
+ brdshm->total[bid - 1] = 0;
+ brdshm->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 °ÊºA¬Ýª© */
+struct pttcache_t *ptt;
+
+void reload_pttcache() {
+ if(ptt->busystate)
+ 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;
+
+ ptt->busystate = 1;
+ ptt->max_film = 0;
+ bzero(ptt->notes, sizeof ptt->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;
+ ptt->next_refresh[section] = ptt->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(ptt->notes[id],sizeof(char), 200*11, fp2);
+ ptt->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);
+ }
+ ptt->next_refresh[section] = -1;
+ ptt->n_notes[section] = ptt->max_film = id-1;
+ ptt->max_history = ptt->max_film - 2;
+ if(ptt->max_history > MAX_HISTORY - 1)
+ ptt->max_history = MAX_HISTORY - 1;
+ if(ptt->max_history <0) ptt->max_history=0;
+
+ fp = fopen("etc/today_is","r");
+ if(fp) {
+ fgets(ptt->today_is,15,fp);
+ if((chr = strchr(ptt->today_is,'\n')))
+ *chr = 0;
+ ptt->today_is[15] = 0;
+ fclose(fp);
+ }
+
+ /* µ¥©Ò¦³¸ê®Æ§ó·s«á¦A³]©w uptime */
+
+ ptt->uptime = ptt->touchtime ;
+ ptt->busystate = 0;
+ }
+}
+
+void resolve_garbage() {
+ int count=0;
+
+ if(ptt == NULL) {
+ ptt = attach_shm(PTTSHM_KEY, sizeof(*ptt));
+ if(ptt->touchtime == 0)
+ ptt->touchtime = 1;
+ }
+ while(ptt->uptime < ptt->touchtime) { /* ¤£¥Îwhileµ¥ */
+ reload_pttcache();
+ if(count ++ > 10 && ptt->busystate) {
+/* Ptt: ³oÃä·|¦³°ÝÃD load¶W¹L10 ¬í·|©Ò¦³¶iloopªºprocess³£Åý busystate = 0
+ ³o¼Ë·|©Ò¦³prcosee³£·|¦bload °ÊºA¬ÝªO ·|³y¦¨load¤j¼W
+ ¦ý¨S¦³¥Î³o­Ófunctionªº¸Ü ¸U¤@load passwdÀɪºprocess¦º¤F ¤S¨S¦³¤H§â¥L
+ ¸Ñ¶} ¦P¼Ëªº°ÝÃDµo¥Í¦breload passwd
+*/
+ ptt->busystate = 0;
+ }
+ }
+}
+
+/*-------------------------------------------------------*/
+/* PTT's cache */
+/*-------------------------------------------------------*/
+/* cachefor from host »P³Ì¦h¤W½u¤H¼Æ */
+struct fromcache_t *fcache;
+
+static void reload_fcache() {
+ if(fcache->busystate)
+ safe_sleep(1);
+ else {
+ FILE *fp;
+
+ fcache->busystate = 1;
+ bzero(fcache->domain, sizeof fcache->domain);
+ if((fp = fopen("etc/domain_name_query","r"))) {
+ char buf[101],*po;
+
+ fcache->top=0;
+ while(fgets(buf,100,fp)) {
+ if(buf[0] && buf[0] != '#' && buf[0] != ' ' &&
+ buf[0] != '\n') {
+ sscanf(buf,"%s",fcache->domain[fcache->top]);
+ po = buf + strlen(fcache->domain[fcache->top]);
+ while(*po == ' ')
+ po++;
+ strncpy(fcache->replace[fcache->top],po,49);
+ fcache->replace[fcache->top]
+ [strlen(fcache->replace[fcache->top])-1] = 0;
+ (fcache->top)++;
+ }
+ }
+ }
+
+ fcache->max_user=0;
+
+ /* µ¥©Ò¦³¸ê®Æ§ó·s«á¦A³]©w uptime */
+ fcache->uptime = fcache->touchtime;
+ fcache->busystate = 0;
+ }
+}
+
+void resolve_fcache() {
+ if(fcache == NULL) {
+ fcache = attach_shm(FROMSHM_KEY, sizeof(*fcache));
+ if(fcache->touchtime == 0)
+ fcache->touchtime = 1;
+ }
+ while(fcache->uptime < fcache->touchtime)
+ reload_fcache();
+}
diff --git a/util/util_passwd.c b/util/util_passwd.c
new file mode 100644
index 00000000..07a79351
--- /dev/null
+++ b/util/util_passwd.c
@@ -0,0 +1,139 @@
+/* $Id: util_passwd.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */
+#include <stdio.h>
+#include <string.h>
+#include <fcntl.h>
+#include <errno.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"
+
+#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/util/util_record.c b/util/util_record.c
new file mode 100644
index 00000000..ad129638
--- /dev/null
+++ b/util/util_record.c
@@ -0,0 +1,245 @@
+/* $Id: util_record.c,v 1.1 2002/03/07 15:13:46 in2 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 ®É¡A¨Ì¾Ú®É¶¡«Ø¥ßÀɮסA¥[¤W¶lÂW */
+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", ++dtime );
+ 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;
+}
diff --git a/util/waterball.pl b/util/waterball.pl
new file mode 100644
index 00000000..7f49d3c5
--- /dev/null
+++ b/util/waterball.pl
@@ -0,0 +1,149 @@
+#!/usr/bin/perl
+use lib '/home/bbs/bin/';
+use LocalVars;
+use Time::Local;
+use POSIX;
+use FileHandle;
+use strict;
+use Mail::Sender;
+
+my($fndes, $fnsrc, $userid, $mailto, $outmode);
+foreach $fndes ( <$JOBSPOOL/water.des.*> ){ #des: userid, mailto, outmode
+ (open FH, "< $fndes") or next;
+ chomp($userid = <FH>);
+ chomp($mailto = <FH>);
+ chomp($outmode= <FH>);
+ close FH;
+ next if( !$userid );
+ print "$userid, $mailto, $outmode\n";
+ `rm -Rf $TMP/water`;
+ `mkdir $TMP/water`;
+
+ $fnsrc = $fndes;
+ $fnsrc =~ s/\.des\./\.src\./;
+ eval{
+ process($fnsrc, "$TMP/water/", $outmode, $userid);
+ };
+ if( $@ ){
+ print "$@\n";
+ }
+ else{
+ chdir "$TMP/water";
+ if( $mailto eq '.' || $mailto =~ /\.bbs/ ){
+ $mailto = "$userid.bbs\@$hostname" if( $mailto eq '.' );
+ foreach my $fn ( <$TMP/water/*> ){
+ my $who = substr($fn, rindex($fn, '/') + 1);
+ my $content = '';
+ open FH, "< $fn";while( <FH> ){chomp;$content .= "$_\n";}
+ if( !MakeMail({mailto => $mailto,
+ subject => "©M $who ªº¤ô²y°O¿ý",
+ body => $content,
+ }) ){ print "fault\n"; }
+ }
+ unlink $fnsrc;
+ unlink $fndes;
+ }
+ else{
+ if( MakeMail({tartarget => "$TMP/$userid.waterball.tgz",
+ tarsource => "*",
+ mailto => "$userid <$mailto>",
+ subject => "¤ô²y¬ö¿ý",
+ body =>
+ "\n ptt2 ¯¸ªø¸s ". POSIX::ctime(time())}
+ ) ){
+ unlink $fnsrc;
+ unlink $fndes;
+ }
+ }
+ }
+}
+
+sub process
+{
+ my($fn, $outdir, $outmode, $me) = @_;
+ my($cmode, $who, $time, $say, $orig, %FH, %LAST, $len);
+ open DIN, "< $fn";
+ while( <DIN> ){
+ chomp;
+ next if( !(($cmode, $who, $time, $say, $orig) = parse($_)) );
+ next if( !$who );
+
+ if( ! $FH{$who} ){
+ $FH{$who} = new FileHandle "> $outdir/$who";
+ }
+ if( $outmode == 0 ){
+ next if( $say =~ /<<¤U¯¸³qª¾>> -- §Ú¨«Åo¡I/ ||
+ $say =~ /<<¤W¯¸³qª¾>> -- §Ú¨Ó°Õ¡I/ );
+ if( $time - $LAST{$who} > 1800 ){
+ if( $LAST{$who} != 0 ){
+ ($FH{$who})->print( POSIX::ctime($LAST{$who}) , "\n");
+ }
+ ($FH{$who})->print( POSIX::ctime($time) );
+ $LAST{$who} = $time;
+ }
+ $len = (length($who) > length($me) ? length($who) : length($me))+1;
+ ($FH{$who})->printf("%-${len}s %s\n", ($cmode?$who:$me).':', $say);
+ }
+ elsif( $outmode == 1 ){
+ ($FH{$who})->print("$orig\n");
+ }
+ }
+ if( $outmode == 0 ){
+ foreach( keys %FH ){
+ ($FH{$_})->print( POSIX::ctime($LAST{$_}) );
+ }
+ }
+ foreach( keys %FH ){
+ ($FH{$_})->close();
+ }
+ close DIN;
+}
+
+sub parse
+{
+ my $dat = $_[0];
+ my($cmode, $who, $year, $month, $day, $hour, $min, $sec, $say);
+ if( $dat =~ /^To/ ){
+ $cmode = 0;
+ ($who, $say, $month, $day, $year, $hour, $min, $sec) =
+ $dat =~ m|^To (\w+):\s*(.*)\[(\d+)/(\d+)/(\d+) (\d+):(\d+):(\d+)\]|;
+ }
+ else{
+ $cmode = 1;
+ ($who, $say, $month, $day, $year, $hour, $min, $sec) =
+ $dat =~ m|¡¹(\w+?)\[37;45m\s*(.*)\[m \[0m\[(\w+)/(\w+)/(\w+) (\w+):(\w+):(\w+)\]|;
+
+ }
+# $time = timelocal($sec,$min,$hours,$mday,$mon,$year);
+
+ return undef if( $month == 0 );
+ return ($cmode, $who, timelocal($sec, $min, $hour, $day, $month - 1, $year), $say, $_[0]);
+}
+
+sub MakeMail
+{
+ my($arg) = @_;
+ my $sender;
+ `$TAR zcf $arg->{tartarget} $arg->{tarsource}`
+ if( $arg->{tarsource} );
+ $sender = new Mail::Sender{smtp => $SMTPSERVER,
+ from => "$hostname¤ô²y¾ã²zµ{¦¡ <in2\@ptt2.csie.ntu.edu.tw>"};
+ foreach( 0..3 ){
+ if( (!$arg->{tartarget} &&
+ $sender->MailMsg({to => $arg->{mailto},
+ subject => $arg->{subject},
+ msg => $arg->{body}
+ }) ) ||
+ ($arg->{tartarget} &&
+ $sender->MailFile({to => $arg->{mailto},
+ subject => $arg->{subject},
+ msg => $arg->{body},
+ file => $arg->{tartarget}})) ){
+ unlink $arg->{tartarget} if( $arg->{tartarget} );
+ return 1;
+ }
+ }
+ print "fault\n";
+ unlink $arg->{tartarget} if( $arg->{tartarget} );
+ return 0;
+}
diff --git a/util/weather.perl b/util/weather.perl
new file mode 100644
index 00000000..c9a35406
--- /dev/null
+++ b/util/weather.perl
@@ -0,0 +1,31 @@
+#!/usr/bin/perl
+# $Id: weather.perl,v 1.1 2002/03/07 15:13:46 in2 Exp $
+#
+# ¤£¯à¶]ªº¸Ü¡A¬Ý¬Ý bbspost ªº¸ô®|¬O§_¥¿½T¡C
+# ¦pªGµo¥Xªº post ¨S¦³®ð¶H³ø§i¦Ó¬O»¡ URL §ä¤£¨ì¡A«h½T©w¤@¤U¯à¤£¯à¬Ý¨ì
+# ¤¤¥¡®ð¶H§½ªº WWW ¤Î URL ¬O§_¥¿½T¡C
+# ²z½×¤W¾A¥Î©Ò¦³ Eagle BBS ¨t¦C¡C
+# -- Beagle Apr 13 1997
+open(BBSPOST, "| bin/webgrep>etc/weather.tmp");
+# ¤é´Á
+open(DATE, "date +'%a %b %d %T %Y' |");
+$date = <DATE>;
+chop $date;
+close DATE;
+
+# Header
+# ¤º®e
+open(WEATHER, "/usr/bin/lynx -dump http://www.cwb.gov.tw/V3.0/weather/text/Data/W03.txt |");
+while (<WEATHER>) {
+ print BBSPOST if ($_ ne "\n");
+}
+close WEATHER;
+
+# ñ¦WÀÉ
+print BBSPOST "\n--\n";
+print BBSPOST "§Ú¬Obeagle©Ò¦³¥i·Rªº¤p»æ°®...¸ó®ü¬°PttªA°È\n";
+print BBSPOST "--\n";
+print BBSPOST "¡¸ [Origin: ¡·ªGÂæ¤p¯¸¡·] [From: [ÂŲùÃP»æ«Î] ] ";
+
+close BBSPOST;
+
diff --git a/util/weather.sh b/util/weather.sh
new file mode 100644
index 00000000..315b0ec3
--- /dev/null
+++ b/util/weather.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+# $Id: weather.sh,v 1.1 2002/03/07 15:13:46 in2 Exp $
+#
+bin/weather.perl
+bin/post Record ¥þ¬Ù¦U¦a¤Ñ®ð¹w³ø [®ð¶H¤p©j] etc/weather.tmp
diff --git a/util/webgrep.c b/util/webgrep.c
new file mode 100644
index 00000000..07089bb6
--- /dev/null
+++ b/util/webgrep.c
@@ -0,0 +1,46 @@
+/* $Id: webgrep.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+int main()
+{
+ char genbuf[256], *str, *buf;
+ while (fgets(genbuf, 255, stdin))
+ {
+ register int ansi;
+ if (!strncmp(genbuf, "References", 10))
+ break;
+ str = genbuf;
+ buf = genbuf;
+ if (!strncmp(genbuf, "lynx: Can't access", 18))
+ {
+ printf("®ð¶H³ø¾É¤p©j¥ð°²¤¤,½Ð¨ìRecordª©Â½¹L¥h¸ê®Æ.");
+ break;
+ }
+ for (ansi = 0; *str; str++)
+ {
+ if (*str == '[' && strchr("0123456789", *(str + 1)))
+ {
+ ansi = 1;
+ }
+ else if (ansi)
+ {
+ if (!strchr("0123456789]", *str))
+ {
+ ansi = 0;
+ if (str)
+ *buf++ = *str;
+ }
+ }
+ else
+ {
+ if (str)
+ *buf++ = *str;
+ }
+ }
+ *buf = 0;
+ printf(genbuf);
+ }
+ return 0;
+}
diff --git a/util/xchatd.c b/util/xchatd.c
new file mode 100644
index 00000000..46fba147
--- /dev/null
+++ b/util/xchatd.c
@@ -0,0 +1,3504 @@
+/* $Id: xchatd.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <time.h>
+#include <sys/resource.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include "config.h"
+#include "pttstruct.h"
+#include "util.h"
+#include "perm.h"
+#include "common.h"
+#include "xchatd.h"
+
+#define SERVER_USAGE
+#define WATCH_DOG
+#undef MONITOR /* ºÊ·þ chatroom ¬¡°Ê¥H¸Ñ¨MªÈ¯É */
+#undef DEBUG /* µ{¦¡°£¿ù¤§¥Î */
+
+#ifdef DEBUG
+#define MONITOR
+#endif
+
+static int gline;
+
+#ifdef WATCH_DOG
+#define MYDOG gline = __LINE__
+#else
+#define MYDOG /* NOOP */
+#endif
+
+
+
+#define CHAT_PIDFILE "log/chat.pid"
+#define CHAT_LOGFILE "log/chat.log"
+#define CHAT_INTERVAL (60 * 30)
+#define SOCK_QLEN 1
+
+
+/* name of the main room (always exists) */
+
+
+#define MAIN_NAME "main"
+#define MAIN_TOPIC "²i¯ù¥i°^¦è¤Ñ¦ò"
+
+
+#define ROOM_LOCKED 1
+#define ROOM_SECRET 2
+#define ROOM_OPENTOPIC 4
+#define ROOM_HANDUP 8
+#define ROOM_ALL (NULL)
+
+
+#define LOCKED(room) (room->rflag & ROOM_LOCKED)
+#define SECRET(room) (room->rflag & ROOM_SECRET)
+#define OPENTOPIC(room) (room->rflag & ROOM_OPENTOPIC)
+#define RHANDUP(room) (room->rflag & ROOM_HANDUP)
+
+#define RESTRICTED(usr) (usr->uflag == 0) /* guest */
+#define CHATSYSOP(usr) (usr->uflag & ( PERM_SYSOP | PERM_CHATROOM))
+/* Thor: SYSOP »P CHATROOM³£¬O chatÁ`ºÞ */
+#define PERM_ROOMOP PERM_CHAT /* Thor: ­É PERM_CHAT¬° PERM_ROOMOP */
+#define PERM_HANDUP PERM_BM /* ­É PERM_BM ¬°¦³¨S¦³Á|¤â¹L */
+#define PERM_SAY PERM_NOTOP /* ­É PERM_NOTOP ¬°¦³¨S¦³µoªíÅv */
+
+/* ¶i¤J®É»Ý²MªÅ */
+/* Thor: ROOMOP¬°©Ð¶¡ºÞ²z­û */
+#define ROOMOP(usr) (usr->uflag & ( PERM_ROOMOP | PERM_SYSOP | PERM_CHATROOM))
+#define CLOAK(usr) (usr->uflag & PERM_CLOAK)
+#define HANDUP(usr) (usr->uflag & PERM_HANDUP)
+#define SAY(usr) (usr->uflag & PERM_SAY)
+/* Thor: ²á¤Ñ«ÇÁô¨­³N */
+
+
+/* ----------------------------------------------------- */
+/* ChatRoom data structure */
+/* ----------------------------------------------------- */
+
+typedef struct ChatRoom ChatRoom;
+typedef struct ChatUser ChatUser;
+typedef struct UserList UserList;
+typedef struct ChatCmd ChatCmd;
+typedef struct ChatAction ChatAction;
+
+struct ChatUser
+{
+ struct ChatUser *unext;
+ int sock; /* user socket */
+ int talksock; /* talk socket */
+ ChatRoom *room;
+ UserList *ignore;
+ int userno;
+ int uflag;
+ int clitype; /* Xshadow: client type. 1 for common client,
+ * 0 for bbs only client */
+ time_t uptime; /* Thor: unused */
+ char userid[IDLEN + 1]; /* real userid */
+ char chatid[9]; /* chat id */
+ char lasthost[30]; /* host address */
+ char ibuf[80]; /* buffer for non-blocking receiving */
+ int isize; /* current size of ibuf */
+};
+
+
+struct ChatRoom
+{
+ struct ChatRoom *next, *prev;
+ char name[IDLEN];
+ char topic[48]; /* Let the room op to define room topic */
+ int rflag; /* ROOM_LOCKED, ROOM_SECRET, ROOM_OPENTOPIC */
+ int occupants; /* number of users in room */
+ UserList *invite;
+};
+
+
+struct UserList
+{
+ struct UserList *next;
+ int userno;
+ char userid[IDLEN + 1];
+};
+
+
+struct ChatCmd
+{
+ char *cmdstr;
+ void (*cmdfunc) ();
+ int exact;
+};
+
+
+static ChatRoom mainroom;
+static ChatUser *mainuser;
+static fd_set mainfds;
+static int maxfds; /* number of sockets to select on */
+static int totaluser; /* current number of connections */
+static struct timeval zerotv; /* timeval for selecting */
+static char chatbuf[256]; /* general purpose buffer */
+static int common_client_command;
+
+static char msg_not_op[] = "¡» ±z¤£¬O³o¶¡²á¤Ñ«Çªº Op";
+static char msg_no_such_id[] = "¡» ¥Ø«e¨S¦³¤H¨Ï¥Î [%s] ³o­Ó²á¤Ñ¥N¸¹";
+static char msg_not_here[] = "¡» [%s] ¤£¦b³o¶¡²á¤Ñ«Ç";
+
+
+#define FUZZY_USER ((ChatUser *) -1)
+
+
+typedef struct userec_t ACCT;
+
+/* ----------------------------------------------------- */
+/* acct_load for check acct */
+/* ----------------------------------------------------- */
+
+int
+acct_load(acct, userid)
+ ACCT *acct;
+ char *userid;
+{
+ int id;
+ if((id=searchuser(userid))<0)
+ {
+ return -1;
+ }
+ else
+ {
+ return get_record(FN_PASSWD, acct, sizeof(ACCT), id);
+ }
+}
+
+
+/* ----------------------------------------------------- */
+/* str_lower for check acct */
+/* ----------------------------------------------------- */
+void
+str_lower(dst, src)
+ char *dst, *src;
+{
+ register int ch;
+
+ do
+ {
+ ch = *src++;
+ if (ch >= 'A' && ch <= 'Z')
+ ch |= 0x20;
+ *dst++ = ch;
+ } while (ch);
+}
+
+/*
+ * str_ncpy() - similar to strncpy(3) but terminates string always with '\0'
+ * if n != 0, and doesn't do padding
+ */
+
+void
+str_ncpy(dst, src, n)
+ char *dst;
+ char *src;
+ int n;
+{
+ char *end;
+
+ end = dst + n;
+
+ do
+ {
+ n = (dst == end) ? 0 : *src++;
+ *dst++ = n;
+ } while (n);
+}
+
+
+/* ----------------------------------------------------- */
+/* usr_fpath for check acct */
+/* ----------------------------------------------------- */
+char *str_home_file = "home/%c/%s/%s";
+
+void
+usr_fpath(buf, userid, fname)
+ char *buf, *userid, *fname;
+{
+ sprintf(buf, str_home_file, userid[0], userid, fname);
+}
+
+/* ----------------------------------------------------- */
+/* chkpasswd for check passwd */
+/* ----------------------------------------------------- */
+char *crypt();
+static char pwbuf[PASSLEN];
+
+int
+chkpasswd(passwd, test)
+ char *passwd, *test;
+{
+ char *pw;
+
+ str_ncpy(pwbuf, test, PASSLEN);
+ pw = crypt(pwbuf, passwd);
+ return (!strncmp(pw, passwd, PASSLEN));
+}
+
+/* ----------------------------------------------------- */
+/* operation log and debug information */
+/* ----------------------------------------------------- */
+
+
+static int flog; /* log file descriptor */
+
+
+static void
+logit(key, msg)
+ char *key;
+ char *msg;
+{
+ time_t now;
+ struct tm *p;
+ char buf[512];
+
+ time(&now);
+ p = localtime(&now);
+ sprintf(buf, "%02d/%02d %02d:%02d:%02d %-13s%s\n",
+ p->tm_mon + 1, p->tm_mday,
+ p->tm_hour, p->tm_min, p->tm_sec, key, msg);
+ write(flog, buf, strlen(buf));
+}
+
+
+static void
+log_init()
+{
+ flog = open(CHAT_LOGFILE, O_WRONLY | O_CREAT | O_APPEND, 0644);
+ logit("START", "chat daemon");
+}
+
+
+static void
+log_close()
+{
+ close(flog);
+}
+
+
+#ifdef DEBUG
+static void
+debug_user()
+{
+ register ChatUser *user;
+ int i;
+ char buf[80];
+
+ i = 0;
+ for (user = mainuser; user; user = user->unext)
+ {
+ sprintf(buf, "%d) %s %s", ++i, user->userid, user->chatid);
+ logit("DEBUG_U", buf);
+ }
+}
+
+
+static void
+debug_room()
+{
+ register ChatRoom *room;
+ int i;
+ char buf[80];
+
+ i = 0;
+ room = &mainroom;
+
+ do
+ {
+ sprintf(buf, "%d) %s %d", ++i, room->name, room->occupants);
+ logit("DEBUG_R", buf);
+ } while (room = room->next);
+}
+#endif /* DEBUG */
+
+
+/* ----------------------------------------------------- */
+/* string routines */
+/* ----------------------------------------------------- */
+
+
+static int valid_chatid(register char *id) {
+ register int ch, len;
+
+ for(len = 0; (ch = *id); id++) {
+ /* Thor: check for endless */
+ MYDOG;
+
+ if(ch == '/' || ch == '*' || ch == ':')
+ return 0;
+ if(++len > 8)
+ return 0;
+ }
+ return len;
+}
+
+/* Case Independent strcmp : 1 ==> euqal */
+
+
+static int
+str_equal(s1, s2)
+ register unsigned char *s1, *s2; /* Thor: ¥[¤W unsigned,
+ * ÁקK¤¤¤åªº°ÝÃD */
+{
+ register int c1, c2;
+
+ for (;;)
+ { /* Thor: check for endless */
+ MYDOG;
+
+ c1 = *s1;
+ if (c1 >= 'A' && c1 <= 'Z')
+ c1 |= 32;
+
+ c2 = *s2;
+ if (c2 >= 'A' && c2 <= 'Z')
+ c2 |= 32;
+
+ if (c1 != c2)
+ return 0;
+
+ if (!c1)
+ return 1;
+
+ s1++;
+ s2++;
+ }
+}
+
+
+/* ----------------------------------------------------- */
+/* match strings' similarity case-insensitively */
+/* ----------------------------------------------------- */
+/* str_match(keyword, string) */
+/* ----------------------------------------------------- */
+/* 0 : equal ("foo", "foo") */
+/* -1 : mismatch ("abc", "xyz") */
+/* ow : similar ("goo", "good") */
+/* ----------------------------------------------------- */
+
+
+static int
+str_match(s1, s2)
+ register unsigned char *s1, *s2; /* Thor: ¥[¤W unsigned,
+ * ÁקK¤¤¤åªº°ÝÃD */
+{
+ register int c1, c2;
+
+ for (;;)
+ { /* Thor: check for endless */
+ MYDOG;
+
+ c2 = *s2;
+ c1 = *s1;
+ if (!c1)
+ {
+ return c2;
+ }
+
+ if (c1 >= 'A' && c1 <= 'Z')
+ c1 |= 32;
+
+ if (c2 >= 'A' && c2 <= 'Z')
+ c2 |= 32;
+
+ if (c1 != c2)
+ return -1;
+
+ s1++;
+ s2++;
+ }
+}
+
+
+/* ----------------------------------------------------- */
+/* search user/room by its ID */
+/* ----------------------------------------------------- */
+
+
+static ChatUser *
+cuser_by_userid(userid)
+ char *userid;
+{
+ register ChatUser *cu;
+
+ for (cu = mainuser; cu; cu = cu->unext)
+ {
+ MYDOG;
+
+ if (str_equal(userid, cu->userid))
+ break;
+ }
+ return cu;
+}
+
+
+static ChatUser *
+cuser_by_chatid(chatid)
+ char *chatid;
+{
+ register ChatUser *cu;
+
+ for (cu = mainuser; cu; cu = cu->unext)
+ {
+ MYDOG;
+
+ if (str_equal(chatid, cu->chatid))
+ break;
+ }
+ return cu;
+}
+
+
+static ChatUser *
+fuzzy_cuser_by_chatid(chatid)
+ char *chatid;
+{
+ register ChatUser *cu, *xuser;
+ int mode;
+
+ xuser = NULL;
+
+ for (cu = mainuser; cu; cu = cu->unext)
+ {
+ MYDOG;
+
+ mode = str_match(chatid, cu->chatid);
+ if (mode == 0)
+ return cu;
+
+ if (mode > 0)
+ {
+ if (xuser == NULL)
+ xuser = cu;
+ else
+ return FUZZY_USER; /* ²Å¦XªÌ¤j©ó 2 ¤H */
+ }
+ }
+ return xuser;
+}
+
+
+static ChatRoom *croom_by_roomid(char *roomid) {
+ register ChatRoom *room;
+
+ room = &mainroom;
+ do {
+ MYDOG;
+
+ if(str_equal(roomid, room->name))
+ break;
+ } while((room = room->next));
+ return room;
+}
+
+
+/* ----------------------------------------------------- */
+/* UserList routines */
+/* ----------------------------------------------------- */
+
+
+static void
+list_free(list)
+ UserList *list;
+{
+ UserList *tmp;
+
+ while (list)
+ {
+ MYDOG;
+
+ tmp = list->next;
+
+ free(list);
+ MYDOG;
+ list = tmp;
+ }
+}
+
+
+static void
+list_add(list, user)
+ UserList **list;
+ ChatUser *user;
+{
+ UserList *node;
+
+ MYDOG;
+
+ if((node = (UserList *) malloc(sizeof(UserList)))) {
+ /* Thor: ¨¾¤îªÅ¶¡¤£°÷ */
+ strcpy(node->userid, user->userid);
+ node->userno = user->userno;
+ node->next = *list;
+ *list = node;
+ }
+ MYDOG;
+}
+
+
+static int
+list_delete(list, userid)
+ UserList **list;
+ char *userid;
+{
+ UserList *node;
+
+ while((node = *list)) {
+ MYDOG;
+
+ if (str_equal(node->userid, userid))
+ {
+ *list = node->next;
+ MYDOG;
+ free(node);
+ MYDOG;
+ return 1;
+ }
+ list = &node->next; /* Thor: list­n¸òµÛ«e¶i */
+ }
+
+ return 0;
+}
+
+
+static int
+list_belong(list, userno)
+ UserList *list;
+ int userno;
+{
+ while (list)
+ {
+ MYDOG;
+
+ if (userno == list->userno)
+ return 1;
+ list = list->next;
+ }
+ return 0;
+}
+
+
+/* ------------------------------------------------------ */
+/* non-blocking socket routines : send message to users */
+/* ------------------------------------------------------ */
+
+
+static void
+do_send(nfds, wset, msg, number)
+ int nfds;
+ fd_set *wset;
+ char *msg;
+ int number;
+{
+ int sr;
+
+ /* Thor: for future reservation bug */
+
+ zerotv.tv_sec = 0;
+ zerotv.tv_usec = 16384; /* Ptt: §ï¦¨16384 ÁקK¤£«ö®Éfor loop¦Ycpu time
+ 16384 ¬ù¨C¬í64¦¸ */
+
+ MYDOG;
+
+ sr = select(nfds + 1, NULL, wset, NULL, &zerotv);
+
+ MYDOG;
+
+ if (sr > 0)
+ {
+ register int len;
+
+ len = strlen(msg) + 1;
+ while (nfds >= 0)
+ {
+ MYDOG;
+
+ if (FD_ISSET(nfds, wset))
+ {
+ MYDOG;
+ send(nfds, msg, len, 0);/* Thor: ¦pªGbufferº¡¤F, ¤´·| block */
+ MYDOG;
+ if (--sr <= 0)
+ return;
+ }
+ nfds--;
+ }
+ }
+}
+
+
+static void
+send_to_room(room, msg, userno, number)
+ ChatRoom *room;
+ char *msg;
+ int userno;
+ int number;
+{
+ ChatUser *cu;
+ fd_set wset, *wptr;
+ int sock, max;
+ static char sendbuf[256];
+ int clitype; /* ¤À¬° bbs client ¤Î common client ¨â¦¸³B²z */
+
+ for (clitype = (number == MSG_MESSAGE || !number) ? 0 : 1; clitype < 2; clitype++)
+ {
+
+ FD_ZERO(wptr = &wset);
+ max = -1;
+
+ for (cu = mainuser; cu; cu = cu->unext)
+ {
+ MYDOG;
+
+ if (room == cu->room || room == ROOM_ALL)
+ {
+ if (cu->clitype == clitype && (!userno || !list_belong(cu->ignore, userno)))
+ {
+ sock = cu->sock;
+ FD_SET(sock, wptr);
+ if (max < sock)
+ max = sock;
+ }
+ }
+ }
+
+ if (max < 0)
+ continue;
+
+ if (clitype)
+ {
+ if (strlen(msg))
+ sprintf(sendbuf, "%3d %s", number, msg);
+ else
+ sprintf(sendbuf, "%3d", number);
+
+ do_send(max, wptr, sendbuf);
+ }
+ else
+ do_send(max, wptr, msg);
+ }
+}
+
+
+static void
+send_to_user(user, msg, userno, number)
+ ChatUser *user;
+ char *msg;
+ int userno;
+ int number;
+{
+ if (!user->clitype && number && number != MSG_MESSAGE)
+ return;
+
+ if (!userno || !list_belong(user->ignore, userno))
+ {
+ fd_set wset, *wptr;
+ int sock;
+ static char sendbuf[256];
+
+ sock = user->sock;
+ FD_ZERO(wptr = &wset);
+ FD_SET(sock, wptr);
+
+ if (user->clitype)
+ {
+ if (strlen(msg))
+ sprintf(sendbuf, "%3d %s", number, msg);
+ else
+ sprintf(sendbuf, "%3d", number);
+ do_send(sock, wptr, sendbuf);
+ }
+ else
+ do_send(sock, wptr, msg);
+ }
+}
+
+#if 0
+static void
+send_to_sock(sock, msg) /* Thor: unused */
+ int sock;
+ char *msg;
+{
+ fd_set wset, *wptr;
+
+ FD_ZERO(wptr = &wset);
+ FD_SET(sock, wptr);
+ do_send(sock, wptr, msg);
+}
+#endif
+
+/* ----------------------------------------------------- */
+
+static void
+room_changed(room)
+ ChatRoom *room;
+{
+ if (!room)
+ return;
+
+ sprintf(chatbuf, "= %s %d %d %s", room->name, room->occupants, room->rflag, room->topic);
+ send_to_room(ROOM_ALL, chatbuf, 0, MSG_ROOMNOTIFY);
+}
+
+static void
+user_changed(cu)
+ ChatUser *cu;
+{
+ if (!cu)
+ return;
+
+ sprintf(chatbuf, "= %s %s %s %s", cu->userid, cu->chatid, cu->room->name, cu->lasthost);
+ if (ROOMOP(cu))
+ strcat(chatbuf, " Op");
+ send_to_room(cu->room, chatbuf, 0, MSG_USERNOTIFY);
+}
+
+static void
+exit_room(user, mode, msg)
+ ChatUser *user;
+ int mode;
+ char *msg;
+{
+ ChatRoom *room;
+
+ if((room = user->room)) {
+ user->room = NULL;
+ user->uflag &= ~PERM_ROOMOP;
+
+ if (--room->occupants > 0)
+ {
+ char *chatid;
+
+ chatid = user->chatid;
+ switch (mode)
+ {
+ case EXIT_LOGOUT:
+
+ sprintf(chatbuf, "¡» %s Â÷¶}¤F ...", chatid);
+ if (msg && *msg)
+ {
+ strcat(chatbuf, ": ");
+ msg[79] = 0; /* Thor:¨¾¤î¤Óªø */
+ strncat(chatbuf, msg, 80);
+ }
+ break;
+
+ case EXIT_LOSTCONN:
+
+ sprintf(chatbuf, "¡» %s ¦¨¤FÂ_½uªº­·ºåÅo", chatid);
+ break;
+
+ case EXIT_KICK:
+
+ sprintf(chatbuf, "¡» «¢«¢¡I%s ³Q½ð¥X¥h¤F", chatid);
+ break;
+ }
+ if (!CLOAK(user)) /* Thor: ²á¤Ñ«ÇÁô¨­³N */
+ send_to_room(room, chatbuf, 0, MSG_MESSAGE);
+
+ sprintf(chatbuf, "- %s", user->userid);
+ send_to_room(room, chatbuf, 0, MSG_USERNOTIFY);
+ room_changed(room);
+
+ return;
+ }
+
+ else if (room != &mainroom)
+ { /* Thor: ¤H¼Æ¬°0®É,¤£¬Omainroom¤~free */
+ register ChatRoom *next;
+
+#ifdef DEBUG
+ debug_room();
+#endif
+
+ sprintf(chatbuf, "- %s", room->name);
+ send_to_room(ROOM_ALL, chatbuf, 0, MSG_ROOMNOTIFY);
+
+ room->prev->next = room->next;
+ if((next = room->next))
+ next->prev = room->prev;
+ list_free(room->invite);
+
+ MYDOG;
+ free(room);
+ MYDOG;
+
+#ifdef DEBUG
+ debug_room();
+#endif
+ }
+ }
+}
+
+
+/* ----------------------------------------------------- */
+/* chat commands */
+/* ----------------------------------------------------- */
+
+/* ----------------------------------------------------- */
+/* (.ACCT) ¨Ï¥ÎªÌ±b¸¹ (account) subroutines */
+/* ----------------------------------------------------- */
+
+static char datemsg[32];
+
+char *
+Ctime(clock)
+ time_t *clock;
+{
+ struct tm *t = localtime(clock);
+ static char week[] = "¤é¤@¤G¤T¥|¤­¤»";
+
+ sprintf(datemsg, "%d¦~%2d¤ë%2d¤é%3d:%02d:%02d ¬P´Á%.2s",
+ t->tm_year - 11, t->tm_mon + 1, t->tm_mday,
+ t->tm_hour, t->tm_min, t->tm_sec, &week[t->tm_wday << 1]);
+ return (datemsg);
+}
+
+static void
+chat_query(cu, msg)
+ ChatUser *cu;
+ char *msg;
+{
+ char str[256];
+ int i;
+ ACCT xuser;
+ FILE *fp;
+
+ if (acct_load(&xuser, msg) >= 0)
+ {
+ sprintf(chatbuf, "%s(%s) ¦@¤W¯¸ %d ¦¸¡A¤å³¹ %d ½g",
+ xuser.userid, xuser.username, xuser.numlogins, xuser.numposts);
+ send_to_user(cu, chatbuf, 0, MSG_MESSAGE);
+
+ sprintf(chatbuf, "³Ìªñ(%s)±q(%s)¤W¯¸", Ctime(&xuser.lastlogin),
+ (xuser.lasthost[0] ? xuser.lasthost : "¥~¤ÓªÅ"));
+ send_to_user(cu, chatbuf, 0, MSG_MESSAGE);
+
+ usr_fpath(chatbuf, xuser.userid, "plans");
+ fp = fopen(chatbuf, "rt");
+ i = 0;
+ while (fp && fgets(str, 256, fp))
+ {
+ if (!strlen(str))
+ continue;
+
+ str[strlen(str) - 1] = 0;
+ send_to_user(cu, str, 0, MSG_MESSAGE);
+ if (++i >= MAX_QUERYLINES)
+ break;
+ }
+ fclose(fp);
+ }
+ else
+ {
+ sprintf(chatbuf, msg_no_such_id, msg);
+ send_to_user(cu, chatbuf, 0, MSG_MESSAGE);
+ }
+}
+
+static void
+chat_clear(cu, msg)
+ ChatUser *cu;
+ char *msg;
+{
+ if (cu->clitype)
+ send_to_user(cu, "", 0, MSG_CLRSCR);
+ else
+ send_to_user(cu, "/c", 0, MSG_MESSAGE);
+}
+
+static void
+chat_date(cu, msg)
+ ChatUser *cu;
+ char *msg;
+{
+ time_t thetime;
+
+ time(&thetime);
+ sprintf(chatbuf, "¡» ¼Ð·Ç®É¶¡: %s", Ctime(&thetime));
+ send_to_user(cu, chatbuf, 0, MSG_MESSAGE);
+}
+
+
+static void
+chat_topic(cu, msg)
+ ChatUser *cu;
+ char *msg;
+{
+ ChatRoom *room;
+ char *topic;
+
+ if (!ROOMOP(cu) && !OPENTOPIC(cu->room))
+ {
+ send_to_user(cu, msg_not_op, 0, MSG_MESSAGE);
+ return;
+ }
+
+ if (*msg == '\0')
+ {
+ send_to_user(cu, "¡° ½Ð«ü©w¸ÜÃD", 0, MSG_MESSAGE);
+ return;
+ }
+
+ room = cu->room;
+ topic = room->topic; /* Thor: room ¦³¥i¯à NULL¶Ü?? */
+ strncpy(topic, msg, 47);
+ topic[47] = '\0';
+
+ if (cu->clitype)
+ send_to_room(room, topic, 0, MSG_TOPIC);
+ else
+ {
+ sprintf(chatbuf, "/t%s", topic);
+ send_to_room(room, chatbuf, 0, 0);
+ }
+
+ room_changed(room);
+
+ sprintf(chatbuf, "¡» %s ±N¸ÜÃD§ï¬° %s", cu->chatid, topic);
+ if (!CLOAK(cu)) /* Thor: ²á¤Ñ«ÇÁô¨­³N */
+ send_to_room(room, chatbuf, 0, MSG_MESSAGE);
+}
+
+
+static void
+chat_version(cu, msg)
+ ChatUser *cu;
+ char *msg;
+{
+ sprintf(chatbuf, "%d %d", XCHAT_VERSION_MAJOR, XCHAT_VERSION_MINOR);
+ send_to_user(cu, chatbuf, 0, MSG_VERSION);
+}
+
+static void
+chat_nick(cu, msg)
+ ChatUser *cu;
+ char *msg;
+{
+ char *chatid, *str;
+ ChatUser *xuser;
+
+ chatid = nextword(&msg);
+ chatid[8] = '\0';
+ if (!valid_chatid(chatid))
+ {
+ send_to_user(cu, "¡° ³o­Ó²á¤Ñ¥N¸¹¬O¤£¥¿½Tªº", 0, MSG_MESSAGE);
+ return;
+ }
+
+ xuser = cuser_by_chatid(chatid);
+ if (xuser != NULL && xuser != cu)
+ {
+ send_to_user(cu, "¡° ¤w¸g¦³¤H±¶¨¬¥ýµnÅo", 0, MSG_MESSAGE);
+ return;
+ }
+
+ str = cu->chatid;
+
+ sprintf(chatbuf, "¡° %s ±N²á¤Ñ¥N¸¹§ï¬° %s", str, chatid);
+ if (!CLOAK(cu)) /* Thor: ²á¤Ñ«ÇÁô¨­³N */
+ send_to_room(cu->room, chatbuf, cu->userno, MSG_MESSAGE);
+
+ strcpy(str, chatid);
+
+ user_changed(cu);
+
+ if (cu->clitype)
+ send_to_user(cu, chatid, 0, MSG_NICK);
+ else
+ {
+ sprintf(chatbuf, "/n%s", chatid);
+ send_to_user(cu, chatbuf, 0, 0);
+ }
+}
+
+static void
+chat_list_rooms(cuser, msg)
+ ChatUser *cuser;
+ char *msg;
+{
+ ChatRoom *cr, *room;
+
+ if (RESTRICTED(cuser))
+ {
+ send_to_user(cuser, "¡° ±z¨S¦³Åv­­¦C¥X²{¦³ªº²á¤Ñ«Ç", 0, MSG_MESSAGE);
+ return;
+ }
+
+ if (common_client_command)
+ send_to_user(cuser, "", 0, MSG_ROOMLISTSTART);
+ else
+ send_to_user(cuser, " ½Í¤Ñ«Ç¦WºÙ ¢x¤H¼Æ¢x¸ÜÃD ", 0, MSG_MESSAGE);
+
+ room = cuser->room;
+ cr = &mainroom;
+ do
+ {
+ MYDOG;
+
+
+ if (!SECRET(cr) || CHATSYSOP(cuser) || (cr == room && ROOMOP(cuser)))
+ {
+ if (common_client_command)
+ {
+ sprintf(chatbuf, "%s %d %d %s", cr->name, cr->occupants, cr->rflag, cr->topic);
+ send_to_user(cuser, chatbuf, 0, MSG_ROOMLIST);
+ }
+ else
+ {
+ sprintf(chatbuf, " %-12s¢x%4d¢x%s", cr->name, cr->occupants, cr->topic);
+ if (LOCKED(cr))
+ strcat(chatbuf, " [Âê¦í]");
+ if (SECRET(cr))
+ strcat(chatbuf, " [¯µ±K]");
+ if (OPENTOPIC(cr))
+ strcat(chatbuf, " [¸ÜÃD]");
+ send_to_user(cuser, chatbuf, 0, MSG_MESSAGE);
+ }
+
+ }
+ } while((cr = cr->next));
+
+ if (common_client_command)
+ send_to_user(cuser, "", 0, MSG_ROOMLISTEND);
+}
+
+
+static void
+chat_do_user_list(cu, msg, theroom)
+ ChatUser *cu;
+ char *msg;
+ ChatRoom *theroom;
+{
+ ChatRoom *myroom, *room;
+ ChatUser *user;
+
+ int start, stop, curr = 0;
+ start = atoi(nextword(&msg));
+ stop = atoi(nextword(&msg));
+
+ myroom = cu->room;
+
+#ifdef DEBUG
+ logit(cu->chatid, "do user list");
+#endif
+
+ if (common_client_command)
+ send_to_user(cu, "", 0, MSG_USERLISTSTART);
+ else
+ send_to_user(cu, " ²á¤Ñ¥N¸¹¢x¨Ï¥ÎªÌ¥N¸¹ ¢x²á¤Ñ«Ç ", 0, MSG_MESSAGE);
+
+ for (user = mainuser; user; user = user->unext)
+ {
+ MYDOG;
+
+
+ room = user->room;
+ if ((theroom != ROOM_ALL) && (theroom != room))
+ continue;
+
+ if (myroom != room)
+ {
+ if (RESTRICTED(cu) ||
+ (room && SECRET(room) && !CHATSYSOP(cu)))
+ continue;
+ }
+
+ if (CLOAK(user)) /* Thor: Áô¨­³N */
+ continue;
+
+
+ curr++;
+ if (start && curr < start)
+ continue;
+ else if (stop && (curr > stop))
+ break;
+
+ if (common_client_command)
+ {
+ if (!room)
+ continue; /* Xshadow: ÁÙ¨S¶i¤J¥ô¦ó©Ð¶¡ªº´N¤£¦C¥X */
+
+ sprintf(chatbuf, "%s %s %s %s", user->chatid, user->userid, room->name, user->lasthost);
+ if (ROOMOP(user))
+ strcat(chatbuf, " Op");
+ }
+ else
+ {
+ sprintf(chatbuf, " %-8s¢x%-12s¢x%s", user->chatid, user->userid, room ? room->name : "[¦bªù¤f±r«Þ]");
+ if (ROOMOP(user))
+ strcat(chatbuf, " [Op]");
+ }
+
+#ifdef DEBUG
+ logit("list_U", chatbuf);
+#endif
+
+ send_to_user(cu, chatbuf, 0, common_client_command ? MSG_USERLIST : MSG_MESSAGE);
+ }
+ if (common_client_command)
+ send_to_user(cu, "", 0, MSG_USERLISTEND);
+}
+
+static void
+chat_list_by_room(cu, msg)
+ ChatUser *cu;
+ char *msg;
+{
+ ChatRoom *whichroom;
+ char *roomstr;
+
+ roomstr = nextword(&msg);
+ if (*roomstr == '\0')
+ whichroom = cu->room;
+ else
+ {
+ if ((whichroom = croom_by_roomid(roomstr)) == NULL)
+ {
+ sprintf(chatbuf, "¡° ¨S¦³ [%s] ³o­Ó²á¤Ñ«Ç", roomstr);
+ send_to_user(cu, chatbuf, 0, MSG_MESSAGE);
+ return;
+ }
+
+ if (whichroom != cu->room && SECRET(whichroom) && !CHATSYSOP(cu))
+ { /* Thor: ­n¤£­n´ú¦P¤@roomÁöSECRET¦ý¥i¥H¦C?
+ * Xshadow: §Ú§ï¦¨¦P¤@ room ´N¥i¥H¦C */
+ send_to_user(cu, "¡° µLªk¦C¥X¦b¯µ±K²á¤Ñ«Çªº¨Ï¥ÎªÌ", 0, MSG_MESSAGE);
+ return;
+ }
+ }
+ chat_do_user_list(cu, msg, whichroom);
+}
+
+
+static void
+chat_list_users(cu, msg)
+ ChatUser *cu;
+ char *msg;
+{
+ chat_do_user_list(cu, msg, ROOM_ALL);
+}
+
+static void
+chat_chatroom(cu, msg)
+ ChatUser *cu;
+ char *msg;
+{
+ if (common_client_command)
+ send_to_user(cu, "§å½ð½ð¯ùÃÀÀ] 4 21", 0, MSG_CHATROOM);
+}
+
+static void
+chat_map_chatids(cu, whichroom)
+ ChatUser *cu; /* Thor: ÁÙ¨S¦³§@¤£¦P¶¡ªº */
+ ChatRoom *whichroom;
+{
+ int c;
+ ChatRoom *myroom, *room;
+ ChatUser *user;
+
+ /* myroom = cu->room; */
+ myroom = whichroom;
+ send_to_user(cu,
+ " ²á¤Ñ¥N¸¹ ¨Ï¥ÎªÌ¥N¸¹ ¢x ²á¤Ñ¥N¸¹ ¨Ï¥ÎªÌ¥N¸¹ ¢x ²á¤Ñ¥N¸¹ ¨Ï¥ÎªÌ¥N¸¹ ", 0, MSG_MESSAGE);
+
+ c = 0;
+
+ for (user = mainuser; user; user = user->unext)
+ {
+ MYDOG;
+
+ room = user->room;
+ MYDOG;
+ if (whichroom != ROOM_ALL && whichroom != room)
+ continue;
+ MYDOG;
+ if (myroom != room)
+ {
+ if (RESTRICTED(cu) || /* Thor: ­n¥ýcheck room ¬O¤£¬OªÅªº */
+ (room && SECRET(room) && !CHATSYSOP(cu)))
+ continue;
+ }
+ MYDOG;
+ if (CLOAK(user)) /* Thor:Áô¨­³N */
+ continue;
+ sprintf(chatbuf + (c * 24), " %-8s%c%-12s%s",
+ user->chatid, ROOMOP(user) ? '*' : ' ',
+ user->userid, (c < 2 ? "¢x" : " "));
+ MYDOG;
+ if (++c == 3)
+ {
+ send_to_user(cu, chatbuf, 0, MSG_MESSAGE);
+ c = 0;
+ }
+ MYDOG;
+ }
+ if (c > 0)
+ send_to_user(cu, chatbuf, 0, MSG_MESSAGE);
+}
+
+
+static void
+chat_map_chatids_thisroom(cu, msg)
+ ChatUser *cu;
+ char *msg;
+{
+ chat_map_chatids(cu, cu->room);
+}
+
+
+static void
+chat_setroom(cu, msg)
+ ChatUser *cu;
+ char *msg;
+{
+ char *modestr;
+ ChatRoom *room;
+ char *chatid;
+ int sign;
+ int flag;
+ char *fstr = NULL;
+
+ if (!ROOMOP(cu))
+ {
+ send_to_user(cu, msg_not_op, 0, MSG_MESSAGE);
+ return;
+ }
+
+ modestr = nextword(&msg);
+ sign = 1;
+ if (*modestr == '+')
+ modestr++;
+ else if (*modestr == '-')
+ {
+ modestr++;
+ sign = 0;
+ }
+ if (*modestr == '\0')
+ {
+ send_to_user(cu,
+ "¡° ½Ð«ü©wª¬ºA: {[+(³]©w)][-(¨ú®ø)]}{[l(Âê¦í)][s(¯µ±K)][t(¶}©ñ¸ÜÃD)}", 0, MSG_MESSAGE);
+ return;
+ }
+
+ room = cu->room;
+ chatid = cu->chatid;
+
+ while (*modestr)
+ {
+ flag = 0;
+ switch (*modestr)
+ {
+ case 'l':
+ case 'L':
+ flag = ROOM_LOCKED;
+ fstr = "Âê¦í";
+ break;
+
+ case 's':
+ case 'S':
+ flag = ROOM_SECRET;
+ fstr = "¯µ±K";
+ break;
+
+ case 't':
+ case 'T':
+ flag = ROOM_OPENTOPIC;
+ fstr = "¶}©ñ¸ÜÃD";
+ break;
+ case 'h':
+ case 'H':
+ flag = ROOM_OPENTOPIC;
+ fstr = "Á|¤âµo¨¥";
+ break;
+
+ default:
+ sprintf(chatbuf, "¡° ª¬ºA¿ù»~¡G[%c]", *modestr);
+ send_to_user(cu, chatbuf, 0, MSG_MESSAGE);
+ }
+
+ /* Thor: check room ¬O¤£¬OªÅªº, À³¸Ó¤£¬OªÅªº */
+ if (flag && (room->rflag & flag) != sign * flag)
+ {
+ room->rflag ^= flag;
+ sprintf(chatbuf, "¡° ¥»²á¤Ñ«Ç³Q %s %s [%s] ª¬ºA",
+ chatid, sign ? "³]©w¬°" : "¨ú®ø", fstr);
+ if (!CLOAK(cu)) /* Thor: ²á¤Ñ«ÇÁô¨­³N */
+ send_to_room(room, chatbuf, 0, MSG_MESSAGE);
+ }
+ modestr++;
+ }
+ room_changed(room);
+}
+
+static char *chat_msg[] =
+{
+ "[//]help", "MUD-like ªÀ¥æ°Êµü",
+ "[/h]elp op", "½Í¤Ñ«ÇºÞ²z­û±M¥Î«ü¥O",
+ "[/a]ct <msg>", "°µ¤@­Ó°Ê§@",
+ "[/b]ye [msg]", "¹D§O",
+ "[/c]lear [/d]ate", "²M°£¿Ã¹õ ¥Ø«e®É¶¡",
+ /* "[/d]ate", "¥Ø«e®É¶¡", *//* Thor: «ü¥O¤Ó¦h */
+
+#if 0
+ "[/f]ire <user> <msg>", "µo°e¼ö°T", /* Thor.0727: ©M flag ½Äkey */
+#endif
+
+ "[/i]gnore [user]", "©¿²¤¨Ï¥ÎªÌ",
+ "[/j]oin <room>", "«Ø¥ß©Î¥[¤J½Í¤Ñ«Ç",
+ "[/l]ist [start [stop]]", "¦C¥X½Í¤Ñ«Ç¨Ï¥ÎªÌ",
+ "[/m]sg <id|user> <msg>", "¸ò <id> »¡®¨®¨¸Ü",
+ "[/n]ick <id>", "±N½Í¤Ñ¥N¸¹´«¦¨ <id>",
+ "[/p]ager", "¤Á´«©I¥s¾¹",
+ "[/q]uery <user>", "¬d¸ßºô¤Í",
+ "[/r]oom", "¦C¥X¤@¯ë½Í¤Ñ«Ç",
+ "[/t]ape", "¶}Ãö¿ý­µ¾÷",
+ "[/u]nignore <user>", "¨ú®ø©¿²¤",
+
+#if 0
+ "[/u]sers", "¦C¥X¯¸¤W¨Ï¥ÎªÌ",
+#endif
+
+ "[/w]ho", "¦C¥X¥»½Í¤Ñ«Ç¨Ï¥ÎªÌ",
+ "[/w]hoin <room>", "¦C¥X½Í¤Ñ«Ç<room> ªº¨Ï¥ÎªÌ",
+ NULL
+};
+
+
+static char *room_msg[] =
+{
+ "[/f]lag [+-][lsth]", "³]©wÂê©w¡B¯µ±K¡B¶}©ñ¸ÜÃD¡BÁ|¤âµo¨¥",
+ "[/i]nvite <id>", "ÁܽР<id> ¥[¤J½Í¤Ñ«Ç",
+ "[/kick] <id>", "±N <id> ½ð¥X½Í¤Ñ«Ç",
+ "[/o]p <id>", "±N Op ªºÅv¤OÂಾµ¹ <id>",
+ "[/topic] <text>", "´«­Ó¸ÜÃD",
+ "[/w]all", "¼s¼½ (¯¸ªø±M¥Î)",
+ NULL
+};
+
+
+static void
+chat_help(cu, msg)
+ ChatUser *cu;
+ char *msg;
+{
+ char **table, *str;
+
+ if (str_equal(nextword(&msg), "op"))
+ {
+ send_to_user(cu, "½Í¤Ñ«ÇºÞ²z­û±M¥Î«ü¥O", 0, MSG_MESSAGE);
+ table = room_msg;
+ }
+ else
+ {
+ table = chat_msg;
+ }
+
+ while((str = *table++)) {
+ sprintf(chatbuf, " %-20s- %s", str, *table++);
+ send_to_user(cu, chatbuf, 0, MSG_MESSAGE);
+ }
+}
+
+
+static void
+chat_private(cu, msg)
+ ChatUser *cu;
+ char *msg;
+{
+ char *recipient;
+ ChatUser *xuser;
+ int userno;
+
+ userno = 0;
+ recipient = nextword(&msg);
+ xuser = (ChatUser *) fuzzy_cuser_by_chatid(recipient);
+ if (xuser == NULL)
+ { /* Thor.0724: ¥Î userid¤]¥i¶Ç®¨®¨¸Ü */
+ xuser = cuser_by_userid(recipient);
+ }
+ if (xuser == NULL)
+ {
+ sprintf(chatbuf, msg_no_such_id, recipient);
+ }
+ else if (xuser == FUZZY_USER)
+ { /* ambiguous */
+ strcpy(chatbuf, "¡° ½Ð«ü©ú²á¤Ñ¥N¸¹");
+ }
+ else if (*msg)
+ {
+ userno = cu->userno;
+ sprintf(chatbuf, "*%s* ", cu->chatid);
+ msg[79] = 0; /* Thor:¨¾¤î¤Óªø */
+ strncat(chatbuf, msg, 80);
+ send_to_user(xuser, chatbuf, userno, MSG_MESSAGE);
+
+ if (xuser->clitype)
+ { /* Xshadow: ¦pªG¹ï¤è¬O¥Î client ¤W¨Óªº */
+ sprintf(chatbuf, "%s %s ", cu->userid, cu->chatid);
+ msg[79] = 0;
+ strncat(chatbuf, msg, 80);
+ send_to_user(xuser, chatbuf, userno, MSG_PRIVMSG);
+ }
+ if (cu->clitype)
+ {
+ sprintf(chatbuf, "%s %s ", xuser->userid, xuser->chatid);
+ msg[79] = 0;
+ strncat(chatbuf, msg, 80);
+ send_to_user(cu, chatbuf, 0, MSG_MYPRIVMSG);
+ }
+
+ sprintf(chatbuf, "%s> ", xuser->chatid);
+ strncat(chatbuf, msg, 80);
+ }
+ else
+ {
+ sprintf(chatbuf, "¡° ±z·Q¹ï %s »¡¤°»ò¸Ü©O¡H", xuser->chatid);
+ }
+ send_to_user(cu, chatbuf, userno, MSG_MESSAGE); /* Thor: userno ­n§ï¦¨ 0
+ * ¶Ü? */
+}
+
+
+static void
+chat_cloak(cu, msg)
+ ChatUser *cu;
+ char *msg;
+{
+ if (CHATSYSOP(cu))
+ {
+ cu->uflag ^= PERM_CLOAK;
+ sprintf(chatbuf, "¡» %s", CLOAK(cu) ? MSG_CLOAKED : MSG_UNCLOAK);
+ send_to_user(cu, chatbuf, 0, MSG_MESSAGE);
+ }
+}
+
+
+
+/* ----------------------------------------------------- */
+
+
+static void
+arrive_room(cuser, room)
+ ChatUser *cuser;
+ ChatRoom *room;
+{
+ char *rname;
+
+ /* Xshadow: ¤£¥²°eµ¹¦Û¤v, ¤Ï¥¿´«©Ð¶¡´N·|­«·s build user list */
+ sprintf(chatbuf, "+ %s %s %s %s", cuser->userid, cuser->chatid, room->name, cuser->lasthost);
+ if (ROOMOP(cuser))
+ strcat(chatbuf, " Op");
+ send_to_room(room, chatbuf, 0, MSG_USERNOTIFY);
+
+ cuser->room = room;
+ room->occupants++;
+ rname = room->name;
+
+ room_changed(room);
+
+ if (cuser->clitype)
+ {
+ send_to_user(cuser, rname, 0, MSG_ROOM);
+ send_to_user(cuser, room->topic, 0, MSG_TOPIC);
+ }
+ else
+ {
+ sprintf(chatbuf, "/r%s", rname);
+ send_to_user(cuser, chatbuf, 0, 0);
+ sprintf(chatbuf, "/t%s", room->topic);
+ send_to_user(cuser, chatbuf, 0, 0);
+ }
+
+ sprintf(chatbuf, "¡° %s ¶i¤J [%s] ¥]´[",
+ cuser->chatid, rname);
+ if (!CLOAK(cuser)) /* Thor: ²á¤Ñ«ÇÁô¨­³N */
+ send_to_room(room, chatbuf, cuser->userno, MSG_MESSAGE);
+}
+
+
+static int
+enter_room(cuser, rname, msg)
+ ChatUser *cuser;
+ char *rname;
+ char *msg;
+{
+ ChatRoom *room;
+ int create;
+
+ create = 0;
+ room = croom_by_roomid(rname);
+ if (room == NULL)
+ {
+ /* new room */
+
+#ifdef MONITOR
+ logit(cuser->userid, "create new room");
+#endif
+
+ MYDOG;
+
+ room = (ChatRoom *) malloc(sizeof(ChatRoom));
+ MYDOG;
+ if (room == NULL)
+ {
+ send_to_user(cuser, "¡° µLªk¦A·sÅP¥]´[¤F", 0, MSG_MESSAGE);
+ return 0;
+ }
+
+ memset(room, 0, sizeof(ChatRoom));
+ memcpy(room->name, rname, IDLEN - 1);
+ strcpy(room->topic, "³o¬O¤@­Ó·s¤Ñ¦a");
+
+ sprintf(chatbuf, "+ %s 1 0 %s", room->name, room->topic);
+ send_to_room(ROOM_ALL, chatbuf, 0, MSG_ROOMNOTIFY);
+
+ if (mainroom.next != NULL)
+ mainroom.next->prev = room;
+ room->next = mainroom.next;
+ mainroom.next = room;
+ room->prev = &mainroom;
+
+ create = 1;
+ }
+ else
+ {
+ if (cuser->room == room)
+ {
+ sprintf(chatbuf, "¡° ±z¥»¨Ó´N¦b [%s] ²á¤Ñ«ÇÅo :)", rname);
+ send_to_user(cuser, chatbuf, 0, MSG_MESSAGE);
+ return 0;
+ }
+
+ if (!CHATSYSOP(cuser) && LOCKED(room) && !list_belong(room->invite, cuser->userno))
+ {
+ send_to_user(cuser, "¡° ¤º¦³´c¤ü¡A«D½Ð²ö¤J", 0, MSG_MESSAGE);
+ return 0;
+ }
+ }
+
+ exit_room(cuser, EXIT_LOGOUT, msg);
+ arrive_room(cuser, room);
+
+ if (create)
+ cuser->uflag |= PERM_ROOMOP;
+
+ return 0;
+}
+
+
+static void
+logout_user(cuser)
+ ChatUser *cuser;
+{
+ int sock;
+ ChatUser *xuser, *prev;
+
+#ifdef DEBUG
+ logit("before", "logout");
+ debug_user();
+#endif
+
+ sock = cuser->sock;
+ shutdown(sock, 2);
+ close(sock);
+
+ MYDOG;
+
+ FD_CLR(sock, &mainfds);
+
+#if 0 /* Thor: ¤]³\¤£®t³o¤@­Ó */
+ if (sock >= maxfds)
+ maxfds = sock - 1;
+#endif
+
+ list_free(cuser->ignore);
+
+#ifdef DEBUG
+ debug_user();
+#endif
+
+ xuser = mainuser;
+ if (xuser == cuser)
+ {
+ mainuser = cuser->unext;
+ }
+ else
+ {
+ do
+ {
+ prev = xuser;
+ xuser = xuser->unext;
+ if (xuser == cuser)
+ {
+ prev->unext = cuser->unext;
+ break;
+ }
+ } while (xuser);
+ }
+
+ MYDOG;
+
+#ifdef DEBUG
+ sprintf(chatbuf, "%p", cuser);
+ logit("free cuser", chatbuf);
+#endif
+
+ free(cuser);
+
+#ifdef DEBUG
+ logit("after", "logout");
+ debug_user();
+#endif
+
+#if 0
+ next = cuser->next;
+ prev = cuser->prev;
+ prev->next = next;
+ if (next)
+ next->prev = prev;
+
+ if (cuser)
+ free(cuser);
+ MYDOG;
+
+#endif
+
+ totaluser--;
+}
+
+
+static void
+print_user_counts(cuser)
+ ChatUser *cuser;
+{
+ ChatRoom *room;
+ int num, userc, suserc, roomc, number;
+
+ userc = suserc = roomc = 0;
+
+ room = &mainroom;
+ do
+ {
+ MYDOG;
+
+ num = room->occupants;
+ if (SECRET(room))
+ {
+ suserc += num;
+ if (CHATSYSOP(cuser))
+ roomc++;
+ }
+ else
+ {
+ userc += num;
+ roomc++;
+ }
+ } while((room = room->next));
+
+ number = (cuser->clitype) ? MSG_MOTD : MSG_MESSAGE;
+
+ sprintf(chatbuf,
+ "¡ó Åwªï¥úÁ{¡i§å½ð½ð¯ùÃÀÀ]¡j¡A¥Ø«e¶}¤F %d ¶¡¥]´[", roomc);
+ send_to_user(cuser, chatbuf, 0, number);
+
+ sprintf(chatbuf, "¡ó ¦@¦³ %d ¤H¨ÓÂ\\Àsªù°}", userc);
+ if (suserc)
+ sprintf(chatbuf + strlen(chatbuf), " [%d ¤H¦b¯µ±K²á¤Ñ«Ç]", suserc);
+ send_to_user(cuser, chatbuf, 0, number);
+}
+
+
+static int
+login_user(cu, msg)
+ ChatUser *cu;
+ char *msg;
+{
+ int utent;
+
+ char *level;
+ char *userid;
+ char *chatid;
+ struct sockaddr_in from;
+ int fromlen;
+ struct hostent *hp;
+
+
+ ACCT acct;
+ char buf[20];
+
+ /*
+ * Thor.0819: SECURED_CHATROOM : /! userid chatid passwd , userno
+ * el ¦bcheck§¹passwd«á¨ú±o
+ */
+ /* Xshadow.0915: common client support : /-! userid chatid password */
+
+ /* ¶Ç°Ñ¼Æ¡Guserlevel, userid, chatid */
+
+ /* client/server ª©¥»¨Ì¾Ú userid §ì .PASSWDS §PÂ_ userlevel */
+
+ userid = nextword(&msg);
+ chatid = nextword(&msg);
+
+
+#ifdef DEBUG
+ logit("ENTER", userid);
+#endif
+ /* Thor.0730: parse space before passwd */
+ level = msg;
+
+ /* Thor.0813: ¸õ¹L¤@ªÅ®æ§Y¥i, ¦]¬°¤Ï¥¿¦pªGchatid¦³ªÅ®æ, ±K½X¤]¤£¹ï */
+ /* ´Nºâ±K½X¹ï, ¤]¤£·|«ç»ò¼Ë:p */
+ /* ¥i¬O¦pªG±K½X²Ä¤@­Ó¦r¬OªÅ®æ, ¨º¸õ¤Ó¦hªÅ®æ·|¶i¤£¨Ó... */
+ if (*level == ' ')
+ level++;
+
+ /* Thor.0729: load acct */
+ if (!*userid || (acct_load(&acct, userid) < 0))
+ {
+
+#ifdef DEBUG
+ logit("noexist", chatid);
+#endif
+
+ if (cu->clitype)
+ send_to_user(cu, "¿ù»~ªº¨Ï¥ÎªÌ¥N¸¹", 0, ERR_LOGIN_NOSUCHUSER);
+ else
+ send_to_user(cu, CHAT_LOGIN_INVALID, 0, 0);
+
+ return -1;
+ }
+ else if(strncmp(level, acct.passwd, PASSLEN) &&
+ !chkpasswd(acct.passwd, level))
+ {
+
+#ifdef DEBUG
+ logit("fake", chatid);
+#endif
+
+ if (cu->clitype)
+ send_to_user(cu, "±K½X¿ù»~", 0, ERR_LOGIN_PASSERROR);
+ else
+ send_to_user(cu, CHAT_LOGIN_INVALID, 0, 0);
+ return -1;
+ }
+ else
+ {
+ /* Thor.0729: if ok, read level. */
+ sprintf(buf, "%d", acct.userlevel);
+ level = buf;
+ /* Thor.0819: read userno for client/server bbs */
+ utent = searchuser(acct.userid);
+ }
+
+ /* Thor.0819: for client/server bbs */
+/*
+ for (xuser = mainuser; xuser; xuser = xuser->unext)
+ {
+ MYDOG;
+
+ if (xuser->userno == utent)
+ {
+
+ #ifdef DEBUG
+ logit("enter", "bogus");
+ #endif
+ if (cu->clitype)
+ send_to_user(cu, "½Ð¤Å¬£»º¤À¨­¶i¤J²á¤Ñ«Ç !!", 0, ERR_LOGIN_USERONLINE);
+ else
+ send_to_user(cu, CHAT_LOGIN_BOGUS, 0, 0);
+ return -1;
+ }
+ }
+*/
+ if (!valid_chatid(chatid))
+ {
+
+#ifdef DEBUG
+ logit("enter", chatid);
+#endif
+
+ if (cu->clitype)
+ send_to_user(cu, "¤£¦Xªkªº²á¤Ñ«Ç¥N¸¹ !!", 0, ERR_LOGIN_NICKERROR);
+ else
+ send_to_user(cu, CHAT_LOGIN_INVALID, 0, 0);
+ return 0;
+ }
+
+#ifdef DEBUG
+ debug_user();
+#endif
+
+ if (cuser_by_chatid(chatid) != NULL)
+ {
+ /* chatid in use */
+
+#ifdef DEBUG
+ logit("enter", "duplicate");
+#endif
+
+ if (cu->clitype)
+ send_to_user(cu, "³o­Ó¥N¸¹¤w¸g¦³¤H¨Ï¥Î", 0, ERR_LOGIN_NICKINUSE);
+ else
+ send_to_user(cu, CHAT_LOGIN_EXISTS, 0, 0);
+ return 0;
+ }
+
+ cu->userno = utent;
+ cu->uflag = atoi(level) & ~(PERM_ROOMOP | PERM_CLOAK | PERM_HANDUP | PERM_SAY);
+ /* Thor: ¶i¨Ó¥ý²MªÅROOMOP(¦PPERM_CHAT), CLOAK */
+ strcpy(cu->userid, userid);
+ memcpy(cu->chatid, chatid, 8);
+ cu->chatid[8] = '\0';
+
+ /* Xshadow: ¨ú±o client ªº¨Ó·½ */
+ fromlen = sizeof(from);
+ if (!getpeername(cu->sock, (struct sockaddr *) & from, &fromlen))
+ {
+ if ((hp = gethostbyaddr((char *) &from.sin_addr, sizeof(struct in_addr), from.sin_family)))
+ {
+ strcpy(cu->lasthost, hp->h_name);
+ }
+ else
+ strcpy(cu->lasthost, (char *) inet_ntoa(from.sin_addr));
+
+ }
+ else
+ {
+ strcpy(cu->lasthost, "[¥~¤ÓªÅ]");
+ }
+
+ if (cu->clitype)
+ send_to_user(cu, "¶¶§Q", 0, MSG_LOGINOK);
+ else
+ send_to_user(cu, CHAT_LOGIN_OK, 0, 0);
+
+ arrive_room(cu, &mainroom);
+
+ send_to_user(cu, "", 0, MSG_MOTDSTART);
+ print_user_counts(cu);
+ send_to_user(cu, "", 0, MSG_MOTDEND);
+
+#ifdef DEBUG
+ logit("enter", "OK");
+#endif
+
+ return 0;
+}
+
+
+static void
+chat_act(cu, msg)
+ ChatUser *cu;
+ char *msg;
+{
+ if (*msg && (!RHANDUP(cu->room) || SAY(cu) || ROOMOP(cu)))
+ {
+ sprintf(chatbuf, "%s %s", cu->chatid, msg);
+ send_to_room(cu->room, chatbuf, cu->userno, MSG_MESSAGE);
+ }
+}
+
+
+static void
+chat_ignore(cu, msg)
+ ChatUser *cu;
+ char *msg;
+{
+
+ if (RESTRICTED(cu))
+ {
+ strcpy(chatbuf, "¡° ±z¨S¦³ ignore §O¤HªºÅv§Q");
+ }
+ else
+ {
+ char *ignoree;
+
+ ignoree = nextword(&msg);
+ if (*ignoree)
+ {
+ ChatUser *xuser;
+
+ xuser = cuser_by_userid(ignoree);
+
+ if (xuser == NULL)
+ {
+
+ sprintf(chatbuf, msg_no_such_id, ignoree);
+
+#if 0
+ sprintf(chatbuf, "¡» ½Í¤Ñ«Ç²{¦b¨S¦³ [%s] ³o¸¹¤Hª«", ignoree);
+#endif
+ }
+ else if (xuser == cu || CHATSYSOP(xuser) ||
+ (ROOMOP(xuser) && (xuser->room == cu->room)))
+ {
+ sprintf(chatbuf, "¡» ¤£¥i¥H ignore [%s]", ignoree);
+ }
+ else
+ {
+
+ if (list_belong(cu->ignore, xuser->userno))
+ {
+ sprintf(chatbuf, "¡° %s ¤w¸g³Q­áµ²¤F", xuser->chatid);
+ }
+ else
+ {
+ list_add(&(cu->ignore), xuser);
+ sprintf(chatbuf, "¡» ±N [%s] ¥´¤J§N®c¤F :p", xuser->chatid);
+ }
+ }
+ }
+ else
+ {
+ UserList *list;
+
+ if((list = cu->ignore))
+ {
+ int len;
+ char buf[16];
+
+ send_to_user(cu, "¡» ³o¨Ç¤H³Q¥´¤J§N®c¤F¡G", 0, MSG_MESSAGE);
+ len = 0;
+ do
+ {
+ sprintf(buf, "%-13s", list->userid);
+ strcpy(chatbuf + len, buf);
+ len += 13;
+ if (len >= 78)
+ {
+ send_to_user(cu, chatbuf, 0, MSG_MESSAGE);
+ len = 0;
+ }
+ } while((list = list->next));
+
+ if (len == 0)
+ return;
+ }
+ else
+ {
+ strcpy(chatbuf, "¡» ±z¥Ø«e¨Ã¨S¦³ ignore ¥ô¦ó¤H");
+ }
+ }
+ }
+
+ send_to_user(cu, chatbuf, 0, MSG_MESSAGE);
+}
+
+
+static void
+chat_unignore(cu, msg)
+ ChatUser *cu;
+ char *msg;
+{
+ char *ignoree;
+
+ ignoree = nextword(&msg);
+
+ if (*ignoree)
+ {
+ sprintf(chatbuf, (list_delete(&(cu->ignore), ignoree)) ?
+ "¡» [%s] ¤£¦A³Q§A§N¸¨¤F" :
+ "¡» ±z¨Ã¥¼ ignore [%s] ³o¸¹¤Hª«", ignoree);
+ }
+ else
+ {
+ strcpy(chatbuf, "¡» ½Ð«ü©ú user ID");
+ }
+ send_to_user(cu, chatbuf, 0, MSG_MESSAGE);
+}
+
+
+static void
+chat_join(cu, msg)
+ ChatUser *cu;
+ char *msg;
+{
+ if (RESTRICTED(cu))
+ {
+ send_to_user(cu, "¡° ±z¨S¦³¥[¤J¨ä¥L²á¤Ñ«ÇªºÅv­­", 0, MSG_MESSAGE);
+ }
+ else
+ {
+ char *roomid = nextword(&msg);
+
+ if (*roomid)
+ enter_room(cu, roomid, msg);
+ else
+ send_to_user(cu, "¡° ½Ð«ü©w²á¤Ñ«Çªº¦W¦r", 0, MSG_MESSAGE);
+ }
+}
+
+
+static void
+chat_kick(cu, msg)
+ ChatUser *cu;
+ char *msg;
+{
+ char *twit;
+ ChatUser *xuser;
+ ChatRoom *room;
+
+ if (!ROOMOP(cu))
+ {
+ send_to_user(cu, msg_not_op, 0, MSG_MESSAGE);
+ return;
+ }
+
+ twit = nextword(&msg);
+ xuser = cuser_by_chatid(twit);
+
+ if (xuser == NULL)
+ {
+ sprintf(chatbuf, msg_no_such_id, twit);
+ send_to_user(cu, chatbuf, 0, MSG_MESSAGE);
+ return;
+ }
+
+ room = cu->room;
+ if (room != xuser->room || CLOAK(xuser))
+ { /* Thor: ²á¤Ñ«ÇÁô¨­³N */
+ sprintf(chatbuf, msg_not_here, twit);
+ send_to_user(cu, chatbuf, 0, MSG_MESSAGE);
+ return;
+ }
+
+ if (CHATSYSOP(xuser))
+ { /* Thor: ½ð¤£¨« CHATSYSOP */
+ sprintf(chatbuf, "¡» ¤£¥i¥H kick [%s]", twit);
+ send_to_user(cu, chatbuf, 0, MSG_MESSAGE);
+ return;
+ }
+
+ exit_room(xuser, EXIT_KICK, (char *) NULL);
+
+ if (room == &mainroom)
+ logout_user(xuser);
+ else
+ enter_room(xuser, MAIN_NAME, (char *) NULL);
+}
+
+
+static void
+chat_makeop(cu, msg)
+ ChatUser *cu;
+ char *msg;
+{
+ char *newop;
+ ChatUser *xuser;
+ ChatRoom *room;
+
+ if (!ROOMOP(cu))
+ {
+ send_to_user(cu, msg_not_op, 0, MSG_MESSAGE);
+ return;
+ }
+
+ newop = nextword(&msg);
+ xuser = cuser_by_chatid(newop);
+
+ if (xuser == NULL)
+ {
+ sprintf(chatbuf, msg_no_such_id, newop);
+ send_to_user(cu, chatbuf, 0, MSG_MESSAGE);
+ return;
+ }
+
+ if (cu == xuser)
+ {
+ sprintf(chatbuf, "¡° ±z¦­´N¤w¸g¬O Op ¤F°Ú");
+ send_to_user(cu, chatbuf, 0, MSG_MESSAGE);
+ return;
+ }
+
+ room = cu->room;
+
+ if (room != xuser->room || CLOAK(xuser))
+ { /* Thor: ²á¤Ñ«ÇÁô¨­³N */
+ sprintf(chatbuf, msg_not_here, xuser->chatid);
+ send_to_user(cu, chatbuf, 0, MSG_MESSAGE);
+ return;
+ }
+
+ cu->uflag &= ~PERM_ROOMOP;
+ xuser->uflag |= PERM_ROOMOP;
+
+ user_changed(cu);
+ user_changed(xuser);
+
+ sprintf(chatbuf, "¡° %s ±N Op Åv¤OÂಾµ¹ %s",
+ cu->chatid, xuser->chatid);
+ if (!CLOAK(cu)) /* Thor: ²á¤Ñ«ÇÁô¨­³N */
+ send_to_room(room, chatbuf, 0, MSG_MESSAGE, MSG_MESSAGE);
+}
+
+
+
+static void
+chat_invite(cu, msg)
+ ChatUser *cu;
+ char *msg;
+{
+ char *invitee;
+ ChatUser *xuser;
+ ChatRoom *room;
+ UserList **list;
+
+ if (!ROOMOP(cu))
+ {
+ send_to_user(cu, msg_not_op, 0, MSG_MESSAGE);
+ return;
+ }
+
+ invitee = nextword(&msg);
+ xuser = cuser_by_chatid(invitee);
+ if (xuser == NULL)
+ {
+ sprintf(chatbuf, msg_no_such_id, invitee);
+ send_to_user(cu, chatbuf, 0, MSG_MESSAGE);
+ return;
+ }
+
+ room = cu->room; /* Thor: ¬O§_­n check room ¬O§_ NULL ? */
+ list = &(room->invite);
+
+ if (list_belong(*list, xuser->userno))
+ {
+ sprintf(chatbuf, "¡° %s ¤w¸g±µ¨ü¹LÁܽФF", xuser->chatid);
+ send_to_user(cu, chatbuf, 0, MSG_MESSAGE);
+ return;
+ }
+ list_add(list, xuser);
+
+ sprintf(chatbuf, "¡° %s Áܽбz¨ì [%s] ²á¤Ñ«Ç",
+ cu->chatid, room->name);
+ send_to_user(xuser, chatbuf, 0, MSG_MESSAGE); /* Thor: ­n¤£­n¥i¥H ignore? */
+ sprintf(chatbuf, "¡° %s ¦¬¨ì±zªºÁܽФF", xuser->chatid);
+ send_to_user(cu, chatbuf, 0, MSG_MESSAGE);
+}
+
+
+static void
+chat_broadcast(cu, msg)
+ ChatUser *cu;
+ char *msg;
+{
+ if (!CHATSYSOP(cu))
+ {
+ send_to_user(cu, "¡° ±z¨S¦³¦b²á¤Ñ«Ç¼s¼½ªºÅv¤O!", 0, MSG_MESSAGE);
+ return;
+ }
+ if (*msg == '\0')
+ {
+ send_to_user(cu, "¡° ½Ð«ü©w¼s¼½¤º®e", 0, MSG_MESSAGE);
+ return;
+ }
+ sprintf(chatbuf, "¡° " BBSNAME "½Í¤Ñ«Ç¼s¼½¤¤ [%s].....",
+ cu->chatid);
+ send_to_room(ROOM_ALL, chatbuf, 0, MSG_MESSAGE);
+ sprintf(chatbuf, "¡» %s", msg);
+ send_to_room(ROOM_ALL, chatbuf, 0, MSG_MESSAGE);
+}
+
+
+static void
+chat_goodbye(cu, msg)
+ ChatUser *cu;
+ char *msg;
+{
+ exit_room(cu, EXIT_LOGOUT, msg);
+ /* Thor: ­n¤£­n¥[ logout_user(cu) ? */
+}
+
+
+/* --------------------------------------------- */
+/* MUD-like social commands : action */
+/* --------------------------------------------- */
+
+struct ChatAction
+{
+ char *verb; /* °Êµü */
+ char *chinese; /* ¤¤¤å½Ķ */
+ char *part1_msg; /* ¤¶µü */
+ char *part2_msg; /* °Ê§@ */
+};
+
+
+static ChatAction party_data[] =
+{
+ {"aluba", "ªü¾|¤Ú", "§â", "¬[¤W¬W¤lªü¾|¤Ú!!"},
+ {"aodre", "´º¥õ", "¹ï", "ªº´º¥õ¦³¦p·Ê·Ê¦¿¤ô,³sºø¤£µ´¡K¡K"},
+ {"bearhug", "¼ö¾Ö", "¼ö±¡ªº¾Ö©ê", ""},
+ {"blade", "¤@¤M", "¤@¤M±Òµ{§â", "°e¤W¦è¤Ñ"},
+ {"bless", "¯¬ºÖ", "¯¬ºÖ", "¤ß·Q¨Æ¦¨"},
+ {"board", "¥D¾÷ªO", "§â", "§ì¥h¸÷¥D¾÷ªO"},
+ {"bokan", "®ð¥\\", "Âù´x·L¦X¡A»W¶Õ«Ýµo¡K¡K¬ðµM¶¡¡A¹q¥ú¥E²{¡A¹ï", "¨Ï¥X¤F¢Ðo--¢Ùan¡I"},
+ {"bow", "Áù°`", "²¦°`²¦·qªº¦V", "Áù°`"},
+ {"box", "¹õ¤§¤º", "¶}©l½üÂ\\¦¡²¾¦ì¡A¹ï", "§@¨xŦ§ðÀ»"},
+ {"boy", "¥­©³Áç", "±q­I«á®³¥X¤F¥­©³Áç¡A§â", "ºV©ü¤F"},
+ {"bye", "ÙTÙT", "¦V", "»¡ÙTÙT!!"},
+ {"call", "©I³ê", "¤jÁnªº©I³ê,°Ú~~", "°Ú~~~§A¦b­þ¸Ì°Ú°Ú°Ú°Ú~~~~"},
+ {"caress", "»´¼¾", "»´»´ªº¼¾ºNµÛ", ""},
+ {"clap", "¹ª´x", "¦V", "¼ö¯P¹ª´x"},
+ {"claw", "§ì§ì", "±q¿ß«}¼Ö¶é­É¤F°¦¿ß¤ö¡A§â", "§ì±o¦º¥h¬¡¨Ó"},
+ {"comfort", "¦w¼¢", "·Å¨¥¦w¼¢", ""},
+ {"cong", "®¥³ß", "±q­I«á®³¥X¤F©Ô¬¶¡AËé¡IËé¡I®¥³ß", ""},
+ {"cpr", "¤f¹ï¤f", "¹ïµÛ", "°µ¤f¹ï¤f¤H¤u©I§l"},
+ {"cringe", "¤^¼¦", "¦V", "¨õ°`©}½¥¡A·n§À¤^¼¦"},
+ {"cry", "¤j­ú", "¦V", "Àz°Þ¤j­ú"},
+ {"dance", "¸õ»R", "©Ô¤F", "ªº¤â½¡½¡°_»R" },
+ {"destroy", "·´·À", "²½°_¤F¡y·¥¤j·´·À©G¤å¡z¡AÅF¦V", ""},
+ {"dogleg", "ª¯»L", "¹ï", "ª¯»L"},
+ {"drivel", "¬y¤f¤ô", "¹ïµÛ", "¬y¤f¤ô"},
+ {"envy", "¸r¼}", "¦V", "¬yÅS¥X¸r¼}ªº²´¥ú"},
+ {"eye", "°e¬îªi", "¹ï", "ÀW°e¬îªi"},
+ {"fire", "¾R°Ý", "®³µÛ¤õ¬õªºÅK´Î¨«¦V", ""},
+ {"forgive", "­ì½Ì", "±µ¨ü¹Dºp¡A­ì½Ì¤F", ""},
+ {"french", "ªk¦¡§k", "§â¦ÞÀY¦ù¨ì", "³ïÄV¸Ì¡ã¡ã¡ã«z¡I¤@­Ó®öº©ªºªk°ê¤ó²`§k"},
+ {"giggle", "¶Ì¯º", "¹ïµÛ", "¶Ì¶Ìªº§b¯º"},
+ {"glue", "¸É¤ß", "¥Î¤T¬í½¦¡A§â", "ªº¤ßÂH¤F°_¨Ó"},
+ {"goodbye", "§i§O", "²\\²´¨L¨Lªº¦V", "§i§O"},
+ {"grin", "¦l¯º", "¹ï", "ÅS¥X¨¸´cªº¯º®e"},
+ {"growl", "©H­ý", "¹ï", "©H­ý¤£¤w"},
+ {"hand", "´¤¤â", "¸ò", "´¤¤â"},
+ {"hide", "¸ú", "¸ú¦b", "­I«á"},
+ {"hospitl", "°eÂå°|", "§â", "°e¶iÂå°|"},
+ {"hug", "¾Ö©ê", "»´»´¦a¾Ö©ê", ""},
+ {"hrk", "ª@Às®±", "¨Ií¤F¨­§Î¡A¶×»E¤F¤º«l¡A¹ï", "¨Ï¥X¤F¤@°O¢Öo--¢àyu--¢Ùan¡I¡I¡I"},
+ {"jab", "ÂW¤H", "·Å¬XªºÂWµÛ", ""},
+ {"judo", "¹LªÓºL", "§ì¦í¤F", "ªº¦çÃÌ¡AÂਭ¡K¡K°Ú¡A¬O¤@°O¹LªÓºL¡I"},
+ {"kickout", "½ð", "¥Î¤j¸}§â", "½ð¨ì¤s¤U¥h¤F"},
+ {"kick", "½ð¤H", "§â", "½ðªº¦º¥h¬¡¨Ó"},
+ {"kiss", "»´§k", "»´§k", "ªºÁyÀU"},
+ {"laugh", "¼J¯º", "¤jÁn¼J¯º", ""},
+ {"levis", "µ¹§Ú", "»¡¡Gµ¹§Ú", "¡I¨ä¾l§K½Í¡I"},
+ {"lick", "»Q", "¨g»Q", ""},
+ {"lobster", "À£¨î", "¬I®i°f½¼§Î©T©w¡A§â", "À£¨î¦b¦aªO¤W"},
+ {"love", "ªí¥Õ", "¹ï", "²`±¡ªºªí¥Õ"},
+ {"marry", "¨D±B", "±·µÛ¤E¦Ê¤E¤Q¤E¦·ª´ºÀ¦V", "¨D±B"},
+ {"no", "¤£­n°Ú", "«÷©R¹ïµÛ", "·nÀY~~~~¤£­n°Ú~~~~"},
+ {"nod", "ÂIÀY", "¦V", "ÂIÀYºÙ¬O"},
+ {"nudge", "³»¨{¤l", "¥Î¤â¨y³»", "ªºªÎ¨{¤l"},
+ {"pad", "©çªÓ»H", "»´©ç", "ªºªÓ»H"},
+ {"pettish", "¼»¼b", "¸ò", "ÜÝÁnÜÝ®ð¦a¼»¼b"},
+ {"pili", "ÅRÆE", "¨Ï¥X §g¤l­· ¤Ñ¦a®Ú ¯ë­YÄb ¤T¦¡¦X¤@¥´¦V", "~~~~~~"},
+ {"pinch", "À¾¤H", "¥Î¤Oªº§â", "À¾ªº¶Â«C"},
+ {"roll", "¥´ºu", "©ñ¥X¦hº¸³Oªº­µ¼Ö,", "¦b¦a¤Wºu¨Óºu¥h"},
+ {"protect", "«OÅ@", "«OÅ@µÛ", ""},
+ {"pull", "©Ô", "¦º©R¦a©Ô¦í", "¤£©ñ"},
+ {"punch", "´~¤H", "¬½¬½´~¤F", "¤@¹y"},
+ {"rascal", "­A¿à", "¸ò", "­A¿à"},
+ {"recline", "¤JÃh", "Æp¨ì", "ªºÃh¸ÌºÎµÛ¤F¡K¡K"},
+ {"respond", "­t³d", "¦w¼¢", "»¡¡G¡y¤£­n­ú¡A§Ú·|­t³dªº¡K¡K¡z"},
+ {"shrug", "ÁqªÓ", "µL©`¦a¦V", "Áq¤FÁqªÓ»H"},
+ {"sigh", "¼Û®ð", "¹ï", "¼Û¤F¤@¤f®ð"},
+ {"slap", "¥´¦Õ¥ú", "°Ô°Ôªº¤Ú¤F", "¤@¹y¦Õ¥ú"},
+ {"smooch", "¾Ö§k", "¾Ö§kµÛ", ""},
+ {"snicker", "Åѯº", "¼K¼K¼K..ªº¹ï", "Åѯº"},
+ {"sniff", "¤£®h", "¹ï", "¶á¤§¥H»ó"},
+ {"spank", "¥´§¾§¾", "¥Î¤Ú´x¥´", "ªºÁv³¡"},
+ {"squeeze", "ºò¾Ö", "ºòºò¦a¾Ö©êµÛ", ""},
+ {"sysop", "¥l³ê", "¥s¥X¤F§å½ð½ð¡A§â", "½ò«ó¤F¡I"},
+ {"thank", "·PÁÂ", "¦V", "·PÁ±o¤­Åé§ë¦a"},
+ {"tickle", "·kÄo", "©B¼T!©B¼T!·k", "ªºÄo"},
+ {"wake", "·n¿ô", "»´»´¦a§â", "·n¿ô"},
+ {"wave", "´§¤â", "¹ïµÛ", "«÷©Rªº·n¤â"},
+ {"welcome", "Åwªï", "Åwªï", "¶i¨Ó¤K¨ö¤@¤U"},
+ {"what", "¤°»ò", "»¡¡G¡y", "­ù¤½½M±K«zÃ÷Å¥¬Y?¡H?¡S?¡z"},
+ {"whip", "Ã@¤l", "¤â¤W®³µÛÄúÀë¡A¥ÎÃ@¤lµh¥´", ""},
+ {"wink", "¯w²´", "¹ï", "¯«¯µªº¯w¯w²´·ú"},
+ {"zap", "²r§ð", "¹ï", "ºÆ¨gªº§ðÀ»"},
+ {NULL, NULL, NULL, NULL}
+};
+
+static int
+chicken_action(cu, cmd, party)
+ ChatUser *cu;
+ char *cmd;
+ char *party;
+{
+return 0;
+}
+static int
+party_action(cu, cmd, party)
+ ChatUser *cu;
+ char *cmd;
+ char *party;
+{
+ ChatAction *cap;
+ char *verb;
+
+ for (cap = party_data; (verb = cap->verb); cap++)
+ {
+ MYDOG;
+
+ if (str_equal(cmd, verb))
+ {
+ if (*party == '\0')
+ {
+ party = "¤j®a";
+ }
+ else
+ {
+ ChatUser *xuser;
+
+ xuser = fuzzy_cuser_by_chatid(party);
+ if (xuser == NULL)
+ { /* Thor.0724: ¥Î userid¤]¹À³q */
+ xuser = cuser_by_userid(party);
+ }
+
+ if (xuser == NULL)
+ {
+ sprintf(chatbuf, msg_no_such_id, party);
+ send_to_user(cu, chatbuf, 0, MSG_MESSAGE);
+ return 0;
+ }
+ else if (xuser == FUZZY_USER)
+ {
+ sprintf(chatbuf, "¡° ½Ð«ü©ú²á¤Ñ¥N¸¹");
+ send_to_user(cu, chatbuf, 0, MSG_MESSAGE);
+ return 0;
+ }
+ else if (cu->room != xuser->room || CLOAK(xuser))
+ {
+ sprintf(chatbuf, msg_not_here, party);
+ send_to_user(cu, chatbuf, 0, MSG_MESSAGE);
+ return 0;
+ }
+ else
+ {
+ party = xuser->chatid;
+ }
+ }
+ sprintf(chatbuf, "%s %s %s %s",
+ cu->chatid, cap->part1_msg, party, cap->part2_msg);
+ send_to_room(cu->room, chatbuf, cu->userno, MSG_MESSAGE);
+ return 0; /* Thor: cu->room ¬O§_¬° NULL? */
+ }
+ }
+ return 1;
+}
+
+
+/* --------------------------------------------- */
+/* MUD-like social commands : speak */
+/* --------------------------------------------- */
+
+
+static ChatAction speak_data[] =
+{
+
+ {
+ "ask", "¸ß°Ý", "°Ý", NULL
+ },
+ {
+ "chant", "ºq¹|", "°ªÁnºq¹|", NULL
+ },
+ {
+ "cheer", "³Üªö", "³Üªö", NULL
+ },
+ {
+ "chuckle", "»´¯º", "»´¯º", NULL
+ },
+ {
+ "curse", "·t·F", "·t·F", NULL
+ },
+ /* {"curse", "©G½|", NULL}, */
+ {
+ "demand", "­n¨D", "­n¨D", NULL
+ },
+ {
+ "frown", "½K¬ÜÀY", "ÂÙ¬Ü", NULL
+ },
+ {
+ "groan", "©D§u", "©D§u", NULL
+ },
+ {
+ "grumble", "µo¨cÄÌ", "µo¨cÄÌ", NULL
+ },
+ {
+ "guitar", "¼u°Û", "Ãä¼uµÛ¦N¥L¡AÃä°ÛµÛ", NULL
+ },
+ /* {"helpme", "©I±Ï","¤jÁn©I±Ï",NULL}, */
+ {
+ "hum", "³ä³ä", "³ä³ä¦Û»y", NULL
+ },
+ {
+ "moan", "«è¹Ä", "«è¹Ä", NULL
+ },
+ {
+ "notice", "±j½Õ", "±j½Õ", NULL
+ },
+ {
+ "order", "©R¥O", "©R¥O", NULL
+ },
+ {
+ "ponder", "¨H«ä", "¨H«ä", NULL
+ },
+ {
+ "pout", "äþ¼L", "äþµÛ¼L»¡", NULL
+ },
+ {
+ "pray", "¬èë", "¬èë", NULL
+ },
+ {
+ "request", "Àµ¨D", "Àµ¨D", NULL
+ },
+ {
+ "shout", "¤j½|", "¤j½|", NULL
+ },
+ {
+ "sing", "°Ûºq", "°Ûºq", NULL
+ },
+ {
+ "smile", "·L¯º", "·L¯º", NULL
+ },
+ {
+ "smirk", "°²¯º", "°²¯º", NULL
+ },
+ {
+ "swear", "µo»}", "µo»}", NULL
+ },
+ {
+ "tease", "¼J¯º", "¼J¯º", NULL
+ },
+ {
+ "whimper", "¶ã«|", "¶ã«|ªº»¡", NULL
+ },
+ {
+ "yawn", "«¢¤í", "Ã䥴«¢¤íÃ仡", NULL
+ },
+ {
+ "yell", "¤j³Û", "¤j³Û", NULL
+ },
+ {
+ NULL, NULL, NULL, NULL
+ }
+};
+
+
+static int
+speak_action(cu, cmd, msg)
+ ChatUser *cu;
+ char *cmd;
+ char *msg;
+{
+ ChatAction *cap;
+ char *verb;
+
+ for (cap = speak_data; (verb = cap->verb); cap++)
+ {
+ MYDOG;
+
+ if (str_equal(cmd, verb))
+ {
+ sprintf(chatbuf, "%s %s¡G %s",
+ cu->chatid, cap->part1_msg, msg);
+ send_to_room(cu->room, chatbuf, cu->userno, MSG_MESSAGE);
+ return 0; /* Thor: cu->room ¬O§_¬° NULL? */
+ }
+ }
+ return 1;
+}
+
+
+/* -------------------------------------------- */
+/* MUD-like social commands : condition */
+/* -------------------------------------------- */
+
+
+static ChatAction condition_data[] =
+{
+ {
+ "applaud", "©ç¤â", "°Ô°Ô°Ô°Ô°Ô°Ô°Ô....", NULL
+ },
+ {
+ "ayo", "­üËç³Þ", "­üËç³Þ~~~", NULL
+ },
+ {
+ "back", "§¤¦^¨Ó", "¦^¨Ó§¤¥¿Ä~Äò¾Ä¾Ô", NULL
+ },
+ {
+ "blood", "¦b¦å¤¤", "­Ë¦b¦åªy¤§¤¤", NULL
+ },
+ {
+ "blush", "Áy¬õ", "Áy³£¬õ¤F", NULL
+ },
+ {
+ "broke", "¤ß¸H", "ªº¤ß¯}¸H¦¨¤@¤ù¤@¤ùªº", NULL
+ }, /* Thor.0731:À³Æ[²³­n¨D */
+ /* {"bokan", "Bo Kan! Bo Kan!", NULL}, */
+ {
+ "careles", "¨S¤H²z", "¶ã¡ã¡ã³£¨S¦³¤H²z§Ú :~~~~", NULL
+ },
+ {
+ "chew", "¶ß¥Ê¤l", "«Ü±y¶¢ªº¶ß°_¥Ê¤l¨Ó¤F", NULL
+ },
+ {
+ "climb", "ª¦¤s", "¦Û¤vºCºCª¦¤W¤s¨Ó¡K¡K", NULL
+ },
+ {
+ "cold", "·P«_¤F", "·P«_¤F,¶ý¶ý¤£Åý§Ú¥X¥hª± :~~~(", NULL
+ },
+ {
+ "cough", "«y¹Â", "«y¤F´XÁn", NULL
+ },
+ {
+ "die", "¼ÉÀÅ", "·í³õ¼ÉÀÅ", NULL
+ },
+ {
+ "faint", "©ü­Ë", "·í³õ©ü­Ë", NULL
+ },
+ {
+ "flop", "­»¿¼¥Ö", "½ò¨ì­»¿¼¥Ö... ·Æ­Ë¡I", NULL
+ },
+ {
+ "fly", "ÄÆÄƵM", "ÄÆÄƵM", NULL
+ },
+ {
+ "frown", "ÂÙ¬Ü", "ÂÙ¬Ü", NULL
+ },
+ {
+ "gold", "®³ª÷µP", "°ÛµÛ¡G¡yª÷£|£±£½ª÷£|£±£½ ¥X°ê¤ñÁÉ! ±o«a­x¡A®³ª÷µP¡A¥úºa­Ë¾H¨Ó¡I¡z", NULL
+ },
+ {
+ "gulu", "¨{¤l¾j", "ªº¨{¤lµo¥X©BÂP~~~©BÂP~~~ªºÁn­µ", NULL
+ },
+ {
+ "haha", "«z«¢«¢", "«z«¢«¢«¢.....^o^", NULL
+ },
+ /* {"haha", "¤j¯º","«z«¢«¢«¢«¢«¢«¢«¢«¢~~~~!!!!!", NULL}, */
+ {
+ "helpme", "¨D±Ï", "¤j³Û~~~±Ï©R°Ú~~~~", NULL
+ },
+ {
+ "hoho", "¨þ¨þ¯º", "¨þ¨þ¨þ¯º­Ó¤£°±", NULL
+ },
+ {
+ "happy", "°ª¿³", "°ª¿³±o¦b¦a¤W¥´ºu", NULL
+ },
+ /* {"happy", "°ª¿³", "¢ç¢Ï¡I *^_^*", NULL}, */
+ /* {"happy", "", "r-o-O-m....Å¥¤F¯u²n¡I", NULL}, */
+ /* {"hurricane", "¢Ö¢÷---¢à£B¢ý--¢Ù¢é¢ö¡I¡I¡I", NULL}, */
+ {
+ "idle", "§b¦í¤F", "§b¦í¤F", NULL
+ },
+ {
+ "jacky", "®Ì®Ì", "µl¤l¯ëªº®Ì¨Ó®Ì¥h", NULL
+ },
+
+#if 0
+ /* Thor.0729: ¤£ª¾¨ä·N */
+ {
+ "lag", "ºô¸ôºC", "lllllllaaaaaaaaaaaagggggggggggggg.................", NULL
+ },
+#endif
+
+ {
+ "luck", "©¯¹B", "«z¡IºÖ®ð°Õ¡I", NULL
+ },
+ {
+ "macarn", "¤@ºØ»R", "¶}©l¸õ°_¤F¢Ûa¢Ña¢àe¢Üa¡ã¡ã¡ã¡ã", NULL
+ },
+ {
+ "miou", "ØpØp", "ØpØp¤f­]¤f­]¡ã¡ã¡ã¡ã¡ã", NULL
+ },
+ {
+ "mouth", "«ó¼L", "«ó¼L¤¤!!", NULL
+ },
+ {
+ "nani", "«ç»ò·|", "¡G©`£®°Ú®º??", NULL
+ },
+ {
+ "nose", "¬y»ó¦å", "¬y»ó¦å", NULL
+ },
+ {
+ "puke", "¹Ã¦R", "¹Ã¦R¤¤", NULL
+ },
+ /* {"puke", "¯uäú¤ß¡A§ÚÅ¥¤F³£·Q¦R", NULL}, */
+ {
+ "rest", "¥ð®§", "¥ð®§¤¤¡A½Ð¤Å¥´ÂZ", NULL
+ },
+ {
+ "reverse", "½¨{", "½¨{", NULL
+ },
+ {
+ "room", "¶}©Ð¶¡", "r-o-O-m-r-O-¢Ý-Mmm-rR¢à........", NULL
+ },
+ {
+ "shake", "·nÀY", "·n¤F·nÀY", NULL
+ },
+ {
+ "sleep", "ºÎµÛ", "­w¦bÁä½L¤WºÎµÛ¤F¡A¤f¤ô¬y¶iÁä½L¡A³y¦¨·í¾÷¡I", NULL
+ },
+ /* {"sleep", "Zzzzzzzzzz¡A¯uµL²á¡A³£§ÖºÎµÛ¤F", NULL}, */
+ {
+ "so", "´NÂæ¤l", "´NÂæ¤l!!", NULL
+ },
+ {
+ "sorry", "¹Dºp", "¶ã°Ú!!§Ú¹ï¤£°_¤j®a,§Ú¹ï¤£°_°ê®aªÀ·|~~~~~~¶ã°Ú~~~~~", NULL
+ },
+ {
+ "story", "Á¿¥j", "¶}©lÁ¿¥j¤F", NULL
+ },
+ {
+ "strut", "·nÂ\\¨«", "¤j·n¤jÂ\\¦a¨«", NULL
+ },
+ {
+ "suicide", "¦Û±þ", "¦Û±þ", NULL
+ },
+ {
+ "tea", "ªw¯ù", "ªw¤F³ý¦n¯ù", NULL
+ },
+ {
+ "think", "«ä¦Ò", "¬nµÛÀY·Q¤F¤@¤U", NULL
+ },
+ {
+ "tongue", "¦R¦Þ", "¦R¤F¦R¦ÞÀY", NULL
+ },
+ {
+ "wall", "¼²Àð", "¶]¥h¼²Àð", NULL
+ },
+ {
+ "wawa", "«z«z", "«z«z«z~~~~~!!!!! ~~~>_<~~~", NULL
+ },
+ /* {"wawa","«z«z«z......>_<",NULL}, */
+ {
+ "www", "¨L¨L", "¨L¨L¨L!!!", NULL
+ },
+ {
+ "zzz", "¥´©I", "©IÂP~~~~ZZzZz£C¢èZZzzZzzzZZ...", NULL
+ },
+
+ {
+ NULL, NULL, NULL, NULL
+ }
+};
+
+
+static int
+condition_action(cu, cmd)
+ ChatUser *cu;
+ char *cmd;
+{
+ ChatAction *cap;
+ char *verb;
+
+ for (cap = condition_data; (verb = cap->verb); cap++)
+ {
+ MYDOG;
+
+ if (str_equal(cmd, verb))
+ {
+ sprintf(chatbuf, "%s %s",
+ cu->chatid, cap->part1_msg);
+ send_to_room(cu->room, chatbuf, cu->userno, MSG_MESSAGE);
+ return 1; /* Thor: cu->room ¬O§_¬° NULL? */
+ }
+ }
+ return 0;
+}
+
+
+/* --------------------------------------------- */
+/* MUD-like social commands : help */
+/* --------------------------------------------- */
+
+
+static char *dscrb[] =
+{
+ "¡i Verb + Nick¡G °Êµü + ¹ï¤è¦W¦r ¡j ¨Ò¡G//kick piggy",
+ "¡i Verb + Message¡G°Êµü + ­n»¡ªº¸Ü ¡j ¨Ò¡G//sing ¤Ñ¤Ñ¤ÑÂÅ",
+ "¡i Verb¡G°Êµü ¡j ¡ô¡õ¡G¸ܭ«´£", NULL
+};
+ChatAction *catbl[] =
+{
+ party_data, speak_data, condition_data, NULL
+};
+
+static void
+chat_partyinfo(cu, msg)
+ ChatUser *cu;
+ char *msg;
+{
+ if (!common_client_command)
+ return; /* only allow common client to retrieve it */
+
+ sprintf(chatbuf, "3 °Ê§@ ¥æ½Í ª¬ºA");
+ send_to_user(cu, chatbuf, 0, MSG_PARTYINFO);
+}
+
+static void
+chat_party(cu, msg)
+ ChatUser *cu;
+ char *msg;
+{
+ int kind, i;
+ ChatAction *cap;
+
+ if (!common_client_command)
+ return;
+
+ kind = atoi(nextword(&msg));
+ if (kind < 0 || kind > 2)
+ return;
+
+ sprintf(chatbuf, "%d %s", kind, kind == 2 ? "I" : "");
+
+ /* Xshadow: ¥u¦³ condition ¤~¬O immediate mode */
+ send_to_user(cu, chatbuf, 0, MSG_PARTYLISTSTART);
+
+ cap = catbl[kind];
+ for (i = 0; cap[i].verb; i++)
+ {
+ sprintf(chatbuf, "%-10s %-20s", cap[i].verb, cap[i].chinese);
+ /* for (j=0;j<1000000;j++); */
+ send_to_user(cu, chatbuf, 0, MSG_PARTYLIST);
+ }
+
+ sprintf(chatbuf, "%d", kind);
+ send_to_user(cu, chatbuf, 0, MSG_PARTYLISTEND);
+}
+
+
+#define SCREEN_WIDTH 80
+#define MAX_VERB_LEN 8
+#define VERB_NO 10
+
+static void
+view_action_verb(cu, cmd) /* Thor.0726: ·s¥[°Êµü¤ÀÃþÅã¥Ü */
+ register ChatUser *cu;
+ char cmd;
+{
+ register int i;
+ register char *p, *q, *data, *expn;
+ register ChatAction *cap;
+
+ send_to_user(cu, "/c", 0, MSG_CLRSCR);
+
+ data = chatbuf;
+
+ if (cmd < '1' || cmd > '3')
+ { /* Thor.0726: ¼g±o¤£¦n, ·Q¿ìªk§ï¶i... */
+ for (i = 0; (p = dscrb[i]); i++)
+ {
+ sprintf(data, " [//]help %d - MUD-like ªÀ¥æ°Êµü ²Ä %d Ãþ", i + 1, i + 1);
+ MYDOG;
+ send_to_user(cu, data, 0, MSG_MESSAGE);
+ send_to_user(cu, p, 0, MSG_MESSAGE);
+ send_to_user(cu, " ", 0, MSG_MESSAGE); /* Thor.0726: ´«¦æ, »Ý­n " "
+ * ¶Ü? */
+ }
+ }
+ else
+ {
+ i = cmd - '1';
+
+ send_to_user(cu, dscrb[i], 0, MSG_MESSAGE);
+
+ expn = chatbuf + 100; /* Thor.0726: À³¸Ó¤£·|overlap§a? */
+
+ *data = '\0';
+ *expn = '\0';
+
+ cap = catbl[i];
+
+ for (i = 0; (p = cap[i].verb); i++)
+ {
+ MYDOG;
+ q = cap[i].chinese;
+
+ strcat(data, p);
+ strcat(expn, q);
+
+ if (((i + 1) % VERB_NO) == 0)
+ {
+ send_to_user(cu, data, 0, MSG_MESSAGE);
+ send_to_user(cu, expn, 0, MSG_MESSAGE); /* Thor.0726: Åã¥Ü¤¤¤åµù¸Ñ */
+ *data = '\0';
+ *expn = '\0';
+ }
+ else
+ {
+ strncat(data, " ", MAX_VERB_LEN - strlen(p));
+ strncat(expn, " ", MAX_VERB_LEN - strlen(q));
+ }
+ }
+ if (i % VERB_NO)
+ {
+ send_to_user(cu, data, 0, MSG_MESSAGE);
+ send_to_user(cu, expn, 0, MSG_MESSAGE); /* Thor.0726: Åã¥Ü¤¤¤åµù¸Ñ */
+ }
+ }
+ /* send_to_user(cu, " ",0); *//* Thor.0726: ´«¦æ, »Ý­n " " ¶Ü? */
+}
+
+void view_chicken_help(cu) /* Ptt: °«Âûµ{¦¡ ªºhelp */
+ register ChatUser *cu;
+{
+
+}
+
+/* ----------------------------------------------------- */
+/* chat user service routines */
+/* ----------------------------------------------------- */
+
+
+static ChatCmd chatcmdlist[] =
+{
+ {"act", chat_act, 0},
+ {"bye", chat_goodbye, 0},
+ {"chatroom", chat_chatroom, 1}, /* Xshadow: for common client */
+ {"clear", chat_clear, 0},
+ {"cloak", chat_cloak, 2},
+ {"date", chat_date, 0},
+ {"flags", chat_setroom, 0},
+ {"help", chat_help, 0},
+ {"ignore", chat_ignore, 1},
+ {"invite", chat_invite, 0},
+ {"join", chat_join, 0},
+ {"kick", chat_kick, 1},
+ {"msg", chat_private, 0},
+ {"nick", chat_nick, 0},
+ {"operator", chat_makeop, 0},
+ {"party", chat_party, 1}, /* Xshadow: party data for common client */
+ {"partyinfo", chat_partyinfo, 1}, /* Xshadow: party info for common
+ * client */
+
+ {"query", chat_query, 0},
+
+ {"room", chat_list_rooms, 0},
+ {"unignore", chat_unignore, 1},
+ {"whoin", chat_list_by_room, 1},
+ {"wall", chat_broadcast, 2},
+
+ {"who", chat_map_chatids_thisroom, 0},
+ {"list", chat_list_users, 0},
+ {"topic", chat_topic, 1},
+ {"version", chat_version, 1},
+
+ {NULL, NULL, 0}
+};
+
+/* Thor: 0 ¤£¥Î exact, 1 ­n exactly equal, 2 ¯µ±K«ü¥O */
+
+
+static int
+command_execute(cu)
+ ChatUser *cu;
+{
+ char *cmd, *msg;
+ ChatCmd *cmdrec;
+ int match, ch;
+
+ msg = cu->ibuf;
+ match = *msg;
+
+ /* Validation routine */
+
+ if (cu->room == NULL)
+ {
+ /* MUST give special /! or /-! command if not in the room yet */
+
+ if (match == '/' && ((ch = msg[1]) == '!' || (ch == '-' && msg[2] == '!')))
+ {
+ cu->clitype = (ch == '-') ? 1 : 0;
+ return (login_user(cu, msg + 2 + cu->clitype));
+ }
+ else
+ return -1;
+ }
+
+ /* If not a /-command, it goes to the room. */
+
+ if (match != '/')
+ {
+ if (match)
+ {
+ char buf[16];
+
+ sprintf(buf, "%s:", cu->chatid);
+ sprintf(chatbuf, "%-10s%s", buf, msg);
+ if (!CLOAK(cu)) /* Thor: ²á¤Ñ«ÇÁô¨­³N */
+ send_to_room(cu->room, chatbuf, cu->userno, MSG_MESSAGE);
+ /* Thor: ­n check cu->room NULL¶Ü? */
+
+ }
+ return 0;
+ }
+
+ msg++;
+ cmd = nextword(&msg);
+ match = 0;
+
+ if (*cmd == '/')
+ {
+ cmd++;
+ if (!*cmd || str_equal(cmd, "help"))
+ {
+ /* Thor.0726: °Êµü¤ÀÃþ */
+ cmd = nextword(&msg);
+ view_action_verb(cu, *cmd);
+ match = 1;
+ }
+ else if (party_action(cu, cmd, msg) == 0)
+ match = 1;
+ else if (speak_action(cu, cmd, msg) == 0)
+ match = 1;
+ else
+ match = condition_action(cu, cmd);
+ }
+ else if(*cmd == '.')
+ {
+ cmd++;
+ if (!*cmd || str_equal(cmd, "help"))
+ {
+ view_chicken_help(cu);
+ match = 1;
+ }
+ else match = chicken_action(cu, cmd, msg);
+ }
+ else
+ {
+ char *str;
+
+ common_client_command = 0;
+ if((*cmd == '-')) {
+ if(cu->clitype) {
+ cmd++; /* Xshadow: «ü¥O±q¤U¤@­Ó¦r¤¸¤~¶}©l */
+ common_client_command = 1;
+ }
+ }
+ for(cmdrec = chatcmdlist; (str = cmdrec->cmdstr); cmdrec++)
+ {
+ MYDOG;
+
+ switch (cmdrec->exact)
+ {
+ case 1: /* exactly equal */
+ match = str_equal(cmd, str);
+ break;
+ case 2: /* Thor: secret command */
+ if (CHATSYSOP(cu))
+ match = str_equal(cmd, str);
+ break;
+ default: /* not necessary equal */
+ match = str_match(cmd, str) >= 0;
+ break;
+ }
+
+ if (match)
+ {
+ cmdrec->cmdfunc(cu, msg);
+ break;
+ }
+ }
+ }
+
+ if (!match)
+ {
+ sprintf(chatbuf, "¡» «ü¥O¿ù»~¡G/%s", cmd);
+ send_to_user(cu, chatbuf, 0, MSG_MESSAGE);
+ }
+ return 0;
+}
+
+
+/* ----------------------------------------------------- */
+/* serve chat_user's connection */
+/* ----------------------------------------------------- */
+
+
+static int
+cuser_serve(cu)
+ ChatUser *cu;
+{
+ register int ch, len, isize;
+ register char *str, *cmd;
+ static char buf[80];
+
+ str = buf;
+ len = recv(cu->sock, str, sizeof(buf) - 1, 0);
+ if (len <= 0)
+ {
+ /* disconnected */
+
+ exit_room(cu, EXIT_LOSTCONN, (char *) NULL);
+ return -1;
+ }
+
+#if 0
+ /* Xshadow: ±N°e¹Fªº¸ê®Æ©¾¹ê¬ö¿ý¤U¨Ó */
+ memcpy(logbuf, buf, sizeof(buf));
+ for (ch = 0; ch < sizeof(buf); ch++)
+ if (!logbuf[ch])
+ logbuf[ch] = '$';
+
+ logbuf[len + 1] = '\0';
+ logit("recv: ", logbuf);
+#endif
+
+#if 0
+ logit(cu->userid, str);
+#endif
+
+ isize = cu->isize;
+ cmd = cu->ibuf + isize;
+ while (len--)
+ {
+ MYDOG;
+
+ ch = *str++;
+
+ if (ch == '\r' || !ch)
+ continue;
+ if (ch == '\n')
+ {
+ *cmd = '\0';
+
+ isize = 0;
+ cmd = cu->ibuf;
+
+ if (command_execute(cu) < 0)
+ return -1;
+
+ continue;
+ }
+ if (isize < 79)
+ {
+ *cmd++ = ch;
+ isize++;
+ }
+ }
+ cu->isize = isize;
+ return 0;
+}
+
+
+/* ----------------------------------------------------- */
+/* chatroom server core routines */
+/* ----------------------------------------------------- */
+
+static int
+start_daemon()
+{
+ int fd, value;
+ char buf[80];
+ struct sockaddr_in fsin;
+ struct linger ld;
+ struct rlimit limit;
+ time_t dummy;
+ struct tm *dummy_time;
+
+ /*
+ * More idiot speed-hacking --- the first time conversion makes the C
+ * library open the files containing the locale definition and time zone.
+ * If this hasn't happened in the parent process, it happens in the
+ * children, once per connection --- and it does add up.
+ */
+
+ time(&dummy);
+ dummy_time = gmtime(&dummy);
+ dummy_time = localtime(&dummy);
+ strftime(buf, 80, "%d/%b/%Y:%H:%M:%S", dummy_time);
+
+ /* --------------------------------------------------- */
+ /* speed-hacking DNS resolve */
+ /* --------------------------------------------------- */
+
+ gethostname(buf, sizeof(buf));
+
+ /* Thor: ¸U¤@server©|¥¼±µ¨üconnection, ´N¦^¥hªº¸Ü, client ²Ä¤@¦¸·|¶i¤J¥¢±Ñ */
+ /* ©Ò¥H²¾¦Ü listen «á */
+
+ /* --------------------------------------------------- */
+ /* detach daemon process */
+ /* --------------------------------------------------- */
+
+ close(0);
+ close(1);
+ close(2);
+
+ if (fork())
+ exit(0);
+
+ chdir(BBSHOME);
+
+ setsid();
+
+ /* --------------------------------------------------- */
+ /* adjust the resource limit */
+ /* --------------------------------------------------- */
+
+ getrlimit(RLIMIT_NOFILE, &limit);
+ limit.rlim_cur = limit.rlim_max;
+ setrlimit(RLIMIT_NOFILE, &limit);
+
+#if 0
+ while (fd)
+ {
+ close(--fd);
+ }
+
+ value = getpid();
+ setpgrp(0, value);
+
+ if ((fd = open("/dev/tty", O_RDWR)) >= 0)
+ {
+ ioctl(fd, TIOCNOTTY, 0); /* Thor : ¬°¤°»òÁÙ­n¥Î tty? */
+ close(fd);
+ }
+#endif
+
+ fd = open(CHAT_PIDFILE, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+ if (fd >= 0)
+ {
+ /* sprintf(buf, "%5d\n", value); */
+ sprintf(buf, "%5d\n", getpid());
+ write(fd, buf, 6);
+ close(fd);
+ }
+
+#if 0
+ /* ------------------------------ */
+ /* trap signals */
+ /* ------------------------------ */
+
+ for (fd = 1; fd < NSIG; fd++)
+ {
+
+ signal(fd, SIG_IGN);
+ }
+#endif
+
+ fd = socket(PF_INET, SOCK_STREAM, 0);
+
+#if 0
+ value = fcntl(fd, F_GETFL, 0);
+ fcntl(fd, F_SETFL, value | O_NDELAY);
+#endif
+
+ value = 1;
+ setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &value, sizeof(value));
+
+#if 0
+ setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, (char *) &value, sizeof(value));
+
+ value = 81920;
+ setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *) &value, sizeof(value));
+#endif
+
+ ld.l_onoff = ld.l_linger = 0;
+ setsockopt(fd, SOL_SOCKET, SO_LINGER, (char *) &ld, sizeof(ld));
+
+ memset((char *) &fsin, 0, sizeof(fsin));
+ fsin.sin_family = AF_INET;
+ fsin.sin_port = htons(NEW_CHATPORT);
+ fsin.sin_addr.s_addr = htonl(INADDR_ANY);
+
+ if (bind(fd, (struct sockaddr *) & fsin, sizeof(fsin)) < 0)
+ exit(1);
+
+ listen(fd, SOCK_QLEN);
+
+ return fd;
+}
+
+
+static void
+free_resource(fd)
+ int fd;
+{
+ static int loop = 0;
+ register ChatUser *user;
+ register int sock, num;
+
+ num = 0;
+ for (user = mainuser; user; user = user->unext)
+ {
+ MYDOG;
+
+ num++;
+ sock = user->sock;
+ if (fd < sock)
+ fd = sock;
+ }
+
+ sprintf(chatbuf, "%d, %d user (%d -> %d)", ++loop, num, maxfds, fd);
+ logit("LOOP", chatbuf);
+
+ maxfds = fd + 1;
+}
+
+
+#ifdef SERVER_USAGE
+static void
+server_usage()
+{
+ struct rusage ru;
+ char buf[2048];
+
+ if (getrusage(RUSAGE_SELF, &ru))
+ return;
+
+ sprintf(buf, "\n[Server Usage]\n\n"
+ "user time: %.6f\n"
+ "system time: %.6f\n"
+ "maximum resident set size: %lu P\n"
+ "integral resident set size: %lu\n"
+ "page faults not requiring physical I/O: %ld\n"
+ "page faults requiring physical I/O: %ld\n"
+ "swaps: %ld\n"
+ "block input operations: %ld\n"
+ "block output operations: %ld\n"
+ "messages sent: %ld\n"
+ "messages received: %ld\n"
+ "signals received: %ld\n"
+ "voluntary context switches: %ld\n"
+ "involuntary context switches: %ld\n"
+ "gline: %d\n\n",
+
+ (double) ru.ru_utime.tv_sec + (double) ru.ru_utime.tv_usec / 1000000.0,
+ (double) ru.ru_stime.tv_sec + (double) ru.ru_stime.tv_usec / 1000000.0,
+ ru.ru_maxrss,
+ ru.ru_idrss,
+ ru.ru_minflt,
+ ru.ru_majflt,
+ ru.ru_nswap,
+ ru.ru_inblock,
+ ru.ru_oublock,
+ ru.ru_msgsnd,
+ ru.ru_msgrcv,
+ ru.ru_nsignals,
+ ru.ru_nvcsw,
+ ru.ru_nivcsw,
+ gline);
+
+ write(flog, buf, strlen(buf));
+}
+#endif
+
+
+static void
+abort_server()
+{
+ log_close();
+ exit(1);
+}
+
+
+static void
+reaper()
+{
+ int state;
+
+ while (waitpid(-1, &state, WNOHANG | WUNTRACED) > 0)
+ {
+ MYDOG;
+ }
+}
+
+
+int
+main()
+{
+ register int msock, csock, nfds;
+ register ChatUser *cu;
+ register fd_set *rptr, *xptr;
+ fd_set rset, xset;
+ struct timeval tv;
+ time_t uptime, tmaintain;
+
+ msock = start_daemon();
+
+ setgid(BBSGID);
+ setuid(BBSUID);
+
+ log_init();
+
+ signal(SIGBUS, SIG_IGN);
+ signal(SIGSEGV, SIG_IGN);
+ signal(SIGPIPE, SIG_IGN);
+ signal(SIGURG, SIG_IGN);
+
+ signal(SIGCHLD, reaper);
+ signal(SIGTERM, abort_server);
+
+#ifdef SERVER_USAGE
+ signal(SIGPROF, server_usage);
+#endif
+
+ /* ----------------------------- */
+ /* init variable : rooms & users */
+ /* ----------------------------- */
+
+ mainuser = NULL;
+ memset(&mainroom, 0, sizeof(mainroom));
+ strcpy(mainroom.name, MAIN_NAME);
+ strcpy(mainroom.topic, MAIN_TOPIC);
+
+ /* ----------------------------------- */
+ /* main loop */
+ /* ----------------------------------- */
+
+#if 0
+ /* Thor: ¦blisten «á¤~¦^client, ¨C¦¸¶i¨Ó´N·|¦¨¥\ */
+ if (fork())
+ exit(0);
+#endif
+
+ FD_ZERO(&mainfds);
+ FD_SET(msock, &mainfds);
+ rptr = &rset;
+ xptr = &xset;
+ maxfds = msock + 1;
+
+ tmaintain = time(0) + CHAT_INTERVAL;
+
+ for (;;)
+ {
+ uptime = time(0);
+ if (tmaintain < uptime)
+ {
+ tmaintain = uptime + CHAT_INTERVAL;
+
+ /* client/server ª©¥»§Q¥Î ping-pong ¤èªk§PÂ_ user ¬O¤£¬OÁÙ¬¡µÛ */
+ /* ¦pªG client ¤w¸gµ²§ô¤F¡A´NÄÀ©ñ¨ä resource */
+
+ free_resource(msock);
+ }
+
+ MYDOG;
+
+ memcpy(rptr, &mainfds, sizeof(fd_set));
+ memcpy(xptr, &mainfds, sizeof(fd_set));
+
+ /* Thor: for future reservation bug */
+
+ tv.tv_sec = CHAT_INTERVAL;
+ tv.tv_usec = 0;
+
+ MYDOG;
+
+ nfds = select(maxfds, rptr, NULL, xptr, &tv);
+
+ MYDOG;
+ /* free idle user & chatroom's resource when no traffic */
+
+ if (nfds == 0)
+ {
+ continue;
+ }
+
+ /* check error condition */
+
+ if (nfds < 0)
+ {
+ csock = errno;
+ continue;
+ }
+
+ /* accept new connection */
+
+ if (FD_ISSET(msock, rptr))
+ {
+ for (;;)
+ {
+ MYDOG; /* Thor: check for endless */
+ csock = accept(msock, NULL, NULL);
+
+ if (csock >= 0)
+ {
+ MYDOG;
+ if((cu = (ChatUser *) malloc(sizeof(ChatUser))))
+ {
+ memset(cu, 0, sizeof(ChatUser));
+ cu->sock = csock;
+
+ cu->unext = mainuser;
+ mainuser = cu;
+
+#if 0
+ if (mainuser.next)
+ mainuser.next->prev = cu;
+ cu->next = mainuser.next;
+ mainuser.next = cu;
+ cu->prev = &mainuser;
+#endif
+
+ totaluser++;
+ FD_SET(csock, &mainfds);
+ if (csock >= maxfds)
+ maxfds = csock + 1;
+
+#ifdef DEBUG
+ logit("accept", "OK");
+#endif
+ }
+ else
+ {
+ close(csock);
+ logit("accept", "malloc fail");
+ }
+ MYDOG;
+
+ break;
+ }
+
+ csock = errno;
+ if (csock != EINTR)
+ {
+ break;
+ }
+ }
+
+ FD_CLR(msock, rptr);
+
+ if (--nfds <= 0)
+ continue;
+ }
+
+ for (cu = mainuser; cu; cu = cu->unext)
+ {
+ MYDOG;
+
+ csock = cu->sock;
+
+ if (FD_ISSET(csock, xptr))
+ {
+ logout_user(cu);
+ FD_CLR(csock, xptr);
+ }
+ else if (FD_ISSET(csock, rptr))
+ {
+ if (cuser_serve(cu) < 0)
+ logout_user(cu);
+ }
+ else
+ {
+ continue;
+ }
+
+ FD_CLR(csock, rptr);
+ if (--nfds <= 0)
+ break;
+ }
+
+ /* end of main loop */
+ }
+}
diff --git a/util/xchatd.h b/util/xchatd.h
new file mode 100644
index 00000000..d0a6e1e4
--- /dev/null
+++ b/util/xchatd.h
@@ -0,0 +1,111 @@
+/* $Id: xchatd.h,v 1.1 2002/03/07 15:13:46 in2 Exp $ */
+
+#ifndef _XCHAT_H_
+#define _XCHAT_H_
+
+#define XCHAT_VERSION_MAJOR 3
+#define XCHAT_VERSION_MINOR 0
+
+/* ----------------------------------------------------- */
+/* XCHAT response code : RFI 3-digit */
+/* ----------------------------------------------------- */
+/* Response : */
+/* 1xx Informative message */
+/* 2xx Command ok */
+/* 3xx Command ok so far, send the rest of it */
+/* 4xx Command correct, but NG for some reason */
+/* 5xx Command unimplemented, incorrect, or serious */
+/* program error occurred */
+/* Function : */
+/* x0x Connection, setup, and miscellaneous messages */
+/* x1x Newsgroup selection */
+/* x2x Article selection */
+/* x3x Distribution functions */
+/* x4x Posting */
+/* x8x Nonstandard extensions (AUTHINFO, XGTITLE) */
+/* x9x Debugging output */
+/* Information : */
+/* No defined semantics */
+/* ----------------------------------------------------- */
+
+/* ¨Ñ·sª© client ¨Ï¥Î */
+
+#define MSG_LOGINOK 100
+#define MSG_VERSION 103
+#define MSG_MESSAGE 106
+
+#define MSG_CHATROOM 110
+#define MSG_TOPIC 113
+#define MSG_ROOM 116
+#define MSG_NICK 118
+#define MSG_CLRSCR 120
+
+#define MSG_MOTDSTART 130
+#define MSG_MOTD 330
+#define MSG_MOTDEND 230
+
+#define MSG_ROOMLISTSTART 133
+#define MSG_ROOMLIST 333
+#define MSG_ROOMLISTEND 233
+#define MSG_ROOMNOTIFY 134
+
+#define MSG_USERLISTSTART 136
+#define MSG_USERLIST 336
+#define MSG_USERLISTEND 236
+#define MSG_USERNOTIFY 137
+
+#define MSG_PARTYINFO 140
+#define MSG_PARTYLISTSTART 340
+#define MSG_PARTYLIST 240
+#define MSG_PARTYLISTEND 141
+
+#define MSG_PRIVMSG 145
+#define MSG_MYPRIVMSG 146
+
+#define ERR_LOGIN_NICKINUSE 501
+#define ERR_LOGIN_NICKERROR 502
+#define ERR_LOGIN_USERONLINE 503
+#define ERR_LOGIN_NOSUCHUSER 504
+#define ERR_LOGIN_PASSERROR 505
+
+static int
+Isspace (ch)
+ int ch;
+{
+ return (ch == ' ' || ch == '\t' || ch == 10 || ch == 13);
+}
+
+static char *
+nextword (str)
+ char **str;
+{
+ char *head, *tail;
+ int ch;
+
+ head = *str;
+ for (;;) {
+
+ ch = *head;
+ if (!ch) {
+ *str = head;
+ return head;
+ }
+ if (!Isspace (ch))
+ break;
+ head++;
+ }
+
+ tail = head + 1;
+ while((ch = *tail)) {
+ if(Isspace (ch)) {
+ *tail++ = '\0';
+ break;
+ }
+ tail++;
+ }
+ *str = tail;
+
+ return head;
+}
+
+#endif /* _XCHAT_H_ */
diff --git a/util/yearsold.c b/util/yearsold.c
new file mode 100644
index 00000000..74e711ee
--- /dev/null
+++ b/util/yearsold.c
@@ -0,0 +1,112 @@
+/* $Id: yearsold.c,v 1.1 2002/03/07 15:13:46 in2 Exp $ */
+/* ¯¸¤W¦~Äֲέp */
+
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+#include <sys/types.h>
+#include "config.h"
+#include "pttstruct.h"
+#include "common.h"
+#include "util.h"
+
+#define MAX_LINE 16
+
+struct userec_t cuser;
+
+void
+ outs(fp, buf, mode)
+FILE *fp;
+char buf[], mode;
+{
+ static char state = '0';
+
+ if (state != mode)
+ fprintf(fp, "[3%cm", state = mode);
+ if (buf[0])
+ {
+ fprintf(fp, buf);
+ buf[0] = 0;
+ }
+}
+
+int main()
+{
+ int i, j, k;
+ char buf[256];
+ FILE *fp;
+ int year, max, item, maxyear;
+ long totalyear;
+ int act[25];
+ time_t now;
+ struct tm *ptime;
+
+ now = time(NULL);
+ ptime = localtime(&now);
+
+ if(passwd_mmap())
+ exit(1);
+
+ memset(act, 0, sizeof(act));
+ for(k = 1; k <= MAX_USERS; k++) {
+ passwd_query(k, &cuser);
+ if (((ptime->tm_year - cuser.year) < 10) || ((ptime->tm_year - cuser.year) >
+ 33))
+ continue;
+
+ act[ptime->tm_year - cuser.year - 10]++;
+ act[24]++;
+ }
+
+ for (i = max = totalyear = maxyear = 0; i < 24; i++)
+ {
+ totalyear += act[i] * (i + 10);
+ if (act[i] > max)
+ {
+ max = act[i];
+ maxyear = i;
+ }
+ }
+
+ item = max / MAX_LINE + 1;
+
+ if ((fp = fopen(BBSHOME"/etc/yearsold", "w")) == NULL)
+ {
+ printf("cann't open etc/yearsold\n");
+ return 1;
+ }
+
+ fprintf(fp, "\t\t\t  " BBSNAME
+ " ¦~Äֲέp [%02d/%02d/%02d] \n\n",
+ ptime->tm_year % 100, ptime->tm_mon, ptime->tm_mday);
+ for (i = MAX_LINE + 1; i > 0; i--)
+ {
+ strcpy(buf, " ");
+ for (j = 0; j < 24; j++)
+ {
+ max = item * i;
+ year = act[j];
+ if (year && (max > year) && (max - item <= year))
+ {
+ outs(fp, buf, '7');
+ fprintf(fp, "%-3d", year);
+ }
+ else if (max <= year)
+ {
+ outs(fp, buf, '4');
+ fprintf(fp, "¢i ");
+ }
+ else
+ strcat(buf, " ");
+ }
+ fprintf(fp, "\n");
+ }
+
+
+ fprintf(fp, " "
+ "10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33\n\n"
+ "\t\t ¦³®Ä²Î­p¤H¦¸¡G%-9d¥­§¡¦~ÄÖ¡G%d\n"
+ ,act[24], (int)totalyear / act[24]);
+ fclose(fp);
+ return 0;
+}