$NetBSD: patch-af,v 1.2 2010/07/17 08:57:18 obache Exp $ --- skkserv/skkserv.c.orig 1997-01-20 19:16:36.000000000 +0000 +++ skkserv/skkserv.c @@ -100,8 +100,10 @@ #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 @@ -121,6 +123,9 @@ int format; /* 0 (old-style) / non-0 (n 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 @@ char *argv[]; 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 @@ char *argv[]; 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 @@ char *argv[]; 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 @@ char *argv[]; 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 @@ showusage() 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 @@ mksock() 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 @@ mkjtab() 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, @@ -455,15 +526,22 @@ mknewjtab() 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 +552,32 @@ main_loop() 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,16 +605,20 @@ main_loop() * 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); } /* @@ -724,6 +822,9 @@ set_hname() 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 +837,7 @@ set_hname() strcat(hname, inet_ntoa(*(struct in_addr *)*p++)); } #endif + } strcat(hname, ": "); }