freebsd-src/gnu/usr.sbin/ypserv/yp_svc.c
Bill Paul 76064c01e5 Updates, fixes and cleanups -- oh my.
In ypserv:

yp_svc.c:
- small signal handler tweak (hopefully the last): just use sigemptyset()
to clear sa_mask.

Makefile.yp:
- Let the user specify the location of master.passwd when updating
maps (e.g. make MASTER_PASSWD=/some/path/to/master.passwd). Editing
the file to change the location of master.passwd still works. This
is mostly to let yppassswdd specify the name of the master.passwd
file itself.

In yppasswdd:

yppasswdd.c:
- Roll in some minor changes (mostly casts) from Olaf Kirch's latest
yppasswd package release (version 0.7).
- Use daemon() instead of doing all the deamonizing gruntwork ourselves.
- Call pw_init() after daemonizing ourselves. pw_init() sets up some
resource limits and blocks some signals for us. We used to do this before
every password change, but there's really no point in calling it more
than once during the life of the program.
- Change install_reaper() so that we can use it to de-install the SIGCHLD
handler if we need to (and we do in pw_mkdb() -- this is what I get for
splicing code from two different programs together).
- Use sigemptyset(&act.sa_mask) rather than act.sa_mask = 0: the latter is
decidedly non-portable. (In IRIX, HP-UX and Solaris, sigset_t is an
array of longs, not an int.)

update.c:
- Roll in change from new version (check that we're not modifying an NIS
entry in validate_args()).
- Get rid of call to pw_init() (moved to yppasswdd.c).
- Check return values from pw_util routines and return error status to
yppasswd clients if there's a problem.
- Straighten out password file copying mechanism a little. Keep a grip
on the original password file rather than summarily overwriting it so
that we can restore everything if we fail to fork() a process to update
the NIS maps.
- Pass the name of the password template file (specified with -m or
/etc/master.passwd by default) to the yppwupdate script, which in
turn should now pass it to /var/yp/Makefile.

pw_util.c:
- Nuke the pw_edit() and pw_prompt() functions -- we don't need them.
- Change all warn()s, warnx()s and err()s to syslog()s.
- Make sure we return error status to caller rather than bailing out
in pw_lock() and pw_tmp().
- Don't block SIGTERM in pw_init() (by ignoring SIGTERM, we prevent
yppasswdd from being shut down cleanly).
- Don't let pw_error() exit. (This stuff was stolen from chpass and vipw
which are interactive programs; it's okay to let pw_error() bail out
for these programs, but not in a daemon like yppasswdd).
- Fix signal handling in pw_mkdb (we need to temporarily de-install the
SIGCHLD handler so that we can wait on the pwd_mkdb child ourselves).

pw_copy.c:
- Change all warn()s, warnx()s and err()s to syslog()s.
- Add a bunch of returns() and make pw_copy() return and int ( 0 on success,
-1 on failure) so that update.c can flag errors properly.
- Return -1 after calling pw_error() to signal failures rather than
relying on pw_error() to bail out.
- Abort copying if we discover that we've been asked to change an entry
for a user that exists in the NIS passwd maps but not in the master.passwd
template file. This can happen if the passwd maps and the template file
fall out of sync with each other (or if somebody tries to spoof
us). The old behavior was to create add the entry to the password file,
which yppasswdd should not do under any circumstances.

Makefile:
- update VERSION to 0.7

yppasswdd.8:
- fix typo (forgot a carriage return somewhere)
- remove bogus reference to pwunconv(8) which FreeBSD doesn't have.
- bump version from 0.5 to 0.7
- Reflect changes in password file handling.

yppwupdate:
- Log map rebuilds to /var/yp/ypupdate.log.
- Pass the name of the template password file to /var/yp/Makefile as
$MASTER_PASSWD.
1995-07-19 17:44:41 +00:00

431 lines
11 KiB
C

