|
|
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 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;
}