|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - downloadIndex: ┃ T u ┃
Length: 22502 (0x57e6) Types: TextFile Names: »update.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki └─ ⟦this⟧ »EUUGD11/euug-87hel/sec8/mcp/src/update.c«
#include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <strings.h> #include <ctype.h> #include <lastlog.h> #include "sysdep.h" #include "macros.h" #include "mem.h" #include "gpa.h" #include "lists.h" #include "account.h" #ifdef SENDMAIL #include "alias.h" #endif #include "class.h" #include "groupmap.h" #include "job.h" #include "range.h" #include "sig.h" #include "sort.h" #include "save.h" #define DAY (4*21600) #ifdef SENDMAIL extern struct list AliasList, Aliases; #endif extern struct list AccountList, Users, ClassList, Classes, GroupMapList; extern struct list Groups, RangeList, Ranges, Sigs, SigList, Vigs, Shells; extern struct list Null_List; extern int ModBits; extern addr makeusername(), DEF_SHELL; extern char *crypt(), *mktemp(), *sprintf(), *when(), *rsalt(), *makepass(); extern time_t choosedate(); static char *XXXXXX = "/mcpXXXXXX"; static char desc[DESCSIZE+1]; /* these are defined in add.c */ extern struct list idlist; extern struct list rnlist; extern struct list pwlist; extern struct list mdlist; #ifdef SENDMAIL /* * Update an alias */ updalias(c, v) int c; char **v; { struct alias *al, *a; struct account *ac; struct class *cs; struct sig *sg; struct groupmap *gm; register int i; int cc; addr *namev; char prompt[MEDIUM_BUF]; if (c > 2) { err1("%s: too many arguments", (char *)v[0]); return; } if (c < 2) { err1("usage: %s <alias>", (char *)v[0]); return; } al = getalnam((char *)v[1]); if (!al) { err1("%s: no such alias", (char *)v[1]); return; } namev = get_gpa(2); (void) sprintf(prompt, "Name [%s]: ", al->al_name); GetLine(prompt, 1, &cc, namev, &Null_List); if (cc == 0 || eq(*namev, al->al_name)) { err("no change"); return; } if (aliasexists((char *)*namev)) { err1("%s: alias exists", (char *)*namev); return; } critical(); /* * If this alias name appears in any of the other alias lists * it must be changed there alias well. */ for (i=0; i < AliasList.l_count; i++) { a = (struct alias *) AliasList.l_list[i]; (void) strlistchg(&a->al_addresses, al->al_name, (char *)*namev); } for (i=0; i < AccountList.l_count; i++) { ac = (struct account *) AccountList.l_list[i]; if (strlistchg(&ac->ac_aliases, al->al_name, (char *)*namev)) ModBits |= AC; } for (i=0; i < GroupMapList.l_count; i++) { gm = (struct groupmap *) GroupMapList.l_list[i]; (void) strlistchg(&gm->gm_aliases, al->al_name, (char *)*namev); } for (i=0; i < ClassList.l_count; i++) { cs = (struct class *) ClassList.l_list[i]; (void) strlistchg(&cs->cs_aliases, al->al_name, (char *)*namev); } for (i=0; i < SigList.l_count; i++) { sg = (struct sig *) SigList.l_list[i]; (void) strlistchg(&sg->sg_aliases, al->al_name, (char *)*namev); } (void) strlistchg(&Aliases, al->al_name, (char *)*namev); FREEMEM(al->al_name); savestr(&al->al_name, (char *)*namev); sort_list(&AliasList, aliascmp); ModBits |= AL; puts("updated"); non_critical(); return; } #endif /* * Update a class */ updclass(c, v) int c; addr *v; { struct class cl, *cs; struct account *ac; #ifdef SENDMAIL struct alias *al; #endif struct stat statbuf; addr *namev; char tempf[MEDIUM_BUF], errmsg[LONG_BUF], prompt[LONG_BUF]; FILE *f, *fopen(); time_t now; int i, cc, changed = 0, ch; if ( c > 2 ) { err1("%s: too many arguments", (char *)v[0]); return; } if ( c != 2 ) { err1("usage: %s <class>", (char *)v[0]); return; } cs = getcsnam((char *)v[1]); if (!cs) { err1("%s: no such class", (char *)v[1]); return; } bcopy(&cl, cs, sizeof (struct class)); namev = get_gpa(2); (void) sprintf(prompt, "Name [%s]: ", cl.cs_name); GetLine(prompt, 1, &cc, namev, &Null_List); if (cc) { if (eq(*namev, v[1])) ; /* no change */ else if (classexists((char *)*namev)) { err("that name is taken"); return; } else changed = 1; } (void) printf("Class set to end %s\n", when(cl.cs_exptime)); if (no("Do you wish to change it? [no] ") == 0) { if (!cl.cs_exptime || yesno("Should the class expire? ")) { err("Set the expiration date."); cl.cs_exptime = choosedate(cl.cs_exptime); (void) printf("Class set to end %s\n", when(cl.cs_exptime)); } else cl.cs_exptime = 0; if (cl.cs_exptime != cs->cs_exptime) changed = 1; } i = no("Edit description? [no] "); critical(); if (i) goto finish; (void) strcpy(tempf, TMPDIR); (void) strcat(tempf, XXXXXX); (void) mktemp(tempf); f = fopen(tempf, "w"); if (f == NULL) { err1("%s: cannot open (write)", tempf); non_critical(); return; } fputs(cl.cs_desc, f); (void) fclose(f); (void) stat(tempf, &statbuf); now = statbuf.st_mtime; for (;;) { edit(tempf); if (stat(tempf, &statbuf) == -1) { perr(tempf); (void) unlink(tempf); non_critical(); return; } if (statbuf.st_size > DESCSIZE) { (void) sprintf(errmsg, "description is %d characters too long", DESCSIZE - statbuf.st_size); err(errmsg); continue; } break; } if (statbuf.st_mtime == now) goto finish; changed = 1; f = fopen(tempf, "r"); if (f == NULL) { err1("%s: cannot open (read)", tempf); non_critical(); return; } FREEMEM(cl.cs_desc); i = 0; while ((ch = getc(f)) != EOF) desc[i++] = ch; desc[i] = '\0'; cl.cs_dsize = i; savestr(&cl.cs_desc, desc); (void) fclose(f); (void) unlink(tempf); finish: if (*namev != NIL && !eq(*namev, v[1])) { FREEMEM(cl.cs_name); savestr(&cl.cs_name, (char *)*namev); for (i=0; i < AccountList.l_count; i++) { ac = (struct account *)AccountList.l_list[i]; if (strlistchg(&ac->ac_classes, (char *)v[1], cl.cs_name)) ModBits |= AC; } #ifdef SENDMAIL for (i=0; i < AliasList.l_count; i++) { al = (struct alias *) AliasList.l_list[i]; if (strlistchg(&al->al_classes, (char *)v[1], cl.cs_name)) ModBits |= AL; } #endif (void) strlistchg(&Classes, (char *)v[1], cl.cs_name); } if (changed) { bcopy(cs, &cl, sizeof (struct class)); sort_list(&ClassList, classcmp); ModBits |= CS; puts("updated"); } else err("no change"); non_critical(); return; } /* * Update a sig */ updsig(c, v) int c; addr *v; { struct sig s, *sg; #ifdef SENDMAIL struct alias *al; #endif struct account *ac; struct stat statbuf; addr *namev; char tempf[MEDIUM_BUF], errmsg[LONG_BUF], prompt[LONG_BUF]; FILE *f, *fopen(); time_t now; int i, cc, changed = 0, ch; if ( c > 2 ) { err1("%s: too many arguments", (char *)v[0]); return; } if ( c != 2 ) { err1("usage: %s <sig>", (char *)v[0]); return; } sg = getsgnam((char *)v[1]); if (!sg) { err1("%s: no such sig", (char *)v[1]); return; } bcopy(&s, sg, sizeof (struct sig)); namev = get_gpa(2); (void) sprintf(prompt, "Name [%s]: ", s.sg_name); GetLine(prompt, 1, &cc, namev, &Null_List); if (cc) { if (eq(*namev, v[1])) ; /* no change */ else if (sigexists((char *)*namev)) { err("that name is taken"); return; } else changed = 1; } (void) printf("Sig set to end %s\n", when(s.sg_exptime)); if (no("Do you wish to change it? [no] ") == 0) { if (!s.sg_exptime || yesno("Should the sig expire? ")) { err("Set the expiration date."); s.sg_exptime = choosedate(s.sg_exptime); (void) printf("Project set to end %s\n", when(s.sg_exptime)); } else s.sg_exptime = 0; if (s.sg_exptime != sg->sg_exptime) changed = 1; } i = no("Edit description? [no] "); critical(); if (i) goto finish; (void) strcpy(tempf, TMPDIR); (void) strcat(tempf, XXXXXX); (void) mktemp(tempf); f = fopen(tempf, "w"); if (f == NULL) { err1("%s: cannot open (write)", tempf); non_critical(); return; } fputs(s.sg_desc, f); (void) fclose(f); (void) stat(tempf, &statbuf); now = statbuf.st_mtime; for (;;) { edit(tempf); if (stat(tempf, &statbuf) == -1) { perr(tempf); (void) unlink(tempf); non_critical(); return; } if (statbuf.st_size > DESCSIZE) { (void) sprintf(errmsg, "description is %d characters too long", DESCSIZE - statbuf.st_size); err(errmsg); continue; } break; } if (statbuf.st_mtime == now) goto finish; changed = 1; f = fopen(tempf, "r"); if (f == NULL) { err1("%s: cannot open (read)", tempf); non_critical(); return; } FREEMEM(s.sg_desc); i = 0; while ((ch = getc(f)) != EOF) desc[i++] = ch; desc[i] = '\0'; s.sg_dsize = i; savestr(&s.sg_desc, desc); (void) fclose(f); (void) unlink(tempf); finish: if (*namev != NIL && !eq(*namev, v[1])) { FREEMEM(s.sg_name); savestr(&s.sg_name, (char *)*namev); for (i=0; i < AccountList.l_count; i++) { ac = (struct account *)AccountList.l_list[i]; if (strlistchg(&ac->ac_sigs, (char *)v[1], s.sg_name)) ModBits |= AC; } #ifdef SENDMAIL for (i=0; i < AliasList.l_count; i++) { al = (struct alias *) AliasList.l_list[i]; if (strlistchg(&al->al_sigs, (char *)v[1], s.sg_name)) ModBits |= AL; } #endif (void) strlistchg(&Sigs, (char *)v[1], s.sg_name); } if (changed) { bcopy(sg, &s, sizeof (struct sig)); sort_list(&SigList, sigcmp); ModBits |= SG; puts("updated"); } else err("no change"); non_critical(); return; } /* * Add a group */ updgroup(c, v) int c; addr *v; { struct groupmap g, *gm; #ifdef SENDMAIL struct alias *al; #endif struct account *ac; struct range *rg; char prompt[SHORT_BUF]; addr *tempv, *namev; int i, cc, gid, changed = 0; if ( c > 2 ) { err1("%s: too many arguments", (char *)v[0]); return; } if (c != 2) { err1("usage: %s <name>", (char *)v[0]); return; } gm = getgmnam((char *)v[1]); if (!gm) { err1("%s: group exists", (char *)v[1]); return; } bcopy(&g, gm, sizeof (struct groupmap)); namev = get_gpa(2); tempv = get_gpa(2); (void) sprintf(prompt, "Name [%s]: ", g.gm_name); GetLine(prompt, 1, &cc, namev, &Null_List); if (cc) { if (!eq(*namev, v[1])) ; /* no change */ else if (groupexists((char *)*namev)) { err("that name is taken"); return; } else changed = 1; } (void) sprintf(prompt, "Gid [%d]: ", g.gm_gid); GetLine(prompt, 1, &cc, tempv, &Null_List); if (cc) { if (!validint((char *)*tempv)) { err1("%s makes no sense to me", (char *)tempv); return; } gid = atoi((char *)*tempv); if (gidexists(g.gm_gid)) { err("that gid is taken"); return; } else { g.gm_gid = gid; changed = 1; } } critical(); if (g.gm_gid != gm->gm_gid) { changed = 1; for (i=0; i < AccountList.l_count; i++) { ac = (struct account *) AccountList.l_list[i]; if (ac->ac_gid == gm->gm_gid) { ac->ac_gid = g.gm_gid; ModBits |= AC; } } } if (*namev != NIL && !eq(*namev, v[1])) { changed = 1; FREEMEM(g.gm_name); savestr(&g.gm_name, (char *)*namev); (void) strlistchg(&Groups, (char *)v[1], g.gm_name); for (i=0; i < AccountList.l_count; i++) { ac = (struct account *) AccountList.l_list[i]; if (strlistchg(&ac->ac_groups, (char *)v[1], g.gm_name)) ModBits |= AC; } #ifdef SENDMAIL for (i=0; i < AliasList.l_count; i++) { al = (struct alias *) AliasList.l_list[i]; if (strlistchg(&al->al_groups, (char *)v[1], g.gm_name)) ModBits |= AL; } #endif rg = getrgnam((char *)v[1]); if (rg) { FREEMEM(rg->rg_name); savestr(&rg->rg_name, g.gm_name); (void) strlistchg(&Ranges, (char *)v[1], g.gm_name); sort_list(&RangeList, rangecmp); ModBits |= RG; } if (vigexists((char *)v[1])) { (void) strlistchg(&Vigs, (char *)v[1], g.gm_name); ModBits |= VG; } } if (changed) { bcopy(gm, &g, sizeof (struct groupmap)); sort_list(&GroupMapList, gmapcmp); ModBits |= GR; puts("updated"); } else err("no change"); non_critical(); return; } /* * Update a range */ updrange(c, v) int c; addr *v; { struct range r, *rr, *rg; char prompt[SHORT_BUF]; addr *tempv, *namev; int cc, indx, changed = 0; if ( c > 2 ) { err1("%s: too many arguments", (char *)v[0]); return; } if (c != 2) { err1("usage: %s <name>", (char *)v[0]); return; } rr = getrgnam((char *)v[1]); if (!rr) { err1("%s: no such range", (char *)v[1]); return; } bcopy(&r, rr, sizeof (struct range)); namev = get_gpa(2); tempv = get_gpa(2); /* * New name? */ (void) sprintf(prompt, "Name [%s]: ", r.rg_name); GetLine(prompt, 1, &cc, namev, &Groups); if (cc) { if (!groupexists((char *)*namev)) { err1("%s: no such group", (char *)*namev); return; } if (eq(*namev, v[1])) ; /* no change */ else if (rangeexists((char *)namev)) { err("that name is taken"); return; } else changed = 1; } /* * From? */ (void) sprintf(prompt, "From [%d]: ", r.rg_from); GetLine(prompt, 1, &cc, tempv, &Null_List); if (cc) { if (!validint((char *)*tempv)) { err1("%s makes no sense to me", (char *)*tempv); return; } r.rg_from = atoi((char *)*tempv); (void) clear_gpa(tempv, 2); changed = 1; } /* * To? */ (void) sprintf(prompt, "To [%d]: ", r.rg_to); GetLine(prompt, 1, &cc, tempv, &Null_List); if (cc) { if (!validint((char *)*tempv)) { err1("%s makes no sense to me", (char *)*tempv); return; } r.rg_to = atoi((char *)*tempv); (void) clear_gpa(tempv, 2); changed = 1; } /* * New mode? */ (void) sprintf(prompt, "Mode [%s] : ", (r.rg_mode == RG_SHARED ? "shared" : "exclusive")); GetLine(prompt, 1, &cc, tempv, &mdlist); if (!cc) ; /* no change */ else if (eq(*tempv, "shared")) { r.rg_mode = RG_SHARED; changed = 1; } else if (eq(*tempv, "exclusive")) { r.rg_mode = RG_EXCLUSIVE; changed = 1; } else { err1("%s: unknown mode", (char *)*tempv); return; } /* * Check to see if the new range conflicts with existing ranges */ for (indx=0; indx < RangeList.l_count; indx++) { rg = (struct range *) RangeList.l_list[indx]; if (rg == rr) continue; if (rg->rg_mode == RG_SHARED && r.rg_mode == RG_SHARED) continue; if (INRANGE(r.rg_from, rg->rg_from, rg->rg_to)) { err1("conflicts with range of group %s", rg->rg_name); return; } if (INRANGE(r.rg_to, rg->rg_from, rg->rg_to)) { err1("conflicts with range of group %s", rg->rg_name); return; } } critical(); if (*namev != NIL && !eq(*namev, v[1])) { FREEMEM(r.rg_name); savestr(&r.rg_name, (char *)*tempv); (void) strlistchg(&Ranges, (char *)v[1], r.rg_name); } if (changed) { bcopy(rr, &r, sizeof (struct range)); sort_list(&RangeList, rangecmp); ModBits |= RG; puts("updated"); } else err("no change"); non_critical(); return; } upduser(c, v) int c; char **v; { struct account *ac, *ac2; struct groupmap *gm; #ifdef SENDMAIL struct alias *al; struct class *cs; struct sig *sg; int ogid, j; #endif addr *namev, *realnamev, *idv, *uidv, *gidv, *dirv, *passwdv, *shellv; int uid, gid, changed = 0; #ifdef DOFILES int mvdir = 0; #endif int cc; register int i; char *cp, prompt[LONG_BUF], errmsg[LONG_BUF]; if ( c > 2 ) { err1("%s: too many arguments", (char *)v[0]); return; } if ( c != 2 ) { err1("usage: %s <user>", (char *)v[0]); return; } ac = getacnam((char *)v[1]); if (!ac) { err1("%s: no such user", (char *)v[1]); return; } namev = get_gpa(2); realnamev = get_gpa(17); idv = get_gpa(2); passwdv = get_gpa(2); uidv = get_gpa(2); gidv = get_gpa(2); dirv = get_gpa(2); shellv = get_gpa(2); /* * Change login name? */ (void) sprintf(prompt, "Login name [%s]: ", ac->ac_name); GetLine(prompt, 1, &cc, namev, &Null_List); /* * Change real name? */ (void) sprintf(prompt, "Real Name [%s]: ", ac->ac_realname); GetLine(prompt, 16, &cc, realnamev, &Null_List); /* * Change id? */ (void) sprintf(prompt, "Id [%s]: ", ac->ac_id); GetLine(prompt, 1, &cc, idv, &idlist); /* * Change password? */ (void) sprintf(prompt, "Password (RETURN means no change): "); GetLine(prompt, 1, &cc, passwdv, &pwlist); /* * Change uid? */ (void) sprintf(prompt, "Uid [%d]: ", ac->ac_uid); GetLine(prompt, 1, &cc, uidv, &Null_List); if (cc && !validint((char *)*uidv)) { err1("%s makes no sense to me", (char *)*uidv); return; } /* * Change gid? */ (void) sprintf(prompt, "Gid [%d]: ", ac->ac_gid); GetLine(prompt, 1, &cc, gidv, &Null_List); if (cc && !validint((char *)*gidv)) { err1("%s makes no sense to me", (char *)*gidv); return; } /* * Rename home directory? */ (void) sprintf(prompt, "Home [%s]: ", ac->ac_dir); GetFilenames(prompt, 1, &cc, dirv); #ifdef DOFILES if (cc && !eq(*dirv, ac->ac_dir) && fileexists((char *)*dirv)) err2("%s already exists, so I won't move %s", (char *)*dirv, (char *)ac->ac_dir); else mvdir = 1; #endif /* * New shell? */ (void) sprintf(prompt, "Shell [%s]: ", ac->ac_shell); GetLine(prompt, 1, &cc, shellv, &Shells); if (cc && !fileexists((char *)*shellv)) err1("Warning: %s does not exist", (char *)*shellv); critical(); /* * If given a different user name, use it. No duplicate * user names allowed (of course). */ if (*namev != NIL && !eq(*namev, ac->ac_name)) { if (!userexists((char *)*namev)) { /* * Update group member lists */ for (i=0; i < GroupMapList.l_count; i++) { gm = (struct groupmap *)GroupMapList.l_list[i]; if (strlistchg(&gm->gm_mem, (char *)v[1], (char *)*namev)) ModBits |= GR; } #ifdef SENDMAIL /* * Update aliases */ for (i=0; i < AliasList.l_count; i++) { al = (struct alias *) AliasList.l_list[i]; if (strlistchg(&al->al_addresses, (char *)v[1], (char *)*namev)) ModBits |= AL; } al = getalnam((char *)ac->ac_name); if (al) { ModBits |= AL; for (i=0; i < AccountList.l_count; i++) { ac2 = (struct account *) AccountList.l_list[i]; if (!strlistchg(&ac2->ac_aliases, al->al_name, (char *)*namev)) continue; ModBits |= AC; } for (i=0; i < GroupMapList.l_count; i++) { gm = (struct groupmap *) GroupMapList.l_list[i]; (void) strlistchg(&gm->gm_aliases, al->al_name, (char *)*namev); } for (i=0; i < ClassList.l_count; i++) { cs = (struct class *) ClassList.l_list[i]; (void) strlistchg(&cs->cs_aliases, al->al_name, (char *)*namev); } for (i=0; i < SigList.l_count; i++) { sg = (struct sig *) SigList.l_list[i]; (void) strlistchg(&sg->sg_aliases, al->al_name, (char *)*namev); } (void) strlistchg(&Aliases, al->al_name, (char *)*namev); FREEMEM(al->al_name); savestr(&al->al_name, (char *)*namev); sort_list(&AliasList, aliascmp); } #endif /* * Now fix the accounts struct and the users * completion list */ (void) strlistchg(&Users, (char *)ac->ac_name, (char *)*namev); FREEMEM((char *)ac->ac_name); savestr((char **)&ac->ac_name, (char *)*namev); ModBits |= (AC|PW); changed++; } else { err1("%s: user exists", (char *)*namev); err("login name unchanged"); } } /* * If given a new real name, use it. */ if (*realnamev != NIL) { cp = (char *)glob(realnamev); if (!eq(cp, ac->ac_realname)) { FREEMEM((char *)ac->ac_realname); savestr((char **)&ac->ac_realname, cp); ModBits |= AC; changed++; } } /* * If id changed, record it. Since the user already has an * account we don't care if his id matches anyone else's * The check for duplicate ids is done at when a user is added. */ if (*idv != NIL && !eq(*idv, ac->ac_id)) { FREEMEM((char *)ac->ac_id); savestr((char **)&ac->ac_id, (char *)*idv); ModBits |= AC; changed++; } /* * Handle change of password */ if (*passwdv != NIL) { FREEMEM((char *)ac->ac_passwd); if (eq(*passwdv, "unused")) savestr((char **)&ac->ac_passwd, "*"); else if (eq(*passwdv, "none")) savestr((char **)&ac->ac_passwd, ""); else if (eq(*passwdv, "generate")) { cp = makepass(); savestr((char **)&ac->ac_passwd, crypt(cp, rsalt())); (void) printf("password is \"%s\"\n", cp); } else savestr((char **)&ac->ac_passwd, crypt((char *)*passwdv, rsalt())); ModBits |= PW; changed++; } /* * Note home directory change, if any. This must be before * checking for a change in uid so that the omni_chown isn't * suddenly left high and dry if user's directory is moved. */ if (*dirv != NIL && !eq(*dirv, ac->ac_dir)) { #ifdef DOFILES if (mvdir) add_job(JB_MV, ac->ac_dir, *dirv, NIL); #else err("Don't forget to move the user's home directory"); #endif FREEMEM((char *)ac->ac_dir); savestr((char **)&ac->ac_dir, (char *)*dirv); ModBits |= PW; changed++; } /* * Handle a change of uid. This entails changing the ownership * of this user's files when savechanges() is called. Sharing * of uids is permitted but a warning message is printed. */ if (*uidv != NIL) { uid = atoi((char *)*uidv); if (uid <= 0) err("uid is out of range"); else if (uid != ac->ac_uid && uid >= 0) { ac2 = getacuid(uid); if (ac2) (void) printf("warning: uid %d is shared by %s\n", uid, ac2->ac_name); #ifdef DOFILES add_job(JB_OMNICHOWN, &ac->ac_uid, &uid, NIL); #else err("Do not forget to chown the user files."); #endif ac->ac_uid = uid; sort_list(&AccountList, acctcmp); ModBits |= (AC|PW); add_job(JB_LASTLOG, &ac->ac_uid, (addr)&ac->ac_ll, NIL); changed++; } } /* * Handle a change of gid. Must make sure there is group * associated with the gid. */ if (*gidv != NIL) { gid = atoi((char *)*gidv); if (gid < 0) err("gid is out of range"); else if (!(gm = getgmgid(gid))) { (void) sprintf(errmsg, "no group associated with gid %d", gid); err(errmsg); } else if (gid != ac->ac_gid) { #ifdef SENDMAIL ogid = ac->ac_gid; #endif ac->ac_gid = gid; ModBits |= (AC|PW); #ifdef SENDMAIL if (gm->gm_aliases.l_count) RXBindings(ac); gm = getgmgid(ogid); for (j=0; j < gm->gm_aliases.l_count; j++) { al = getalnam((char *)gm->gm_aliases.l_list[j]); if (!al) continue; /* trouble */ if (!instrlist(&al->al_addresses, (char *)ac->ac_name)) { strlistadd(&al->al_addresses, (char *)ac->ac_name); sort_list(&al->al_addresses, pstrcmp); ModBits |= AL; } } #endif changed++; } } /* * Make change in shell if necessary. */ if (*shellv != NIL && !eq(*shellv, ac->ac_shell)) { FREEMEM((char *)ac->ac_shell); savestr((char **)&ac->ac_shell, (char *)*shellv); ModBits |= PW; changed++; } if (changed) puts("updated"); else err("no change"); non_critical(); return; }