Hi, lately I was reading on misc@ [1] that there's no way to remove a user from secondary groups but by hand. I also searched for a PR but couldn't find one. The attached diff remedies the problem:
# id test uid=1001(test) gid=10(users) groups=10(users), 9(wsrc), 69(network), 117(dialer) # usermod -G wsrc,network test # id test uid=1001(test) gid=10(users) groups=10(users), 9(wsrc), 69(network) # usermod -G wsrc,network,dialer test # id test uid=1001(test) gid=10(users) groups=10(users), 9(wsrc), 69(network), 117(dialer) I actually copied the code from rm_user_from_groups() which makes it a bit redundant, but I don't think it's worth writing a own function for it. As I am a total C newbie I'm thrilled to hear some comments :-) [1] http://marc.info/?l=openbsd-misc&m=130073011016781&w=2 Frank. Index: usr.sbin/user/user.c =================================================================== RCS file: /cvs/src/usr.sbin/user/user.c,v retrieving revision 1.79 diff -u -r1.79 user.c --- usr.sbin/user/user.c 6 Apr 2011 11:36:26 -0000 1.79 +++ usr.sbin/user/user.c 8 Apr 2011 17:49:45 -0000 @@ -491,28 +491,24 @@ { struct group *grp; struct stat st; + size_t login_len; FILE *from; FILE *to; char buf[LINE_MAX]; char f[MaxFileNameLen]; char *colon; + char *cp; + char *ep; int fd; int cc; int i; int j; + login_len = strlen(user); for (i = 0 ; i < ngroups ; i++) { - if ((grp = getgrnam(groups[i])) == NULL) { + if ((grp = getgrnam(groups[i])) == NULL) warnx("can't append group `%s' for user `%s'", groups[i], user); - } else { - for (j = 0 ; grp->gr_mem[j] ; j++) { - if (strcmp(user, grp->gr_mem[j]) == 0) { - /* already in it */ - groups[i] = ""; - } - } - } } if ((from = fopen(_PATH_GROUP, "r")) == NULL) { warn("can't append group for `%s': can't open `%s'", user, @@ -549,6 +545,35 @@ warnx("badly formed entry `%s'", buf); continue; } + + /* remove user from group */ + for (cp = buf, cc = 0; *cp != '\0' && cc < 3; cp++) { + if (*cp == ':') + cc++; + } + if (cc != 3) { + buf[strcspn(buf, "\n")] = '\0'; + warnx("Malformed entry `%s'. Skipping", buf); + continue; + } + while ((cp = strstr(cp, user)) != NULL) { + if ((cp[-1] == ':' || cp[-1] == ',') && + (cp[login_len] == ',' || cp[login_len] == '\n')) { + ep = cp + login_len; + if (cp[login_len] == ',') + ep++; + else if (cp[-1] == ',') + cp--; + memmove(cp, ep, strlen(ep) + 1); + } else { + if ((cp = strchr(cp, ',')) == NULL) + break; + cp++; + } + } + cc = strlen(buf); + + /* add user to groups */ for (i = 0 ; i < ngroups ; i++) { j = (int)(colon - buf); if (strncmp(groups[i], buf, j) == 0 && -- Frank Brodbeck <[email protected]>
