home *** CD-ROM | disk | FTP | other *** search
- Subject: v08i048: Account creation/manipulation program, Part08/08
- Newsgroups: mod.sources
- Approved: mirror!rs
-
- Submitted by: Kyle Jones <xanth!kyle>
- Mod.sources: Volume 8, Issue 48
- Archive-name: mcp/Part08
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line,
- # then unpack it by saving it in a file and typing "sh file".
- # If all goes well, you will see the message "End of archive 8 (of 8)."
- # Contents: src/save.c src/save.h src/shell.c src/sig.c src/sig.h
- # src/signals.c src/sort.c src/sort.h src/sysdep.h src/tty.c
- # src/version.c src/yesno.c src/update.c
- # Wrapped by rs@mirror on Fri Feb 6 15:56:15 1987
- PATH=/bin:/usr/bin:/usr/ucb; export PATH
- echo shar: extracting "'src/save.c'" '(8666 characters)'
- if test -f 'src/save.c' ; then
- echo shar: will not over-write existing file "'src/save.c'"
- else
- sed 's/^X//' >src/save.c <<'@//E*O*F src/save.c//'
- X/**************************************************************************\
- X* *
- X* save.c *
- X* *
- X* These are the routines that save the information into the respective *
- X* accounting files. An important thing to remember here is that the save *
- X* and checkpointing routines USE THE SAME TEMPORARY FILES. So no *
- X* checkpointing must be done while saving is being done, and vice versa. *
- X* Conflicts are avoided by blocking the all signals that would trigger *
- X* either periodic or crash checkpointing, until saving is complete. *
- X* *
- X* Also the tempfiles must be in the same filesystem as their associated *
- X* accounting files or the rename() system call will fail attempting to *
- X* link the tempfile to the accounting file with errno == EXDEV. *
- X* *
- X\**************************************************************************/
- X
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <signal.h>
- X#include <lastlog.h>
- X#include <strings.h>
- X#include "sysdep.h"
- X#include "macros.h"
- X#include "mem.h"
- X#include "lists.h"
- X#include "account.h"
- X#ifdef SENDMAIL
- X#include "alias.h"
- X#endif
- X#include "class.h"
- X#include "sig.h"
- X#include "range.h"
- X#include "groupmap.h"
- X#include "save.h"
- X
- Xextern int ModBits;
- Xextern time_t PWLockTime, time();
- X
- X#ifdef SENDMAIL
- Xextern struct list AliasList;
- X#endif
- Xextern struct list AccountList, GroupMapList, SigList, ClassList, RangeList;
- Xextern struct list Vigs;
- X
- Xsave_pw()
- X
- X{
- X FILE *pwf;
- X int i;
- X struct account *ac;
- X#ifdef BSD4_3
- X char *av[4];
- X char tmpdotdir[MEDIUM_BUF], tmpdotpag[MEDIUM_BUF];
- X char dotdir[MEDIUM_BUF], dotpag[MEDIUM_BUF];
- X#endif
- X
- X pwf = fopen(PWDTMP, "w");
- X if (pwf == NULL) {
- X perr(PWDTMP);
- X return;
- X }
- X for (i=0; i < AccountList.l_count; i++) {
- X ac = (struct account *) AccountList.l_list[i];
- X (void) fprintf(pwf, "%s:%s:%d:%d:%s:%s:%s\n",
- X ac->ac_name,
- X ac->ac_passwd,
- X ac->ac_uid,
- X ac->ac_gid,
- X ac->ac_gecos,
- X ac->ac_dir,
- X ac->ac_shell);
- X }
- X (void) fclose(pwf);
- X#ifdef BSD4_3
- X (void) strcpy(tmpdotdir, PWDTMP);
- X (void) strcpy(tmpdotpag, PWDTMP);
- X (void) strcpy(dotdir, PWDFILE);
- X (void) strcpy(dotpag, PWDFILE);
- X (void) strcat(tmpdotdir, ".dir");
- X (void) strcat(tmpdotpag, ".pag");
- X (void) strcat(dotdir, ".dir");
- X (void) strcat(dotpag, ".pag");
- X (void) unlink(tmpdotdir);
- X (void) unlink(tmpdotpag);
- X av[0] = "shell-escape";
- X av[1] = DBMPASSWORD;
- X av[2] = PWDTMP;
- X av[3] = (char *) 0;
- X if (shellescape(3, (addr *)av) != 0) {
- X err1("%s failed", DBMPASSWORD);
- X return;
- X }
- X if (rename(tmpdotdir, dotdir) == -1) {
- X perr("rename");
- X err2("%s -> %s rename failed", tmpdotdir, dotdir);
- X return;
- X }
- X if (rename(tmpdotpag, dotpag) == -1) {
- X perr("rename");
- X err2("%s -> %s rename failed", tmpdotdir, dotdir);
- X return;
- X }
- X#endif
- X if (rename(PWDTMP, PWDFILE) == -1) {
- X perr(PWDTMP);
- X return;
- X }
- X ModBits &= ~PW;
- X (void) unlink(PWDCKP);
- X return;
- X}
- X
- X#ifdef SENDMAIL
- Xsave_al()
- X
- X{
- X FILE *alf, *bindf;
- X struct alias *al;
- X char *av[3];
- X register int i;
- X
- X alf = fopen(ALIASTMP, "w");
- X if (alf == NULL) {
- X perr(ALIASTMP);
- X return;
- X }
- X bindf = fopen(ALBINDTMP, "w");
- X if (bindf == NULL) {
- X perr(ALBINDTMP);
- X (void) fclose(alf);
- X return;
- X }
- X for (i=0; i < AliasList.l_count; i++) {
- X al = (struct alias *) AliasList.l_list[i];
- X (void) fprintf(alf, "%s:", al->al_name);
- X listout(&al->al_addresses, alf);
- X fputs("\n", alf);
- X (void) fprintf(bindf, "%s:", al->al_name);
- X listout(&al->al_groups, bindf);
- X fputs(":", bindf);
- X listout(&al->al_classes, bindf);
- X fputs(":", bindf);
- X listout(&al->al_sigs, bindf);
- X fputs("\n", bindf);
- X }
- X (void) fclose(alf);
- X (void) fclose(bindf);
- X av[0] = "shell-escape";
- X av[1] = NEWALIASES;
- X av[2] = (char *)0;
- X if (rename(ALIASTMP, ALIASFILE) == -1) {
- X perr(ALIASTMP);
- X return;
- X }
- X if (rename(ALBINDTMP, ALBIND) == -1) {
- X perr(ALBINDTMP);
- X return;
- X }
- X if (shellescape(2, (addr *) av) != 0) {
- X err1("newaliases seemed unhappy with %s", ALIASFILE);
- X return;
- X }
- X ModBits &= ~AL;
- X (void) unlink(ALIASCKP);
- X (void) unlink(ALBINDCKP);
- X}
- X#endif
- X
- Xsave_ac()
- X
- X{
- X FILE *acf;
- X register int i;
- X struct account *ac;
- X
- X acf = fopen(ACTMP, "w");
- X if (acf == NULL) {
- X perr(ACTMP);
- X return;
- X }
- X for (i=0; i < AccountList.l_count; i++) {
- X ac = (struct account *) AccountList.l_list[i];
- X (void) fprintf(acf, "%s:%s:%s:%d:%d:",
- X ac->ac_name,
- X ac->ac_realname,
- X ac->ac_id,
- X ac->ac_uid,
- X ac->ac_gid);
- X listout(&ac->ac_groups, acf);
- X fputs(":", acf);
- X listout(&ac->ac_classes, acf);
- X fputs(":", acf);
- X listout(&ac->ac_sigs, acf);
- X fputs(":", acf);
- X#ifdef SENDMAIL
- X listout(&ac->ac_aliases, acf);
- X#endif
- X fputs("\n", acf);
- X }
- X (void) fclose(acf);
- X if (rename(ACTMP, ACFILE) == -1) {
- X perr(ACTMP);
- X return;
- X }
- X ModBits &= ~AC;
- X (void) unlink(ACCKP);
- X return;
- X}
- X
- Xsave_gr()
- X
- X{
- X FILE *grf;
- X register int i;
- X struct groupmap *gm;
- X
- X grf = fopen(GRPTMP, "w");
- X if (grf == NULL) {
- X perr(GRPTMP);
- X return;
- X }
- X for (i=0; i < GroupMapList.l_count; i++) {
- X gm = (struct groupmap *) GroupMapList.l_list[i];
- X (void) fprintf(grf, "%s:%s:%d:",
- X gm->gm_name,
- X gm->gm_passwd,
- X gm->gm_gid);
- X listout(&gm->gm_mem, grf);
- X fputs("\n", grf);
- X }
- X (void) fclose(grf);
- X if (rename(GRPTMP, GRPFILE) == -1) {
- X perr(GRPTMP);
- X return;
- X }
- X ModBits &= ~GR;
- X (void) unlink(GRPCKP);
- X return;
- X}
- X
- Xsave_cs()
- X
- X{
- X struct class *cs;
- X register int i;
- X FILE *csf;
- X
- X csf = fopen(CSTMP, "w");
- X if (csf == NULL) {
- X perr(CSTMP);
- X return;
- X }
- X for (i=0; i < ClassList.l_count; i++) {
- X cs = (struct class *) ClassList.l_list[i];
- X (void) fprintf(csf, "%s %d %d\n", cs->cs_name, cs->cs_dsize,
- X cs->cs_exptime);
- X (void) fprintf(csf, "%s", cs->cs_desc);
- X }
- X (void) fclose(csf);
- X if (rename(CSTMP, CSFILE) == -1) {
- X perr(CSTMP);
- X return;
- X }
- X ModBits &= ~CS;
- X (void) unlink(CSCKP);
- X return;
- X}
- X
- Xsave_sg()
- X
- X{
- X struct sig *sg;
- X register int i;
- X FILE *sgf;
- X
- X sgf = fopen(SIGTMP, "w");
- X if (sgf == NULL) {
- X perr(SIGTMP);
- X return;
- X }
- X for (i=0; i < SigList.l_count; i++) {
- X sg = (struct sig *) SigList.l_list[i];
- X (void) fprintf(sgf, "%s %d %d\n", sg->sg_name, sg->sg_dsize,
- X sg->sg_exptime);
- X (void) fprintf(sgf, "%s", sg->sg_desc);
- X }
- X (void) fclose(sgf);
- X if (rename(SIGTMP, SIGFILE) == -1) {
- X perr(SIGTMP);
- X return;
- X }
- X ModBits &= ~SG;
- X (void) unlink(SIGCKP);
- X return;
- X}
- X
- Xsave_rg()
- X
- X{
- X struct range *rg;
- X register int i;
- X FILE *rgf;
- X
- X rgf = fopen(RANGETMP, "w");
- X if (rgf == NULL) {
- X perr(RANGETMP);
- X return;
- X }
- X for (i=0; i < RangeList.l_count; i++) {
- X rg = (struct range *) RangeList.l_list[i];
- X (void) fprintf(rgf, "%s\t%d\t%d\t%s\n",
- X rg->rg_name,
- X rg->rg_from,
- X rg->rg_to,
- X (rg->rg_mode == RG_SHARED ? "shared" : "exclusive"));
- X }
- X (void) fclose(rgf);
- X if (rename(RANGETMP, RANGEFILE) == -1) {
- X perr(RANGETMP);
- X return;
- X }
- X ModBits &= ~RG;
- X (void) unlink(RANGECKP);
- X return;
- X}
- X
- Xsave_vg()
- X
- X{
- X register int i;
- X FILE *vgf;
- X
- X vgf = fopen(VIGTMP, "w");
- X if (vgf == NULL) {
- X perr(VIGTMP);
- X return;
- X }
- X for (i=0; i < Vigs.l_count; i++)
- X (void) fprintf(vgf, "%s\n", Vigs.l_list[i]);
- X (void) fclose(vgf);
- X if (rename(VIGTMP, VIGFILE) == -1) {
- X perr(VIGTMP);
- X return;
- X }
- X ModBits &= ~VG;
- X (void) unlink(VIGCKP);
- X return;
- X}
- X
- Xsaveandexit()
- X
- X{
- X savechanges();
- X exitmcp();
- X}
- X
- Xsavechanges()
- X
- X{
- X if (ModBits == 0 || lock_check() == 0)
- X return;
- X /*
- X * Interrupts are disabled for obvious reasons.
- X * SIGTERM, SIGALRM, SIGHUP, and SIGQUIT must be blocked because
- X * the save and checkpoint routines use the same tempfiles.
- X * If a checkpoint were to occur while files where being saved,
- X * chaos would ensue.
- X */
- X critical();
- X
- X do_jobs();
- X
- X (ModBits&PW) && backup(PW) && save_pw();
- X (ModBits&AC) && backup(AC) && save_ac();
- X#ifdef SENDMAIL
- X (ModBits&AL) && backup(AL) && save_al();
- X#endif
- X (ModBits&CS) && backup(CS) && save_cs();
- X (ModBits&GR) && backup(GR) && save_gr();
- X (ModBits&RG) && backup(RG) && save_rg();
- X (ModBits&SG) && backup(SG) && save_sg();
- X (ModBits&VG) && backup(VG) && save_vg();
- X sync();
- X (void) time(&PWLockTime);
- X
- X non_critical();
- X return;
- X}
- X
- Xstatic char *acctfile[] = {
- X PWDFILE,
- X ACFILE,
- X#ifdef SENDMAIL
- X ALIASFILE,
- X ALBIND,
- X#endif
- X CSFILE,
- X GRPFILE,
- X RANGEFILE,
- X SIGFILE,
- X VIGFILE,
- X (char *) 0
- X};
- X
- Xint
- Xlock_check()
- X
- X{
- X register int i;
- X struct stat s;
- X int uhoh = 0;
- X
- X if (!fileexists(PWDLOCK)) {
- X err1("My %s lockfile has been been removed!", PWDLOCK);
- X if (yesno("Do the save anyway? ") == 0)
- X return 0;
- X }
- X for (i=0; acctfile[i]; i++) {
- X if (stat(acctfile[i], &s) == -1)
- X continue;
- X if (s.st_mtime > PWLockTime) {
- X err1("%s has been modified", acctfile[i]);
- X uhoh = 1;
- X }
- X }
- X if (uhoh) {
- X err1("My %s lock has been violated.", PWDLOCK);
- X err("");
- X return yesno("Do the save anyway? ");
- X }
- X return 1;
- X}
- @//E*O*F src/save.c//
- if test 8666 -ne "`wc -c <'src/save.c'`"; then
- echo shar: error transmitting "'src/save.c'" '(should have been 8666 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'src/save.h'" '(601 characters)'
- if test -f 'src/save.h' ; then
- echo shar: will not over-write existing file "'src/save.h'"
- else
- sed 's/^X//' >src/save.h <<'@//E*O*F src/save.h//'
- X/**********************************************************************\
- X* *
- X* save.h *
- X* *
- X* Definitions for ModBits flags which determine which files have been *
- X* modified. *
- X* *
- X\**********************************************************************/
- X
- X#define AC 0x01 /* accounts */
- X#ifdef SENDMAIL
- X#define AL 0x02 /* aliases or alias bindings */
- X#endif
- X#define CS 0x04 /* classes */
- X#define GR 0x08 /* group */
- X#define PW 0x10 /* passwd */
- X#define RG 0x20 /* ranges */
- X#define SG 0x40 /* sigs */
- X#define VG 0x80 /* vigs */
- @//E*O*F src/save.h//
- if test 601 -ne "`wc -c <'src/save.h'`"; then
- echo shar: error transmitting "'src/save.h'" '(should have been 601 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'src/shell.c'" '(3616 characters)'
- if test -f 'src/shell.c' ; then
- echo shar: will not over-write existing file "'src/shell.c'"
- else
- sed 's/^X//' >src/shell.c <<'@//E*O*F src/shell.c//'
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/time.h>
- X#include <sys/resource.h>
- X#include <sys/ioctl.h>
- X#include <sys/wait.h>
- X#include <signal.h>
- X#include <strings.h>
- X#include "sysdep.h"
- X#include "macros.h"
- X#include "mem.h"
- X
- X#ifdef BSD4_3
- Xuid_t getuid();
- Xgid_t getgid();
- X#endif
- X
- X#define NILRUSAGE (struct rusage *) 0
- X
- Xchar *getenv();
- X
- Xextern addr DEF_SHELL;
- Xextern int DevTty, kids;
- X
- Xint
- Xshellescape(c, v)
- Xint c;
- Xaddr *v;
- X
- X{
- X int kidpid, mypgrp, newpgrp, pid, omask, exitcode = 0;
- X union wait status;
- X
- X mypgrp = getpgrp(0);
- X
- X c--; v++;
- X /*
- X * Don't want to be interrupted while forking and leave zombies
- X * and things floating around. WHo knows what happens when the
- X * parent is interrupted in the midst of a vfork() ?
- X */
- X critical();
- X kidpid = vfork();
- X if (kidpid == -1) {
- X perr("vfork failed!");
- X return -1;
- X }
- X non_critical();
- X
- X if (kidpid) {
- X /*
- X * Do nothing here, because we are the parent; we should go
- X * directly to the wait loop.
- X */
- X }
- X else if (c == 0) {
- X char *shell = getenv("SHELL");
- X char *sname;
- X
- X if (!shell)
- X shell = (char *)DEF_SHELL;
- X if (!kidpid) {
- X sname = rindex(shell, '/');
- X sname = (sname ? sname+1 : shell);
- X pid = getpid();
- X (void) ioctl(DevTty, TIOCSPGRP, (char *)&pid);
- X (void) setpgrp(0, pid);
- X (void) setuid(getuid()); /* better safe than... */
- X (void) setgid(getgid()); /* ... */
- X execl(shell, sname, 0);
- X perr(shell);
- X _exit(1);
- X }
- X }
- X else {
- X if (!kidpid) {
- X pid = getpid();
- X (void) ioctl(DevTty, TIOCSPGRP, (char *)&pid);
- X (void) setpgrp(0, pid);
- X (void) setuid(getuid());
- X (void) setgid(getgid());
- X execvp((char *)*v, (char **)v);
- X perr((char *)*v);
- X _exit(1);
- X }
- X }
- X for (;;) {
- X /*
- X * KLUDGE ALERT! BATTLE STATIONS...
- X *
- X * Here we temporarily block possible SIGALRM's that
- X * might be generated when mcp wants to checkpoint itself.
- X * This is due to a bug in wait3() (4.2 BSD). If the signal
- X * were processed while in wait3(), the wait3() would be
- X * restarted >>without<< the WUNTRACED option, which would
- X * cause a deadlock here if the child were to stop.
- X *
- X * SIGALRM will be released once the child
- X * has terminated.
- X */
- X omask = sigblock(mask(SIGALRM));
- X
- X pid = wait3(&status, WUNTRACED, NILRUSAGE);
- X if (pid == 0)
- X continue;
- X else if (pid > 0 && pid != kidpid) {
- X /*
- X * Apparently this isn't the child we just spawned
- X * (could be an omnichown that terminated), so
- X * we note its passing.
- X */
- X kids--;
- X continue;
- X }
- X if (WIFSTOPPED(status)) {
- X /*
- X * The child has stopped due to some signal,
- X * so mcp stops itself with the same signal
- X * to achieve transparency.
- X */
- X (void) kill(getpid(), (int)status.w_stopsig);
- X /*
- X * We've been continued, but the our parent
- X * (the shell) has given us back the tty, so
- X * we must pass it back to the child before
- X * continuing it.
- X */
- X (void) setpgrp(kidpid, kidpid);
- X (void) ioctl(DevTty, TIOCSPGRP, (char *)&kidpid);
- X /*
- X * Now set the child in motion...
- X */
- X (void) killpg(kidpid, SIGCONT);
- X /*
- X * And keep waiting...
- X */
- X continue;
- X }
- X break;
- X }
- X
- X /*
- X * Note if anything went amiss.
- X */
- X if (status.w_termsig != 0)
- X exitcode = status.w_termsig;
- X if (status.w_retcode != 0)
- X exitcode = status.w_retcode;
- X /*
- X * Child has exited, so now we can release any pending
- X * SIGALRM.
- X */
- X (void) sigsetmask(omask);
- X
- X /*
- X * Take command of the tty again.
- X */
- X (void) ioctl(DevTty, TIOCGPGRP, (char *)&newpgrp);
- X (void) setpgrp(0, newpgrp);
- X (void) ioctl(DevTty, TIOCSPGRP, (char *)&mypgrp);
- X (void) setpgrp(0, mypgrp);
- X
- X return exitcode;
- X}
- @//E*O*F src/shell.c//
- if test 3616 -ne "`wc -c <'src/shell.c'`"; then
- echo shar: error transmitting "'src/shell.c'" '(should have been 3616 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'src/sig.c'" '(1855 characters)'
- if test -f 'src/sig.c' ; then
- echo shar: will not over-write existing file "'src/sig.c'"
- else
- sed 's/^X//' >src/sig.c <<'@//E*O*F src/sig.c//'
- X#include <sys/types.h>
- X#include <sys/file.h>
- X#include <stdio.h>
- X#include "sysdep.h"
- X#include "mem.h"
- X#include "lists.h"
- X#include "sig.h"
- X
- Xextern struct list SigList;
- Xextern int ssigcmp();
- Xlong lseek();
- X
- Xstatic char sdesc[DESCSIZE+1], sname[SHORT_BUF], ssize[SHORT_BUF];
- Xstatic char sexp[SHORT_BUF];
- Xstruct sig sg = { sname, 0, (time_t)0, sdesc };
- X
- Xint SG_FileDes = UNDEFINED;
- X
- Xsetsgent()
- X
- X{
- X if (SG_FileDes == UNDEFINED) {
- X SG_FileDes = open(SIGFILE, O_RDONLY);
- X if (SG_FileDes < 0) {
- X perr(SIGFILE);
- X goodbye(1);
- X }
- X }
- X lseek(SG_FileDes, (long) 0, L_SET)<0 &&
- X perr("setsgent: lseek failed?!");
- X return;
- X}
- X
- Xendsgent()
- X
- X{
- X if (SG_FileDes == UNDEFINED)
- X return;
- X (void) close(SG_FileDes);
- X SG_FileDes = UNDEFINED;
- X return;
- X}
- X
- Xstruct sig *
- Xgetsgent()
- X
- X{
- X register int i;
- X char c;
- X
- X if (SG_FileDes == UNDEFINED)
- X setsgent();
- X#ifdef SENDMAIL
- X zerolist(&sg.sg_aliases);
- X#endif
- X i = 0;
- X while (read(SG_FileDes, &c, 1) != 0) {
- X c &= 0177;
- X if (c == ' ')
- X break;
- X sname[i++] = c;
- X }
- X sname[i] = '\0';
- X if (i == 0)
- X return (struct sig *)0;
- X i = 0;
- X while (read(SG_FileDes, &c, 1) != 0) {
- X c &= 0177;
- X if (c == ' ')
- X break;
- X ssize[i++] = c;
- X }
- X ssize[i] = '\0';
- X if (i == 0)
- X return (struct sig *)0;
- X i = 0;
- X while (read(SG_FileDes, &c, 1) != 0) {
- X c &= 0177;
- X if (c == '\n')
- X break;
- X sexp[i++] = c;
- X }
- X sexp[i] = '\0';
- X if (i == 0)
- X return (struct sig *)0;
- X /* result of intermediate assignment used in read() to stifle lint */
- X sg.sg_dsize = i = atoi(ssize);
- X sg.sg_exptime = atoi(sexp);
- X if (read(SG_FileDes, sg.sg_desc, i) != sg.sg_dsize)
- X fatal1("%s: bad file format", SIGFILE);
- X sg.sg_desc[sg.sg_dsize] = '\0';
- X return(&sg);
- X}
- X
- Xstruct sig *
- Xgetsgnam(name)
- Xchar *name;
- X
- X{
- X int indx, found;
- X
- X indx = search_list(&SigList, name, ssigcmp, &found);
- X if (found)
- X return (struct sig *) SigList.l_list[indx];
- X return (struct sig *) 0;
- X}
- @//E*O*F src/sig.c//
- if test 1855 -ne "`wc -c <'src/sig.c'`"; then
- echo shar: error transmitting "'src/sig.c'" '(should have been 1855 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'src/sig.h'" '(298 characters)'
- if test -f 'src/sig.h' ; then
- echo shar: will not over-write existing file "'src/sig.h'"
- else
- sed 's/^X//' >src/sig.h <<'@//E*O*F src/sig.h//'
- Xstruct sig {
- X char *sg_name;
- X off_t sg_dsize; /* description size (bytes) */
- X time_t sg_exptime; /* expiration date (0=never) */
- X char *sg_desc; /* pointer to description */
- X#ifdef SENDMAIL
- X struct list sg_aliases; /* aliases sig is bound to */
- X#endif
- X};
- X
- Xstruct sig *getsgent(), *getsgnam();
- @//E*O*F src/sig.h//
- if test 298 -ne "`wc -c <'src/sig.h'`"; then
- echo shar: error transmitting "'src/sig.h'" '(should have been 298 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'src/signals.c'" '(1569 characters)'
- if test -f 'src/signals.c' ; then
- echo shar: will not over-write existing file "'src/signals.c'"
- else
- sed 's/^X//' >src/signals.c <<'@//E*O*F src/signals.c//'
- X#include <stdio.h>
- X#include <setjmp.h>
- X#include <signal.h>
- X#include "sysdep.h"
- X#include "macros.h"
- X
- Xextern jmp_buf interrupt;
- Xstatic int critlevel, handling_yet;
- X#if CKPTIME > 0
- Xextern int wakeup();
- X#endif
- X
- X#ifdef sun
- X#define sighandler (void (*)())
- X#else
- X#define sighandler (int (*)())
- X#endif
- X
- Xint_hand()
- X
- X{
- X (void) fflush(stdout);
- X longjmp(interrupt, SIGINT);
- X}
- X
- Xhup_hand() { panic("Hangup received"); }
- Xterm_hand() { panic("Terminate signal received"); }
- Xquit_hand() { panic("Quit signal received"); }
- X
- Xsetsignals()
- X
- X{
- X extern int root;
- X
- X (void) signal(SIGQUIT, sighandler quit_hand);
- X (void) signal(SIGINT, sighandler int_hand);
- X if (root) {
- X (void) signal(SIGHUP, sighandler hup_hand);
- X (void) signal(SIGTERM, sighandler term_hand);
- X#if CKPTIME > 0
- X (void) signal(SIGALRM, sighandler wakeup);
- X#endif
- X }
- X (void) sigsetmask(0);
- X handling_yet = 1;
- X}
- X
- Xtstp()
- X
- X{
- X (void) kill(getpid(), SIGTSTP);
- X return;
- X}
- X
- X/*
- X * Keep user from interrupting the program during a critical section
- X * of code. Used when updating interdependent data structures to insure
- X * consistency. Also used by the memory management routines to make sure
- X * allocations and free's are atomic.
- X */
- Xcritical()
- X
- X{
- X if (!handling_yet) return;
- X if (!critlevel++) {
- X (void) signal(SIGINT, sighandler SIG_IGN);
- X (void) sigsetmask(mask(SIGHUP)|mask(SIGTERM)|
- X mask(SIGQUIT)|mask(SIGALRM));
- X }
- X return;
- X}
- X
- X/*
- X * Critical's other half
- X */
- Xnon_critical()
- X
- X{
- X if (!handling_yet) return;
- X if (!--critlevel) {
- X (void) signal(SIGINT, sighandler int_hand);
- X (void) sigsetmask(0);
- X }
- X return;
- X}
- @//E*O*F src/signals.c//
- if test 1569 -ne "`wc -c <'src/signals.c'`"; then
- echo shar: error transmitting "'src/signals.c'" '(should have been 1569 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'src/sort.c'" '(1838 characters)'
- if test -f 'src/sort.c' ; then
- echo shar: will not over-write existing file "'src/sort.c'"
- else
- sed 's/^X//' >src/sort.c <<'@//E*O*F src/sort.c//'
- X#include <sys/types.h>
- X#include <lastlog.h>
- X#include "sysdep.h"
- X#include "mem.h"
- X#include "lists.h"
- X#include "account.h"
- X#ifdef SENDMAIL
- X#include "alias.h"
- X#endif
- X#include "class.h"
- X#include "command.h"
- X#include "sig.h"
- X#include "range.h"
- X#include "groupmap.h"
- X
- X#ifdef SENDMAIL
- Xint aliascmp(a, aa)
- Xstruct alias **a, **aa;
- X
- X{
- X return strcmp((char *)((*a)->al_name), (char *)((*aa)->al_name));
- X}
- X
- Xint saliascmp(s, a)
- Xchar *s;
- Xstruct alias *a;
- X
- X{
- X return strcmp(s, a->al_name);
- X}
- X#endif
- X
- Xint acctcmp(a, aa)
- Xstruct account **a, **aa;
- X
- X{
- X register int cmpval;
- X
- X cmpval = (*a)->ac_uid - (*aa)->ac_uid;
- X if (cmpval != 0) return cmpval;
- X return strcmp((char *)((*a)->ac_name), (char *)((*aa)->ac_name));
- X}
- X
- Xint iacctcmp(n, a)
- Xint *n;
- Xstruct account *a;
- X
- X{
- X return *n - a->ac_uid;
- X}
- X
- Xint commcmp(c, cc)
- Xstruct command *c, *cc;
- X
- X{
- X return strcmp(c->c_name, cc->c_name);
- X}
- X
- Xint scommcmp(s, c)
- Xchar *s;
- Xstruct command *c;
- X
- X{
- X return strcmp(s, c->c_name);
- X}
- X
- X
- Xint classcmp(c, cc)
- Xstruct class **c, **cc;
- X
- X{
- X return strcmp((*c)->cs_name, (*cc)->cs_name);
- X}
- X
- Xint sclasscmp(s, c)
- Xchar *s;
- Xstruct class *c;
- X
- X{
- X return strcmp(s, c->cs_name);
- X}
- X
- Xint gmapcmp(g, gg)
- Xstruct groupmap **g, **gg;
- X
- X{
- X return (*g)->gm_gid - (*gg)->gm_gid;
- X}
- X
- Xint igmapcmp(n, g)
- Xint *n;
- Xstruct groupmap *g;
- X
- X{
- X return *n - g->gm_gid;
- X}
- X
- Xint rangecmp(r, rr)
- Xstruct range **r, **rr;
- X
- X{
- X return strcmp((*r)->rg_name, (*rr)->rg_name);
- X}
- X
- Xint srangecmp(s, r)
- Xchar *s;
- Xstruct range *r;
- X
- X{
- X return strcmp(s, r->rg_name);
- X}
- X
- Xint sigcmp(s, ss)
- Xstruct sig **s, **ss;
- X
- X{
- X return strcmp((*s)->sg_name, (*ss)->sg_name);
- X}
- X
- Xint ssigcmp(s, sg)
- Xchar *s;
- Xstruct sig *sg;
- X
- X{
- X return strcmp(s, sg->sg_name);
- X}
- X
- Xpstrcmp(p, pp)
- Xchar **p, **pp;
- X
- X{
- X return strcmp(*p, *pp);
- X}
- X
- Xsort_list(l, compfunc)
- Xstruct list *l;
- Xint (*compfunc)();
- X
- X{
- X qsort((char *)l->l_list, l->l_count, sizeof (addr), compfunc);
- X}
- @//E*O*F src/sort.c//
- if test 1838 -ne "`wc -c <'src/sort.c'`"; then
- echo shar: error transmitting "'src/sort.c'" '(should have been 1838 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'src/sort.h'" '(243 characters)'
- if test -f 'src/sort.h' ; then
- echo shar: will not over-write existing file "'src/sort.h'"
- else
- sed 's/^X//' >src/sort.h <<'@//E*O*F src/sort.h//'
- Xextern int acctcmp(), iacctcmp(), commcmp(), scommcmp(), classcmp();
- Xextern int sclasscmp(), gmapcmp(), igmapcmp(), rangecmp(), srangecmp();
- Xextern int sigcmp(), ssigcmp(), pstrcmp();
- X#ifdef SENDMAIL
- Xextern int aliascmp(), saliascmp();
- X#endif
- @//E*O*F src/sort.h//
- if test 243 -ne "`wc -c <'src/sort.h'`"; then
- echo shar: error transmitting "'src/sort.h'" '(should have been 243 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'src/sysdep.h'" '(10026 characters)'
- if test -f 'src/sysdep.h' ; then
- echo shar: will not over-write existing file "'src/sysdep.h'"
- else
- sed 's/^X//' >src/sysdep.h <<'@//E*O*F src/sysdep.h//'
- X/****************************************************************************\
- X* *
- X* sysdep.h *
- X* *
- X* This file contains all the system dependent #define's. In certain places *
- X* you may configure mcp to your liking by commenting out certain *
- X* definitions. *
- X* *
- X\****************************************************************************/
- X
- X/*
- X * Define BSD4_3 if this is a 4.3 BSD system. Currently all this entails
- X * is that mcp must use mkpasswd(8) to create the .dir and .pag passwd
- X * database files.
- X */
- X#define BSD4_3
- X
- X/*
- X * If this is 4.3 BSD system then DBMPASSWORD must point to the mkpaswd(8)
- X * command.
- X */
- X#ifdef BSD4_3
- X#define DBMPASSWORD "/etc/mkpasswd"
- X#endif
- X
- X/*
- X * DEF_VISUAL and DEF_EDITOR should define two different editors.
- X * For dumb terminals
- X * If getenv("EDITOR") returns NULL, DEF_EDITOR will be used when editing
- X * a class or sig description.
- X * For smart terminals
- X * If getenv("VISUAL") returns NULL, DEF_VISUAL will be used when
- X * a class or sig description.
- X * Smart terminals are anything but "dumb", "network", and "dialup"
- X */
- X#define DEF_VISUAL "/usr/new/jove"
- X#define DEF_EDITOR "/bin/ed"
- X
- X/*
- X * If for some ghastly reason TERM isn't defined, mcp will assume this.
- X */
- X#define DEF_TERM "dumb"
- X
- X/*
- X * Disabling a user means changing his shell to be whatever DISABLED_SH
- X * is defined to be. An example disabled shell is in ../misc/sorry
- X */
- X#define DISABLED_SH "/usr/misc/sorry"
- X
- X/*
- X * Freezing a user means changing his shell to be whatever FREEZE_SH
- X * is defined to be. An example shell for a frozen user is in
- X * ../misc/freeze
- X */
- X#define FREEZE_SH "/usr/misc/freeze"
- X
- X/*
- X * If defined HELPDIR should tell where the help files used in
- X * describe-command wiil be installed. If HELPDIR is not defined,
- X * the help facilities will not be compiled in.
- X */
- X#define HELPDIR "/usr/mcphelp"
- X
- X/*
- X * DEF_PAGER is used to display the help pages from describe-command
- X * if the environmental variable PAGER is not defined.
- X * DEF_PAGER should understand nroff underlining sequences.
- X * No need to define this if HELPDIR isn't defined.
- X */
- X#ifdef HELPDIR
- X#define DEF_PAGER "/usr/ucb/more"
- X#endif
- X
- X/*
- X * If DOFILES is defined mcp will create home directories for new users,
- X * remove home directories, mail, and secretmail of deleted users. Also
- X * if a user's uid is changed all his file ownerships will reflect this.
- X * Otherwise it will be up to the system administrator to do these tasks.
- X * Mcp will remind the SA of his responsibilities if DOFILES is undefined.
- X */
- X#define DOFILES
- X
- X/*
- X * Mcp assumes that all user directories are under USERDIR as a default.
- X * If this is a Sun system, code will be compiled in so that at runtime
- X * mcp will check to see if USERDIR is mounted on a directory on another
- X * host (a fileserver). If so mcp will by necessity use
- X * remote commands to manipulate the home directories of users.
- X */
- X#define USERDIR "/usr1"
- X
- X/*
- X * If SENDMAIL is defined mcp will update the aliases data file and use
- X * "newaliases" command as necessary to build the actual aliases database.
- X * This includes the usual removal of users form aliases as accounts
- X * are deleted, etc.
- X *
- X */
- X#define SENDMAIL
- X
- X/*
- X * This is the standard mail spool directory. When users are deleted,
- X * so is their mail if DOFILES is defined.
- X */
- X#define MAILSPOOL "/usr/spool/mail"
- X/*
- X * This is the standard secretmail spool. I doubt if anyone actually
- X * uses xsend and xget anymore but you never know...
- X */
- X#define SMAILSPOOL "/usr/spool/secretmail"
- X
- X/*
- X * Directory for mcp to create it's temporary edit files in. When adding
- X * or updating class and sig descriptions mcp will put the description in
- X * a temp file in this directory and invoke and either DEF_EDITOR or
- X * DEF_VISUAL on it.
- X */
- X#define TMPDIR "/tmp"
- X
- X/*
- X * New passwords created in add-user will be encrypted with this salt.
- X * This is a convenience so that accounts with unchanged passwords can be
- X * easily spotted by scanning the password file for this salt.
- X */
- X#define CRYPT_SALT "//"
- X
- X/*
- X * DEF_GROUP will be the group offered as a default in add-user, so this
- X * generally should be defined to be the name of the group with the most
- X * members.
- X */
- X#define DEF_GROUP "student"
- X
- X/*
- X * DESCSIZE determines the maximum size that class and sig descriptions
- X * will be allowed to be (in characters). 512 has proven to be more than
- X * enough here. Usually we can barely claw together 100.
- X */
- X#define DESCSIZE 512
- X
- X/*
- X * If defined mcp will checkpoint changes in the accounting files each
- X * CKPTIME minutes. If not defined no automatic checkpointing will
- X * be done although checkpoint files will still be written if mcp encounters
- X * an unexpected signal.
- X */
- X#define CKPTIME 5
- X
- X/****************************************************************************\
- X* *
- X* These define the locations of the accounting files. Each accounting file *
- X* (account, alias, class, group, passwd, range, sig, vig) also has a *
- X* #define for a backup file, a temporary file for storing intermediate *
- X* changes to the Accounts file, and a checkpoint file. Mcp checkpoints any *
- X* changes it has made in memory to the checkpoint file once every CKPTIME *
- X* seconds. *
- X* *
- X* Each temporary file (e.g. ACTMP) MUST be in the same filesystem as its *
- X* respective accounting file because the save routines do a rename(2) call *
- X* from the temp file to the accounting file. *
- X* *
- X\****************************************************************************/
- X
- X/*
- X * the account file
- X */
- X#define ACFILE "/usr/adm/accts/Accounts"
- X#define ACBAK "/usr/adm/accts/Accounts.bak"
- X#define ACTMP "/usr/adm/accts/Accounts.tmp"
- X#define ACCKP "/usr/adm/accts/Accounts.mcp"
- X
- X/*
- X * the class file
- X */
- X#define CSFILE "/usr/adm/accts/Classes"
- X#define CSBAK "/usr/adm/accts/Classes.bak"
- X#define CSTMP "/usr/adm/accts/Classes.tmp"
- X#define CSCKP "/usr/adm/accts/Classes.mcp"
- X
- X/*
- X * the group file
- X *
- X * Note that since mcp uses getgrent(3) to read the
- X * group file, changing the define here does no good in that respect.
- X * However you can make mcp write out its version of the group file
- X * anywhere you like by changing these, if you suspect mcp of mangling.
- X */
- X#define GRPFILE "/etc/group"
- X#define GRPBAK "/etc/group.bak"
- X#define GRPTMP "/etc/group.tmp"
- X#define GRPCKP "/etc/group.mcp"
- X
- X/*
- X * the passwd file
- X *
- X * Note that since mcp uses getpwent(3) to read the
- X * passwd file, changing the define here does no good in that respect.
- X * However you can make mcp write out it's version of the passwd file
- X * anywhere you like by changing these, if you suspect mcp of mangling.
- X */
- X#define PWDFILE "/etc/passwd"
- X#define PWDBAK "/etc/passwd.bak"
- X#define PWDTMP "/etc/passwd.tmp"
- X#define PWDCKP "/etc/passwd.mcp"
- X#define PWDLOCK "/etc/ptmp"
- X
- X/*
- X * the range file
- X */
- X#define RANGEFILE "/usr/adm/accts/Ranges"
- X#define RANGEBAK "/usr/adm/accts/Ranges.bak"
- X#define RANGETMP "/usr/adm/accts/Ranges.tmp"
- X#define RANGECKP "/usr/adm/accts/Ranges.mcp"
- X
- X/*
- X * the sig file
- X */
- X#define SIGFILE "/usr/adm/accts/Sigs"
- X#define SIGBAK "/usr/adm/accts/Sigs.bak"
- X#define SIGTMP "/usr/adm/accts/Sigs.tmp"
- X#define SIGCKP "/usr/adm/accts/Sigs.mcp"
- X
- X/*
- X * the vig file
- X */
- X#define VIGFILE "/usr/adm/accts/Vigs"
- X#define VIGBAK "/usr/adm/accts/Vigs.bak"
- X#define VIGTMP "/usr/adm/accts/Vigs.tmp"
- X#define VIGCKP "/usr/adm/accts/Vigs.mcp"
- X
- X/*
- X * These alias file definitions will be #ifdef'ed out if you have not
- X * #define'd SENDMAIL above. If you do plan to use mcp to manipulate the
- X * sendmail aliases, check these definitions. ALIASFILE *must* be the aliases
- X * file that sendmail uses.
- X */
- X#ifdef SENDMAIL
- X# define ALIASFILE "/usr/lib/aliases"
- X# define ALIASBAK "/usr/lib/aliases.bak"
- X# define ALIASTMP "/usr/lib/aliases.tmp"
- X# define ALIASCKP "/usr/lib/aliases.mcp"
- X# define ALBIND "/usr/adm/accts/AliasBindings"
- X# define ALBINDBAK "/usr/adm/accts/AliasBindings.bak"
- X# define ALBINDTMP "/usr/adm/accts/AliasBindings.tmp"
- X# define ALBINDCKP "/usr/adm/accts/AliasBindings.mcp"
- X/* path to the newaliases command to update the aliases database */
- X# define NEWALIASES "/usr/ucb/newaliases"
- X#endif
- X
- X/**************************\
- X* *
- X* Other file definitions. *
- X* *
- X\**************************/
- X
- X/*
- X * Standard location for the lastlog, used by login(1) and finger(1).
- X */
- X#define LASTLOG "/usr/adm/lastlog"
- X
- X
- X/*
- X * Mcp gets the list of available shells from this file and builds a
- X * completion list from it. The file format is one shell per line
- X * with the first line containing the shell that will be the default
- X * in add-user. For 4.3 BSD systems it is convenient to use /etc/shells,
- X * since the passwd(1) command already uses this list. Mcp will ignore the
- X * comments in this file, for compatibility with /etc/shells on 4.3 BSD
- X * systems.
- X */
- X#define SHELLFILE "/etc/shells"
- X
- X/****************************************************************************\
- X* *
- X* These definitions are needed only if DOFILES is #define'd above. For Sun *
- X* systems, the pathnames for the executables should be correct for the *
- X* fileserver and all the clients. The paths given will work if the *
- X* commands have not been moved from the locations in which they were *
- X* distributed. *
- X* *
- X* Mcp uses these chiefly as remote commands on Sun systems. FIND is used *
- X* to change the onwership of user files in all cases involving more than *
- X* one file. Otherwise mcp will use the system primitives chmod(), *
- X* chown(), etc., instead of these commands. *
- X* *
- X\****************************************************************************/
- X
- X#ifdef DOFILES
- X#define MV "/bin/mv"
- X#define RM "/bin/rm"
- X#define MKDIR "/bin/mkdir"
- X#define CHGRP "/bin/chgrp"
- X#define CHOWN "/etc/chown"
- X#define CHMOD "/bin/chmod"
- X#define FIND "/usr/bin/find"
- X#define NICE "/bin/nice"
- X#endif
- @//E*O*F src/sysdep.h//
- if test 10026 -ne "`wc -c <'src/sysdep.h'`"; then
- echo shar: error transmitting "'src/sysdep.h'" '(should have been 10026 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'src/tty.c'" '(431 characters)'
- if test -f 'src/tty.c' ; then
- echo shar: will not over-write existing file "'src/tty.c'"
- else
- sed 's/^X//' >src/tty.c <<'@//E*O*F src/tty.c//'
- X#include <sys/ioctl.h>
- X
- Xextern int DevTty;
- X
- Xcbreak()
- X
- X{
- X struct sgttyb sg;
- X
- X (void) ioctl(DevTty, TIOCGETP, (char *)&sg);
- X sg.sg_flags |= CBREAK;
- X sg.sg_flags &= ~(CRMOD|ECHO|RAW);
- X (void) ioctl(DevTty, TIOCSETP, (char *)&sg);
- X return;
- X}
- X
- Xnocbreak()
- X
- X{
- X struct sgttyb sg;
- X
- X (void) ioctl(DevTty, TIOCGETP, (char *)&sg);
- X sg.sg_flags &= ~CBREAK;
- X sg.sg_flags |= (CRMOD|ECHO);
- X (void) ioctl(DevTty, TIOCSETP, (char *)&sg);
- X return;
- X}
- @//E*O*F src/tty.c//
- if test 431 -ne "`wc -c <'src/tty.c'`"; then
- echo shar: error transmitting "'src/tty.c'" '(should have been 431 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'src/version.c'" '(577 characters)'
- if test -f 'src/version.c' ; then
- echo shar: will not over-write existing file "'src/version.c'"
- else
- sed 's/^X//' >src/version.c <<'@//E*O*F src/version.c//'
- Xstatic struct notice {
- X char *n_version;
- X char *n_copyright;
- X};
- Xstatic struct notice Note = {
- X"mcp version 1.0 (#2) ",
- X"(c) 1986 by Kyle E. Jones\n\n\
- XAll sources and documentation of this mcp distribution are\n\
- Xincluded in this copyright, but permission is granted to\n\
- Xcopy and redistribute any part of this distribution, provided\n\
- Xthat this notice is a conspicuous part of the redistribution,\n\
- Xand that no part of this distribution is sold.\n\n\
- XThis software is distributed 'as is', without warranties of any kind.\n\
- X"
- X};
- X
- X
- XShowVersion()
- X
- X{
- X err(Note.n_version);
- X}
- @//E*O*F src/version.c//
- if test 577 -ne "`wc -c <'src/version.c'`"; then
- echo shar: error transmitting "'src/version.c'" '(should have been 577 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'src/yesno.c'" '(1858 characters)'
- if test -f 'src/yesno.c' ; then
- echo shar: will not over-write existing file "'src/yesno.c'"
- else
- sed 's/^X//' >src/yesno.c <<'@//E*O*F src/yesno.c//'
- X#include <stdio.h>
- X#include "sysdep.h"
- X#include "mem.h"
- X#include "lists.h"
- X#include "gpa.h"
- X
- Xstatic char *yn[4] = { "yes", "no", "YES!!!", "NO!!!" };
- Xstatic char *y[1] = { "yes" };
- Xstatic char *n[1] = { "no" };
- X
- Xstruct list YesNo = { 4, 4, (addr *)yn };
- X
- Xstatic struct list Yes = { 1, 1, (addr *)y };
- Xstatic struct list No = { 1, 1, (addr *)n };
- X
- X/*
- X * Query for a yes or no answer. Allows carriage return to default
- X * yes. Returns 1 if answer is yes, 0 for no.
- X */
- Xyes(prompt)
- Xchar *prompt;
- X
- X{
- X addr *argv;
- X int argc;
- X char **cpp;
- X
- X argv = get_gpa(2);
- X cpp = (char **) argv;
- X do {
- X GetLine(prompt, 1, &argc, argv, &Yes);
- X if (argc == 0 || **cpp == 'y' || **cpp == 'Y') {
- X pop_gpa(2);
- X return(1);
- X }
- X else if (**cpp == 'n' || **cpp == 'N') {
- X pop_gpa(2);
- X return(0);
- X }
- X } while (clear_gpa(argv, 2));
- X /* NOTREACHED */
- X}
- X
- X
- X/*
- X * Query for a yes or no answer. Allows carriage return to default
- X * no. Returns 1 if answer is no, 0 for yes.
- X */
- Xno(prompt)
- Xchar *prompt;
- X
- X{
- X addr *argv;
- X int argc;
- X char **cpp;
- X
- X argv = get_gpa(2);
- X cpp = (char **) argv;
- X do {
- X GetLine(prompt, 1, &argc, argv, &No);
- X if (argc == 0 || **cpp == 'n' || **cpp == 'N') {
- X pop_gpa(2);
- X return(1);
- X }
- X else if (**cpp == 'y' || **cpp == 'Y') {
- X pop_gpa(2);
- X return(0);
- X }
- X } while (clear_gpa(argv, 2));
- X /* NOTREACHED */
- X}
- X
- X
- X/*
- X * Query for a yes or no answer. Disallows carriage return default;
- X * answer must be specified. Returns 1 if answer is yes, 0 for no.
- X */
- Xyesno(prompt)
- Xchar *prompt;
- X
- X{
- X addr *argv;
- X int argc;
- X char **cpp;
- X
- X argv = get_gpa(2);
- X cpp = (char **) argv;
- X do {
- X GetLine(prompt, 1, &argc, argv, &YesNo);
- X if (argc == 0) continue;
- X if (**cpp == 'y' || **cpp == 'Y') {
- X pop_gpa(2);
- X return(1);
- X }
- X else if (**cpp == 'n' || **cpp == 'N') {
- X pop_gpa(2);
- X return(0);
- X }
- X } while (clear_gpa(argv, 2));
- X /* NOTREACHED */
- X}
- @//E*O*F src/yesno.c//
- if test 1858 -ne "`wc -c <'src/yesno.c'`"; then
- echo shar: error transmitting "'src/yesno.c'" '(should have been 1858 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'src/update.c'" '(22502 characters)'
- if test -f 'src/update.c' ; then
- echo shar: will not over-write existing file "'src/update.c'"
- else
- sed 's/^X//' >src/update.c <<'@//E*O*F src/update.c//'
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include <strings.h>
- X#include <ctype.h>
- X#include <lastlog.h>
- X#include "sysdep.h"
- X#include "macros.h"
- X#include "mem.h"
- X#include "gpa.h"
- X#include "lists.h"
- X#include "account.h"
- X#ifdef SENDMAIL
- X#include "alias.h"
- X#endif
- X#include "class.h"
- X#include "groupmap.h"
- X#include "job.h"
- X#include "range.h"
- X#include "sig.h"
- X#include "sort.h"
- X#include "save.h"
- X
- X#define DAY (4*21600)
- X
- X#ifdef SENDMAIL
- Xextern struct list AliasList, Aliases;
- X#endif
- Xextern struct list AccountList, Users, ClassList, Classes, GroupMapList;
- Xextern struct list Groups, RangeList, Ranges, Sigs, SigList, Vigs, Shells;
- Xextern struct list Null_List;
- Xextern int ModBits;
- Xextern addr makeusername(), DEF_SHELL;
- Xextern char *crypt(), *mktemp(), *sprintf(), *when(), *rsalt(), *makepass();
- Xextern time_t choosedate();
- X
- Xstatic char *XXXXXX = "/mcpXXXXXX";
- Xstatic char desc[DESCSIZE+1];
- X
- X/* these are defined in add.c */
- Xextern struct list idlist;
- Xextern struct list rnlist;
- Xextern struct list pwlist;
- Xextern struct list mdlist;
- X
- X#ifdef SENDMAIL
- X/*
- X * Update an alias
- X */
- Xupdalias(c, v)
- Xint c;
- Xchar **v;
- X
- X{
- X struct alias *al, *a;
- X struct account *ac;
- X struct class *cs;
- X struct sig *sg;
- X struct groupmap *gm;
- X register int i;
- X int cc;
- X addr *namev;
- X char prompt[MEDIUM_BUF];
- X
- X if (c > 2) {
- X err1("%s: too many arguments", (char *)v[0]);
- X return;
- X }
- X if (c < 2) {
- X err1("usage: %s <alias>", (char *)v[0]);
- X return;
- X }
- X al = getalnam((char *)v[1]);
- X if (!al) {
- X err1("%s: no such alias", (char *)v[1]);
- X return;
- X }
- X
- X namev = get_gpa(2);
- X (void) sprintf(prompt, "Name [%s]: ", al->al_name);
- X GetLine(prompt, 1, &cc, namev, &Null_List);
- X if (cc == 0 || eq(*namev, al->al_name)) {
- X err("no change");
- X return;
- X }
- X if (aliasexists((char *)*namev)) {
- X err1("%s: alias exists", (char *)*namev);
- X return;
- X }
- X
- X critical();
- X
- X /*
- X * If this alias name appears in any of the other alias lists
- X * it must be changed there alias well.
- X */
- X for (i=0; i < AliasList.l_count; i++) {
- X a = (struct alias *) AliasList.l_list[i];
- X (void) strlistchg(&a->al_addresses, al->al_name, (char *)*namev);
- X }
- X for (i=0; i < AccountList.l_count; i++) {
- X ac = (struct account *) AccountList.l_list[i];
- X if (strlistchg(&ac->ac_aliases, al->al_name, (char *)*namev))
- X ModBits |= AC;
- X }
- X for (i=0; i < GroupMapList.l_count; i++) {
- X gm = (struct groupmap *) GroupMapList.l_list[i];
- X (void) strlistchg(&gm->gm_aliases, al->al_name, (char *)*namev);
- X }
- X for (i=0; i < ClassList.l_count; i++) {
- X cs = (struct class *) ClassList.l_list[i];
- X (void) strlistchg(&cs->cs_aliases, al->al_name, (char *)*namev);
- X }
- X for (i=0; i < SigList.l_count; i++) {
- X sg = (struct sig *) SigList.l_list[i];
- X (void) strlistchg(&sg->sg_aliases, al->al_name, (char *)*namev);
- X }
- X
- X (void) strlistchg(&Aliases, al->al_name, (char *)*namev);
- X FREEMEM(al->al_name);
- X savestr(&al->al_name, (char *)*namev);
- X sort_list(&AliasList, aliascmp);
- X ModBits |= AL;
- X puts("updated");
- X non_critical();
- X
- X return;
- X}
- X#endif
- X
- X/*
- X * Update a class
- X */
- Xupdclass(c, v)
- Xint c;
- Xaddr *v;
- X
- X{
- X struct class cl, *cs;
- X struct account *ac;
- X#ifdef SENDMAIL
- X struct alias *al;
- X#endif
- X struct stat statbuf;
- X addr *namev;
- X char tempf[MEDIUM_BUF], errmsg[LONG_BUF], prompt[LONG_BUF];
- X FILE *f, *fopen();
- X time_t now;
- X int i, cc, changed = 0, ch;
- X
- X if ( c > 2 ) {
- X err1("%s: too many arguments", (char *)v[0]);
- X return;
- X }
- X if ( c != 2 ) {
- X err1("usage: %s <class>", (char *)v[0]);
- X return;
- X }
- X cs = getcsnam((char *)v[1]);
- X if (!cs) {
- X err1("%s: no such class", (char *)v[1]);
- X return;
- X }
- X bcopy(&cl, cs, sizeof (struct class));
- X
- X namev = get_gpa(2);
- X
- X (void) sprintf(prompt, "Name [%s]: ", cl.cs_name);
- X GetLine(prompt, 1, &cc, namev, &Null_List);
- X if (cc) {
- X if (eq(*namev, v[1]))
- X ; /* no change */
- X else if (classexists((char *)*namev)) {
- X err("that name is taken");
- X return;
- X }
- X else
- X changed = 1;
- X }
- X (void) printf("Class set to end %s\n", when(cl.cs_exptime));
- X if (no("Do you wish to change it? [no] ") == 0) {
- X if (!cl.cs_exptime || yesno("Should the class expire? ")) {
- X err("Set the expiration date.");
- X cl.cs_exptime = choosedate(cl.cs_exptime);
- X (void) printf("Class set to end %s\n", when(cl.cs_exptime));
- X }
- X else
- X cl.cs_exptime = 0;
- X if (cl.cs_exptime != cs->cs_exptime)
- X changed = 1;
- X }
- X i = no("Edit description? [no] ");
- X
- X critical();
- X if (i)
- X goto finish;
- X (void) strcpy(tempf, TMPDIR);
- X (void) strcat(tempf, XXXXXX);
- X (void) mktemp(tempf);
- X f = fopen(tempf, "w");
- X if (f == NULL) {
- X err1("%s: cannot open (write)", tempf);
- X non_critical();
- X return;
- X }
- X fputs(cl.cs_desc, f);
- X (void) fclose(f);
- X (void) stat(tempf, &statbuf);
- X now = statbuf.st_mtime;
- X for (;;) {
- X edit(tempf);
- X if (stat(tempf, &statbuf) == -1) {
- X perr(tempf);
- X (void) unlink(tempf);
- X non_critical();
- X return;
- X }
- X if (statbuf.st_size > DESCSIZE) {
- X (void) sprintf(errmsg,
- X "description is %d characters too long",
- X DESCSIZE - statbuf.st_size);
- X err(errmsg);
- X continue;
- X }
- X break;
- X }
- X if (statbuf.st_mtime == now)
- X goto finish;
- X changed = 1;
- X f = fopen(tempf, "r");
- X if (f == NULL) {
- X err1("%s: cannot open (read)", tempf);
- X non_critical();
- X return;
- X }
- X FREEMEM(cl.cs_desc);
- X i = 0;
- X while ((ch = getc(f)) != EOF)
- X desc[i++] = ch;
- X desc[i] = '\0';
- X cl.cs_dsize = i;
- X savestr(&cl.cs_desc, desc);
- X (void) fclose(f);
- X (void) unlink(tempf);
- X
- Xfinish:
- X if (*namev != NIL && !eq(*namev, v[1])) {
- X FREEMEM(cl.cs_name);
- X savestr(&cl.cs_name, (char *)*namev);
- X for (i=0; i < AccountList.l_count; i++) {
- X ac = (struct account *)AccountList.l_list[i];
- X if (strlistchg(&ac->ac_classes, (char *)v[1], cl.cs_name))
- X ModBits |= AC;
- X }
- X#ifdef SENDMAIL
- X for (i=0; i < AliasList.l_count; i++) {
- X al = (struct alias *) AliasList.l_list[i];
- X if (strlistchg(&al->al_classes, (char *)v[1], cl.cs_name))
- X ModBits |= AL;
- X }
- X#endif
- X (void) strlistchg(&Classes, (char *)v[1], cl.cs_name);
- X }
- X if (changed) {
- X bcopy(cs, &cl, sizeof (struct class));
- X sort_list(&ClassList, classcmp);
- X ModBits |= CS;
- X puts("updated");
- X }
- X else
- X err("no change");
- X non_critical();
- X
- X return;
- X}
- X
- X/*
- X * Update a sig
- X */
- Xupdsig(c, v)
- Xint c;
- Xaddr *v;
- X
- X{
- X struct sig s, *sg;
- X#ifdef SENDMAIL
- X struct alias *al;
- X#endif
- X struct account *ac;
- X struct stat statbuf;
- X addr *namev;
- X char tempf[MEDIUM_BUF], errmsg[LONG_BUF], prompt[LONG_BUF];
- X FILE *f, *fopen();
- X time_t now;
- X int i, cc, changed = 0, ch;
- X
- X if ( c > 2 ) {
- X err1("%s: too many arguments", (char *)v[0]);
- X return;
- X }
- X if ( c != 2 ) {
- X err1("usage: %s <sig>", (char *)v[0]);
- X return;
- X }
- X sg = getsgnam((char *)v[1]);
- X if (!sg) {
- X err1("%s: no such sig", (char *)v[1]);
- X return;
- X }
- X bcopy(&s, sg, sizeof (struct sig));
- X
- X namev = get_gpa(2);
- X
- X (void) sprintf(prompt, "Name [%s]: ", s.sg_name);
- X GetLine(prompt, 1, &cc, namev, &Null_List);
- X if (cc) {
- X if (eq(*namev, v[1]))
- X ; /* no change */
- X else if (sigexists((char *)*namev)) {
- X err("that name is taken");
- X return;
- X }
- X else
- X changed = 1;
- X }
- X (void) printf("Sig set to end %s\n", when(s.sg_exptime));
- X if (no("Do you wish to change it? [no] ") == 0) {
- X if (!s.sg_exptime || yesno("Should the sig expire? ")) {
- X err("Set the expiration date.");
- X s.sg_exptime = choosedate(s.sg_exptime);
- X (void) printf("Project set to end %s\n", when(s.sg_exptime));
- X }
- X else
- X s.sg_exptime = 0;
- X if (s.sg_exptime != sg->sg_exptime)
- X changed = 1;
- X }
- X i = no("Edit description? [no] ");
- X
- X critical();
- X if (i)
- X goto finish;
- X (void) strcpy(tempf, TMPDIR);
- X (void) strcat(tempf, XXXXXX);
- X (void) mktemp(tempf);
- X f = fopen(tempf, "w");
- X if (f == NULL) {
- X err1("%s: cannot open (write)", tempf);
- X non_critical();
- X return;
- X }
- X fputs(s.sg_desc, f);
- X (void) fclose(f);
- X (void) stat(tempf, &statbuf);
- X now = statbuf.st_mtime;
- X for (;;) {
- X edit(tempf);
- X if (stat(tempf, &statbuf) == -1) {
- X perr(tempf);
- X (void) unlink(tempf);
- X non_critical();
- X return;
- X }
- X if (statbuf.st_size > DESCSIZE) {
- X (void) sprintf(errmsg,
- X "description is %d characters too long",
- X DESCSIZE - statbuf.st_size);
- X err(errmsg);
- X continue;
- X }
- X break;
- X }
- X if (statbuf.st_mtime == now)
- X goto finish;
- X changed = 1;
- X f = fopen(tempf, "r");
- X if (f == NULL) {
- X err1("%s: cannot open (read)", tempf);
- X non_critical();
- X return;
- X }
- X FREEMEM(s.sg_desc);
- X i = 0;
- X while ((ch = getc(f)) != EOF)
- X desc[i++] = ch;
- X desc[i] = '\0';
- X s.sg_dsize = i;
- X savestr(&s.sg_desc, desc);
- X (void) fclose(f);
- X (void) unlink(tempf);
- X
- Xfinish:
- X if (*namev != NIL && !eq(*namev, v[1])) {
- X FREEMEM(s.sg_name);
- X savestr(&s.sg_name, (char *)*namev);
- X for (i=0; i < AccountList.l_count; i++) {
- X ac = (struct account *)AccountList.l_list[i];
- X if (strlistchg(&ac->ac_sigs, (char *)v[1], s.sg_name))
- X ModBits |= AC;
- X }
- X#ifdef SENDMAIL
- X for (i=0; i < AliasList.l_count; i++) {
- X al = (struct alias *) AliasList.l_list[i];
- X if (strlistchg(&al->al_sigs, (char *)v[1], s.sg_name))
- X ModBits |= AL;
- X }
- X#endif
- X (void) strlistchg(&Sigs, (char *)v[1], s.sg_name);
- X }
- X if (changed) {
- X bcopy(sg, &s, sizeof (struct sig));
- X sort_list(&SigList, sigcmp);
- X ModBits |= SG;
- X puts("updated");
- X }
- X else
- X err("no change");
- X non_critical();
- X
- X return;
- X}
- X
- X/*
- X * Add a group
- X */
- Xupdgroup(c, v)
- Xint c;
- Xaddr *v;
- X
- X{
- X struct groupmap g, *gm;
- X#ifdef SENDMAIL
- X struct alias *al;
- X#endif
- X struct account *ac;
- X struct range *rg;
- X char prompt[SHORT_BUF];
- X addr *tempv, *namev;
- X int i, cc, gid, changed = 0;
- X
- X if ( c > 2 ) {
- X err1("%s: too many arguments", (char *)v[0]);
- X return;
- X }
- X if (c != 2) {
- X err1("usage: %s <name>", (char *)v[0]);
- X return;
- X }
- X gm = getgmnam((char *)v[1]);
- X if (!gm) {
- X err1("%s: group exists", (char *)v[1]);
- X return;
- X }
- X bcopy(&g, gm, sizeof (struct groupmap));
- X
- X namev = get_gpa(2);
- X tempv = get_gpa(2);
- X
- X (void) sprintf(prompt, "Name [%s]: ", g.gm_name);
- X GetLine(prompt, 1, &cc, namev, &Null_List);
- X if (cc) {
- X if (!eq(*namev, v[1]))
- X ; /* no change */
- X else if (groupexists((char *)*namev)) {
- X err("that name is taken");
- X return;
- X }
- X else
- X changed = 1;
- X }
- X
- X (void) sprintf(prompt, "Gid [%d]: ", g.gm_gid);
- X GetLine(prompt, 1, &cc, tempv, &Null_List);
- X if (cc) {
- X if (!validint((char *)*tempv)) {
- X err1("%s makes no sense to me", (char *)tempv);
- X return;
- X }
- X gid = atoi((char *)*tempv);
- X if (gidexists(g.gm_gid)) {
- X err("that gid is taken");
- X return;
- X }
- X else {
- X g.gm_gid = gid;
- X changed = 1;
- X }
- X }
- X
- X critical();
- X if (g.gm_gid != gm->gm_gid) {
- X changed = 1;
- X for (i=0; i < AccountList.l_count; i++) {
- X ac = (struct account *) AccountList.l_list[i];
- X if (ac->ac_gid == gm->gm_gid) {
- X ac->ac_gid = g.gm_gid;
- X ModBits |= AC;
- X }
- X }
- X }
- X if (*namev != NIL && !eq(*namev, v[1])) {
- X changed = 1;
- X FREEMEM(g.gm_name);
- X savestr(&g.gm_name, (char *)*namev);
- X (void) strlistchg(&Groups, (char *)v[1], g.gm_name);
- X for (i=0; i < AccountList.l_count; i++) {
- X ac = (struct account *) AccountList.l_list[i];
- X if (strlistchg(&ac->ac_groups, (char *)v[1], g.gm_name))
- X ModBits |= AC;
- X }
- X#ifdef SENDMAIL
- X for (i=0; i < AliasList.l_count; i++) {
- X al = (struct alias *) AliasList.l_list[i];
- X if (strlistchg(&al->al_groups, (char *)v[1], g.gm_name))
- X ModBits |= AL;
- X }
- X#endif
- X rg = getrgnam((char *)v[1]);
- X if (rg) {
- X FREEMEM(rg->rg_name);
- X savestr(&rg->rg_name, g.gm_name);
- X (void) strlistchg(&Ranges, (char *)v[1], g.gm_name);
- X sort_list(&RangeList, rangecmp);
- X ModBits |= RG;
- X }
- X if (vigexists((char *)v[1])) {
- X (void) strlistchg(&Vigs, (char *)v[1], g.gm_name);
- X ModBits |= VG;
- X }
- X }
- X if (changed) {
- X bcopy(gm, &g, sizeof (struct groupmap));
- X sort_list(&GroupMapList, gmapcmp);
- X ModBits |= GR;
- X puts("updated");
- X }
- X else
- X err("no change");
- X
- X non_critical();
- X return;
- X}
- X
- X/*
- X * Update a range
- X */
- Xupdrange(c, v)
- Xint c;
- Xaddr *v;
- X
- X{
- X struct range r, *rr, *rg;
- X char prompt[SHORT_BUF];
- X addr *tempv, *namev;
- X int cc, indx, changed = 0;
- X
- X if ( c > 2 ) {
- X err1("%s: too many arguments", (char *)v[0]);
- X return;
- X }
- X if (c != 2) {
- X err1("usage: %s <name>", (char *)v[0]);
- X return;
- X }
- X rr = getrgnam((char *)v[1]);
- X if (!rr) {
- X err1("%s: no such range", (char *)v[1]);
- X return;
- X }
- X bcopy(&r, rr, sizeof (struct range));
- X
- X namev = get_gpa(2);
- X tempv = get_gpa(2);
- X
- X /*
- X * New name?
- X */
- X (void) sprintf(prompt, "Name [%s]: ", r.rg_name);
- X GetLine(prompt, 1, &cc, namev, &Groups);
- X if (cc) {
- X if (!groupexists((char *)*namev)) {
- X err1("%s: no such group", (char *)*namev);
- X return;
- X }
- X if (eq(*namev, v[1]))
- X ; /* no change */
- X else if (rangeexists((char *)namev)) {
- X err("that name is taken");
- X return;
- X }
- X else
- X changed = 1;
- X }
- X
- X /*
- X * From?
- X */
- X (void) sprintf(prompt, "From [%d]: ", r.rg_from);
- X GetLine(prompt, 1, &cc, tempv, &Null_List);
- X if (cc) {
- X if (!validint((char *)*tempv)) {
- X err1("%s makes no sense to me", (char *)*tempv);
- X return;
- X }
- X r.rg_from = atoi((char *)*tempv);
- X (void) clear_gpa(tempv, 2);
- X changed = 1;
- X }
- X
- X /*
- X * To?
- X */
- X (void) sprintf(prompt, "To [%d]: ", r.rg_to);
- X GetLine(prompt, 1, &cc, tempv, &Null_List);
- X if (cc) {
- X if (!validint((char *)*tempv)) {
- X err1("%s makes no sense to me", (char *)*tempv);
- X return;
- X }
- X r.rg_to = atoi((char *)*tempv);
- X (void) clear_gpa(tempv, 2);
- X changed = 1;
- X }
- X
- X /*
- X * New mode?
- X */
- X (void) sprintf(prompt, "Mode [%s] : ",
- X (r.rg_mode == RG_SHARED ? "shared" : "exclusive"));
- X GetLine(prompt, 1, &cc, tempv, &mdlist);
- X if (!cc)
- X ; /* no change */
- X else if (eq(*tempv, "shared")) {
- X r.rg_mode = RG_SHARED;
- X changed = 1;
- X }
- X else if (eq(*tempv, "exclusive")) {
- X r.rg_mode = RG_EXCLUSIVE;
- X changed = 1;
- X }
- X else {
- X err1("%s: unknown mode", (char *)*tempv);
- X return;
- X }
- X
- X /*
- X * Check to see if the new range conflicts with existing ranges
- X */
- X for (indx=0; indx < RangeList.l_count; indx++) {
- X rg = (struct range *) RangeList.l_list[indx];
- X if (rg == rr)
- X continue;
- X if (rg->rg_mode == RG_SHARED && r.rg_mode == RG_SHARED)
- X continue;
- X if (INRANGE(r.rg_from, rg->rg_from, rg->rg_to)) {
- X err1("conflicts with range of group %s", rg->rg_name);
- X return;
- X }
- X if (INRANGE(r.rg_to, rg->rg_from, rg->rg_to)) {
- X err1("conflicts with range of group %s", rg->rg_name);
- X return;
- X }
- X }
- X
- X critical();
- X if (*namev != NIL && !eq(*namev, v[1])) {
- X FREEMEM(r.rg_name);
- X savestr(&r.rg_name, (char *)*tempv);
- X (void) strlistchg(&Ranges, (char *)v[1], r.rg_name);
- X }
- X if (changed) {
- X bcopy(rr, &r, sizeof (struct range));
- X sort_list(&RangeList, rangecmp);
- X ModBits |= RG;
- X puts("updated");
- X }
- X else
- X err("no change");
- X non_critical();
- X
- X return;
- X}
- X
- Xupduser(c, v)
- Xint c;
- Xchar **v;
- X
- X{
- X struct account *ac, *ac2;
- X struct groupmap *gm;
- X#ifdef SENDMAIL
- X struct alias *al;
- X struct class *cs;
- X struct sig *sg;
- X int ogid, j;
- X#endif
- X addr *namev, *realnamev, *idv, *uidv, *gidv, *dirv, *passwdv, *shellv;
- X int uid, gid, changed = 0;
- X#ifdef DOFILES
- X int mvdir = 0;
- X#endif
- X int cc;
- X register int i;
- X char *cp, prompt[LONG_BUF], errmsg[LONG_BUF];
- X
- X if ( c > 2 ) {
- X err1("%s: too many arguments", (char *)v[0]);
- X return;
- X }
- X if ( c != 2 ) {
- X err1("usage: %s <user>", (char *)v[0]);
- X return;
- X }
- X ac = getacnam((char *)v[1]);
- X if (!ac) {
- X err1("%s: no such user", (char *)v[1]);
- X return;
- X }
- X
- X namev = get_gpa(2);
- X realnamev = get_gpa(17);
- X idv = get_gpa(2);
- X passwdv = get_gpa(2);
- X uidv = get_gpa(2);
- X gidv = get_gpa(2);
- X dirv = get_gpa(2);
- X shellv = get_gpa(2);
- X
- X /*
- X * Change login name?
- X */
- X (void) sprintf(prompt, "Login name [%s]: ", ac->ac_name);
- X GetLine(prompt, 1, &cc, namev, &Null_List);
- X
- X /*
- X * Change real name?
- X */
- X (void) sprintf(prompt, "Real Name [%s]: ", ac->ac_realname);
- X GetLine(prompt, 16, &cc, realnamev, &Null_List);
- X
- X /*
- X * Change id?
- X */
- X (void) sprintf(prompt, "Id [%s]: ", ac->ac_id);
- X GetLine(prompt, 1, &cc, idv, &idlist);
- X
- X /*
- X * Change password?
- X */
- X (void) sprintf(prompt, "Password (RETURN means no change): ");
- X GetLine(prompt, 1, &cc, passwdv, &pwlist);
- X
- X /*
- X * Change uid?
- X */
- X (void) sprintf(prompt, "Uid [%d]: ", ac->ac_uid);
- X GetLine(prompt, 1, &cc, uidv, &Null_List);
- X if (cc && !validint((char *)*uidv)) {
- X err1("%s makes no sense to me", (char *)*uidv);
- X return;
- X }
- X
- X /*
- X * Change gid?
- X */
- X (void) sprintf(prompt, "Gid [%d]: ", ac->ac_gid);
- X GetLine(prompt, 1, &cc, gidv, &Null_List);
- X if (cc && !validint((char *)*gidv)) {
- X err1("%s makes no sense to me", (char *)*gidv);
- X return;
- X }
- X
- X /*
- X * Rename home directory?
- X */
- X (void) sprintf(prompt, "Home [%s]: ", ac->ac_dir);
- X GetFilenames(prompt, 1, &cc, dirv);
- X#ifdef DOFILES
- X if (cc && !eq(*dirv, ac->ac_dir) && fileexists((char *)*dirv))
- X err2("%s already exists, so I won't move %s", (char *)*dirv,
- X (char *)ac->ac_dir);
- X else
- X mvdir = 1;
- X#endif
- X
- X /*
- X * New shell?
- X */
- X (void) sprintf(prompt, "Shell [%s]: ", ac->ac_shell);
- X GetLine(prompt, 1, &cc, shellv, &Shells);
- X if (cc && !fileexists((char *)*shellv))
- X err1("Warning: %s does not exist", (char *)*shellv);
- X
- X critical();
- X
- X /*
- X * If given a different user name, use it. No duplicate
- X * user names allowed (of course).
- X */
- X if (*namev != NIL && !eq(*namev, ac->ac_name)) {
- X if (!userexists((char *)*namev)) {
- X /*
- X * Update group member lists
- X */
- X for (i=0; i < GroupMapList.l_count; i++) {
- X gm = (struct groupmap *)GroupMapList.l_list[i];
- X if (strlistchg(&gm->gm_mem, (char *)v[1], (char *)*namev))
- X ModBits |= GR;
- X }
- X#ifdef SENDMAIL
- X /*
- X * Update aliases
- X */
- X for (i=0; i < AliasList.l_count; i++) {
- X al = (struct alias *) AliasList.l_list[i];
- X if (strlistchg(&al->al_addresses, (char *)v[1],
- X (char *)*namev))
- X ModBits |= AL;
- X }
- X al = getalnam((char *)ac->ac_name);
- X if (al) {
- X ModBits |= AL;
- X for (i=0; i < AccountList.l_count; i++) {
- X ac2 = (struct account *) AccountList.l_list[i];
- X if (!strlistchg(&ac2->ac_aliases, al->al_name,
- X (char *)*namev))
- X continue;
- X ModBits |= AC;
- X }
- X for (i=0; i < GroupMapList.l_count; i++) {
- X gm = (struct groupmap *) GroupMapList.l_list[i];
- X (void) strlistchg(&gm->gm_aliases, al->al_name,
- X (char *)*namev);
- X }
- X for (i=0; i < ClassList.l_count; i++) {
- X cs = (struct class *) ClassList.l_list[i];
- X (void) strlistchg(&cs->cs_aliases, al->al_name,
- X (char *)*namev);
- X }
- X for (i=0; i < SigList.l_count; i++) {
- X sg = (struct sig *) SigList.l_list[i];
- X (void) strlistchg(&sg->sg_aliases, al->al_name,
- X (char *)*namev);
- X }
- X (void) strlistchg(&Aliases, al->al_name, (char *)*namev);
- X FREEMEM(al->al_name);
- X savestr(&al->al_name, (char *)*namev);
- X sort_list(&AliasList, aliascmp);
- X }
- X#endif
- X /*
- X * Now fix the accounts struct and the users
- X * completion list
- X */
- X (void) strlistchg(&Users, (char *)ac->ac_name, (char *)*namev);
- X FREEMEM((char *)ac->ac_name);
- X savestr((char **)&ac->ac_name, (char *)*namev);
- X ModBits |= (AC|PW);
- X changed++;
- X }
- X else {
- X err1("%s: user exists", (char *)*namev);
- X err("login name unchanged");
- X }
- X }
- X
- X /*
- X * If given a new real name, use it.
- X */
- X if (*realnamev != NIL) {
- X cp = (char *)glob(realnamev);
- X if (!eq(cp, ac->ac_realname)) {
- X FREEMEM((char *)ac->ac_realname);
- X savestr((char **)&ac->ac_realname, cp);
- X ModBits |= AC;
- X changed++;
- X }
- X }
- X
- X /*
- X * If id changed, record it. Since the user already has an
- X * account we don't care if his id matches anyone else's
- X * The check for duplicate ids is done at when a user is added.
- X */
- X if (*idv != NIL && !eq(*idv, ac->ac_id)) {
- X FREEMEM((char *)ac->ac_id);
- X savestr((char **)&ac->ac_id, (char *)*idv);
- X ModBits |= AC;
- X changed++;
- X }
- X
- X /*
- X * Handle change of password
- X */
- X if (*passwdv != NIL) {
- X FREEMEM((char *)ac->ac_passwd);
- X if (eq(*passwdv, "unused"))
- X savestr((char **)&ac->ac_passwd, "*");
- X else if (eq(*passwdv, "none"))
- X savestr((char **)&ac->ac_passwd, "");
- X else if (eq(*passwdv, "generate")) {
- X cp = makepass();
- X savestr((char **)&ac->ac_passwd, crypt(cp, rsalt()));
- X (void) printf("password is \"%s\"\n", cp);
- X }
- X else
- X savestr((char **)&ac->ac_passwd,
- X crypt((char *)*passwdv, rsalt()));
- X ModBits |= PW;
- X changed++;
- X }
- X
- X /*
- X * Note home directory change, if any. This must be before
- X * checking for a change in uid so that the omni_chown isn't
- X * suddenly left high and dry if user's directory is moved.
- X */
- X if (*dirv != NIL && !eq(*dirv, ac->ac_dir)) {
- X#ifdef DOFILES
- X if (mvdir)
- X add_job(JB_MV, ac->ac_dir, *dirv, NIL);
- X#else
- X err("Don't forget to move the user's home directory");
- X#endif
- X FREEMEM((char *)ac->ac_dir);
- X savestr((char **)&ac->ac_dir, (char *)*dirv);
- X ModBits |= PW;
- X changed++;
- X }
- X
- X /*
- X * Handle a change of uid. This entails changing the ownership
- X * of this user's files when savechanges() is called. Sharing
- X * of uids is permitted but a warning message is printed.
- X */
- X if (*uidv != NIL) {
- X uid = atoi((char *)*uidv);
- X if (uid <= 0)
- X err("uid is out of range");
- X else if (uid != ac->ac_uid && uid >= 0) {
- X ac2 = getacuid(uid);
- X if (ac2)
- X (void) printf("warning: uid %d is shared by %s\n",
- X uid, ac2->ac_name);
- X#ifdef DOFILES
- X add_job(JB_OMNICHOWN, &ac->ac_uid, &uid, NIL);
- X#else
- X err("Do not forget to chown the user files.");
- X#endif
- X ac->ac_uid = uid;
- X sort_list(&AccountList, acctcmp);
- X ModBits |= (AC|PW);
- X add_job(JB_LASTLOG, &ac->ac_uid, (addr)&ac->ac_ll, NIL);
- X changed++;
- X }
- X }
- X
- X /*
- X * Handle a change of gid. Must make sure there is group
- X * associated with the gid.
- X */
- X if (*gidv != NIL) {
- X gid = atoi((char *)*gidv);
- X if (gid < 0)
- X err("gid is out of range");
- X else if (!(gm = getgmgid(gid))) {
- X (void) sprintf(errmsg,
- X "no group associated with gid %d",
- X gid);
- X err(errmsg);
- X }
- X else if (gid != ac->ac_gid) {
- X#ifdef SENDMAIL
- X ogid = ac->ac_gid;
- X#endif
- X ac->ac_gid = gid;
- X ModBits |= (AC|PW);
- X#ifdef SENDMAIL
- X if (gm->gm_aliases.l_count)
- X RXBindings(ac);
- X gm = getgmgid(ogid);
- X for (j=0; j < gm->gm_aliases.l_count; j++) {
- X al = getalnam((char *)gm->gm_aliases.l_list[j]);
- X if (!al) continue; /* trouble */
- X if (!instrlist(&al->al_addresses, (char *)ac->ac_name)) {
- X strlistadd(&al->al_addresses, (char *)ac->ac_name);
- X sort_list(&al->al_addresses, pstrcmp);
- X ModBits |= AL;
- X }
- X }
- X#endif
- X changed++;
- X }
- X }
- X
- X /*
- X * Make change in shell if necessary.
- X */
- X if (*shellv != NIL && !eq(*shellv, ac->ac_shell)) {
- X FREEMEM((char *)ac->ac_shell);
- X savestr((char **)&ac->ac_shell, (char *)*shellv);
- X ModBits |= PW;
- X changed++;
- X }
- X
- X if (changed)
- X puts("updated");
- X else
- X err("no change");
- X non_critical();
- X
- X return;
- X}
- @//E*O*F src/update.c//
- if test 22502 -ne "`wc -c <'src/update.c'`"; then
- echo shar: error transmitting "'src/update.c'" '(should have been 22502 characters)'
- fi
- fi # end of overwriting check
- echo shar: "End of archive 8 (of 8)."
- cp /dev/null ark8isdone
- DONE=true
- for I in 1 2 3 4 5 6 7 8; do
- if test -! f ark${I}isdone; then
- echo "You still need to run archive ${I}."
- DONE=false
- fi
- done
- case $DONE in
- true)
- echo "You have run all 8 archives."
- echo 'See the README file'
- ;;
- esac
- ## End of shell archive.
- exit 0
-