edgroup.c revision 30259
119370Spst/*- 219370Spst * Copyright (C) 1996 319370Spst * David L. Nugent. All rights reserved. 419370Spst * 546283Sdfr * Redistribution and use in source and binary forms, with or without 619370Spst * modification, are permitted provided that the following conditions 719370Spst * are met: 819370Spst * 1. Redistributions of source code must retain the above copyright 919370Spst * notice, this list of conditions and the following disclaimer. 1019370Spst * 2. Redistributions in binary form must reproduce the above copyright 1119370Spst * notice, this list of conditions and the following disclaimer in the 1219370Spst * documentation and/or other materials provided with the distribution. 1319370Spst * 1419370Spst * THIS SOFTWARE IS PROVIDED BY DAVID L. NUGENT AND CONTRIBUTORS ``AS IS'' AND 1519370Spst * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1619370Spst * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1719370Spst * ARE DISCLAIMED. IN NO EVENT SHALL DAVID L. NUGENT OR CONTRIBUTORS BE LIABLE 1819370Spst * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1919370Spst * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2019370Spst * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2119370Spst * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2219370Spst * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2319370Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2419370Spst * SUCH DAMAGE. 2519370Spst */ 2619370Spst 2719370Spst#ifndef lint 2819370Spststatic const char rcsid[] = 2919370Spst "$Id$"; 3019370Spst#endif /* not lint */ 3119370Spst 3219370Spst#include <stdio.h> 3319370Spst#include <stdlib.h> 3419370Spst#include <string.h> 3519370Spst#include <unistd.h> 3619370Spst#include <stdarg.h> 3719370Spst#include <sys/types.h> 3819370Spst#include <sys/stat.h> 3919370Spst#include <pwd.h> 4019370Spst#include <grp.h> 4119370Spst#include <fcntl.h> 4219370Spst#include <sys/param.h> 4319370Spst#include <ctype.h> 4419370Spst 4519370Spst#include "pwupd.h" 4619370Spst 4719370Spststatic int 4819370Spstisingroup(char const * name, char **mem) 4919370Spst{ 5019370Spst int i; 5119370Spst 5219370Spst for (i = 0; mem[i] != NULL; i++) 5319370Spst if (strcmp(name, mem[i]) == 0) 5419370Spst return i; 5519370Spst return -1; 5619370Spst} 5719370Spst 5819370Spststatic char groupfile[] = _PATH_GROUP; 5919370Spststatic char grouptmp[] = _PATH_GROUP ".new"; 6019370Spst 6119370Spstint 6219370Spsteditgroups(char *name, char **groups) 6319370Spst{ 6419370Spst int rc = 0; 6519370Spst int infd; 6619370Spst 6719370Spst if ((infd = open(groupfile, O_RDWR | O_CREAT | O_EXLOCK, 0644)) != -1) { 6819370Spst FILE *infp; 6919370Spst 7019370Spst if ((infp = fdopen(infd, "r+")) == NULL) 7119370Spst close(infd); 7219370Spst else { 7319370Spst int outfd; 7419370Spst 7519370Spst if ((outfd = open(grouptmp, O_RDWR | O_CREAT | O_TRUNC | O_EXLOCK, 0644)) != -1) { 7619370Spst FILE *outfp; 7719370Spst 7819370Spst if ((outfp = fdopen(outfd, "w+")) == NULL) 7919370Spst close(outfd); 8019370Spst else { 8119370Spst int linelen = PWBUFSZ; 8219370Spst int outlen = PWBUFSZ; 8319370Spst int memlen = 200; /* Arbitrary */ 8419370Spst char *line = malloc(linelen); 8519370Spst char *outl = malloc(outlen); 8619370Spst char **mems = malloc(memlen * sizeof(char *)); 8719370Spst int namlen = strlen(name); 8819370Spst 8919370Spst if (line == NULL || outl == NULL || mems == NULL) { 9019370Spst mem_abort: 9119370Spst rc = 0; 9219370Spst } else { 9319370Spst while (fgets(line, linelen, infp) != NULL) { 9419370Spst char *p; 9519370Spst int l; 9619370Spst 9719370Spst while ((p = strchr(line, '\n')) == NULL) 9819370Spst { 9919370Spst if (extendline(&line, &linelen, linelen + PWBUFSZ) == -1) { 10019370Spst goto mem_abort; 10119370Spst } 10219370Spst l = strlen(line); 10319370Spst if (fgets(line + l, linelen - l, infp) == NULL) 10419370Spst break; /* No newline terminator on last line */ 10519370Spst } 10619370Spst l = strlen(line) + namlen + 1; 10719370Spst if (extendline(&outl, &outlen, l) == -1) { 10819370Spst goto mem_abort; 10919370Spst } 11019370Spst if (*line == '#') 11119370Spst strcpy(outl, line); 11219370Spst else if (*line == '\n') 11319370Spst *outl = '\0'; 11419370Spst else { 11519370Spst int i, 11619370Spst mno = 0; 11719370Spst char *cp = line; 11819370Spst char const *sep = ":\n"; 11919370Spst struct group grp; 12019370Spst 12119370Spst memset(&grp, 0, sizeof grp); 12219370Spst for (i = 0; (p = strsep(&cp, sep)) != NULL; i++) { 12319370Spst switch (i) { 12419370Spst case 0: /* Group name */ 12519370Spst grp.gr_name = p; 12619370Spst break; 12719370Spst case 1: /* Group password */ 12819370Spst grp.gr_passwd = p; 12919370Spst break; 13019370Spst case 2: /* Group id */ 13119370Spst grp.gr_gid = atoi(p); 13219370Spst break; 13319370Spst case 3: /* Member list */ 13419370Spst cp = p; 13519370Spst sep = ",\n"; 13619370Spst break; 13719370Spst default: /* Individual members */ 13819370Spst if (*p) { 13919370Spst if (extendarray(&mems, &memlen, mno + 2) == -1) { 14019370Spst goto mem_abort; 14119370Spst } 14219370Spst mems[mno++] = p; 14319370Spst } 14419370Spst break; 14519370Spst } 14619370Spst } 14719370Spst if (i < 2) /* Bail out - insufficient fields */ 14819370Spst continue; 14919370Spst 15019370Spst grp.gr_mem = mems; 15119370Spst for (i = mno; i < memlen; i++) 15219370Spst mems[i] = NULL; 15319370Spst 15419370Spst /* 15519370Spst * Delete from group, or add to group? 15619370Spst */ 15719370Spst if (groups == NULL || isingroup(grp.gr_name, groups) == -1) { /* Delete */ 15819370Spst int idx; 15919370Spst 16019370Spst while ((idx = isingroup(name, mems)) != -1) { 16119370Spst for (i = idx; i < (memlen - 1); i++) 16219370Spst mems[i] = mems[i + 1]; 16319370Spst mems[i] = NULL; 16419370Spst --mno; 16519370Spst } 16619370Spst /* 16719370Spst * Special case - deleting user and group may be user's own 16819370Spst */ 16919370Spst if (groups == NULL && mems[0] == NULL && strcmp(name, grp.gr_name) == 0) { 17019370Spst /* 17119370Spst * First, make _sure_ we don't have other members 17219370Spst */ 17319370Spst struct passwd *pwd; 17419370Spst 17519370Spst setpwent(); 17619370Spst while ((pwd = getpwent()) != NULL && pwd->pw_gid != grp.gr_gid); 17719370Spst endpwent(); 17819370Spst if (pwd == NULL) /* No members at all */ 17919370Spst continue; /* Drop the group */ 18019370Spst } 18119370Spst } else if (isingroup(name, mems) == -1) { 18219370Spst if (extendarray(&mems, &memlen, mno + 2) == -1) { 18319370Spst goto mem_abort; 18419370Spst } 18519370Spst grp.gr_mem = mems; /* May have realloced() */ 18619370Spst mems[mno++] = name; 18719370Spst mems[mno ] = NULL; 18819370Spst } 18919370Spst fmtgrentry(&outl, &outlen, &grp, PWF_GROUP); 19019370Spst } 19119370Spst fputs(outl, outfp); 19219370Spst } 19319370Spst if (fflush(outfp) != EOF) { 19419370Spst rc = 1; 19519370Spst 19619370Spst /* 19719370Spst * Copy data back into the original file and truncate 19819370Spst */ 19919370Spst rewind(infp); 20019370Spst rewind(outfp); 20119370Spst while (fgets(outl, outlen, outfp) != NULL) 20219370Spst fputs(outl, infp); 20319370Spst 20419370Spst /* 20519370Spst * This is a gross hack, but we may have corrupted the 20619370Spst * original file. Unfortunately, it will lose preservation 20719370Spst * of the inode. 20819370Spst */ 20919370Spst if (fflush(infp) == EOF || ferror(infp)) 21019370Spst rc = rename(grouptmp, groupfile) == 0; 21119370Spst else 21219370Spst ftruncate(infd, ftell(infp)); 21319370Spst } 21419370Spst } 21519370Spst free(mems); 21619370Spst free(outl); 21719370Spst free(line); 21819370Spst fclose(outfp); 21919370Spst } 22019370Spst remove(grouptmp); 22119370Spst } 22219370Spst fclose(infp); 22319370Spst } 22419370Spst } 22519370Spst return rc; 22619370Spst} 22719370Spst