Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 7 Sep 2001 15:34:37 -0700 (PDT)
From:      alan@batie.org
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   bin/30424: Generalization of vipw to lock pwdb while being edited by a script
Message-ID:  <200109072234.f87MYbi56103@aggie.rdrop.com>

next in thread | raw e-mail | index | archive | help

>Number:         30424
>Category:       bin
>Synopsis:       Generalization of vipw to lock pwdb while being edited by a script
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Fri Sep 07 15:40:01 PDT 2001
>Closed-Date:
>Last-Modified:
>Originator:     Alan Batie
>Release:        FreeBSD 4.3-STABLE i386
>Organization:
RainDrop Laboratories
>Environment:
System: FreeBSD aggie.rdrop.com 4.3-STABLE FreeBSD 4.3-STABLE #3: Wed Sep 5 13:36:38 PDT 2001 root@aggie.rdrop.com:/usr/src/freebsd/sys/compile/AGORA i386


>Description:
	I have scripts to update accounts, and need to have the password
	file locked while they run to avoid having a user change their
	password at the same time and losing one of the updates.  Since
	vipw already does most of what needs to be done, I've modified it
	so that when invoked as "pw_lock", instead of running vi, it runs
	the specified command, but still does all the locking and database
	updating.
>How-To-Repeat:
	N/A
>Fix:

*** vipw.c.orig	Tue Oct 31 23:06:55 2000
--- vipw.c	Mon Nov  6 19:10:09 2000
***************
*** 57,65 ****
--- 57,69 ----
  
  #include "pw_util.h"
  
+ #define PROG_VIPW	"vipw"
+ #define PROG_PWLOCK	"pw_lock"
+ 
  extern char *mppath;
  extern char *masterpasswd;
  char *tempname;
+ char *progname;
  
  void	copyfile __P((int, int));
  static void	usage __P((void));
***************
*** 73,78 ****
--- 77,90 ----
  	struct stat begin, end;
  	int ch;
  
+ 	/*  Strip the path, if present, from the program name  */
+ 	progname = strrchr(argv[0], '/');
+ 	if (progname == NULL) {
+ 	    progname = argv[0];
+ 	} else {
+ 	    progname++;		/*  Skip past the '/'  */
+ 	}
+ 
  	while ((ch = getopt(argc, argv, "d:")) != -1)
  		switch (ch) {
  		case 'd':
***************
*** 97,104 ****
  	argc -= optind;
  	argv += optind;
  
! 	if (argc != 0)
  		usage();
  
  	pw_init();
  	pfd = pw_lock();
--- 109,117 ----
  	argc -= optind;
  	argv += optind;
  
! 	if (argc != 0 && strcmp(progname, PROG_VIPW) == 0) {
  		usage();
+ 	}
  
  	pw_init();
  	pfd = pw_lock();
***************
*** 111,117 ****
  	for (;;) {
  		if (stat(tempname, &begin))
  			pw_error(tempname, 1, 1);
! 		pw_edit(0);
  		if (stat(tempname, &end))
  			pw_error(tempname, 1, 1);
  		if (begin.st_mtime == end.st_mtime) {
--- 124,137 ----
  	for (;;) {
  		if (stat(tempname, &begin))
  			pw_error(tempname, 1, 1);
! 		if (strcmp(progname, PROG_VIPW) == 0) {
! 			pw_edit(0);
! 		} else if (strcmp(progname, PROG_PWLOCK) == 0) {
! 			pw_runcmd(argv);
! 		} else {
! 			warnx("Unknown invocation mode '%s'", progname);
! 			pw_error((char *)NULL, 0, 0);
! 		}
  		if (stat(tempname, &end))
  			pw_error(tempname, 1, 1);
  		if (begin.st_mtime == end.st_mtime) {
*** pw_util.h.org	Sun Nov  5 12:10:42 2000
--- pw_util.h	Sun Nov  5 12:28:21 2000
***************
*** 40,42 ****
--- 40,43 ----
  int	pw_mkdb __P((char *));
  void	pw_prompt __P((void));
  int	pw_tmp __P((void));
+ int	pw_runcmd __P((char **argv));
*** pw_util.c.org	Sun Nov  5 12:08:15 2000
--- pw_util.c	Mon Nov  6 19:24:53 2000
***************
*** 260,262 ****
--- 260,290 ----
  	(void)unlink(tempname);
  	exit(eval);
  }
+ 
+ int
+ pw_runcmd(char **argv)
+ {
+ 	union wait pstat;
+ 	pid_t pid;
+ 	char *progname;
+ 
+ 	/*  Strip the path, if present, from the program name  */
+ 	progname = strrchr(argv[0], '/');
+ 	if (progname == NULL) {
+ 	    progname = argv[0];
+ 	} else {
+ 	    progname++;		/*  Skip past the '/'  */
+ 	}
+ 
+ 	if (!(pid = vfork())) {
+ 		execl(argv[0], progname, tempname, (char *)NULL);
+ 		warn("Command '%s' failed", argv[0]);
+ 		pw_error((char *)NULL, 0, 0);
+ 	}
+ 	pid = waitpid(pid, (int *)&pstat, 0);
+ 	if (pid == -1 || pstat.w_status) {
+ 		return(0);
+ 	}
+ 	(void)printf("%s: done\n", argv[0]);
+ 	return(1);
+ }
*** Makefile.orig	Fri Sep  7 15:08:10 2001
--- Makefile	Fri Sep  7 15:08:54 2001
***************
*** 2,7 ****
--- 2,8 ----
  # $FreeBSD: src/usr.sbin/vipw/Makefile,v 1.2.14.1 2001/04/25 12:11:09 ru Exp $
  
  PROG=	vipw
+ LINKS=	${BINDIR}/vipw ${BINDIR}/pw_lock
  SRCS=	pw_util.c vipw.c
  MAN=	vipw.8
  
*** vipw.8.orig	Fri Sep  7 15:10:22 2001
--- vipw.8	Fri Sep  7 15:22:57 2001
***************
*** 41,46 ****
--- 41,48 ----
  .Sh SYNOPSIS
  .Nm
  .Op Fl d Ar directory
+ .Nm pw_lock
+ .Ar command arg ...
  .Sh DESCRIPTION
  .Nm Vipw
  edits the password file after setting the appropriate locks,
***************
*** 83,88 ****
--- 85,95 ----
  at very large sites could take several minutes.  Until this update
  is completed, the password file is unavailable for other updates
  and the new information is not available to programs.
+ .Pp
+ If invoked as
+ .Nm pw_lock
+ , the user database is locked, the command is run, and then the user
+ database is updated as above.
  .Sh ENVIRONMENT
  If the following environment variable exists it will be utilized by
  .Nm :
>Release-Note:
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200109072234.f87MYbi56103>