|
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 - metrics - downloadIndex: T a
Length: 21617 (0x5471) Types: TextFile Names: »add.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki └─⟦this⟧ »EUUGD11/euug-87hel/sec8/mcp/src/add.c«
/***************************************************************\ * * * add.c * * * * Routines to add various things, users, groups, classes, etc. * * * \***************************************************************/ #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, validint(); extern addr gethomedir(); extern addr makeusername(), DEF_SHELL; extern char *crypt(), *mktemp(), *sprintf(), *makepass(), *when(); extern time_t choosedate(); static char *XXXXXX = "/mcpXXXXXX"; static char desc[DESCSIZE+1]; static char *idl[1] = { "exception" }; static char *pwl[3] = { "generate", "none", "unused" }; static char *rnl[1]; static char *mdl[2] = { "exclusive", "shared" }; struct list idlist = { 1, 1, (addr *)idl }; struct list pwlist = { 3, 3, (addr *)pwl }; struct list rnlist = { 1, 1, (addr *)rnl }; struct list mdlist = { 2, 2, (addr *)mdl }; #ifdef SENDMAIL /* * Add an alias */ addalias(c, v) int c; addr *v; { struct alias al; struct account *ac; addr *addressv; int cc; register int i; if (c > 2) { err1("%s: too many arguments", (char *)v[0]); return; } if (c != 2) { err1("usage: %s <name>", (char *)v[0]); return; } if (aliasexists((char *)v[1])) { err1("%s: alias exists", (char *)v[1]); return; } addressv = get_gpa(257); GetLine("Addresses: ", 256, &cc, addressv, &Null_List); critical(); savestr(&al.al_name, (char *)v[1]); zerolist(&al.al_addresses); zerolist(&al.al_classes); zerolist(&al.al_sigs); zerolist(&al.al_groups); for (i=0; i < cc; i++) { strlistadd(&al.al_addresses, (char *)addressv[i]); ac = getacnam((char *)addressv[i]); if (ac) strlistadd(&ac->ac_aliases, (char *)addressv[i]); } sort_list(&al.al_addresses, pstrcmp); strlistadd(&Aliases, (char *)v[1]); genlistadd(&AliasList, (addr)&al, sizeof (struct alias)); sort_list(&Aliases, pstrcmp); sort_list(&AliasList, aliascmp); ModBits |= AL; puts("added"); non_critical(); return; } #endif /* * Add a class */ addclass(c, v) int c; addr *v; { struct class cs; struct stat statbuf; char tempf[MEDIUM_BUF], errmsg[LONG_BUF]; FILE *f, *fopen(); time_t now, time(); int tries, i, ch; if ( c > 2 ) { err1("%s: too many arguments", (char *)v[0]); return; } if ( c != 2 ) { err1("usage: %s <class>", (char *)v[0]); return; } if (classexists((char *)v[1])) { err1("%s: class exists", (char *)v[1]); return; } if (yesno("Should the class expire? ") == 0) cs.cs_exptime = (time_t) 0; else { (void) time(&now); err("Set the expiration date."); cs.cs_exptime = choosedate(now); (void) printf("Ends %s\n", when(cs.cs_exptime)); } (void) strcpy(tempf, TMPDIR); (void) strcat(tempf, XXXXXX); (void) mktemp(tempf); tries = 0; edit_it: tries++; f = fopen(tempf, "w"); if (f == NULL) { err1("%s: cannot open (write)", tempf); return; } (void) fprintf(f, "Instructor: \n\n"); (void) fprintf(f, "...\n"); (void) fclose(f); re_edit: edit(tempf); if (stat(tempf, &statbuf) == -1) { perr(tempf); if (tries < 5) { sleep(2); goto edit_it; } else { err1("%s aborted", (char *)v[0]); (void) unlink(tempf); return; } } if (statbuf.st_size > DESCSIZE) { (void)sprintf(errmsg, "description is %d characters too long", DESCSIZE - statbuf.st_size); err(errmsg); sleep(2); goto re_edit; } critical(); f = fopen(tempf, "r"); if (f == NULL) { err1("%s: cannot open (read)", tempf); non_critical(); return; } savestr(&cs.cs_name, (char *)v[1]); i = 0; while ((ch = getc(f)) != EOF) desc[i++] = (char) ch; desc[i] = '\0'; cs.cs_dsize = i; savestr(&cs.cs_desc, desc); (void) fclose(f); #ifdef SENDMAIL zerolist(&cs.cs_aliases); #endif genlistadd(&ClassList, (addr) &cs, sizeof (struct class)); strlistadd(&Classes, cs.cs_name); sort_list(&ClassList, classcmp); sort_list(&Classes, pstrcmp); (void) unlink(tempf); ModBits |= CS; puts("added"); non_critical(); return; } /* * Add a group */ addgroup(c, v) int c; addr *v; { struct groupmap gm; char prompt[SHORT_BUF]; addr *gidv; int cc, gid; if ( c > 2 ) { err1("%s: too many arguments", (char *)v[0]); return; } if (c != 2) { err1("usage: %s <name>", (char *)v[0]); return; } if (groupexists((char *)v[1])) { err1("%s: group exists", (char *)v[1]); return; } gm.gm_gid = nextgid(); (void) sprintf(prompt, "Gid [%d]: ", gm.gm_gid); gidv = get_gpa(2); do { GetLine(prompt, 1, &cc, gidv, &Null_List); if (cc) { if (!validint((char *)*gidv)) { err1("%s makes no sense to me", (char *)*gidv); continue; } gid = atoi((char *)*gidv); if (gidexists(gid)) err("that gid is taken"); else { gm.gm_gid = gid; break; } } else break; } while (clear_gpa(gidv, 2)); critical(); savestr(&gm.gm_name, (char *)v[1]); savestr(&gm.gm_passwd, "*"); zerolist(&gm.gm_mem); #ifdef SENDMAIL zerolist(&gm.gm_aliases); #endif genlistadd(&GroupMapList, (addr) &gm, sizeof (struct groupmap)); sort_list(&GroupMapList, gmapcmp); strlistadd(&Groups, gm.gm_name); sort_list(&Groups, pstrcmp); ModBits |= GR; puts("added"); non_critical(); return; } int nextgid() { register int i, next = 0; struct groupmap *gm; for (i=0; i<GroupMapList.l_count; i++) { gm = (struct groupmap *) GroupMapList.l_list[i]; if (gm->gm_gid > next) return next; /* * Since gid's may be shared (gag) by two or more group names * the seemingly obvious next++ actually must be... */ next = gm->gm_gid + 1; } return next; } /* * Add a range */ addrange(c, v) int c; addr *v; { struct range r, *rg; char prompt[SHORT_BUF]; addr *fromv, *tov, *modev; int cc, indx; if ( c > 2 ) { err1("%s: too many arguments", (char *)v[0]); return; } if (c != 2) { err1("usage: %s <name>", (char *)v[0]); return; } if (!groupexists((char *)v[1])) { err1("%s: no such group", (char *)v[1]); return; } (void) strcpy(prompt, "From: "); fromv = get_gpa(2); do { GetLine(prompt, 1, &cc, fromv, &Null_List); if (cc && !validint((char *)*fromv)) { cc = 0; continue; } } while (cc == 0 && clear_gpa(fromv, 2)); (void) strcpy(prompt, "To : "); tov = get_gpa(2); do { GetLine(prompt, 1, &cc, tov, &Null_List); if (cc && !validint((char *)*tov)) { cc = 0; continue; } } while (cc == 0 && clear_gpa(tov, 2)); (void) strcpy(prompt, "Mode: "); modev = get_gpa(2); do { GetLine(prompt, 1, &cc, modev, &mdlist); } while (cc == 0 && clear_gpa(modev, 2)); if (eq(*modev, "shared")) r.rg_mode = RG_SHARED; else if (eq(*modev, "exclusive")) r.rg_mode = RG_EXCLUSIVE; else { err1("%s: unknown mode", (char *)*modev); return; } r.rg_from = atoi((char *)*fromv); r.rg_to = atoi((char *)*tov); for (indx=0; indx < RangeList.l_count; indx++) { rg = (struct range *) RangeList.l_list[indx]; 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(); savestr(&r.rg_name, (char *)v[1]); genlistadd(&RangeList, (addr) &r, sizeof (struct range)); sort_list(&RangeList, rangecmp); strlistadd(&Ranges, (char *)v[1]); sort_list(&Ranges, pstrcmp); ModBits |= RG; puts("added"); non_critical(); return; } /* * Add a sig */ addsig(c, v) int c; addr *v; { struct sig sg; struct stat statbuf; FILE *f, *fopen(); time_t now, time(); int tries, i, ch; char tempf[SHORT_BUF+1], errmsg[LONG_BUF]; if ( c > 2 ) { err1("%s: too many arguments", (char *)v[0]); return; } if ( c != 2 ) { err1("usage: %s <name>", (char *)v[0]); return; } if (sigexists((char *)v[1])) { err1("%s: sig exists", (char *)v[1]); return; } if (yesno("Should the sig expire? ") == 0) sg.sg_exptime = (time_t) 0; else { (void) time(&now); err("Set the expiration date."); sg.sg_exptime = choosedate(now); (void) printf("Sig ends %s\n", when(sg.sg_exptime)); } (void) strcpy(tempf, TMPDIR); (void) strcat(tempf, XXXXXX); (void) mktemp(tempf); tries = 0; edit_it: tries++; f = fopen(tempf, "w"); if (f == NULL) { err1("%s: cannot open (write)", tempf); return; } (void) fprintf(f, "Guru: \n\n"); (void) fprintf(f, "...\n"); (void) fclose(f); re_edit: edit(tempf); if (stat(tempf, &statbuf) == -1) { perr(tempf); if (tries < 5) { sleep(2); goto edit_it; } else { err1("%s aborted", (char *)v[0]); (void) unlink(tempf); return; } } if (statbuf.st_size > DESCSIZE) { (void) sprintf(errmsg, "description is %d characters too long", DESCSIZE - statbuf.st_size); err(errmsg); sleep(2); goto re_edit; } critical(); f = fopen(tempf, "r"); if (f == NULL) { err1("%s: cannot open (read)", tempf); non_critical(); return; } savestr(&sg.sg_name, (char *)v[1]); i = 0; while ((ch = getc(f)) != EOF) desc[i++] = (char) ch; desc[i] = '\0'; sg.sg_dsize = i; savestr(&sg.sg_desc, desc); (void) fclose(f); #ifdef SENDMAIL zerolist(&sg.sg_aliases); #endif genlistadd(&SigList, (addr) &sg, sizeof (struct sig)); strlistadd(&Sigs, sg.sg_name); sort_list(&SigList, sigcmp); sort_list(&Sigs, pstrcmp); (void) unlink(tempf); ModBits |= SG; puts("added"); non_critical(); return; } #ifdef SENDMAIL addtoalias(c, v) int c; addr *v; { struct alias *al; struct account *ac; addr *addressv; int cc, added = 0, notes = 0; register int indx; 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; } addressv = get_gpa(65); GetLine("Addresses: ", 64, &cc, addressv, &Null_List); if (cc == 0) { err("no change"); return; } critical(); for (indx=0; indx < cc; indx++) { ac = getacnam((char *)addressv[indx]); if (ac) { if (!instrlist(&ac->ac_aliases, (char *)v[1])) { strlistadd(&ac->ac_aliases, (char *)v[1]); sort_list(&ac->ac_aliases, pstrcmp); ModBits |= AC; } else { err1("%s: already in alias", (char *)ac->ac_name); continue; } } if (!instrlist(&al->al_addresses, (char *)addressv[indx])) { strlistadd(&al->al_addresses, (char *)addressv[indx]); added++; } else if (!ac) err1("%s: already in alias", (char *)addressv[indx]); else { err1("%s: unique membership noted", (char *)ac->ac_name); notes++; } } if (added) { sort_list(&al->al_addresses, pstrcmp); ModBits |= AL; (void) printf("%d added\n", added); } else if (!notes) err("no change"); non_critical(); return; } #endif addtoclass(c, v) int c; addr *v; { struct account *ac; struct class *cs; addr *userv; int cc, added = 0; register int indx; #ifdef SENDMAIL struct alias *al; register int j; #endif 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; } userv = get_gpa(65); GetLine("Users: ", 64, &cc, userv, &Users); if (cc == 0) { err("no change"); return; } critical(); for (indx=0; indx < cc; indx++) { ac = getacnam((char *)userv[indx]); if (!ac) { err1("%s: no such user", (char *)userv[indx]); continue; } if (instrlist(&ac->ac_classes, (char *)v[1])) { err1("%s: already is in class\n", (char *)userv[indx]); continue; } strlistadd(&ac->ac_classes, (char *)v[1]); sort_list(&ac->ac_classes, pstrcmp); #ifdef SENDMAIL for (j=0; j < cs->cs_aliases.l_count; j++) { al = getalnam((char *)cs->cs_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 added++; } if (added) { ModBits |= AC; (void) printf("%d added\n", added); } else err("no change"); non_critical(); return; } addtogroup(c, v) int c; addr *v; { struct account *ac; struct groupmap *gm; addr *userv; int cc, added = 0; register int indx; #ifdef SENDMAIL struct alias *al; register int j; #endif if ( c > 2 ) { err1("%s: too many arguments", (char *)v[0]); return; } if (c != 2) { err1("usage: %s <group>", (char *)v[0]); return; } gm = getgmnam((char *)v[1]); if (!gm) { err1("%s: no such group", (char *)v[1]); return; } userv = get_gpa(65); GetLine("Users: ", 64, &cc, userv, &Users); if (cc == 0) { err("no change"); return; } critical(); for (indx=0; indx < cc; indx++) { if (instrlist(&gm->gm_mem, (char *)userv[indx])) { err1("%s: is in group", (char *)userv[indx]); continue; } ac = getacnam((char *)userv[indx]); if (!ac) { err1("%s: no such user", (char *)userv[indx]); continue; } strlistadd(&ac->ac_groups, (char *)v[1]); strlistadd(&gm->gm_mem, (char *)userv[indx]); sort_list(&ac->ac_groups, pstrcmp); #ifdef SENDMAIL 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 added++; } if (added) { ModBits |= AC|GR; sort_list(&gm->gm_mem, pstrcmp); (void) printf("%d added\n", added); } else err("no change"); non_critical(); return; } addtosig(c, v) int c; addr *v; { struct account *ac; struct sig *sg; addr *userv; int cc, added = 0; register int indx; #ifdef SENDMAIL struct alias *al; register int j; #endif 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; } userv = get_gpa(65); GetLine("Users: ", 64, &cc, userv, &Users); if (cc == 0) { err("no change"); return; } critical(); for (indx=0; indx < cc; indx++) { ac = getacnam((char *)userv[indx]); if (!ac) { err1("%s: no such user", (char *)userv[indx]); continue; } if (instrlist(&ac->ac_sigs, (char *)v[1])) { err1("%s: already is in sig", (char *)userv[indx]); continue; } strlistadd(&ac->ac_sigs, (char *)v[1]); sort_list(&ac->ac_sigs, pstrcmp); #ifdef SENDMAIL for (j=0; j < sg->sg_aliases.l_count; j++) { al = getalnam((char *)sg->sg_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 added++; } if (added) { ModBits |= AC; (void) printf("%d added\n", added); } else err("no change"); non_critical(); return; } adduser(c, v) int c; addr *v; { struct account *aa; struct groupmap *gm; addr *realnamev, *idv, *passwdv, *groupv, *uidv, *shellv; addr username, def_dir, *dirv; addr shell, dir; addr password[SHORT_BUF]; char prompt[MEDIUM_BUF], prompt2[MEDIUM_BUF], *salt; int cc, uid, n; addr_t cap[SHORT_BUF]; if ( c > 2 ) { err1("%s: too many arguments", (char *)v[0]); return; } if (c > 1 && userexists((char *)v[1])) { err1("%s: user exists", (char *) v[1]); return; } if (c > 1) { (void) strcpy((char *)cap, (char *)v[1]); capitalize((char *)cap); rnlist.l_count = 1; rnlist.l_list[0] = cap; } else rnlist.l_count = 0; realnamev = get_gpa(17); do { GetLine("Real Name: ", 16, &cc, realnamev, &rnlist); } while (cc == 0 && clear_gpa(realnamev, 17)); /* * If we were handed a username, take it. If not, we must manufacture * one from the Real Name. */ if (c > 1) username = v[1]; else { username = makeusername(cc, realnamev); (void) printf("login name is \"%s\"\n", username); } /* * Unique identification, like SSN */ idv = get_gpa(2); do { GetLine("Id: ", 1, &cc, idv, &idlist); } while (cc == 0 && clear_gpa(idv, 2)); if (!eq(*idv, "exception") && (aa = getacid((char *)*idv))) { (void) sprintf(prompt, "%s shares that id. continue? [no] ", (char *)aa->ac_name); if (no(prompt)) return; } /* * Give the user a password */ (void) sprintf(prompt, "Password [%s]: ", *idv); passwdv = get_gpa(2); GetLine(prompt, 1, &cc, passwdv, &pwlist); if (cc) if (eq(*passwdv, "none")) (void) strcpy((char *)password, ""); else if (eq(*passwdv, "unused")) (void) strcpy((char *)password, "*"); else if (eq(*passwdv, "generate")) { (void) strcpy((char *)password, makepass()); (void) printf("password is \"%s\"\n", password); } else { salt = CRYPT_SALT; (void) strcpy((char *)password, crypt((char *)*passwdv, salt)); } else { salt = CRYPT_SALT; (void) strcpy((char *)password, crypt((char *)*idv, salt)); } (void) sprintf(prompt, "Group [%s]: ", DEF_GROUP); groupv = get_gpa(2); do { GetLine(prompt, 1, &cc, groupv, &Groups); if (cc) { gm = getgmnam((char *)*groupv); if (!gm) err1("%s: no such group", (char *)*groupv); else break; } else { gm = getgmnam(DEF_GROUP); if (!gm) { err1("%s: no such group", DEF_GROUP); continue; } break; } } while (clear_gpa(groupv, 2)); uid = findnextuid(gm->gm_name); if (uid == NOMORE) { err1("no more free uids for group %s!", gm->gm_name); return; } (void) sprintf(prompt, "Uid [%d]: ", uid); uidv = get_gpa(2); do { GetLine(prompt, 1, &cc, uidv, &Null_List); if (cc) { if (!validint((char *)*uidv)) { err1("%s makes no sense to me", (char *)*uidv); continue; } n = atoi((char *)*uidv); aa = getacuid(n); if (aa) { (void) sprintf(prompt2, "%s shares that uid, use anyway? ", aa->ac_name); if (yesno(prompt2)) { uid = n; break; } } else { uid = n; break; } } else break; } while (clear_gpa(uidv, 2)); /* * Shell */ (void) sprintf(prompt, "Shell [%s]: ", DEF_SHELL); shellv = get_gpa(2); GetLine(prompt, 1, &cc, shellv, &Shells); shell = (cc == 0) ? DEF_SHELL : *shellv; /* * Home directory. */ def_dir = gethomedir((char *)username, gm->gm_name); (void) sprintf(prompt, "Home [%s]: ", def_dir); dirv = get_gpa(2); GetFilenames(prompt, 1, &cc, dirv); dir = (cc == 0) ? def_dir : *dirv; addu(uid, gm->gm_gid, username, glob(realnamev), (addr)password, *idv, dir, shell); #ifndef DOFILES err("Don't forget to create this user's directory!"); #endif puts("added"); return; } addvig(c, v) int c; addr *v; { if ( c > 2 ) { err1("%s: too many arguments", (char *)v[0]); return; } if (c != 2) { err1("usage: %s <name>", (char *)v[0]); return; } if (!groupexists((char *)v[1])) { err1("%s: no such group", (char *)v[1]); return; } critical(); strlistadd(&Vigs, (char *)v[1]); sort_list(&Vigs, pstrcmp); ModBits |= VG; puts("added"); non_critical(); return; } addu(uid, gid, username, realname, password, id, dir, shell) int uid, gid; addr username, realname, password, id, dir, shell; { struct account ac; #ifdef SENDMAIL struct groupmap *gm; struct alias *al; register int j; #endif #ifdef DOFILES int zero = 0; #endif critical(); #ifdef SENDMAIL zerolist(&ac.ac_aliases); #endif zerolist(&ac.ac_groups); zerolist(&ac.ac_sigs); zerolist(&ac.ac_classes); ac.ac_uid = uid; ac.ac_gid = gid; savestr((char **)&ac.ac_name, (char *)username); savestr((char **)&ac.ac_realname, (char *)realname); savestr((char **)&ac.ac_gecos, (char *)realname); savestr((char **)&ac.ac_passwd, (char *)password); savestr((char **)&ac.ac_id, (char *)id); savestr((char **)&ac.ac_dir, (char *)dir); savestr((char **)&ac.ac_shell, (char *)shell); ac.ac_ll.ll_time = (time_t) 0; (void) strncpy(ac.ac_ll.ll_line, "", sizeof ac.ac_ll.ll_line); (void) strncpy(ac.ac_ll.ll_host, "", sizeof ac.ac_ll.ll_host); genlistadd(&AccountList, (addr) &ac, sizeof (struct account)); sort_list(&AccountList, acctcmp); strlistadd(&Users, (char *)ac.ac_name); sort_list(&Users, pstrcmp); #ifdef DOFILES add_job(JB_MKDIR, ac.ac_dir, (addr)&ac.ac_uid, (addr)&zero); #endif add_job(JB_LASTLOG, (addr) &ac.ac_uid, (addr)&ac.ac_ll, NIL); ModBits |= (AC|PW); #ifdef SENDMAIL gm = getgmgid(ac.ac_gid); 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 non_critical(); return; }