/*
* And thus spoke RPCGEN:
* Please do not edit this file.
* It was generated using rpcgen.
*
* And thus replied Lpd@NannyMUD:
* Who cares? :-) /Peter Eriksson <pen@signum.se>
*
* $Id: yp_svc.c,v 1.5 1995/07/08 21:42:59 ats Exp $
*/
#include "system.h"
#include "yp.h"
#include <stdio.h>
#include <stdlib.h>
#include <rpc/pmap_clnt.h>
#include <string.h>
#include <memory.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <syslog.h>
#include <errno.h>
#include <paths.h>
#include <signal.h>
extern int errno;
extern void Perror __P((char *, ...));
extern void my_svc_run __P((void));
extern void reapchild __P((int));
#ifdef __STDC__
#define SIG_PF void(*)(int)
#endif
static void
ypprog_2(struct svc_req *rqstp, register SVCXPRT *transp)
{
union {
domainname ypproc_domain_2_arg;
domainname ypproc_domain_nonack_2_arg;
ypreq_key ypproc_match_2_arg;
ypreq_key ypproc_first_2_arg;
ypreq_key ypproc_next_2_arg;
ypreq_xfr ypproc_xfr_2_arg;
ypreq_nokey ypproc_all_2_arg;
ypreq_nokey ypproc_master_2_arg;
ypreq_nokey ypproc_order_2_arg;
domainname ypproc_maplist_2_arg;
} argument;
char *result;
xdrproc_t __xdr_argument, __xdr_result;
char *(*local)(char *, struct svc_req *);
switch (rqstp->rq_proc) {
case YPPROC_NULL:
__xdr_argument = (xdrproc_t) xdr_void;
__xdr_result = (xdrproc_t) xdr_void;
local = (char *(*)(char *, struct svc_req *)) ypproc_null_2_svc;
break;
case YPPROC_DOMAIN:
__xdr_argument = (xdrproc_t) __xdr_domainname;
__xdr_result = (xdrproc_t) xdr_bool;
local = (char *(*)(char *, struct svc_req *)) ypproc_domain_2_svc;
break;
case YPPROC_DOMAIN_NONACK:
__xdr_argument = (xdrproc_t) __xdr_domainname;
__xdr_result = (xdrproc_t) xdr_bool;
local = (char *(*)(char *, struct svc_req *)) ypproc_domain_nonack_2_svc;
break;
case YPPROC_MATCH:
__xdr_argument = (xdrproc_t) __xdr_ypreq_key;
__xdr_result = (xdrproc_t) __xdr_ypresp_val;
local = (char *(*)(char *, struct svc_req *)) ypproc_match_2_svc;
break;
case YPPROC_FIRST:
#if 0 /* Bug in Sun's yp.x RPC prototype file */
__xdr_argument = (xdrproc_t) __xdr_ypreq_key;
#else
__xdr_argument = (xdrproc_t) __xdr_ypreq_nokey;
#endif
__xdr_result = (xdrproc_t) __xdr_ypresp_key_val;
local = (char *(*)(char *, struct svc_req *)) ypproc_first_2_svc;
break;
case YPPROC_NEXT:
__xdr_argument = (xdrproc_t) __xdr_ypreq_key;
__xdr_result = (xdrproc_t) __xdr_ypresp_key_val;
local = (char *(*)(char *, struct svc_req *)) ypproc_next_2_svc;
break;
case YPPROC_XFR:
__xdr_argument = (xdrproc_t) __xdr_ypreq_xfr;
__xdr_result = (xdrproc_t) __xdr_ypresp_xfr;
local = (char *(*)(char *, struct svc_req *)) ypproc_xfr_2_svc;
break;
case YPPROC_CLEAR:
__xdr_argument = (xdrproc_t) xdr_void;
__xdr_result = (xdrproc_t) xdr_void;
local = (char *(*)(char *, struct svc_req *)) ypproc_clear_2_svc;
break;
case YPPROC_ALL:
__xdr_argument = (xdrproc_t) __xdr_ypreq_nokey;
__xdr_result = (xdrproc_t) __xdr_ypresp_all;
local = (char *(*)(char *, struct svc_req *)) ypproc_all_2_svc;
break;
case YPPROC_MASTER:
__xdr_argument = (xdrproc_t) __xdr_ypreq_nokey;
__xdr_result = (xdrproc_t) __xdr_ypresp_master;
local = (char *(*)(char *, struct svc_req *)) ypproc_master_2_svc;
break;
case YPPROC_ORDER:
__xdr_argument = (xdrproc_t) __xdr_ypreq_nokey;
__xdr_result = (xdrproc_t) __xdr_ypresp_order;
local = (char *(*)(char *, struct svc_req *)) ypproc_order_2_svc;
break;
case YPPROC_MAPLIST:
__xdr_argument = (xdrproc_t) __xdr_domainname;
__xdr_result = (xdrproc_t) __xdr_ypresp_maplist;
local = (char *(*)(char *, struct svc_req *)) ypproc_maplist_2_svc;
break;
default:
svcerr_noproc(transp);
return;
}
(void) memset((char *)&argument, 0, sizeof (argument));
if (!svc_getargs(transp, __xdr_argument, (caddr_t) &argument)) {
svcerr_decode(transp);
return;
}
result = (*local)((char *)&argument, rqstp);
if (result != NULL && !svc_sendreply(transp, __xdr_result, result)) {
svcerr_systemerr(transp);
}
if (!svc_freeargs(transp, __xdr_argument, (caddr_t) &argument)) {
fprintf(stderr, "unable to free arguments");
exit(1);
}
return;
}
#if 0
static void
yppush_xfrrespprog_1(struct svc_req *rqstp, register SVCXPRT *transp)
{
union {
int fill;
} argument;
char *result;
xdrproc_t __xdr_argument, __xdr_result;
char *(*local)(char *, struct svc_req *);
switch (rqstp->rq_proc) {
case YPPUSHPROC_NULL:
__xdr_argument = (xdrproc_t) xdr_void;
__xdr_result = (xdrproc_t) xdr_void;
local = (char *(*)(char *, struct svc_req *)) yppushproc_null_1_svc;
break;
case YPPUSHPROC_XFRRESP:
__xdr_argument = (xdrproc_t) xdr_void;
__xdr_result = (xdrproc_t) __xdr_yppushresp_xfr;
local = (char *(*)(char *, struct svc_req *)) yppushproc_xfrresp_1_svc;
break;
default:
svcerr_noproc(transp);
return;
}
(void) memset((char *)&argument, 0, sizeof (argument));
if (!svc_getargs(transp, __xdr_argument, (caddr_t) &argument)) {
svcerr_decode(transp);
return;
}
result = (*local)((char *)&argument, rqstp);
if (result != NULL && !svc_sendreply(transp, __xdr_result, result)) {
svcerr_systemerr(transp);
}
if (!svc_freeargs(transp, __xdr_argument, (caddr_t) &argument)) {
fprintf(stderr, "unable to free arguments");
exit(1);
}
return;
}
static void
ypbindprog_2(struct svc_req *rqstp, register SVCXPRT *transp)
{
union {
domainname ypbindproc_domain_2_arg;
ypbind_setdom ypbindproc_setdom_2_arg;
} argument;
char *result;
xdrproc_t __xdr_argument, __xdr_result;
char *(*local)(char *, struct svc_req *);
switch (rqstp->rq_proc) {
case YPBINDPROC_NULL:
__xdr_argument = (xdrproc_t) xdr_void;
__xdr_result = (xdrproc_t) xdr_void;
local = (char *(*)(char *, struct svc_req *)) ypbindproc_null_2_svc;
break;
case YPBINDPROC_DOMAIN:
__xdr_argument = (xdrproc_t) __xdr_domainname;
__xdr_result = (xdrproc_t) __xdr_ypbind_resp;
local = (char *(*)(char *, struct svc_req *)) ypbindproc_domain_2_svc;
break;
case YPBINDPROC_SETDOM:
__xdr_argument = (xdrproc_t) __xdr_ypbind_setdom;
__xdr_result = (xdrproc_t) xdr_void;
local = (char *(*)(char *, struct svc_req *)) ypbindproc_setdom_2_svc;
break;
default:
svcerr_noproc(transp);
return;
}
(void) memset((char *)&argument, 0, sizeof (argument));
if (!svc_getargs(transp, __xdr_argument, (caddr_t) &argument)) {
svcerr_decode(transp);
return;
}
result = (*local)((char *)&argument, rqstp);
if (result != NULL && !svc_sendreply(transp, __xdr_result, result)) {
svcerr_systemerr(transp);
}
if (!svc_freeargs(transp, __xdr_argument, (caddr_t) &argument)) {
fprintf(stderr, "unable to free arguments");
exit(1);
}
return;
}
#endif
extern int debug_flag;
extern int dns_flag;
#ifndef _PATH_YP
#define _PATH_YP "/var/yp"
#endif
char *path_ypdb = _PATH_YP;
char *progname;
int main(int argc, char **argv)
{
register SVCXPRT *transp;
int i;
int my_port = -1;
int my_socket;
struct sockaddr_in socket_address;
int result;
int sunos_4_kludge = 0;
struct sigaction sa;
progname = strrchr (argv[0], '/');
if (progname == (char *) NULL)
progname = argv[0];
else
progname++;
openlog(progname, LOG_PID, TCPW_FACILITY);
for (i = 1; i < argc && argv[i][0] == '-'; i++)
{
if (strcmp(argv[i], "-debug") == 0 || strcmp(argv[i], "-d") == 0)
debug_flag = 1;
else if (strcmp(argv[i], "-dns") == 0 || strcmp(argv[i], "-b") == 0)
dns_flag = 1;
else if ((argv[i][1] == 'p') && (argv[i][2] >= '0') && (argv[i][2] <= '9'))
my_port = atoi(argv[i] + 2);
else if (strcmp(argv[i], "-k") == 0)
sunos_4_kludge = 1;
else
{
fprintf(stderr, "%s: Unknown command line switch: %s\n",
progname,
argv[i]);
exit(1);
}
}
if (!debug_flag)
if(daemon(0,0))
{
perror("daemon()");
exit (1);
}
if (debug_flag)
Perror("[Welcome to the NYS YP Server, version 0.13]\n");
if (i < argc)
{
path_ypdb = argv[i];
if (debug_flag)
Perror("Using database directory: %s\n", path_ypdb);
}
/* Change current directory to database location */
if (chdir(path_ypdb) < 0)
{
Perror("%s: chdir: %", argv[0], strerror(errno));
exit(1);
}
/*
* Ignore SIGPIPEs. They can hurt us if someone does a ypcat
* and then hits CTRL-C before it terminates.
*/
sigaction(SIGPIPE, NULL, &sa);
sa.sa_handler = SIG_IGN;
sa.sa_flags |= SA_RESTART;
sigemptyset(&sa.sa_mask);
sigaction(SIGPIPE, &sa, NULL);
sigaction(SIGCHLD, NULL, &sa);
sa.sa_flags |= SA_RESTART;
sa.sa_handler = reapchild;
sigemptyset(&sa.sa_mask);
sigaction(SIGCHLD, &sa, NULL);
(void) pmap_unset(YPPROG, YPVERS);
if (sunos_4_kludge)
(void) pmap_unset(YPPROG, 1);
if (my_port >= 0)
{
my_socket = socket (AF_INET, SOCK_DGRAM, 0);
if (my_socket < 0)
{
Perror("%s: can not create UDP: %s",
progname, strerror(errno));
exit (1);
}
socket_address.sin_family = AF_INET;
socket_address.sin_addr.s_addr = htonl (INADDR_ANY);
socket_address.sin_port = htons (my_port);
result = bind (my_socket, (struct sockaddr *) &socket_address,
sizeof (socket_address));
if (result < 0)
{
Perror("%s: can not create UDP: %s",
progname, strerror(errno));
exit (1);
}
}
else
my_socket = RPC_ANYSOCK;
transp = svcudp_create(my_socket);
if (transp == NULL) {
Perror("cannot create udp service.");
exit(1);
}
if (!svc_register(transp, YPPROG, YPVERS, ypprog_2, IPPROTO_UDP)) {
Perror("unable to register (YPPROG, YPVERS, udp).");
exit(1);
}
if (sunos_4_kludge) {
/*
** This is just to make us reply to YP version 1 calls which SunOS 4's
** ypbind seems to insist on finding. If someone _really_ tries to
** use this the they will probably be bitten - _hard_, since I haven't
** got the faintest idea on how the XDR calls for YP version 1 should
** look like. The Domain_NoNack call seems to be compatible though :-)
*/
if (!svc_register(transp, YPPROG, 1, ypprog_2, IPPROTO_UDP)) {
fprintf(stderr, "unable to register (YPPROG, 1, udp).");
exit(1);
}
}
if (my_port >= 0)
{
my_socket = socket (AF_INET, SOCK_STREAM, 0);
if (my_socket < 0)
{
Perror("%s: can not create TCP: %s",
progname, strerror(errno));
exit (1);
}
socket_address.sin_family = AF_INET;
socket_address.sin_addr.s_addr = htonl (INADDR_ANY);
socket_address.sin_port = htons (my_port);
result = bind (my_socket, (struct sockaddr *) &socket_address,
sizeof (socket_address));
if (result < 0)
{
Perror("%s: can not create TCP: %s",
progname, strerror(errno));
exit (1);
}
}
else
my_socket = RPC_ANYSOCK;
transp = svctcp_create(my_socket, 0, 0);
if (transp == NULL) {
Perror("%s: cannot create tcp service\n", progname);
exit(1);
}
if (!svc_register(transp, YPPROG, YPVERS, ypprog_2, IPPROTO_TCP)) {
Perror("%s: unable to register (YPPROG, YPVERS, tcp)\n", progname);
exit(1);
}
my_svc_run();
Perror("svc_run returned");
exit(1);
/* NOTREACHED */
}