22c63a7337
Diff is taken from FreeBSD ports. - Combine patch-af and patch-bsearch into single file, because those are diff files for the same file. - Add LICENSE.
382 lines
10 KiB
C
382 lines
10 KiB
C
$NetBSD: patch-skkserv_skkserv.c,v 1.1 2013/03/10 18:53:32 hiramatsu Exp $
|
|
|
|
Add IPv6 support and binary search capability.
|
|
|
|
--- skkserv/skkserv.c.orig 2013-03-11 01:53:23.000000000 +0900
|
|
+++ skkserv/skkserv.c 2013-03-11 01:53:24.000000000 +0900
|
|
@@ -100,14 +100,16 @@
|
|
#define SERVER_NOT_FOUND "4"
|
|
#define SERVER_FULL "9"
|
|
|
|
+#define warn(m) \
|
|
+ {if (debug) fprintf(errout, "%s: %s\n", pgmnm, m);}
|
|
#define err(m) \
|
|
- {if (debug) fprintf(errout, "%s: %s\n", pgmnm, m); exit(1);}
|
|
+ {warn(m); exit(1);}
|
|
|
|
/*
|
|
* Global Variables
|
|
*/
|
|
|
|
-char pgmver[] = "3.9.4 "; /* version number */
|
|
+char pgmver[] = "3.9.4nb7 (binary search) "; /* version number */
|
|
|
|
char *pgmnm; /* program name */
|
|
char *jname; /* name of shared dictionary */
|
|
@@ -121,6 +123,9 @@
|
|
int jtab1[KANAMOJI]; /* index-table by 1st letter (1st part)*/
|
|
int jtab2[KANAMOJI]; /* index-table by 1st letter (2nd part)*/
|
|
int initsock; /* socket for waiting requests */
|
|
+#ifdef PF_INET6
|
|
+int initsock6; /* IPv6 socket for waiting requests */
|
|
+#endif
|
|
int clientsock[MAXCLNT]; /* socket for each client */
|
|
int nclients; /* max index for active clients */
|
|
|
|
@@ -130,8 +135,18 @@
|
|
int parg;
|
|
int setjisho = 0;
|
|
int ctlterm; /* fildes for control terminal */
|
|
- void reread();
|
|
+ RETSIGTYPE req_reread();
|
|
+
|
|
+#ifdef SKKSERV_UID
|
|
+ gid_t gid = SKKSERV_GID;
|
|
|
|
+ /* revoke privilege if any */
|
|
+ if (geteuid() == 0) {
|
|
+ setgroups(1, &gid);
|
|
+ setgid(SKKSERV_GID);
|
|
+ setuid(SKKSERV_UID);
|
|
+ }
|
|
+#endif
|
|
pgmnm = argv[0];
|
|
debug = 0;
|
|
errout = stderr;
|
|
@@ -200,7 +215,10 @@
|
|
fclose(stderr);
|
|
|
|
/* detach child process from control terminal */
|
|
-#ifdef HAVE_TIOCNOTTY
|
|
+#ifdef HAVE_SETSID
|
|
+ setsid();
|
|
+#else
|
|
+#ifdef TIOCNOTTY
|
|
if ((ctlterm = open("/dev/tty", 2)) >= 0) {
|
|
ioctl(ctlterm, TIOCNOTTY, 0);
|
|
close(ctlterm);
|
|
@@ -215,6 +233,7 @@
|
|
signal(SIGHUP, SIG_IGN);
|
|
if (fork() != 0) exit(0);
|
|
#endif
|
|
+#endif
|
|
} else { /* debug mode */
|
|
fprintf(errout, "SKK-JISYO is %s\n", jname);
|
|
fflush(errout);
|
|
@@ -222,7 +241,7 @@
|
|
if (errout != stderr) fclose(stderr);
|
|
}
|
|
|
|
- signal(SIGINT, reread);
|
|
+ signal(SIGINT, req_reread);
|
|
/* 1993/6/5 by kam, re-read dictionary by "INT" signal */
|
|
|
|
nclients = 0;
|
|
@@ -244,8 +263,11 @@
|
|
mksock()
|
|
{
|
|
struct sockaddr_in sin;
|
|
+#ifdef PF_INET6
|
|
+ struct sockaddr_in6 sin6;
|
|
+#endif
|
|
struct servent *sp;
|
|
- int optbuf = 1; /* enable socket REUSEADDR */
|
|
+ int optbuf; /* enable socket REUSEADDR */
|
|
|
|
bzero((char*)&sin, sizeof(sin));
|
|
sin.sin_family = AF_INET;
|
|
@@ -262,16 +284,54 @@
|
|
sin.sin_port = htons(portnum);
|
|
|
|
if ((initsock = socket(PF_INET, SOCK_STREAM, 0)) < 0)
|
|
- err("socket error; socket cannot be created");
|
|
- if (setsockopt(initsock, SOL_SOCKET, SO_REUSEADDR,
|
|
+ warn("socket error; socket cannot be created");
|
|
+#ifdef PF_INET6
|
|
+ bzero((char*)&sin6, sizeof(sin6));
|
|
+ sin6.sin6_family = AF_INET6;
|
|
+ /* sin6.sin6_addr.s6_addr = IN6ADDR_ANY_INIT; ... all-zero pattern */
|
|
+ sin6.sin6_port = htons(portnum);
|
|
+ if ((initsock6 = socket(PF_INET6, SOCK_STREAM, 0)) < 0)
|
|
+ warn("socket error; IPv6 socket cannot be created");
|
|
+#endif
|
|
+ optbuf = 1;
|
|
+ if (initsock >= 0 && setsockopt(initsock, SOL_SOCKET, SO_REUSEADDR,
|
|
+ &optbuf, sizeof(optbuf)) < 0)
|
|
+ warn("socket error; cannot set socket option");
|
|
+#ifdef PF_INET6
|
|
+ optbuf = 1;
|
|
+ if (initsock6 >= 0 && setsockopt(initsock6, SOL_SOCKET, SO_REUSEADDR,
|
|
&optbuf, sizeof(optbuf)) < 0)
|
|
- err("socket error; cannot set socket option");
|
|
- if (bind(initsock, (struct sockaddr *)&sin, sizeof(sin))< 0)
|
|
- err("bind error; the socket is already used");
|
|
- if (listen(initsock, MAXQUE) < 0)
|
|
+ warn("socket error; cannot set socket option");
|
|
+#endif
|
|
+ if (initsock >= 0 && bind(initsock, (struct sockaddr *)&sin, sizeof(sin))< 0) {
|
|
+ warn("bind error; the socket is already used");
|
|
+ close(initsock);
|
|
+ initsock = -1;
|
|
+ }
|
|
+#ifdef PF_INET6
|
|
+ if (initsock6 >= 0 && bind(initsock6, (struct sockaddr *)&sin6, sizeof(sin6))< 0) {
|
|
+ warn("bind error; the socket is already used");
|
|
+ close(initsock6);
|
|
+ initsock6 = -1;
|
|
+ }
|
|
+#endif
|
|
+ if (initsock < 0
|
|
+#ifdef PF_INET6
|
|
+ && initsock6 < 0
|
|
+#endif
|
|
+ )
|
|
+ exit(1);
|
|
+ if (initsock >= 0 && listen(initsock, MAXQUE) < 0)
|
|
err("listen error; something wrong happened with the socket");
|
|
+#ifdef PF_INET6
|
|
+ if (initsock6 >= 0 && listen(initsock6, MAXQUE) < 0)
|
|
+ err("listen error; something wrong happened with the IPv6 socket");
|
|
+#endif
|
|
if (debug) {
|
|
fprintf(errout, "file descriptor for initsock is %d\n", initsock);
|
|
+#ifdef PF_INET6
|
|
+ fprintf(errout, "file descriptor for initsock6 is %d\n", initsock6);
|
|
+#endif
|
|
fflush(errout);
|
|
}
|
|
}
|
|
@@ -303,8 +363,19 @@
|
|
mkoldjtab(buf);
|
|
}
|
|
|
|
+/* using stdio in signal handler is unsafe */
|
|
+#ifdef __STDC__
|
|
+volatile
|
|
+#endif
|
|
+int reread_requested;
|
|
+
|
|
+RETSIGTYPE req_reread()
|
|
+{
|
|
+ reread_requested = 1;
|
|
+}
|
|
+
|
|
/* 1993/6/5 by kam, re-read dictionary by "INT" signal */
|
|
-RETSIGTYPE reread()
|
|
+void reread()
|
|
{
|
|
if (fclose(jisho) < 0) {
|
|
fprintf(stderr,
|
|
@@ -382,6 +453,10 @@
|
|
code = KANA_END;
|
|
|
|
while ((c = fgetc(jisho)) != EOF) {
|
|
+ if (c == '>') {
|
|
+ fgets(buf, BUFSIZE, jisho);
|
|
+ continue;
|
|
+ }
|
|
target = ((c & 0xff)<< 8) | (fgetc(jisho) & 0xff);
|
|
if (target == STRMARK) {
|
|
fgets(buf, BUFSIZE, jisho);
|
|
@@ -455,15 +530,22 @@
|
|
main_loop()
|
|
{
|
|
fd_set readfds, writefds, exceptfds;
|
|
- fd_set getrfds();
|
|
+ void getrfds();
|
|
struct sockaddr_in from;
|
|
+#ifdef PF_INET6
|
|
+ struct sockaddr_in6 from6;
|
|
+#endif
|
|
int len;
|
|
register int i;
|
|
|
|
FD_ZERO(&writefds);
|
|
FD_ZERO(&exceptfds);
|
|
for(;;) { /* infinite loop; waiting for client's request */
|
|
- readfds = getrfds();
|
|
+ if (reread_requested) {
|
|
+ reread();
|
|
+ reread_requested = 0;
|
|
+ }
|
|
+ getrfds(&readfds);
|
|
if (select(MAXDTAB, &readfds, &writefds, &exceptfds, NULL) < 0) {
|
|
if (errno == EINTR) /* if signal happens */
|
|
continue;
|
|
@@ -474,16 +556,32 @@
|
|
fflush(errout);
|
|
}
|
|
|
|
- if (FD_ISSET(initsock, &readfds)) {
|
|
+ if (initsock >= 0 && FD_ISSET(initsock, &readfds)) {
|
|
len = sizeof(from);
|
|
if ((clientsock[nclients ++] = accept(initsock, &from, &len)) < 0) {
|
|
err("accept error; something wrong happened with the socket");
|
|
}
|
|
- if (nclients >= MAXDTAB - 3 - debug * 2) {
|
|
+ if (nclients >= MAXDTAB - 3
|
|
+#ifdef PF_INET6
|
|
+ -1
|
|
+#endif
|
|
+ - debug * 2) {
|
|
write(clientsock[--nclients], SERVER_FULL, 1);
|
|
close(clientsock[nclients]);
|
|
}
|
|
}
|
|
+#ifdef PF_INET6
|
|
+ if (initsock6 >= 0 && FD_ISSET(initsock6, &readfds)) {
|
|
+ len = sizeof(from6);
|
|
+ if ((clientsock[nclients ++] = accept(initsock6, &from6, &len)) < 0) {
|
|
+ err("accept error; something wrong happened with the socket");
|
|
+ }
|
|
+ if (nclients >= MAXDTAB - 4 - debug * 2) {
|
|
+ write(clientsock[--nclients], SERVER_FULL, 1);
|
|
+ close(clientsock[nclients]);
|
|
+ }
|
|
+ }
|
|
+#endif
|
|
|
|
/* naiive scheduling */
|
|
for (i = 0; i < nclients; i ++)
|
|
@@ -511,20 +609,24 @@
|
|
* get bit pattern of read file descriptor
|
|
*/
|
|
|
|
-fd_set getrfds()
|
|
+void getrfds(rfds)
|
|
+fd_set *rfds;
|
|
{
|
|
- fd_set rfds;
|
|
register int i;
|
|
|
|
- FD_ZERO(&rfds);
|
|
- FD_SET(initsock, &rfds);
|
|
+ FD_ZERO(rfds);
|
|
+ if (initsock >= 0)
|
|
+ FD_SET(initsock, rfds);
|
|
+#ifdef PF_INET6
|
|
+ if (initsock6 >= 0)
|
|
+ FD_SET(initsock6, rfds);
|
|
+#endif
|
|
for (i = 0; i < nclients; i ++)
|
|
- FD_SET(clientsock[i], &rfds);
|
|
- return (rfds);
|
|
+ FD_SET(clientsock[i], rfds);
|
|
}
|
|
|
|
/*
|
|
- * reply to client: linear search
|
|
+ * reply to client: binary search
|
|
*/
|
|
|
|
search(commsock)
|
|
@@ -537,6 +639,7 @@
|
|
int n; /* number of characters from client */
|
|
int sttpnt; /* start point of searching */
|
|
int endpnt; /* end point of searching */
|
|
+ int curpnt; /* current point of searching */
|
|
int errcod = 0; /* error flag */
|
|
int sstyle; /* search style */
|
|
|
|
@@ -645,18 +748,36 @@
|
|
endpnt = jtab1[KANA_END - code + 1];
|
|
}
|
|
}
|
|
- fseek(jisho, sttpnt, 0);
|
|
if (debug)
|
|
- fprintf(stderr, "from %d to %d\n", sttpnt, endpnt);
|
|
+ fprintf(errout, "from %d to %d\n", sttpnt, endpnt);
|
|
|
|
+ for (;;) {
|
|
+ if ((sstyle & 0x4) == 0) { /* binary search? */
|
|
+ curpnt = (sttpnt + endpnt) / 2;
|
|
+ fseek(jisho, curpnt, 0);
|
|
while ((c = fgetc(jisho)) != EOF) {
|
|
+ curpnt++;
|
|
+ if (c == EOL) break;
|
|
+ }
|
|
+ if (c == EOF) break;
|
|
+ if (curpnt >= endpnt) {
|
|
+ fseek(jisho, sttpnt, 0);
|
|
+ sstyle |= 0x4; /* linear search */
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (debug) {fprintf(errout, "%d:%d\t%d\t%d\t", sstyle, sttpnt, curpnt, endpnt);}
|
|
+ c = fgetc(jisho);
|
|
pbuf = &combuf[1]; /* ' ' is end-symbol */
|
|
while (c == *pbuf && c != ' ' && c != EOL) {
|
|
- if (debug) {fprintf(errout, "1:%d:%d:%d:%d:\n", c, *pbuf, ' ', EOL);}
|
|
+/* if (debug) {fprintf(errout, "1:%d:%d:%d:%d:", c, *pbuf, ' ', EOL);}*/
|
|
+ if (debug) {fprintf(errout, "%c", c);}
|
|
c = fgetc(jisho); pbuf++;
|
|
}
|
|
- if (debug) {fprintf(errout, "1:%d:%d:%d:%d:\n", c, *pbuf, ' ', EOL);}
|
|
+/* if (debug) {fprintf(errout, "1:%d:%d:%d:%d:", c, *pbuf, ' ', EOL);}*/
|
|
+ if (debug) {fprintf(errout, "%c", c);}
|
|
if (c == ' ' && (*pbuf == ' ' || *pbuf == '\n')) { /* found */
|
|
+ if (debug) {fprintf(errout, "found\n");}
|
|
if ((errcod = write(commsock, SERVER_FOUND, 1)) >= 0)
|
|
while ((c = fgetc(jisho)) != EOF) {
|
|
*pbuf = c;
|
|
@@ -672,7 +793,18 @@
|
|
}
|
|
return(0);
|
|
}
|
|
- if (comp(*pbuf, c, sstyle)) {
|
|
+ if (debug) {
|
|
+ int ch;
|
|
+
|
|
+ if (c != ' ')
|
|
+ do {
|
|
+ ch = fgetc(jisho);
|
|
+ fprintf(errout, "%c", ch);
|
|
+ } while (ch != ' ' && ch != EOL);
|
|
+ fprintf(errout, "unmatched\n");
|
|
+ }
|
|
+ if (sstyle & 0x4) {
|
|
+ if (comp(*pbuf, c, sstyle&~0x4)) {
|
|
if (debug) {
|
|
fprintf(stderr, "comp break %d \n", ftell(jisho));
|
|
}
|
|
@@ -684,6 +816,12 @@
|
|
if (c == EOL) break;
|
|
}
|
|
if (ftell(jisho) >= endpnt) break;
|
|
+ } else {
|
|
+ if (comp(*pbuf, c, sstyle&~0x4))
|
|
+ endpnt = curpnt;
|
|
+ else
|
|
+ sttpnt = curpnt;
|
|
+ }
|
|
}
|
|
|
|
if ((errcod = write(commsock, SERVER_NOT_FOUND, 1)) >= 0) {
|
|
@@ -724,6 +862,9 @@
|
|
exit(1);
|
|
}
|
|
hentry = gethostbyname(hname);
|
|
+ if (hentry == NULL) {
|
|
+ fprintf(errout, "%s: WARNING: gethostbyname(%s) failed\n", pgmnm, hname);
|
|
+ } else {
|
|
#ifdef NO_ADDR_LIST
|
|
strcat(hname, ":");
|
|
strcat(hname, hentry->h_addr);
|
|
@@ -736,6 +877,7 @@
|
|
strcat(hname, inet_ntoa(*(struct in_addr *)*p++));
|
|
}
|
|
#endif
|
|
+ }
|
|
strcat(hname, ": ");
|
|
}
|
|
|