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.2 2000/08/26 18:27:19 marekm Exp $")
35 #include <sys/types.h>
38 #include "prototypes.h"
45 static const char *progname, *filename, *fileeditname;
46 static int filelocked = 0, createedit = 0;
47 static int (*unlock)(void);
49 /* local function prototypes */
50 static int create_backup_file(FILE *, const char *, struct stat *);
51 static void vipwexit(const char *, int, int);
52 static void vipwedit(const char *, int (*)(void), int (*)(void));
55 create_backup_file(FILE *fp, const char *backup, struct stat *sb)
63 bkfp = fopen(backup, "w");
68 while ((c = getc(fp)) != EOF) {
69 if (putc(c, bkfp) == EOF) break;
72 if (c != EOF || fflush(bkfp)) {
82 ub.actime = sb->st_atime;
83 ub.modtime = sb->st_mtime;
84 if (utime(backup, &ub) ||
85 chmod(backup, sb->st_mode) ||
86 chown(backup, sb->st_uid, sb->st_gid)) {
95 vipwexit(const char *msg, int syserr, int ret)
98 if (filelocked) (*unlock)();
99 if (createedit) unlink(fileeditname);
100 if (msg) fprintf(stderr, "%s: %s", progname, msg);
101 if (syserr) fprintf(stderr, ": %s", strerror(err));
102 fprintf(stderr, _("\n%s: %s is unchanged\n"), progname, filename);
106 #ifndef DEFAULT_EDITOR
107 #define DEFAULT_EDITOR "vi"
111 vipwedit(const char *file, int (*file_lock)(void), int (*file_unlock)(void))
115 struct stat st1, st2;
118 char filebackup[1024], fileedit[1024];
120 snprintf(filebackup, sizeof filebackup, "%s-", file);
121 snprintf(fileedit, sizeof fileedit, "%s.edit", file);
122 unlock = file_unlock;
124 fileeditname = fileedit;
126 if (access(file, F_OK)) vipwexit(file, 1, 1);
127 if (!file_lock()) vipwexit(_("Couldn't lock file"), errno, 5);
130 /* edited copy has same owners, perm */
131 if (stat(file, &st1)) vipwexit(file, 1, 1);
132 if (!(f = fopen(file, "r"))) vipwexit(file, 1, 1);
133 if (create_backup_file(f, fileedit, &st1))
134 vipwexit(_("Couldn't make backup"), errno, 1);
137 editor = getenv("VISUAL");
139 editor = getenv("EDITOR");
141 editor = DEFAULT_EDITOR;
143 if ((pid = fork()) == -1) vipwexit("fork", 1, 1);
146 execlp(editor, editor, fileedit, (char *) 0);
147 fprintf(stderr, "%s: %s: %s\n", progname, editor, strerror(errno));
150 /* use the system() call to invoke the editor so that it accepts
151 command line args in the EDITOR and VISUAL environment vars */
153 buf = (char *) malloc (strlen(editor) + strlen(fileedit) + 2);
154 snprintf(buf, strlen(editor) + strlen(fileedit) + 2, "%s %s",
156 if (system(buf) != 0) {
157 fprintf(stderr, "%s: %s: %s\n", progname, editor, strerror(errno));
165 pid = waitpid(pid, &status, WUNTRACED);
166 if (WIFSTOPPED(status)) {
167 kill(getpid(), SIGSTOP);
168 kill(getpid(), SIGCONT);
173 if (pid == -1 || !WIFEXITED(status) || WEXITSTATUS(status))
174 vipwexit(editor, 1, 1);
176 if (stat(fileedit, &st2)) vipwexit(fileedit, 1, 1);
177 if (st1.st_mtime == st2.st_mtime) vipwexit(0, 0, 0);
179 /* XXX - here we should check fileedit for errors; if there are any,
180 ask the user what to do (edit again, save changes anyway, or quit
181 without saving). Use pwck or grpck to do the check. --marekm */
185 link(file, filebackup);
186 if (rename(fileedit, file) == -1) {
187 fprintf(stderr, _("%s: can't restore %s: %s (your changes are in %s)\n"),
188 progname, file, strerror(errno), fileedit);
197 main(int argc, char **argv)
205 setlocale(LC_ALL, "");
206 bindtextdomain(PACKAGE, LOCALEDIR);
209 progname = ((c = strrchr(*argv, '/')) ? c+1 : *argv);
210 do_vipw = (strcmp(progname, "vigr") != 0);
212 while ((flag = getopt(argc, argv, "ghps")) != EOF) {
227 `vipw' edits /etc/passwd `vipw -s' edits /etc/shadow\n\
228 `vigr' edits /etc/group `vigr -s' edits /etc/gshadow\n\
237 vipwedit(SHADOW_FILE, spw_lock, spw_unlock);
240 vipwedit(PASSWD_FILE, pw_lock, pw_unlock);
245 vipwedit(SGROUP_FILE, sgr_lock, sgr_unlock);
248 vipwedit(GROUP_FILE, gr_lock, gr_unlock);