2 vipw, vigr edit the password or group file
3 with -s will edit shadow or gshadow file
5 Copyright (C) 1997 Guy Maor <maor@ece.utexas.edu>
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 RCSID (PKG_VER "$Id: vipw.c,v 1.7 2004/06/03 00:27:19 kloczek Exp $")
33 #include <sys/types.h>
36 #include "prototypes.h"
42 static const char *progname, *filename, *fileeditname;
43 static int filelocked = 0, createedit = 0;
44 static int (*unlock) (void);
46 /* local function prototypes */
47 static int create_backup_file (FILE *, const char *, struct stat *);
48 static void vipwexit (const char *, int, int);
49 static void vipwedit (const char *, int (*)(void), int (*)(void));
52 create_backup_file (FILE * fp, const char *backup, struct stat *sb)
60 bkfp = fopen (backup, "w");
66 if (fseek(fp, 0, SEEK_SET) == 0)
67 while ((c = getc(fp)) != EOF) {
68 if (putc(c, bkfp) == EOF)
71 if (c != EOF || ferror(fp) || fflush(bkfp)) {
81 ub.actime = sb->st_atime;
82 ub.modtime = sb->st_mtime;
83 if (utime (backup, &ub) ||
84 chmod (backup, sb->st_mode) ||
85 chown (backup, sb->st_uid, sb->st_gid)) {
93 static void vipwexit (const char *msg, int syserr, int ret)
100 unlink (fileeditname);
102 fprintf (stderr, "%s: %s", progname, msg);
104 fprintf (stderr, ": %s", strerror (err));
105 fprintf (stderr, _("\n%s: %s is unchanged\n"), progname, filename);
109 #ifndef DEFAULT_EDITOR
110 #define DEFAULT_EDITOR "vi"
114 vipwedit (const char *file, int (*file_lock) (void),
115 int (*file_unlock) (void))
119 struct stat st1, st2;
122 char filebackup[1024], fileedit[1024];
124 snprintf (filebackup, sizeof filebackup, "%s-", file);
125 snprintf (fileedit, sizeof fileedit, "%s.edit", file);
126 unlock = file_unlock;
128 fileeditname = fileedit;
130 if (access (file, F_OK))
131 vipwexit (file, 1, 1);
133 vipwexit (_("Couldn't lock file"), errno, 5);
136 /* edited copy has same owners, perm */
137 if (stat (file, &st1))
138 vipwexit (file, 1, 1);
139 if (!(f = fopen (file, "r")))
140 vipwexit (file, 1, 1);
141 if (create_backup_file (f, fileedit, &st1))
142 vipwexit (_("Couldn't make backup"), errno, 1);
145 editor = getenv ("VISUAL");
147 editor = getenv ("EDITOR");
149 editor = DEFAULT_EDITOR;
151 if ((pid = fork ()) == -1)
152 vipwexit ("fork", 1, 1);
154 /* use the system() call to invoke the editor so that it accepts
155 command line args in the EDITOR and VISUAL environment vars */
159 (char *) malloc (strlen (editor) + strlen (fileedit) +
161 snprintf (buf, strlen (editor) + strlen (fileedit) + 2,
162 "%s %s", editor, fileedit);
163 if (system (buf) != 0) {
164 fprintf (stderr, "%s: %s: %s\n", progname, editor,
172 pid = waitpid (pid, &status, WUNTRACED);
173 if (WIFSTOPPED (status)) {
174 kill (getpid (), SIGSTOP);
175 kill (getpid (), SIGCONT);
180 if (pid == -1 || !WIFEXITED (status) || WEXITSTATUS (status))
181 vipwexit (editor, 1, 1);
183 if (stat (fileedit, &st2))
184 vipwexit (fileedit, 1, 1);
185 if (st1.st_mtime == st2.st_mtime)
189 * XXX - here we should check fileedit for errors; if there are any,
190 * ask the user what to do (edit again, save changes anyway, or quit
191 * without saving). Use pwck or grpck to do the check. --marekm
196 link (file, filebackup);
197 if (rename (fileedit, file) == -1) {
200 ("%s: can't restore %s: %s (your changes are in %s)\n"),
201 progname, file, strerror (errno), fileedit);
209 int main (int argc, char **argv)
217 setlocale (LC_ALL, "");
218 bindtextdomain (PACKAGE, LOCALEDIR);
219 textdomain (PACKAGE);
221 progname = ((c = strrchr (*argv, '/')) ? c + 1 : *argv);
222 do_vipw = (strcmp (progname, "vigr") != 0);
224 while ((flag = getopt (argc, argv, "ghps")) != EOF) {
239 `vipw' edits /etc/passwd `vipw -s' edits /etc/shadow\n\
240 `vigr' edits /etc/group `vigr -s' edits /etc/gshadow\n\
249 vipwedit (SHADOW_FILE, spw_lock, spw_unlock);
252 vipwedit (PASSWD_FILE, pw_lock, pw_unlock);
256 vipwedit (SGROUP_FILE, sgr_lock, sgr_unlock);
259 vipwedit (GROUP_FILE, gr_lock, gr_unlock);
262 nscd_flush_cache ("passwd");
263 nscd_flush_cache ("group");
265 nscd_flush_cache ("shadow");