2
Copyright (c) 1996, 1997, 1998, 1999, 2001, 2005 Thorsten Kukuk, <kukuk@suse.de>
3
Copyright (c) 1994, 1995, 1996 Olaf Kirch, <okir@monad.swb.de>
5
This file is part of the NYS YP Server.
7
The YP Server is free software; you can redistribute it and/or
8
modify it under the terms of the GNU General Public License
9
version 2 as published by the Free Software Foundation.
11
The NYS YP Server is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
General Public License for more details.
16
You should have received a copy of the GNU General Public
17
License along with the NYS YP Server; see the file COPYING. If
18
not, write to the Free Software Foundation, Inc., 675 Mass Ave,
19
Cambridge, MA 02139, USA. */
25
#include <sys/types.h>
26
#include <sys/socket.h>
27
#include <sys/ioctl.h>
40
#include <rpc/pmap_clnt.h>
41
#if defined(HAVE_RPC_SVC_SOC_H)
42
#include <rpc/svc_soc.h>
45
#if defined(HAVE_GETOPT_H)
56
#define _PATH_VARRUN "/etc/"
58
#define _YPPASSWDD_PIDFILE _PATH_VARRUN"yppasswdd.pid"
63
int solaris_mode = -1;
66
#define xprt_addr(xprt) (svc_getcaller(xprt)->sin_addr)
67
#define xprt_port(xprt) ntohs(svc_getcaller(xprt)->sin_port)
68
void yppasswdprog_1 (struct svc_req *rqstp, SVCXPRT * transp);
69
void reaper (int sig);
71
/*==============================================================*
72
* RPC dispatch function
73
*==============================================================*/
75
yppasswdprog_1 (struct svc_req *rqstp, SVCXPRT * transp)
79
xdrproc_t xdr_argument, xdr_result;
81
switch (rqstp->rq_proc)
84
svc_sendreply (transp, (xdrproc_t) xdr_void, (char *) NULL);
87
case YPPASSWDPROC_UPDATE:
88
xdr_argument = (xdrproc_t) xdr_yppasswd;
89
xdr_result = (xdrproc_t) xdr_int;
93
svcerr_noproc (transp);
96
memset ((char *) &argument, 0, sizeof (argument));
97
if (!svc_getargs (transp, xdr_argument, (caddr_t) &argument))
99
svcerr_decode (transp);
102
result = yppasswdproc_pwupdate_1 (&argument, rqstp);
104
&& !svc_sendreply (transp, (xdrproc_t) xdr_result, (char *)result))
106
svcerr_systemerr (transp);
108
if (!svc_freeargs (transp, xdr_argument, (caddr_t) &argument))
110
log_msg ("unable to free arguments\n");
115
/* Create a pidfile on startup */
117
create_pidfile (void)
119
int fd, left, written;
124
fd = open (_YPPASSWDD_PIDFILE, O_CREAT | O_RDWR,
125
S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
128
log_msg ("cannot create pidfile %s", _YPPASSWDD_PIDFILE);
133
lock.l_type = F_WRLCK;
135
lock.l_whence = SEEK_SET;
138
/* Is the pidfile locked by another ypserv ? */
139
if (fcntl (fd, F_GETLK, &lock) < 0)
141
log_msg ("fcntl error");
145
if (lock.l_type == F_UNLCK)
146
pid = 0; /* false, region is not locked by another proc */
148
pid = lock.l_pid; /* true, return pid of lock owner */
152
log_msg ("rpc.yppasswdd already running (pid %d) - exiting", pid);
159
lock.l_type = F_WRLCK;
161
lock.l_whence = SEEK_SET;
163
if (0 != fcntl (fd, F_SETLK, &lock))
164
log_msg ("cannot lock pidfile");
165
sprintf (pbuf, "%ld\n", (long) getpid ());
166
left = strlen (pbuf);
170
if ((written = write (fd, ptr, left)) <= 0)
180
usage (FILE * fp, int n)
182
fputs ("Usage: rpc.yppasswdd [--debug] [-s shadowfile] [-p passwdfile] [-e chsh|chfn]\n", fp);
183
fputs (" rpc.yppasswdd [--debug] [-D directory] [-e chsh|chfn]\n", fp);
184
fputs (" rpc.yppasswdd [--debug] [-x program |-E program] [-e chsh|chfn]\n", fp);
185
fputs (" rpc.yppasswdd --port number\n", fp);
186
fputs (" rpc.yppasswdd --version\n", fp);
191
sig_child (int sig UNUSED)
193
int save_errno = errno;
195
while (wait3 (NULL, WNOHANG, NULL) > 0)
200
/* Clean up if we quit the program. */
202
sig_quit (int sig UNUSED)
204
pmap_unset (YPPASSWDPROG, YPPASSWDVERS);
205
unlink (_YPPASSWDD_PIDFILE);
211
install_sighandler (void)
215
sigaction (SIGPIPE, NULL, &sa);
216
sa.sa_handler = SIG_IGN;
217
#if !defined(sun) || (defined(sun) && defined(__svr4__))
218
sa.sa_flags |= SA_RESTART;
219
/* The opposite to SA_ONESHOT, do not restore
220
the signal action. This provides behavior
221
compatible with BSD signal semantics. */
223
sigemptyset (&sa.sa_mask);
224
sigaction (SIGPIPE, &sa, NULL);
225
/* Clear up if child exists */
226
sigaction (SIGCHLD, NULL, &sa);
227
#if !defined(sun) || (defined(sun) && defined(__svr4__))
228
sa.sa_flags |= SA_RESTART;
230
sa.sa_handler = sig_child;
231
sigemptyset (&sa.sa_mask);
232
sigaction (SIGCHLD, &sa, NULL);
233
/* If program quits, give ports free. */
234
sigaction (SIGTERM, NULL, &sa);
235
#if !defined(sun) || (defined(sun) && defined(__svr4__))
236
sa.sa_flags |= SA_RESTART;
238
sa.sa_handler = sig_quit;
239
sigemptyset (&sa.sa_mask);
240
sigaction (SIGTERM, &sa, NULL);
242
sigaction (SIGINT, NULL, &sa);
243
#if !defined(sun) || (defined(sun) && defined(__svr4__))
244
sa.sa_flags |= SA_RESTART;
246
sa.sa_handler = sig_quit;
247
sigemptyset (&sa.sa_mask);
248
sigaction (SIGINT, &sa, NULL);
253
main (int argc, char **argv)
256
int my_port = -1, my_socket;
259
/* Initialize logging. */
260
openlog ("rpc.yppasswdd", LOG_PID, LOG_AUTH);
262
/* Parse the command line options and arguments. */
265
int option_index = 0;
266
static struct option long_options[] =
268
{"version", no_argument, NULL, '\255'},
269
{"usage", no_argument, NULL, 'h'},
270
{"help", no_argument, NULL, 'h'},
271
{"execute", required_argument, NULL, 'x'},
272
{"debug", no_argument, NULL, '\254'},
273
{"port", required_argument, NULL, '\253'},
274
{NULL, 0, NULL, '\0'}
277
c=getopt_long (argc, argv, "e:p:s:uhvD:E:x:m", long_options,
284
if (!strcmp (optarg, "chsh"))
286
else if (!strcmp (optarg, "chfn"))
292
if (solaris_mode == 1)
295
path_passwd = optarg;
298
if (solaris_mode == 1)
302
path_shadow = optarg;
306
if (solaris_mode == 0)
309
path_passwd = malloc (strlen (optarg) + 8);
310
sprintf (path_passwd, "%s/passwd", optarg);
312
path_shadow = malloc (strlen (optarg) + 8);
313
sprintf (path_shadow, "%s/shadow", optarg);
317
external_update_program = strdup(optarg);
321
external_update_program = strdup(optarg);
325
if (solaris_mode == 0)
328
/* do nothing for now. We always run make, and we uses the
335
my_port = atoi (optarg);
337
log_msg ("Using port %d\n", my_port);
341
fprintf (stdout, "rpc.yppasswdd - YP server version %s (with CHECKROOT)\n",
343
#else /* NO CHECKROOT */
344
fprintf (stdout, "rpc.yppasswdd - YP server version %s\n",
346
#endif /* CHECKROOT */
348
case '\254': /* --debug */
356
/* No more arguments allowed. */
360
/* Create tmp and .OLD file names for "passwd" */
361
path_passwd_tmp = malloc (strlen (path_passwd) + 5);
362
if (path_passwd_tmp == NULL)
364
log_msg ("rpc.yppasswdd: out of memory\n");
367
sprintf (path_passwd_tmp, "%s.tmp", path_passwd);
368
path_passwd_old = malloc (strlen (path_passwd) + 5);
369
if (path_passwd_old == NULL)
371
log_msg ("rpc.yppasswdd: out of memory\n");
374
sprintf (path_passwd_old, "%s.OLD", path_passwd);
376
/* Create tmp and .OLD file names for "shadow" */
377
path_shadow_tmp = malloc (strlen (path_shadow) + 5);
378
if (path_shadow_tmp == NULL)
380
log_msg ("rpc.yppasswdd: out of memory\n");
383
sprintf (path_shadow_tmp, "%s.tmp", path_shadow);
384
path_shadow_old = malloc (strlen (path_shadow) + 5);
385
if (path_shadow_old == NULL)
387
log_msg ("rpc.yppasswdd: out of memory\n");
390
sprintf (path_shadow_old, "%s.OLD", path_shadow);
391
#endif /* HAVE_GETSPNAM */
396
log_msg ("rpc.yppasswdd - NYS YP server version %s (with CHECKROOT)\n",
398
#else /* NO CHECKROOT */
399
log_msg ("rpc.yppasswdd - NYS YP server version %s\n", VERSION);
400
#endif /* CHECKROOT */
406
/* We first fork off a child. */
407
if ((i = fork ()) > 0)
412
log_msg ("rpc.yppasswdd: cannot fork: %s\n", strerror (errno));
418
log_msg ("rpc.yppasswdd: cannot setsid: %s\n", strerror (errno));
422
if ((i = fork ()) > 0)
427
log_msg ("rpc.yppasswdd: cannot fork: %s\n", strerror (errno));
431
for (i = 0; i < getdtablesize (); ++i)
437
i = open("/dev/null", O_RDWR);
444
/* Register a signal handler to reap children after they terminated */
445
install_sighandler ();
447
/* Create the RPC server */
448
pmap_unset (YPPASSWDPROG, YPPASSWDVERS);
452
struct sockaddr_in s_in;
455
my_socket = socket (AF_INET, SOCK_DGRAM, 0);
458
log_msg ("can not create UDP: %s", strerror (errno));
462
memset ((char *) &s_in, 0, sizeof (s_in));
463
s_in.sin_family = AF_INET;
464
s_in.sin_addr.s_addr = htonl (INADDR_ANY);
465
s_in.sin_port = htons (my_port);
467
result = bind (my_socket, (struct sockaddr *) &s_in,
471
log_msg ("rpc.yppasswdd: can not bind UDP: %s ", strerror (errno));
476
my_socket = RPC_ANYSOCK;
478
transp = svcudp_create (my_socket);
481
log_msg ("cannot create udp service.\n");
484
if (!svc_register (transp, YPPASSWDPROG, YPPASSWDVERS, yppasswdprog_1,
487
log_msg ("unable to register yppaswdd udp service.\n");
493
log_msg ("svc_run returned\n");
494
unlink (_YPPASSWDD_PIDFILE);