summaryrefslogtreecommitdiffstats
path: root/lib/libutil/pw_util.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libutil/pw_util.c')
-rw-r--r--lib/libutil/pw_util.c57
1 files changed, 44 insertions, 13 deletions
diff --git a/lib/libutil/pw_util.c b/lib/libutil/pw_util.c
index 5eae280..5cd27b1 100644
--- a/lib/libutil/pw_util.c
+++ b/lib/libutil/pw_util.c
@@ -406,22 +406,43 @@ pw_make(const struct passwd *pw)
pw->pw_passwd, (uintmax_t)pw->pw_uid, (uintmax_t)pw->pw_gid,
pw->pw_class, (uintmax_t)pw->pw_change, (uintmax_t)pw->pw_expire,
pw->pw_gecos, pw->pw_dir, pw->pw_shell);
- return line;
+ return (line);
}
/*
- * Copy password file from one descriptor to another, replacing or adding
- * a single record on the way.
+ * Make a passwd line (in v7 format) out of a struct passwd
+ */
+char *
+pw_make_v7(const struct passwd *pw)
+{
+ char *line;
+
+ asprintf(&line, "%s:*:%ju:%ju:%s:%s:%s", pw->pw_name,
+ (uintmax_t)pw->pw_uid, (uintmax_t)pw->pw_gid,
+ pw->pw_gecos, pw->pw_dir, pw->pw_shell);
+ return (line);
+}
+
+/*
+ * Copy password file from one descriptor to another, replacing, deleting
+ * or adding a single record on the way.
*/
int
pw_copy(int ffd, int tfd, const struct passwd *pw, struct passwd *old_pw)
{
char buf[8192], *end, *line, *p, *q, *r, t;
struct passwd *fpw;
+ const struct passwd *spw;
size_t len;
int eof, readlen;
- if ((line = pw_make(pw)) == NULL)
+ spw = pw;
+ if (pw == NULL) {
+ line = NULL;
+ if (old_pw == NULL)
+ return (-1);
+ spw = old_pw;
+ } else if ((line = pw_make(pw)) == NULL)
return (-1);
eof = 0;
@@ -489,7 +510,7 @@ pw_copy(int ffd, int tfd, const struct passwd *pw, struct passwd *old_pw)
*/
*q = t;
- if (fpw == NULL || strcmp(fpw->pw_name, pw->pw_name) != 0) {
+ if (fpw == NULL || fpw->pw_uid != spw->pw_uid) {
/* nope */
if (fpw != NULL)
free(fpw);
@@ -506,11 +527,15 @@ pw_copy(int ffd, int tfd, const struct passwd *pw, struct passwd *old_pw)
}
free(fpw);
- /* it is, replace it */
- len = strlen(line);
- if (write(tfd, line, len) != (int)len)
- goto err;
-
+ /* it is, replace or remove it */
+ if (line != NULL) {
+ len = strlen(line);
+ if (write(tfd, line, len) != (int)len)
+ goto err;
+ } else {
+ /* when removed, avoid the \n */
+ q++;
+ }
/* we're done, just copy the rest over */
for (;;) {
if (write(tfd, q, end - q) != end - q)
@@ -528,16 +553,22 @@ pw_copy(int ffd, int tfd, const struct passwd *pw, struct passwd *old_pw)
goto done;
}
- /* if we got here, we have a new entry */
+ /* if we got here, we didn't find the old entry */
+ if (line == NULL) {
+ errno = ENOENT;
+ goto err;
+ }
len = strlen(line);
if ((size_t)write(tfd, line, len) != len ||
write(tfd, "\n", 1) != 1)
goto err;
done:
- free(line);
+ if (line != NULL)
+ free(line);
return (0);
err:
- free(line);
+ if (line != NULL)
+ free(line);
return (-1);
}
OpenPOWER on IntegriCloud