edgroup.c revision 50479
1275970Scy/*- 2275970Scy * Copyright (C) 1996 3275970Scy * David L. Nugent. All rights reserved. 4275970Scy * 5275970Scy * Redistribution and use in source and binary forms, with or without 6275970Scy * modification, are permitted provided that the following conditions 7275970Scy * are met: 8275970Scy * 1. Redistributions of source code must retain the above copyright 9275970Scy * notice, this list of conditions and the following disclaimer. 10275970Scy * 2. Redistributions in binary form must reproduce the above copyright 11275970Scy * notice, this list of conditions and the following disclaimer in the 12275970Scy * documentation and/or other materials provided with the distribution. 13275970Scy * 14275970Scy * THIS SOFTWARE IS PROVIDED BY DAVID L. NUGENT AND CONTRIBUTORS ``AS IS'' AND 15275970Scy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16275970Scy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17275970Scy * ARE DISCLAIMED. IN NO EVENT SHALL DAVID L. NUGENT OR CONTRIBUTORS BE LIABLE 18275970Scy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19275970Scy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20275970Scy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21275970Scy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22275970Scy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23275970Scy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24275970Scy * SUCH DAMAGE. 25275970Scy */ 26275970Scy 27275970Scy#ifndef lint 28275970Scystatic const char rcsid[] = 29275970Scy "$FreeBSD: head/usr.sbin/pw/edgroup.c 50479 1999-08-28 01:35:59Z peter $"; 30275970Scy#endif /* not lint */ 31275970Scy 32275970Scy#include <stdio.h> 33275970Scy#include <stdlib.h> 34275970Scy#include <string.h> 35275970Scy#include <unistd.h> 36275970Scy#include <stdarg.h> 37275970Scy#include <sys/types.h> 38275970Scy#include <sys/stat.h> 39275970Scy#include <pwd.h> 40275970Scy#include <grp.h> 41275970Scy#include <fcntl.h> 42275970Scy#include <sys/param.h> 43275970Scy#include <ctype.h> 44275970Scy 45275970Scy#include "pwupd.h" 46275970Scy 47275970Scystatic int 48275970Scyisingroup(char const * name, char **mem) 49275970Scy{ 50275970Scy int i; 51275970Scy 52275970Scy for (i = 0; mem[i] != NULL; i++) 53275970Scy if (strcmp(name, mem[i]) == 0) 54275970Scy return i; 55275970Scy return -1; 56275970Scy} 57275970Scy 58275970Scyint 59275970Scyeditgroups(char *name, char **groups) 60275970Scy{ 61275970Scy int rc = 0; 62275970Scy int infd; 63275970Scy char groupfile[MAXPATHLEN]; 64275970Scy char grouptmp[MAXPATHLEN]; 65275970Scy 66275970Scy strncpy(groupfile, getgrpath(_GROUP), MAXPATHLEN - 5); 67275970Scy groupfile[MAXPATHLEN - 5] = '\0'; 68275970Scy strcpy(grouptmp, groupfile); 69275970Scy strcat(grouptmp, ".new"); 70275970Scy 71275970Scy if ((infd = open(groupfile, O_RDWR | O_CREAT, 0644)) != -1) { 72275970Scy FILE *infp; 73275970Scy 74275970Scy if ((infp = fdopen(infd, "r+")) == NULL) 75275970Scy close(infd); 76275970Scy else { 77275970Scy int outfd; 78275970Scy 79275970Scy if ((outfd = open(grouptmp, O_RDWR | O_CREAT | O_TRUNC | O_EXLOCK, 0644)) != -1) { 80275970Scy FILE *outfp; 81275970Scy 82275970Scy if ((outfp = fdopen(outfd, "w+")) == NULL) 83275970Scy close(outfd); 84275970Scy else { 85275970Scy int linelen = PWBUFSZ; 86275970Scy int outlen = PWBUFSZ; 87275970Scy int memlen = 200; /* Arbitrary */ 88275970Scy char *line = malloc(linelen); 89275970Scy char *outl = malloc(outlen); 90275970Scy char **mems = malloc(memlen * sizeof(char *)); 91275970Scy int namlen = strlen(name); 92275970Scy 93275970Scy if (line == NULL || outl == NULL || mems == NULL) { 94275970Scy mem_abort: 95275970Scy rc = 0; 96275970Scy } else { 97275970Scy while (fgets(line, linelen, infp) != NULL) { 98275970Scy char *p; 99275970Scy int l; 100275970Scy 101275970Scy while ((p = strchr(line, '\n')) == NULL) 102275970Scy { 103275970Scy if (extendline(&line, &linelen, linelen + PWBUFSZ) == -1) { 104275970Scy goto mem_abort; 105275970Scy } 106275970Scy l = strlen(line); 107275970Scy if (fgets(line + l, linelen - l, infp) == NULL) 108275970Scy break; /* No newline terminator on last line */ 109275970Scy } 110275970Scy l = strlen(line) + namlen + 1; 111275970Scy if (extendline(&outl, &outlen, l) == -1) { 112275970Scy goto mem_abort; 113275970Scy } 114275970Scy if (*line == '#') 115275970Scy strcpy(outl, line); 116275970Scy else if (*line == '\n') 117275970Scy *outl = '\0'; 118275970Scy else { 119275970Scy int i, 120275970Scy mno = 0; 121275970Scy char *cp = line; 122275970Scy char const *sep = ":\n"; 123275970Scy struct group grp; 124275970Scy 125275970Scy memset(&grp, 0, sizeof grp); 126275970Scy for (i = 0; (p = strsep(&cp, sep)) != NULL; i++) { 127275970Scy switch (i) { 128275970Scy case 0: /* Group name */ 129275970Scy grp.gr_name = p; 130275970Scy break; 131275970Scy case 1: /* Group password */ 132275970Scy grp.gr_passwd = p; 133275970Scy break; 134275970Scy case 2: /* Group id */ 135275970Scy grp.gr_gid = atoi(p); 136275970Scy break; 137275970Scy case 3: /* Member list */ 138275970Scy cp = p; 139275970Scy sep = ",\n"; 140275970Scy break; 141275970Scy default: /* Individual members */ 142275970Scy if (*p) { 143275970Scy if (extendarray(&mems, &memlen, mno + 2) == -1) { 144275970Scy goto mem_abort; 145275970Scy } 146275970Scy mems[mno++] = p; 147275970Scy } 148275970Scy break; 149275970Scy } 150275970Scy } 151275970Scy if (i < 2) /* Bail out - insufficient fields */ 152275970Scy continue; 153275970Scy 154275970Scy grp.gr_mem = mems; 155275970Scy for (i = mno; i < memlen; i++) 156275970Scy mems[i] = NULL; 157275970Scy 158275970Scy /* 159275970Scy * Delete from group, or add to group? 160275970Scy */ 161275970Scy if (groups == NULL || isingroup(grp.gr_name, groups) == -1) { /* Delete */ 162275970Scy int idx; 163275970Scy 164275970Scy while ((idx = isingroup(name, mems)) != -1) { 165275970Scy for (i = idx; i < (memlen - 1); i++) 166275970Scy mems[i] = mems[i + 1]; 167275970Scy mems[i] = NULL; 168275970Scy --mno; 169275970Scy } 170275970Scy /* 171275970Scy * Special case - deleting user and group may be user's own 172275970Scy */ 173275970Scy if (groups == NULL && mems[0] == NULL && strcmp(name, grp.gr_name) == 0) { 174275970Scy /* 175275970Scy * First, make _sure_ we don't have other members 176275970Scy */ 177275970Scy struct passwd *pwd; 178275970Scy 179275970Scy SETPWENT(); 180275970Scy while ((pwd = GETPWENT()) != NULL && (gid_t)pwd->pw_gid != (gid_t)grp.gr_gid); 181275970Scy ENDPWENT(); 182275970Scy if (pwd == NULL) /* No members at all */ 183275970Scy continue; /* Drop the group */ 184275970Scy } 185275970Scy } else if (isingroup(name, mems) == -1) { 186275970Scy if (extendarray(&mems, &memlen, mno + 2) == -1) { 187275970Scy goto mem_abort; 188275970Scy } 189275970Scy grp.gr_mem = mems; /* May have realloced() */ 190275970Scy mems[mno++] = name; 191275970Scy mems[mno ] = NULL; 192275970Scy } 193275970Scy fmtgrentry(&outl, &outlen, &grp, PWF_GROUP); 194275970Scy } 195275970Scy fputs(outl, outfp); 196275970Scy } 197275970Scy if (fflush(outfp) != EOF) { 198275970Scy rc = 1; 199275970Scy 200275970Scy /* 201275970Scy * Copy data back into the original file and truncate 202275970Scy */ 203275970Scy rewind(infp); 204275970Scy rewind(outfp); 205275970Scy while (fgets(outl, outlen, outfp) != NULL) 206275970Scy fputs(outl, infp); 207275970Scy 208275970Scy /* 209275970Scy * This is a gross hack, but we may have corrupted the 210275970Scy * original file. Unfortunately, it will lose preservation 211275970Scy * of the inode. 212275970Scy */ 213275970Scy if (fflush(infp) == EOF || ferror(infp)) 214275970Scy rc = rename(grouptmp, groupfile) == 0; 215275970Scy else 216275970Scy ftruncate(infd, ftell(infp)); 217275970Scy } 218275970Scy } 219275970Scy free(mems); 220275970Scy free(outl); 221275970Scy free(line); 222275970Scy fclose(outfp); 223275970Scy } 224275970Scy remove(grouptmp); 225275970Scy } 226275970Scy fclose(infp); 227275970Scy } 228275970Scy } 229275970Scy return rc; 230275970Scy} 231275970Scy