From: jfh@rpp386.cactus.org (John F Haugh II) Newsgroups: alt.sources Subject: Shadow Login Suite, version 3 (part 6 of 8) Message-ID: <19300@rpp386.cactus.org> Date: 16 May 91 16:32:11 GMT #! /bin/sh # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # gspack.c # spdbm.c # lastlog.h # shell.c # login.c # sub.c # dpmain.c # mail.c # env.c # pwd.h # grpack.c # shadow.h # log.c # grent.c # motd.c # dialup.h # fields.c # gsdbm.c # This archive created: Sun Mar 3 13:27:34 1991 # By: John F Haugh II (River Parishes Programming, Austin TX) export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'gspack.c'" '(2890 characters)' if test -f 'gspack.c' then echo shar: "will not over-write existing file 'gspack.c'" else sed 's/^X//' << \SHAR_EOF > 'gspack.c' X/* X * Copyright 1990, John F. Haugh II X * All rights reserved. X * X * Permission is granted to copy and create derivative works for any X * non-commercial purpose, provided this copyright notice is preserved X * in all copies of source code, or included in human readable form X * and conspicuously displayed on all copies of object code or X * distribution media. X */ X X#include X#include "shadow.h" X#ifdef BSD X#include X#else X#include X#endif X X#ifndef lint Xstatic char sccsid[] = "@(#)gspack.c 3.1 09:13:50 12/13/90"; X#endif X X/* X * sgr_pack - convert a shadow group structure to a packed X * shadow group record X * X * sgr_pack takes the shadow group structure and packs X * the components in a record. this record will be X * unpacked later by sgr_unpack. X */ X Xint Xsgr_pack (sgrp, buf) Xstruct sgrp *sgrp; Xchar *buf; X{ X char *cp; X int i; X X /* X * The name and password are both easy - append each string X * to the buffer. These are always the first two strings X * in a record. X */ X X cp = buf; X strcpy (cp, sgrp->sg_name); X cp += strlen (cp) + 1; X X strcpy (cp, sgrp->sg_passwd); X cp += strlen (cp) + 1; X X /* X * The arrays of administrators and members are slightly X * harder. Each element is appended as a string, with a X * final '\0' appended to serve as a blank string. The X * number of elements is not known in advance, so the X * entire collection of administrators must be scanned to X * find the start of the members. X */ X X for (i = 0;sgrp->sg_adm[i];i++) { X strcpy (cp, sgrp->sg_adm[i]); X cp += strlen (cp) + 1; X } X *cp++ = '\0'; X X for (i = 0;sgrp->sg_mem[i];i++) { X strcpy (cp, sgrp->sg_mem[i]); X cp += strlen (cp) + 1; X } X *cp++ = '\0'; X X return cp - buf; X} X X/* X * sgr_unpack - convert a packed shadow group record to an X * unpacked record X * X * sgr_unpack converts a record which was packed by sgr_pack X * into the normal shadow group structure format. X */ X Xint Xsgr_unpack (buf, len, sgrp) Xchar *buf; Xint len; Xstruct sgrp *sgrp; X{ X char *org = buf; X int i; X X /* X * The name and password are both easy - they are the first X * two strings in the record. X */ X X sgrp->sg_name = buf; X buf += strlen (buf) + 1; X if (buf - org > len) X return -1; X X sgrp->sg_passwd = buf; X buf += strlen (buf) + 1; X if (buf - org > len) X return -1; X X /* X * The administrators and members are slightly more difficult. X * The arrays are lists of strings. Each list is terminated X * by a string of length zero. This string is detected by X * looking for an initial character of '\0'. X */ X X for (i = 0;*buf && i < 1024;i++) { X sgrp->sg_adm[i] = buf; X buf += strlen (buf) + 1; X X if (buf - org > len) X return -1; X } X sgrp->sg_adm[i] = (char *) 0; X if (! *buf) X buf++; X X for (i = 0;*buf && i < 1024;i++) { X sgrp->sg_mem[i] = buf; X buf += strlen (buf) + 1; X X if (buf - org > len) X return -1; X } X sgrp->sg_mem[i] = (char *) 0; X X return 0; X} SHAR_EOF if test 2890 -ne "`wc -c < 'gspack.c'`" then echo shar: "error transmitting 'gspack.c'" '(should have been 2890 characters)' fi fi echo shar: "extracting 'spdbm.c'" '(933 characters)' if test -f 'spdbm.c' then echo shar: "will not over-write existing file 'spdbm.c'" else sed 's/^X//' << \SHAR_EOF > 'spdbm.c' X/* X * Copyright 1990, John F. Haugh II X * All rights reserved. X * X * Use, duplication, and disclosure prohibited without X * the express written permission of the author. X */ X X#ifndef lint Xstatic char sccsid[] = "@(#)spdbm.c 3.1 08:16:16 11/21/90"; X#endif X X#include X#include X#include "config.h" X#include "shadow.h" X X#ifdef NDBM X#include XDBM *sp_dbm; X X/* X * sp_dbm_update X * X * Updates the DBM password files, if they exist. X */ X Xint Xsp_dbm_update (sp) Xstruct spwd *sp; X{ X datum key; X datum content; X char data[BUFSIZ]; X char spwdkey[60]; X char *cp; X int len; X int i; X int cnt; X static int once; X X if (! once) { X if (! sp_dbm) X setspent (); X X once++; X } X if (! sp_dbm) X return 0; X X len = spw_pack (sp, data); X X content.dsize = len; X content.dptr = data; X X key.dsize = strlen (sp->sp_namp); X key.dptr = sp->sp_namp; X if (dbm_store (sp_dbm, key, content, DBM_REPLACE)) X return 0; X X return 1; X} X#endif SHAR_EOF if test 933 -ne "`wc -c < 'spdbm.c'`" then echo shar: "error transmitting 'spdbm.c'" '(should have been 933 characters)' fi fi echo shar: "extracting 'lastlog.h'" '(511 characters)' if test -f 'lastlog.h' then echo shar: "will not over-write existing file 'lastlog.h'" else sed 's/^X//' << \SHAR_EOF > 'lastlog.h' X/* X * Copyright 1989, 1990, John F. Haugh II X * All rights reserved. X * X * Use, duplication, and disclosure prohibited without X * the express written permission of the author. X */ X X/* X * lastlog.h - structure of lastlog file X * X * @(#)lastlog.h 2.3 19:23:49 7/29/90 X * X * This file defines a lastlog file structure which should be sufficient X * to hold the information required by login. It should only be used if X * there is no real lastlog.h file. X */ X Xstruct lastlog { X time_t ll_time; X char ll_line[8]; X}; SHAR_EOF if test 511 -ne "`wc -c < 'lastlog.h'`" then echo shar: "error transmitting 'lastlog.h'" '(should have been 511 characters)' fi fi echo shar: "extracting 'shell.c'" '(2527 characters)' if test -f 'shell.c' then echo shar: "will not over-write existing file 'shell.c'" else sed 's/^X//' << \SHAR_EOF > 'shell.c' X/* X * Copyright 1989, 1990, 1991, John F. Haugh II X * All rights reserved. X * X * Use, duplication, and disclosure prohibited without X * the express written permission of the author. X */ X X#include X#include X#ifndef BSD X#include X#include X#else X#include X#define strchr index X#define strrchr rindex X#endif X#include "config.h" X X#ifndef lint Xstatic char _sccsid[] = "@(#)shell.c 3.2 07:55:08 2/6/91"; X#endif X Xextern char *newenvp[]; X X/* X * shell - execute the named program X * X * shell begins by trying to figure out what argv[0] is going to X * be for the named process. The user may pass in that argument, X * or it will be the last pathname component of the file with a X * '-' prepended. The first attempt is to just execute the named X * file. If the errno comes back "ENOEXEC", the file is assumed X * at first glance to be a shell script. The first two characters X * must be "#!", in which case "/bin/sh" is executed to process X * the file. If all that fails, give up in disgust ... X */ X Xvoid shell (file, arg) Xchar *file; Xchar *arg; X{ X char arg0[BUFSIZ]; X FILE *fp; X char *path; X int err; X X if (file == (char *) 0) X exit (1); X X /* X * The argv[0]'th entry is usually the path name, but X * for various reasons the invoker may want to override X * that. So, we determine the 0'th entry only if they X * don't want to tell us what it is themselves. X */ X X if (arg == (char *) 0) { X if (path = strrchr (file, '/')) X path++; X else X path = file; X X (void) strcpy (arg0 + 1, path); X arg0[0] = '-'; X arg = arg0; X } X#ifndef NDEBUG X printf ("Executing shell %s\n", file); X#endif X X /* X * First we try the direct approach. The system should be X * able to figure out what we are up to without too much X * grief. X */ X X execle (file, arg, (char *) 0, newenvp); X err = errno; X X /* X * It is perfectly OK to have a shell script for a login X * shell, and this code attempts to support that. It X * relies on the standard shell being able to make sense X * of the "#!" magic number. X */ X X if (err == ENOEXEC) { X if (fp = fopen (file, "r")) { X if (getc (fp) == '#' && getc (fp) == '!') { X fclose (fp); X execle ("/bin/sh", "sh", X file, (char *) 0, newenvp); X err = errno; X } else { X fclose (fp); X } X } X } X X /* X * Obviously something is really wrong - I can't figure out X * how to execute this stupid shell, so I might as well give X * up in disgust ... X */ X X sprintf (arg0, "Cannot execute %s", file); X errno = err; X perror (arg0); X exit (err); X} SHAR_EOF if test 2527 -ne "`wc -c < 'shell.c'`" then echo shar: "error transmitting 'shell.c'" '(should have been 2527 characters)' fi fi echo shar: "extracting 'login.c'" '(1164 characters)' if test -f 'login.c' then echo shar: "will not over-write existing file 'login.c'" else sed 's/^X//' << \SHAR_EOF > 'login.c' X/* X * Copyright 1989, 1990, John F. Haugh II X * All rights reserved. X * X * Use, duplication, and disclosure prohibited without X * the express written permission of the author. X */ X X#include X#include X#ifndef BSD X#include X#include X#else X#include X#define strchr index X#define strrchr rindex X#endif X X#ifndef lint Xstatic char sccsid[] = "@(#)login.c 2.3 19:23:55 7/29/90"; X#endif X Xvoid setenv (); X Xvoid login (name) Xchar *name; X{ X char buf[BUFSIZ]; X char *envp[32]; X int envc; X char *cp; X int i; X X#ifndef BSD X (void) memset (buf, '\0', sizeof buf); X#else X bzero (buf, sizeof buf); X#endif X fputs ("login: ", stdout); X X if (fgets (buf, BUFSIZ, stdin) != buf) X exit (1); X X buf[strlen (buf) - 1] = '\0'; /* remove \n [ must be there ] */ X X for (cp = buf;*cp == ' ' || *cp == '\t';cp++) X ; X X for (i = 0;i < BUFSIZ - 1 && isgraph (*cp);name[i++] = *cp++) X ; X X if (*cp) X cp++; X X name[i] = '\0'; X X if (*cp != '\0') { /* process new variables */ X for (envc = 0;envc < 32;envc++) { X envp[envc] = strtok (envc == 0 ? cp:(char *) 0, " \t,"); X X if (envp[envc] == (char *) 0) X break; X } X setenv (envc, envp); X } X} SHAR_EOF if test 1164 -ne "`wc -c < 'login.c'`" then echo shar: "error transmitting 'login.c'" '(should have been 1164 characters)' fi fi echo shar: "extracting 'sub.c'" '(1538 characters)' if test -f 'sub.c' then echo shar: "will not over-write existing file 'sub.c'" else sed 's/^X//' << \SHAR_EOF > 'sub.c' X/* X * Copyright 1989, 1990, John F. Haugh II X * All rights reserved. X * X * Permission is granted to copy and create derivative works for any X * non-commercial purpose, provided this copyright notice is preserved X * in all copies of source code, or included in human readable form X * and conspicuously displayed on all copies of object code or X * distribution media. X */ X X#include X#include X X#include "pwd.h" X X#ifndef lint Xstatic char sccsid[] = "@(#)sub.c 3.2 08:22:12 1/30/91"; X#endif X X#define BAD_SUBROOT "Invalid root directory \"%s\"\n" X#define BAD_SUBROOT2 "invalid root `%s' for user `%s'\n" X#define NO_SUBROOT "Can't change root directory to \"%s\"\n" X#define NO_SUBROOT2 "no subsystem root `%s' for user `%s'\n" X X/* X * subsystem - change to subsystem root X * X * A subsystem login is indicated by the presense of a "*" as X * the first character of the login shell. The given home X * directory will be used as the root of a new filesystem which X * the user is actually logged into. X */ X Xvoid subsystem (pw) Xstruct passwd *pw; X{ X /* X * The new root directory must begin with a "/" character. X */ X X if (pw->pw_dir[0] != '/') { X printf (BAD_SUBROOT, pw->pw_dir); X syslog (LOG_WARN, BAD_SUBROOT2, pw->pw_dir, pw->pw_name); X exit (1); X } X X /* X * The directory must be accessible and the current process X * must be able to change into it. X */ X X if (chdir (pw->pw_dir) || chroot (pw->pw_dir)) { X printf (NO_SUBROOT, pw->pw_dir); X syslog (LOG_WARN, NO_SUBROOT2, pw->pw_dir, pw->pw_name); X exit (1); X } X} SHAR_EOF if test 1538 -ne "`wc -c < 'sub.c'`" then echo shar: "error transmitting 'sub.c'" '(should have been 1538 characters)' fi fi echo shar: "extracting 'dpmain.c'" '(2895 characters)' if test -f 'dpmain.c' then echo shar: "will not over-write existing file 'dpmain.c'" else sed 's/^X//' << \SHAR_EOF > 'dpmain.c' X/* X * Copyright 1990, John F. Haugh II X * All rights reserved. X * X * Permission is granted to copy and create derivative works for any X * non-commercial purpose, provided this copyright notice is preserved X * in all copies of source code, or included in human readable form X * and conspicuously displayed on all copies of object code or X * distribution media. X */ X X#include X#include X#include X#include X#ifdef BSD X#include X#else X#include X#endif X#include "dialup.h" X X#ifndef lint Xstatic char sccsid[] = "@(#)dpmain.c 3.2 12:30:37 12/12/90"; X#endif X X#define DTMP "/etc/d_passwd.tmp" X X/* X * Prompts and messages go here. X */ X X#define PASS1 "Shell password:" X#define PASS2 "re-enter Shell password:" X#define NOMATCH "%s: Passwords do not match, try again.\n" X#define NOFOUND "%s: Shell %s not found.\n" X Xint aflg; Xint dflg; Xchar *Prog; X Xextern char *pw_encrypt(); Xextern char *getpass(); X Xusage () X{ X fprintf (stderr, "Usage: %s -a|c|d shell\n", Prog); X exit (1); X} X Xmain (argc, argv) Xint argc; Xchar **argv; X{ X struct dialup *dial; X struct dialup dent; X struct stat sb; X FILE *fp; X char *shell; X char *cp; X char pass[BUFSIZ]; X int fd; X int found = 0; X int opt; X extern int optind; X extern char *optarg; X X if (Prog = strrchr (argv[0], '/')) X Prog++; X else X Prog = argv[0]; X X while ((opt = getopt (argc, argv, "a:d:")) != EOF) { X switch (opt) { X case 'a': X aflg++; X shell = optarg; X break; X case 'd': X dflg++; X shell = optarg; X break; X default: X usage (); X } X } X if (aflg + dflg != 1) X usage (); X X if (aflg) { X dent.du_shell = shell; X dent.du_passwd = ""; X X if (! (cp = getpass (PASS1))) { X unlink (DTMP); X exit (1); X } X strcpy (pass, cp); X if (! (cp = getpass (PASS2))) { X unlink (DTMP); X exit (1); X } X if (strcmp (pass, cp)) { X fprintf (stderr, NOMATCH, Prog); X unlink (DTMP); X exit (1); X } X dent.du_passwd = pw_encrypt (pass, (char *) 0); X } X if ((fd = open (DTMP, O_CREAT|O_EXCL|O_RDWR, 0600)) < 0) { X sprintf (pass, "%s: can't create %s", Prog, DTMP); X perror (pass); X exit (1); X } X if (! (fp = fdopen (fd, "r+"))) { X sprintf (pass, "%s: can't open %s", Prog, DTMP); X perror (pass); X exit (1); X } X while (dial = getduent ()) { X if (strcmp (dial->du_shell, shell) == 0) { X found = 1; X break; X } X if (putduent (dial, fp)) X goto failure; X } X if (dflg && ! found) { X fprintf (stderr, NOMATCH, Prog, shell); X exit (1); X } X if (aflg) X if (putduent (&dent, fp)) X goto failure; X X while (dial = getduent ()) X if (putduent (dial, fp)) X goto failure; X X if (fflush (fp)) X goto failure; X X if (! stat (DIALPWD, &sb)) { X chown (DTMP, sb.st_uid, sb.st_gid); X chmod (DTMP, sb.st_mode); X unlink (DIALPWD); X } else { X chown (DTMP, 0, 0); X chmod (DTMP, 0400); X } X link (DTMP, DIALPWD); X unlink (DTMP); X X sync (); X exit (0); X Xfailure: X unlink (DTMP); X exit (1); X} SHAR_EOF if test 2895 -ne "`wc -c < 'dpmain.c'`" then echo shar: "error transmitting 'dpmain.c'" '(should have been 2895 characters)' fi fi echo shar: "extracting 'mail.c'" '(998 characters)' if test -f 'mail.c' then echo shar: "will not over-write existing file 'mail.c'" else sed 's/^X//' << \SHAR_EOF > 'mail.c' X/* X * Copyright 1989, 1990, John F. Haugh II X * All rights reserved. X * X * Permission is granted to copy and create derivative works for any X * non-commercial purpose, provided this copyright notice is preserved X * in all copies of source code, or included in human readable form X * and conspicuously displayed on all copies of object code or X * distribution media. X */ X X#include X#include X X#ifndef BSD X#include X#include X#else X#include X#define strchr index X#define strrchr rindex X#endif X X#include "config.h" X#ifdef MAILCHECK X X#ifndef lint Xstatic char sccsid[] = "@(#)mail.c 3.2 13:28:27 12/19/90"; X#endif X Xextern char *getenv(); X Xvoid mailcheck () X{ X struct stat statbuf; X char *mailbox; X X if (! (mailbox = getenv ("MAIL"))) X return; X X if (stat (mailbox, &statbuf) == -1 || statbuf.st_size == 0) X puts ("No mail."); X else if (statbuf.st_atime > statbuf.st_mtime) X puts ("You have mail."); X else X puts ("You have new mail."); X} X#endif SHAR_EOF if test 998 -ne "`wc -c < 'mail.c'`" then echo shar: "error transmitting 'mail.c'" '(should have been 998 characters)' fi fi echo shar: "extracting 'env.c'" '(1788 characters)' if test -f 'env.c' then echo shar: "will not over-write existing file 'env.c'" else sed 's/^X//' << \SHAR_EOF > 'env.c' X/* X * Copyright 1989, 1990, John F. Haugh II X * All rights reserved. X * X * Use, duplication, and disclosure prohibited without X * the express written permission of the author. X */ X X#include X#ifndef BSD X#include X#else X#define strchr index X#define strrchr rindex X#include X#endif X X#ifndef lint Xstatic char _sccsid[] = "@(#)env.c 2.2 19:23:43 7/29/90"; X#endif X Xextern char **environ; Xextern char *newenvp[]; Xextern int newenvc; Xextern int maxenv; X Xchar *strdup (); Xvoid free (); X Xstatic char *forbid[] = { X "HOME", X "IFS", X "PATH", X "SHELL", X (char *) 0 X}; X Xvoid addenv (entry) Xchar *entry; X{ X char *cp; X int i; X int len; X X if (cp = strchr (entry, '=')) X len = cp - entry; X else X return; X X for (i = 0;i < newenvc;i++) X if (strncmp (entry, newenvp[i], len) == 0 && X (newenvp[i][len] == '=' || newenvp[i][len] == '\0')) X break; X X if (i == maxenv) { X puts ("Environment overflow"); X return; X } X if (i == newenvc) { X newenvp[newenvc++] = strdup (entry); X } else { X free (newenvp[i]); X newenvp[i] = strdup (entry); X } X} X Xvoid setenv (argc, argv) Xint argc; Xchar **argv; X{ X int i; X int n; X int noname = 1; X char variable[BUFSIZ]; X char *cp; X X for (i = 0;i < argc;i++) { X if ((n = strlen (argv[i])) >= BUFSIZ) X continue; /* ignore long entries */ X X if (! (cp = strchr (argv[i], '='))) { X (void) strcpy (variable, argv[i]); X } else { X (void) strncpy (variable, argv[i], cp - argv[i]); X variable[cp - argv[i]] = '\0'; X } X for (n = 0;forbid[n] != (char *) 0;n++) X if (strcmp (variable, forbid[n]) == 0) X break; X X if (forbid[n] != (char *) 0) { X printf ("You may not change $%s\n", forbid[n]); X continue; X } X if (cp) { X addenv (argv[i]); X } else { X sprintf (variable, "L%d=%s", noname++, argv[i]); X addenv (variable); X } X } X} SHAR_EOF if test 1788 -ne "`wc -c < 'env.c'`" then echo shar: "error transmitting 'env.c'" '(should have been 1788 characters)' fi fi echo shar: "extracting 'pwd.h'" '(2383 characters)' if test -f 'pwd.h' then echo shar: "will not over-write existing file 'pwd.h'" else sed 's/^X//' << \SHAR_EOF > 'pwd.h' X/* X * Copyright 1990, John F. Haugh II and Steve Simmons X * All rights reserved. X * X * Permission is granted to copy and create derivative works for any X * non-commercial purpose, provided this copyright notice is preserved X * in all copies of source code, or included in human readable form X * and conspicuously displayed on all copies of object code or X * distribution media. X */ X X/* X * Standard definitions for password files. This is an independant X * reimplementation of the definitions used by AT&T, BSD, and POSIX. X * It is not derived from any of those sources. Note that it can be X * site-defined to have non-POSIX features as well. X * X * $RCSfile$ $Revision$ X * X * $Author$ $Date$ X * X * $State$ $Locker$ X * X * $Log$ X */ X X#ifndef PWD_H X#define PWD_H X X#include X X/* X * For now these are defined here. Later they should be moved to X * the configuration file or this file should be generated by X * a configurator. X */ X X#undef BSD_QUOTAS X#define ATT_AGE X#define ATT_COMMENT X X/* X * This is the data structure returned by the getpw* functions. The X * names of the elements and the structure are taken from traditional X * usage. X */ X Xstruct passwd { X char *pw_name ; /* User login name */ X char *pw_passwd ; /* Encrypted passwd or dummy field */ X uid_t pw_uid ; /* User uid number */ X gid_t pw_gid ; /* User group id number */ X#ifdef BSD_QUOTAS X /* Most BSD systems have quotas, most USG ones don't */ X int pw_quota ; /* The BSD magic doodah */ X#endif X#ifdef ATT_AGE X /* Use ATT-style password aging */ X char *pw_age ; /* ATT radix-64 encoded data */ X#endif X#ifdef ATT_COMMENT X /* Provide the unused comment field */ X char *pw_comment; /* Unused comment field */ X#endif X char *pw_gecos ; /* ASCII user name, other data */ X char *pw_dir ; /* User home directory */ X char *pw_shell ; /* User startup shell */ X} ; X X#ifdef ATT_COMMENT X/* Provide the unused comment structure */ Xstruct comment { X char *c_dept; X char *c_name; X char *c_acct; X char *c_bin; X}; X#endif X X#ifdef __STDC__ X Xextern struct passwd *getpwent( void ) ; Xextern struct passwd *getpwuid( uid_t user_uid ) ; Xextern struct passwd *getpwnam( char *name ) ; Xint setpwent( void ); Xint endpwent( void ); X X#else X Xextern struct passwd *getpwent(); Xextern struct passwd *getpwuid(); Xextern struct passwd *getpwnam(); Xint setpwent(); Xint endpwent(); X X#endif /* of ifdef __STDC__ */ X X#endif /* of ifdef PWD_H */ SHAR_EOF if test 2383 -ne "`wc -c < 'pwd.h'`" then echo shar: "error transmitting 'pwd.h'" '(should have been 2383 characters)' fi fi echo shar: "extracting 'grpack.c'" '(1512 characters)' if test -f 'grpack.c' then echo shar: "will not over-write existing file 'grpack.c'" else sed 's/^X//' << \SHAR_EOF > 'grpack.c' X/* X * Copyright 1990, John F. Haugh II X * All rights reserved. X * X * Use, duplication, and disclosure prohibited without X * the express written permission of the author. X * X * Duplication is permitted for non-commercial [ profit making ] X * purposes provided this and other copyright notices remain X * intact. X */ X X#include X#include X#ifdef BSD X#include X#else X#include X#endif X X#ifndef lint Xstatic char sccsid[] = "@(#)grpack.c 3.2 08:11:20 11/21/90"; X#endif X Xint gr_pack (group, buf) Xstruct group *group; Xchar *buf; X{ X char *cp; X int i; X X cp = buf; X strcpy (cp, group->gr_name); X cp += strlen (cp) + 1; X X strcpy (cp, group->gr_passwd); X cp += strlen (cp) + 1; X X memcpy (cp, (void *) &group->gr_gid, sizeof group->gr_gid); X cp += sizeof group->gr_gid; X X for (i = 0;group->gr_mem[i];i++) { X strcpy (cp, group->gr_mem[i]); X cp += strlen (cp) + 1; X } X *cp++ = '\0'; X X return cp - buf; X} X Xint gr_unpack (buf, len, group) Xchar *buf; Xint len; Xstruct group *group; X{ X char *org = buf; X int i; X X group->gr_name = buf; X buf += strlen (buf) + 1; X if (buf - org > len) X return -1; X X group->gr_passwd = buf; X buf += strlen (buf) + 1; X if (buf - org > len) X return -1; X X memcpy ((void *) &group->gr_gid, (void *) buf, sizeof group->gr_gid); X buf += sizeof group->gr_gid; X if (buf - org > len) X return -1; X X for (i = 0;*buf && i < 1024;i++) { X group->gr_mem[i] = buf; X buf += strlen (buf) + 1; X X if (buf - org > len) X return -1; X } X group->gr_mem[i] = (char *) 0; X return 0; X} SHAR_EOF if test 1512 -ne "`wc -c < 'grpack.c'`" then echo shar: "error transmitting 'grpack.c'" '(should have been 1512 characters)' fi fi echo shar: "extracting 'shadow.h'" '(1823 characters)' if test -f 'shadow.h' then echo shar: "will not over-write existing file 'shadow.h'" else sed 's/^X//' << \SHAR_EOF > 'shadow.h' X/* X * Copyright 1988, 1989, 1990, John F. Haugh II X * All rights reserved. X * X * Use, duplication, and disclosure prohibited without X * the express written permission of the author. X */ X X#ifndef _H_SHADOW X#define _H_SHADOW X X/* X * This information is not derived from AT&T licensed sources. Posted X * to the USENET 11/88, and updated 11/90 with information from SVR4. X * X * @(#)shadow.h 3.3 09:06:50 12/7/90 X */ X X#ifdef ITI_AGING Xtypedef time_t sptime; X#else Xtypedef long sptime; X#endif X X/* X * Shadow password security file structure. X */ X Xstruct spwd { X char *sp_namp; /* login name */ X char *sp_pwdp; /* encrypted password */ X sptime sp_lstchg; /* date of last change */ X sptime sp_min; /* minimum number of days between changes */ X sptime sp_max; /* maximum number of days between changes */ X sptime sp_warn; /* number of days of warning before password X expires */ X sptime sp_inact; /* number of days after password expires X until the account becomes unusable. */ X sptime sp_expire; /* days since 1/1/70 until account expires */ X unsigned long sp_flag; /* reserved for future use */ X}; X X/* X * Shadow password security file functions. X */ X Xstruct spwd *getspent (); Xstruct spwd *getspnam (); Xstruct spwd *sgetspent (); Xstruct spwd *fgetspent (); Xvoid setspent (); Xvoid endspent (); Xint putspent (); X X#define SHADOW "/etc/shadow" X X/* X * Shadow group security file structure X */ X Xstruct sgrp { X char *sg_name; /* group name */ X char *sg_passwd; /* group password */ X char **sg_adm; /* group administator list */ X char **sg_mem; /* group membership list */ X}; X X/* X * Shadow group security file functions. X */ X Xstruct sgrp *getsgent (); Xstruct sgrp *getsgnam (); Xstruct sgrp *sgetsgent (); Xstruct sgrp *fgetsgent (); Xvoid setsgent (); Xvoid endsgent (); Xint putsgent (); X X#define GSHADOW "/etc/gshadow" X#endif SHAR_EOF if test 1823 -ne "`wc -c < 'shadow.h'`" then echo shar: "error transmitting 'shadow.h'" '(should have been 1823 characters)' fi fi echo shar: "extracting 'log.c'" '(1543 characters)' if test -f 'log.c' then echo shar: "will not over-write existing file 'log.c'" else sed 's/^X//' << \SHAR_EOF > 'log.c' X/* X * Copyright 1989, 1990, John F. Haugh II X * All rights reserved. X * X * Permission is granted to copy and create derivative works for any X * non-commercial purpose, provided this copyright notice is preserved X * in all copies of source code, or included in human readable form X * and conspicuously displayed on all copies of object code or X * distribution media. X */ X X#include X#include X#include "pwd.h" X#include X#include X#ifndef BSD X#include X#include X#else X#include X#define strchr index X#define strrchr rindex X#endif X#include "config.h" X X#ifndef lint Xstatic char sccsid[] = "@(#)log.c 3.1 12:30:53 12/12/90"; X#endif X X#ifdef LASTLOG X X#include "lastlog.h" X Xextern struct utmp utent; Xextern struct passwd pwent; Xextern struct lastlog lastlog; Xextern char **environ; X Xlong lseek (); Xtime_t time (); X Xvoid log () X{ X int fd; X off_t offset; X struct lastlog newlog; X X if ((fd = open ("/usr/adm/lastlog", O_RDWR)) == -1) X return; X X offset = pwent.pw_uid * sizeof lastlog; X X if (lseek (fd, offset, 0) != offset) { X (void) close (fd); X return; X } X if (read (fd, (char *) &lastlog, sizeof lastlog) != sizeof lastlog) X#ifndef BSD X memset ((char *) &lastlog, sizeof lastlog, 0); X#else X bzero ((char *) &lastlog, sizeof lastlog); X#endif X newlog = lastlog; X X (void) time (&newlog.ll_time); X (void) strncpy (newlog.ll_line, utent.ut_line, sizeof newlog.ll_line); X (void) lseek (fd, offset, 0); X (void) write (fd, (char *) &newlog, sizeof newlog); X (void) close (fd); X} X#endif SHAR_EOF if test 1543 -ne "`wc -c < 'log.c'`" then echo shar: "error transmitting 'log.c'" '(should have been 1543 characters)' fi fi echo shar: "extracting 'grent.c'" '(9437 characters)' if test -f 'grent.c' then echo shar: "will not over-write existing file 'grent.c'" else sed 's/^X//' << \SHAR_EOF > 'grent.c' X/* X * Copyright 1990, John F. Haugh II X * All rights reserved. X * X * Permission is granted to copy and create derivative works for any X * non-commercial purpose, provided this copyright notice is preserved X * in all copies of source code, or included in human readable form X * and conspicuously displayed on all copies of object code or X * distribution media. X */ X X#include X#include X#ifdef BSD X#include X#define strchr index X#define strrchr rindex X#else /* !BSD */ X#include X#endif /* BSD */ X#include "config.h" X X#ifdef AUTOSHADOW X#include "shadow.h" X#endif /* AUTOSHADOW */ X X#ifdef NDBM X#include X#include XDBM *gr_dbm; Xint gr_dbm_mode = -1; X#endif /* NDBM */ X X#ifndef lint Xstatic char sccsid[] = "@(#)grent.c 3.7 08:03:08 12/20/90"; X#endif /* !lint */ X X#define NFIELDS 4 X#define MAXMEM 1024 X Xstatic char grpbuf[4*BUFSIZ]; Xstatic char *grpfields[NFIELDS]; Xstatic char *members[MAXMEM+1]; Xstatic struct group grent; X Xstatic FILE *grpfp; Xstatic char *grpfile = GRPFILE; X#ifdef NDBM Xstatic int dbmopened; Xstatic int dbmerror; X#endif /* NDBM */ X Xchar * Xfgetsx (buf, cnt, f) Xchar *buf; Xint cnt; XFILE *f; X{ X int c; X char *cp = buf; X char *ep; X X while (cnt > 0) { X if (fgets (cp, cnt, f) == 0) X if (cp == buf) X return 0; X else X break; X X if ((ep = strrchr (cp, '\\')) && *(ep + 1) == '\n') { X if ((cnt -= ep - cp) > 0) X *(cp = ep) = '\0'; X } else X break; X } X return buf; X} X Xint Xfputsx (s, stream) Xchar *s; XFILE *stream; X{ X int i; X X for (i = 0;*s;i++, s++) { X if (putc (*s, stream) == EOF) X return EOF; X X if (i > (BUFSIZ/2)) { X if (putc ('\\', stream) == EOF || X putc ('\n', stream) == EOF) X return EOF; X X i = 0; X } X } X return 0; X} X Xstatic char ** Xlist (s) Xchar *s; X{ X int nmembers = 0; X X while (*s) { X members[nmembers++] = s; X if (s = strchr (s, ',')) X *s++ = '\0'; X } X members[nmembers] = (char *) 0; X return members; X} X Xstruct group *sgetgrent (buf) Xchar *buf; X{ X int i; X char *cp; X X strncpy (grpbuf, buf, sizeof grpbuf); X grpbuf[sizeof grpbuf - 1] = '\0'; X if (cp = strrchr (grpbuf, '\n')) X *cp = '\0'; X X for (cp = grpbuf, i = 0;i < NFIELDS && cp;i++) { X grpfields[i] = cp; X if (cp = strchr (cp, ':')) X *cp++ = 0; X } X if (i < (NFIELDS-1) || *grpfields[2] == '\0') X return ((struct group *) 0); X X grent.gr_name = grpfields[0]; X grent.gr_passwd = grpfields[1]; X grent.gr_gid = atoi (grpfields[2]); X grent.gr_mem = list (grpfields[3]); X X return (&grent); X} X Xint Xputgrent (g, f) Xstruct group *g; XFILE *f; X{ X int i; X char *cp; X char buf[BUFSIZ*4]; X X if (! g || ! f) X return -1; X X sprintf (buf, "%s:%s:%d:", g->gr_name, g->gr_passwd, g->gr_gid); X if (g->gr_mem) { X cp = strchr (buf, '\0'); X for (i = 0;g->gr_mem[i];i++) { X if ((cp - buf) + strlen (g->gr_mem[i]) + 2 X >= sizeof buf) X return -1; X X if (i > 0) { X strcpy (cp, ","); X cp++; X } X strcpy (cp, g->gr_mem[i]); X cp = strchr (cp, '\0'); X } X strcat (cp, "\n"); X } else X strcat (buf, "\n"); X X if (fputsx (buf, f) == EOF || ferror (f)) X return -1; X X return 0; X} X X/* X * fgetgrent - get a group file entry from a stream X * X * fgetgrent() reads the next line from a group file formatted stream X * and returns a pointer to the group structure for that line. X */ X Xstruct group *fgetgrent (fp) XFILE *fp; X{ X char buf[BUFSIZ*4]; X char *cp; X X if (fgetsx (buf, sizeof buf, fp) != (char *) 0) { X if (cp = strchr (buf, '\n')) X *cp = '\0'; X X return (sgetgrent (buf)); X } X return 0; X} X X/* X * endgrent - close a group file X * X * endgrent() closes the group file if open. X */ X Xint endgrent () X{ X if (grpfp) X if (fclose (grpfp)) X return -1; X X grpfp = 0; X#ifdef NDBM X if (dbmopened && gr_dbm) { X dbm_close (gr_dbm); X gr_dbm = 0; X } X dbmopened = 0; X dbmerror = 0; X#endif /* NDBM */ X return 0; X} X X/* X * getgrent - get a group entry from the group file X * X * getgrent() opens the group file, if not already opened, and reads X * a single entry. NULL is returned if any errors are encountered reading X * the group file. X */ X Xstruct group *getgrent () X{ X if (! grpfp && setgrent ()) X return 0; X X return fgetgrent (grpfp); X} X X/* X * getgrgid - locate the group entry for a given GID X * X * getgrgid() locates the first group file entry for the given GID. X * If there is a valid DBM file, the DBM files are queried first for X * the entry. Otherwise, a linear search is begun of the group file X * searching for an entry which matches the provided GID. X */ X Xstruct group *getgrgid (gid) Xint gid; X{ X struct group *grp; X#ifdef NDBM X datum key; X datum content; X int cnt; X int i; X char *cp; X char grpkey[64]; X#endif /* NDBM */ X#ifdef AUTOSHADOW X struct sgrp *sgrp; X#endif /* AUTOSHADOW */ X X if (setgrent ()) X return 0; X X#ifdef NDBM X X /* X * If the DBM file are now open, create a key for this GID and X * try to fetch the entry from the database. A matching record X * will be unpacked into a static structure and returned to X * the user. X */ X X if (dbmopened) { X grent.gr_gid = gid; X key.dsize = sizeof grent.gr_gid; X key.dptr = (char *) &grent.gr_gid; X content = dbm_fetch (gr_dbm, key); X if (content.dptr == 0) X return 0; X X if (content.dsize == sizeof (int)) { X memcpy (&cnt, content.dptr, content.dsize); X for (cp = grpbuf, i = 0;i < cnt;i++) { X memcpy (grpkey, &i, sizeof i); X memcpy (grpkey + sizeof i, &grent.gr_gid, X sizeof grent.gr_gid); X X key.dsize = sizeof i + sizeof grent.gr_gid; X key.dptr = grpkey; X X content = dbm_fetch (gr_dbm, key); X if (content.dptr == 0) X return 0; X X memcpy (cp, content.dptr, content.dsize); X cp += content.dsize; X } X grent.gr_mem = members; X gr_unpack (grpbuf, cp - grpbuf, &grent); X#ifdef AUTOSHADOW X if (sgrp = getsgnam (grent.gr_name)) { X grent.gr_passwd = sgrp->sg_passwd; X grent.gr_mem = sgrp->sg_mem; X } X#endif /* AUTOSHADOW */ X return &grent; X } else { X grent.gr_mem = members; X memcpy (grpbuf, content.dptr, content.dsize); X gr_unpack (grpbuf, content.dsize, &grent); X#ifdef AUTOSHADOW X if (sgrp = getsgnam (grent.gr_name)) { X grent.gr_passwd = sgrp->sg_passwd; X grent.gr_mem = sgrp->sg_mem; X } X#endif /* AUTOSHADOW */ X return &grent; X } X } X#endif /* NDBM */ X /* X * Search for an entry which matches the GID. Return the X * entry when a match is found. X */ X X while (grp = getgrent ()) X if (grp->gr_gid == gid) X break; X X#ifdef AUTOSHADOW X if (grp) { X if (sgrp = getsgnam (grent.gr_name)) { X grp->gr_passwd = sgrp->sg_passwd; X grp->gr_mem = sgrp->sg_mem; X } X } X#endif /* AUTOSHADOW */ X return grp; X} X Xstruct group *getgrnam (name) Xchar *name; X{ X struct group *grp; X#ifdef NDBM X datum key; X datum content; X int cnt; X int i; X char *cp; X char grpkey[64]; X#endif /* NDBM */ X#ifdef AUTOSHADOW X struct sgrp *sgrp; X#endif /* AUTOSHADOW */ X X if (setgrent ()) X return 0; X X#ifdef NDBM X X /* X * If the DBM file are now open, create a key for this GID and X * try to fetch the entry from the database. A matching record X * will be unpacked into a static structure and returned to X * the user. X */ X X if (dbmopened) { X key.dsize = strlen (name); X key.dptr = name; X content = dbm_fetch (gr_dbm, key); X if (content.dptr == 0) X return 0; X X if (content.dsize == sizeof (int)) { X memcpy (&cnt, content.dptr, content.dsize); X for (cp = grpbuf, i = 0;i < cnt;i++) { X memcpy (grpkey, &i, sizeof i); X strcpy (grpkey + sizeof i, name); X X key.dsize = sizeof i + strlen (name); X key.dptr = grpkey; X X content = dbm_fetch (gr_dbm, key); X if (content.dptr == 0) X return 0; X X memcpy (cp, content.dptr, content.dsize); X cp += content.dsize; X } X grent.gr_mem = members; X gr_unpack (grpbuf, cp - grpbuf, &grent); X#ifdef AUTOSHADOW X if (sgrp = getsgnam (grent.gr_name)) { X grent.gr_passwd = sgrp->sg_passwd; X grent.gr_mem = sgrp->sg_mem; X } X#endif /* AUTOSHADOW */ X return &grent; X } else { X grent.gr_mem = members; X memcpy (grpbuf, content.dptr, content.dsize); X gr_unpack (grpbuf, content.dsize, &grent); X#ifdef AUTOSHADOW X if (sgrp = getsgnam (grent.gr_name)) { X grent.gr_passwd = sgrp->sg_passwd; X grent.gr_mem = sgrp->sg_mem; X } X#endif /* AUTOSHADOW */ X return &grent; X } X } X#endif /* NDBM */ X /* X * Search for an entry which matches the name. Return the X * entry when a match is found. X */ X X while (grp = getgrent ()) X if (strcmp (grp->gr_name, name) == 0) X break; X X#ifdef AUTOSHADOW X if (grp) { X if (sgrp = getsgnam (grent.gr_name)) { X grp->gr_passwd = sgrp->sg_passwd; X grp->gr_mem = sgrp->sg_mem; X } X } X#endif /* AUTOSHADOW */ X return 0; X} X X/* X * setgrent - open the group file X * X * setgrent() opens the system group file, and the DBM group files X * if they are present. The system group file is rewound if it was X * open already. X */ X Xint Xsetgrent () X{ X#ifdef NDBM X int mode; X#endif /* NDBM */ X X if (! grpfp) { X if (! (grpfp = fopen (grpfile, "r"))) X return -1; X } else { X if (fseek (grpfp, 0L, 0) != 0) X return -1; X } X X /* X * Attempt to open the DBM files if they have never been opened X * and an error has never been returned. X */ X X#ifdef NDBM X if (! dbmerror && ! dbmopened) { X char dbmfiles[BUFSIZ]; X X strcpy (dbmfiles, grpfile); X strcat (dbmfiles, ".pag"); X if (gr_dbm_mode == -1) X mode = O_RDONLY; X else X mode = (gr_dbm_mode == O_RDONLY || X gr_dbm_mode == O_RDWR) ? gr_dbm_mode:O_RDONLY; X X if (access (dbmfiles, 0) || X (! (gr_dbm = dbm_open (grpfile, mode, 0)))) X dbmerror = 1; X else X dbmopened = 1; X } X#endif /* NDBM */ X return 0; X} SHAR_EOF if test 9437 -ne "`wc -c < 'grent.c'`" then echo shar: "error transmitting 'grent.c'" '(should have been 9437 characters)' fi fi echo shar: "extracting 'motd.c'" '(750 characters)' if test -f 'motd.c' then echo shar: "will not over-write existing file 'motd.c'" else sed 's/^X//' << \SHAR_EOF > 'motd.c' X/* X * Copyright 1989, 1990, John F. Haugh II X * All rights reserved. X * X * Use, duplication, and disclosure prohibited without X * the express written permission of the author. X */ X X#include X#ifndef BSD X#include X#include X#else X#include X#define strchr index X#define strrchr rindex X#endif X#include "config.h" X X#ifndef lint Xstatic char _sccsid[] = "@(#)motd.c 2.2 19:23:58 7/29/90"; X#endif X Xextern char home[]; X#ifdef HUSHLOGIN Xextern int hushed; X#endif X X#ifdef MOTD Xvoid motd () X{ X FILE *fp; X register int c; X X#ifdef HUSHLOGIN X if (hushed) X return; X#endif X if ((fp = fopen ("/etc/motd", "r")) == (FILE *) 0) X return; X X while ((c = getc (fp)) != EOF) X putchar (c); X X fclose (fp); X fflush (stdout); X} X#endif SHAR_EOF if test 750 -ne "`wc -c < 'motd.c'`" then echo shar: "error transmitting 'motd.c'" '(should have been 750 characters)' fi fi echo shar: "extracting 'dialup.h'" '(1598 characters)' if test -f 'dialup.h' then echo shar: "will not over-write existing file 'dialup.h'" else sed 's/^X//' << \SHAR_EOF > 'dialup.h' X/* X * Copyright 1989, 1990, John F. Haugh II X * All rights reserved. X * X * Permission is granted to copy and create derivative works for any X * non-commercial purpose, provided this copyright notice is preserved X * in all copies of source code, or included in human readable form X * and conspicuously displayed on all copies of object code or X * distribution media. X */ X X/* X * Structure of the /etc/d_passwd file X * X * The d_passwd file contains the names of login shells which require X * dialup passwords. Each line contains the fully qualified path name X * for the shell, followed by an optional password. Each field is X * separated by a ':'. X * X * Structure of the /etc/dialups file X * X * The dialups file contains the names of ports which may be dialup X * lines. Each line consists of the last component of the path X * name. The leading "/dev/" string is removed. X * X * @(#)dialup.h 3.1 19:44:22 12/10/90 X */ X X#ifndef _DIALUP_H X#define _DIALUP_H X X#include X Xstruct dialup { X char *du_shell; X char *du_passwd; X}; X X#ifdef __STDC__ Xextern void setduent (); Xextern void endduent (); Xextern struct dialup *fgetduent (); Xextern struct dialup *getduent (); Xextern struct dialup *getdushell (); Xextern int putduent (); Xextern int isadialup (); X#else Xextern void setduent (void); Xextern void endduent (void); Xextern struct dialup *fgetduent (FILE *); Xextern struct dialup *getduent (void); Xextern struct dialup *getdushell (char *); Xextern int putduent (struct dialup *, FILE *); Xextern int isadialup (char *); X#endif X X#define DIALPWD "/etc/d_passwd" X#define DIALUPS "/etc/dialups" X X#endif SHAR_EOF if test 1598 -ne "`wc -c < 'dialup.h'`" then echo shar: "error transmitting 'dialup.h'" '(should have been 1598 characters)' fi fi echo shar: "extracting 'fields.c'" '(1230 characters)' if test -f 'fields.c' then echo shar: "will not over-write existing file 'fields.c'" else sed 's/^X//' << \SHAR_EOF > 'fields.c' X/* X * Copyright 1990, John F. Haugh II X * All rights reserved. X * X * Use, duplication, and disclosure prohibited without X * the express written permission of the author. X */ X X#include X#include X#include X X#ifndef lint Xstatic char sccsid[] = "@(#)fields.c 3.2 08:26:23 11/26/90"; X#endif X Xextern char *Progname; X X/* X * valid_field - insure that a field contains all legal characters X * X * The supplied field is scanned for non-printing and other illegal X * characters. If any illegal characters are found, valid_field X * returns -1. Zero is returned for success. X */ X Xint Xvalid_field (field, illegal) Xchar *field; Xchar *illegal; X{ X char *cp; X X for (cp = field;*cp && isprint (*cp) && ! strchr (illegal, *cp);cp++) X ; X X if (*cp) X return -1; X else X return 0; X} X X/* X * change_field - change a single field if a new value is given. X * X * prompt the user with the name of the field being changed and the X * current value. X */ X Xvoid Xchange_field (buf, prompt) Xchar *buf; Xchar *prompt; X{ X char new[BUFSIZ]; X char *cp; X X printf ("\t%s [%s]: ", prompt, buf); X if (fgets (new, BUFSIZ, stdin) != new) X return; X X if (cp = strchr (new, '\n')) X *cp = '\0'; X else X return; X X if (new[0]) X strcpy (buf, new); X} SHAR_EOF if test 1230 -ne "`wc -c < 'fields.c'`" then echo shar: "error transmitting 'fields.c'" '(should have been 1230 characters)' fi fi echo shar: "extracting 'gsdbm.c'" '(1823 characters)' if test -f 'gsdbm.c' then echo shar: "will not over-write existing file 'gsdbm.c'" else sed 's/^X//' << \SHAR_EOF > 'gsdbm.c' X/* X * Copyright 1990, John F. Haugh II X * All rights reserved. X * X * Permission is granted to copy and create derivative works for any X * non-commercial purpose, provided this copyright notice is preserved X * in all copies of source code, or included in human readable form X * and conspicuously displayed on all copies of object code or X * distribution media. X */ X X#ifndef lint Xstatic char sccsid[] = "@(#)gsdbm.c 3.3 11:25:29 12/19/90"; X#endif X X#include X#include X#include "shadow.h" X#include "config.h" X X#ifdef NDBM X#include XDBM *sgr_dbm; X X#define GRP_FRAG 256 X X/* X * sgr_dbm_update X * X * Updates the DBM password files, if they exist. X */ X Xint Xsgr_dbm_update (sgr) Xstruct sgrp *sgr; X{ X datum key; X datum content; X char data[BUFSIZ*8]; X char sgrpkey[60]; X char *cp; X int len; X int i; X int cnt; X static int once; X X if (! once) { X if (! sgr_dbm) X setsgent (); X X once++; X } X if (! sgr_dbm) X return 0; X X len = sgr_pack (sgr, data); X X if (len <= GRP_FRAG) { X content.dsize = len; X content.dptr = data; X X key.dsize = strlen (sgr->sg_name); X key.dptr = sgr->sg_name; X if (dbm_store (sgr_dbm, key, content, DBM_REPLACE)) X return 0; X } else { X content.dsize = sizeof cnt; X content.dptr = (char *) &cnt; X cnt = (len + (GRP_FRAG-1)) / GRP_FRAG; X X key.dsize = strlen (sgr->sg_name); X key.dptr = sgr->sg_name; X if (dbm_store (sgr_dbm, key, content, DBM_REPLACE)) X return 0; X X for (cp = data, i = 0;i < cnt;i++) { X content.dsize = len > GRP_FRAG ? GRP_FRAG:len; X len -= content.dsize; X content.dptr = cp; X cp += content.dsize; X X key.dsize = sizeof i + strlen (sgr->sg_name); X key.dptr = sgrpkey; X memcpy (sgrpkey, &i, sizeof i); X strcpy (sgrpkey + sizeof i, sgr->sg_name); X if (dbm_store (sgr_dbm, key, content, DBM_REPLACE)) X return 0; X } X } X return 1; X} X#endif SHAR_EOF if test 1823 -ne "`wc -c < 'gsdbm.c'`" then echo shar: "error transmitting 'gsdbm.c'" '(should have been 1823 characters)' fi fi exit 0 # End of shell archive -- John F. Haugh II | Distribution to | UUCP: ...!cs.utexas.edu!rpp386!jfh Ma Bell: (512) 255-8251 | GEnie PROHIBITED :-) | Domain: jfh@rpp386.cactus.org "If liberals interpreted the 2nd Amendment the same way they interpret the rest of the Constitution, gun ownership would be mandatory."