[comp.os.os9] REPOST: OS9Lib Part 03/05

ocker@lan.informatik.tu-muenchen.dbp.de (Wolfgang Ocker) (10/20/88)

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 3 (of 5)."
# Contents:  MAN/Sysinfo.prf MAN/Mdir.prf shell.c MAN/Utmp.prf
#   chgrppass.c chpass.c MAN/Group.prf mdir.c grp.c strings.c
#   MAN/Passwd.prf popen.c signal.a
# Wrapped by weo@recsys on Tue Oct 11 14:23:23 1988
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'MAN/Sysinfo.prf' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MAN/Sysinfo.prf'\"
else
echo shar: Extracting \"'MAN/Sysinfo.prf'\" \(2686 characters\)
sed "s/^X//" >'MAN/Sysinfo.prf' <<'END_OF_FILE'
X.fill
X.justify
X.offset 5
X.rightmargin 55
X.pagesize 48
X.m1 2
X.m2 1
X.m3 2
X.m4 3
X.ec \
X.header /Sysinfo/OS9Lib/Sysinfo
X.footer /Page #//Printed (%)/
X.in +5
X.define topic
X.bold
X.in -5
X$1 $2 $3 $4 $5
X.in +5
X.en
X.define endtopic
X
X
X.en
X.define noform
X.nojustify
X.nofill
X.en
X.define noformend
X.justify
X.fill
X.en
X.! Manual created with MWB
X.! END-OF-MACRO
X.topic NAME
XSysinfo - Access the system-wide Parameters
X.endtopic
X.topic SYNOPSIS
X.noform
Xint	info_type (name)
Xchar	*name;
X
Xchar	*info_str (name, str, len)
Xchar	*name;
Xchar	*str;
Xint	len;
X
Xint	info_num(name)
Xchar	*name;
X
Xint	info_is_locked (name)
Xchar	*name;
X
Xint	info_lock (name, signal)
Xchar	*name;
Xint	signal;
X
Xint	info_unlock (name)
Xchar	*name;
X
Xint	info_change (name, signal)
Xchar	*name;
Xint	signal;
X.noformend
X.endtopic
X.topic DESCRIPTION
X	The
X.ul
XSysinfo
Xconcept is complete new for OS9. Designed by TOP Munich and
Xwritten by Wolfgang Ocker, this concept provides the possibility to hold
Xsystem-wide information in a global data-module and allows the locking
Xof abstract `devices` like uucp etc. To access this module there
Xexists various functions.
X
X	The function
X.ul
Xinfo_type()
Xaccepts a string and determines the kind of the entry by this name.
X.ul
Xinfo_str()
Xneeds a string with the name of the possible entry, a pointer to a
Xbuffer where the result will be copied to and the size of the buffer. It
Xextracts the string of the entry defined by the name and copies the
Xfound entry into the buffer.
X.ul
Xinfo_num()
Xaccepts a name and returns the value of the entry.
X.ul
Xinfo_is_locked()
Xneeds a string as an argument and returns the status of the given entry:
Xlocked by another process or free.
X.ul
Xinfo_lock
Xneeds two arguments, the first is the name of the entry, the second is a
Xsignal number with which the process can be killed. If another process
Xwants to lock the entry, the actual locking process will get a signal
Xwhich it has written in by info_lock. This process can make his clean-up
Xand then free the entry. If the signal number in the entry is -1, the
Xlocking process in unkillable.
X.ul
Xinfo_unlock()
Xallows to unlock an entry previous locked by this process. With
X.ul
Xinfo_change()
Xthe signal can be changed. This make sense when the process does some
Xcritical work.
X.endtopic
X.topic RETURN VALUE
XInfo_type returns the kind of the entry on success, -1 on failure. 
XInfo_str returns a pointer to the buffer on success, NULL on failure. 
XInfo_num returns the balue of the entry on success, -1 on failure. 
XInfo_is_locked, info_lock, info_unlock and info_change returns 0 on success,
Xa negative value on failure.
X
X.endtopic
X.topic SEE ALSO
X.noform
XSysinfo, Setup, Getinfo
Xin the TOP Munich Release
X.noformend
X.endtopic
END_OF_FILE
if test 2686 -ne `wc -c <'MAN/Sysinfo.prf'`; then
    echo shar: \"'MAN/Sysinfo.prf'\" unpacked with wrong size!
fi
# end of 'MAN/Sysinfo.prf'
fi
if test -f 'MAN/Mdir.prf' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MAN/Mdir.prf'\"
else
echo shar: Extracting \"'MAN/Mdir.prf'\" \(3028 characters\)
sed "s/^X//" >'MAN/Mdir.prf' <<'END_OF_FILE'
X.fill
X.justify
X.offset 5
X.rightmargin 55
X.pagesize 48
X.m1 2
X.m2 1
X.m3 2
X.m4 3
X.ec \
X.header /Mdir/OS9Lib/Mdir
X.footer /Page #//Printed (%)/
X.in +5
X.define topic
X.bold
X.in -5
X$1 $2 $3 $4 $5
X.in +5
X.en
X.define endtopic
X
X
X.en
X.define noform
X.nojustify
X.nofill
X.en
X.define noformend
X.justify
X.fill
X.en
X.! Manual created with MWB
X.! END-OF-MACRO
X.topic NAME
XMdir - Access the Module Directory
X.endtopic
X.topic SYNOPSIS
X.noform
Xint	_mopen()
X
Xint	_mclose()
X
Xmentry	*_mread()
X
Xint	_mseek (position, place)
X
Xint	position, place;
X
Xint	_mtell()
X
Xint	_mrewind()
X
Xmentry	*_mexist(name)
Xchar	*name;
X
Xchar	*getmodname(mod_addr)
Xstruct modhcom *mod_addr;
X.noformend
X.endtopic
X.topic DESCRIPTION
X.bold
XMdir
Xprovides an easy way to handle access to the module directory. In
X.ul
Xmdir.h
Xa struct _mentry is defined to make the access as simple as possible.
X.in +5
X.nf
X.nj
Xtypedef struct _mentry {
X  /* The name of the module         */
X
X  char           m_name[33]; 
X  /* The link count of the module   */
X  int            m_link;
X
X  /* A pointer to the module header */
X  struct modhcom *m_ptr;
X
X  /* A copy of the module header    */
X  struct modhcom m_head;
X} mentry;
X.fi
X.ju
X.in -5
X
X	Before the first access to the module directory you should call
X.ul
X_mopen
Xto intialize some internal data. When finished with the access, call
X.ul
X_mclose
Xto make sure that everything is cleaned up properly.
X.ul
X_mread
Xreturns the next entry in the module directory. If there is no further
Xentry found, NULL is returned.
X.ul
X_mseek
Xallows the user to seek randomly through the module directory. If place
Xis 0, the seek operation takes place from the start of the module
Xdirectory, if it is 1, it starts from the current position and if it is
X2 it seeks after the last entry in the module directory.
X.ul
X_mtell
Xreturns the current position in the module directory.
X.ul
X_mrewind
Xmoves the pointer back to the beginning of the directory.
X.ul
X_mexist
Xscans through the module directory to see, whether the module `name` has an
Xentry there.
X.ul
Xgetmodname
Xrequires a pointer to a module header and returns the name of the module
Xif found, NULL otherwise.
X.endtopic
X.topic CAVEATS
X_mseek() and _mtell() assuming that every next position has a distance
Xof 1 to the previous, not sizeof (mentry).
X.endtopic
X.topic RETURN VALUE
X_mopen(), mclose() and _mrewind() return 0 on success and -1 on failure. 
X_mread() returns the next entry or NULL if the last one has proceeded or
Xon failure.  _mseek() returns the new position of the pointer on
Xsuccess, -1 on failure.  _mtell() returns the current position of the
Xpointer on success or -1 on failure. _mexist() returns a pointer to the
Xmentry of the module, if found, else NULL. Getmodname() returns the name
Xof the module on success, NULL otherwise.
X
X.endtopic
X.topic EXAMPLES
X.noform
X# include	<mdir.h>
X
Xmentry	*entry;
X
Xif (_mopen() < 0)
X	return;
Xwhile (entry = _mread ())
X	printf ("%s\\n", entry->m_name);
X(void) _mclose ();
X.noformend
X.endtopic
X.topic SEE ALSO
X.noform
XMdir
Xin the OS9 User Manual
X.noformend
X.endtopic
END_OF_FILE
if test 3028 -ne `wc -c <'MAN/Mdir.prf'`; then
    echo shar: \"'MAN/Mdir.prf'\" unpacked with wrong size!
fi
# end of 'MAN/Mdir.prf'
fi
if test -f 'shell.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'shell.c'\"
else
echo shar: Extracting \"'shell.c'\" \(3281 characters\)
sed "s/^X//" >'shell.c' <<'END_OF_FILE'
X/* ------------------------------------------------------------------- *
X |
X | OS9Lib:  shell(), xshell()
X |
X |
X |     Copyright (c) 1988 by Wolfgang Ocker, Puchheim,
X |                           Ulli Dessauer, Germering and
X |                           Reimer Mellin, Muenchen
X |                           (W-Germany)
X |
X |  This  programm can  be  copied and  distributed freely  for any
X |  non-commercial  purposes.   It can only  be  incorporated  into
X |  commercial software with the written permission of the authors.
X |
X |  If you should modify this program, the authors would appreciate
X |  a notice about the changes. Please send a (context) diff or the
X |  complete source to:
X |
X |  address:     Wolfgang Ocker
X |               Lochhauserstrasse 35a
X |               D-8039 Puchheim
X |               West Germany
X |
X |  e-mail:      weo@altger.UUCP, ud@altger.UUCP, ram@altger.UUCP
X |               pyramid!tmpmbx!recco!weo
X |               pyramid!tmpmbx!nitmar!ud
X |               pyramid!tmpmbx!ramsys!ram
X |
X * ----------------------------------------------------------------- */
X
X#define PATCHLEVEL 1
X
X#include <stdio.h>
X#include <modes.h>
X#include <strings.h>
X#include <errno.h>
X
X
Xextern char **environ;
Xextern int  os9forkc();
X
Xextern char *findmod(), *getenv(), *info_str();
X
Xstatic char cmd_name[600];
X
Xint _shell_secure = 0;
X
Xstatic int check_shell()
X{
X  char *shell, *cp, *cp2, *cp3, val_shell[200];
X  
X  errno = E_FNA;
X
X  if ((shell = getenv("SHELL")) == NULL)
X    return(0);
X  
X  if (info_str("valid.shells", val_shell, sizeof(val_shell)) == NULL)
X    strcpy(val_shell, "shell,sh,csh");
X  
X  for (cp = val_shell; cp != NULL && *cp != '\0'; ) {
X    cp2 = cp;
X    if ((cp = index(cp, ',')) != NULL)
X      *cp++ = '\0';
X
X    while (*cp2 == ' ')
X      cp2++;
X    if ((cp3 = index(cp2, ' ')) != NULL)
X      *cp3 = '\0';
X
X    if (!strcmp(shell, cp2))
X      return(1);
X  }
X  
X  return(0);
X}
X
X/*
X * s h e l l 
X */
Xint shell(name)
X  char *name;
X{
X  static char   *argv[] = {NULL, NULL, NULL };
X  static char   cmd[300], cmd_path[100];
X  register char *cp;
X  int           pid, status;
X
X  if (_shell_secure)
X    if (!check_shell())
X      return(-1);
X
X  cp = name;
X  while (*cp == ' ')
X    cp++;
X
X  strcpy(cmd_path, cp);
X
X  if (cp = index(cmd_path, ' '))
X    *cp++ = '\0';
X
X  strcpy(cmd, "ex ");
X  strcat(cmd, findmod(cmd_path, cmd_path));
X  if (cp) {
X    strcat(cmd, " ");
X    strcat(cmd, name+(cp-cmd_path));
X  }
X
X  argv[1] = cmd;
X
X  argv[0] = findmod("shell", "SYSTEM.SHELL");
X  if ((pid = os9exec(os9forkc, argv[0], argv, environ, 0, 0, 3)) == -1)
X    return(-1);
X
X
X  while (wait(&status) != pid) ;
X  
X  if (status &= 0x0ffff) {
X    errno = status;
X    return(-1);
X  }
X  else
X    return(0);
X}
X
X/*
X * x s h e l l
X */
Xint xshell(name)
X  register char *name;
X{
X  register int pid;
X  int          status;
X  char         **argv;
X
X  if (_shell_secure)
X    if (!check_shell())
X      return(-1);
X
X  strcpy(cmd_name, name);
X  if (getargs(cmd_name, &argv) == -1)
X    return(-1);
X
X  if ((pid = os9exec(os9forkc, findmod(argv[0], argv[0]), argv, environ, 
X                     0, 0, 3)) == -1) {
X    free(argv);
X    return(-1);
X  }
X
X  free(argv);
X
X  while (wait(&status) != pid) ;
X
X  if (status &= 0x0ffff) {
X    errno = status;
X    return(-1);
X  }
X  else
X    return(0);
X}
X
END_OF_FILE
if test 3281 -ne `wc -c <'shell.c'`; then
    echo shar: \"'shell.c'\" unpacked with wrong size!
fi
# end of 'shell.c'
fi
if test -f 'MAN/Utmp.prf' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MAN/Utmp.prf'\"
else
echo shar: Extracting \"'MAN/Utmp.prf'\" \(3486 characters\)
sed "s/^X//" >'MAN/Utmp.prf' <<'END_OF_FILE'
X.fill
X.justify
X.offset 5
X.rightmargin 55
X.pagesize 48
X.m1 2
X.m2 1
X.m3 2
X.m4 3
X.ec \
X.header /Utmp/OS9Lib/Utmp
X.footer /Page #//Printed (%)/
X.in +5
X.define topic
X.bold
X.in -5
X$1 $2 $3 $4 $5
X.in +5
X.en
X.define endtopic
X
X
X.en
X.define noform
X.nojustify
X.nofill
X.en
X.define noformend
X.justify
X.fill
X.en
X.! Manual created with MWB
X.! END-OF-MACRO
X.topic NAME
XUtmp - Library to examine the /dd/SYS/utmp file
X.endtopic
X.topic SYNOPSIS
X.noform
Xint	_utmp_stat (stat)
Xchar	*stat;
X
Xint _utmp_write (type, name, line, pid, status, uid, gid)
Xint	type;
Xchar	*name;
Xchar	*line;
Xint	pid;
Xchar	*status;
Xint	uid;
Xint	gid;
X
Xstruct utmp	*getutent ()
X
Xint	setutent ()
X
Xint	endutent ()
X
Xstruct utmp	*getutid (id)
Xstruct utmp	*id;
X
Xstruct utmp	*getutline (line)
Xstruct utmp	*line;
X
Xint	pututline (utmp)
Xstruct utmp	*utmp;
X
Xvoid	utmpname (file)
Xchar	*file;
X.noformend
X.endtopic
X.topic DESCRIPTION
XThe utmp-library offers the programmers a set of functions to have an
Xeasy access to the
X.ul
X/dd/SYS/utmp
Xfile or files which looks like this (e.g. /h0/SYS/wtmp). For these
Xfunction there is a
X.ul
Xstruct utmp
Xdefinied in utmp.h:
X.nf
X.nj
X.in +5
Xstruct utmp {
X  /* User login name                */
X  char   ut_user[33];
X
X  /* /etc/lines id (usually line #) */
X  char   ut_id[4];
X
X  /* device name (console, lnxx)    */
X  char   ut_line[33];
X
X  /* process id                     */
X  short  ut_pid;
X
X  /* User ID, Group ID              */
X  short  ut_uid, ut_gid;
X
X  /* Baud rate                      */
X  int    ut_baud;
X
X  /* type of entry                  */
X  short  ut_type;
X
X  /* time entry was made            */
X  time_t ut_time;
X
X  /* Flags                          */
X  char   ut_status[10];
X};
X.in -5
X.justify
X.fill
X
X	To initialize the access to /dd/SYS/utmp you should call the
Xfunction
X.bold
Xsetutent()
Xwhich opens or rewinds the file. When you have finished your access to
Xthis file you should call
X.bold
Xendutent()
Xto close the file. The function
X.bold
Xgeturent()
Xfetches the next entry of the utmp file and returns a pointer to the
Xstruct utmp which has been filled by this function.
X.bold
XGetutid()
Xrequires a struct utmp where the entry
X.ul
Xut_type
Xis set to the value you look for,
X.bold
Xgetutline()
Xneeds also a struct utmp with
X.ul
Xut_line
Xset to the required contents. With
X.bold
Xpututline()
Xan entry will be added in a free slot of the current file.
X.bold
XUtmpname()
Xrequires a file name and all other operations then take place on this
Xfile instead of the /dd/SYS/utmp.
X
X	There also exist some internal function which may be useful for
Xsome reasons.
X.bold
X_utmp_stat()
Xrequires a string with flags and changes the current flags for this
Xline.
X.bold
X_utmp_write()
Xis the most used internal function. The struct utmp is filled up with
Xthe arguments and then the entry will be written to the utmp file or
Xthey will be deleted from there if
X.ul
Xtype
Xis EMPTY (definied in utmp.h).
X.endtopic
X.topic CAVEATS
XThe functions getutent(), getutid() and getutline() returns pointer to
Xstatic data which will be overwritten by each call of one of these
Xfunctions.
X.endtopic
X.topic RETURN VALUE
X_utmp_stat(), _utmp_write(), setutent (), endutent (), pututline ()
Xreturning 0 on success, -1 on failure.  Getutent(), getutid(),
Xgetutline() returning pointer to struct utmp on success, NULL on
Xfailure. 
X
X.endtopic
X.topic FILES
X.noform
X/dd/SYS/utmp
X.in +5
XThe standard utmp file.
X.in -5
X.noformend
X.endtopic
X.topic SEE ALSO
X.noform
XLogon and mmon
Xin the Documentation of the Top Release.
X.noformend
X.endtopic
END_OF_FILE
if test 3486 -ne `wc -c <'MAN/Utmp.prf'`; then
    echo shar: \"'MAN/Utmp.prf'\" unpacked with wrong size!
fi
# end of 'MAN/Utmp.prf'
fi
if test -f 'chgrppass.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'chgrppass.c'\"
else
echo shar: Extracting \"'chgrppass.c'\" \(3674 characters\)
sed "s/^X//" >'chgrppass.c' <<'END_OF_FILE'
X/* ------------------------------------------------------------------- *
X |
X | OS9Lib:  change_grppasswd()
X |
X |
X |     Copyright (c) 1988 by Wolfgang Ocker, Puchheim,
X |                           Ulli Dessauer, Germering and
X |                           Reimer Mellin, Muenchen
X |                           (W-Germany)
X |
X |  This  programm can  be  copied and  distributed freely  for any
X |  non-commercial  purposes.   It can only  be  incorporated  into
X |  commercial software with the written permission of the authors.
X |
X |  If you should modify this program, the authors would appreciate
X |  a notice about the changes. Please send a (context) diff or the
X |  complete source to:
X |
X |  address:     Wolfgang Ocker
X |               Lochhauserstrasse 35a
X |               D-8039 Puchheim
X |               West Germany
X |
X |  e-mail:      weo@altger.UUCP, ud@altger.UUCP, ram@altger.UUCP
X |               pyramid!tmpmbx!recco!weo
X |               pyramid!tmpmbx!nitmar!ud
X |               pyramid!tmpmbx!ramsys!ram
X |
X * ----------------------------------------------------------------- */
X
X#define PATCHLEVEL 1
X
X#include <stdio.h>
X#include <modes.h>
X#include <grp.h>
X#include <strings.h>
X
Xextern struct group  *_getgr();
Xextern char          *crypt();
X
Xstatic struct group  group;
Xstatic char	     line[256];
X
X/*
X * c h a n g e _ g r p p a s s w d
X */
Xchange_grppasswd (name, password)
X  char *name, *password;
X{
X  char          *cryptpw;
X  int           found, pos, Count;
X  struct group  *gr;
X  int           grfd, tmpfd;
X  char          tmpname[256], tmp[256];
X  char          *cp1, *cp2;
X
X  /*
X   * Group-File fuer Update oeffnen
X   */
X  if ((grfd = open(GROUP, S_IREAD+S_IWRITE)) < 0)
X    return(-1);
X
X  found = 0;
X
X  /*
X   * zunaechst suchen wir im Password-File den Eintrag fuer den User
X   */
X  while (pos = lseek(grfd, 0, 1), (Count = readln(grfd, line, BUFSIZ)) > 0) {
X    line[Count] = '\0';
X    gr = _getgr(&group, line);
X
X    if (gr && (!_strccmp(name, gr->gr_name))) {
X      found = 1;
X      break;
X    }
X  }
X
X  if (!found)
X    return(-1);
X
X  /*
X   * erstes Colon suchen (danach steht das Passwort)
X   */
X  if (!(cp1 = index(line, ':'))) {
X    close(grfd);
X    return(-1);
X  }
X
X  if (!(cp2 = index(cp1+1, ':'))) {
X    close(grfd);
X    return(-1);
X  }
X
X  if (strlen(password))
X    if (strlen(gr->gr_passwd) < 2)
X      cryptpw = crypt(password, _rnd_salt());
X    else
X      cryptpw = crypt(password, gr->gr_passwd);
X
X  if (cp2-cp1 == 15) {
X    /*
X     * Passwort einkopieren
X     */
X    for (cp1 += 1; cp1 < cp2; cp1++)
X      *cryptpw++ = *cp1;
X
X    lseek(grfd, -Count, 1);
X    writeln(grfd, line, strlen(line));
X    close(grfd);
X    return(0);
X  }
X  else {
X    _ss_lock(grfd, -1);
X    lseek(grfd, 0, 0);
X
X    sprintf(tmpname, "/dd/grXXXXXX");
X    mktemp(tmpname);
X
X    if ((tmpfd = creat(tmpname, S_IREAD+S_IWRITE)) < 0) {
X      close(grfd);
X      return(-1);
X    }
X
X    while (lseek(grfd, 0, 1) != pos) {
X      Count = readln(grfd, tmp, BUFSIZ);
X      writeln(tmpfd, tmp, Count);
X    }
X
X    write(tmpfd, line, cp1-line+1);
X    if (strlen(password))
X      write(tmpfd, cryptpw, strlen(cryptpw));
X
X    /*
X     * ein bisschen trickreich: wir schreiben bis zum CR!!
X     */
X    writeln(tmpfd, cp2, strlen(line));
X 
X    Count = readln(grfd, tmp, BUFSIZ);
X
X    while ((Count = readln(grfd, tmp, BUFSIZ)) > 0)
X      writeln(tmpfd, tmp, Count);
X    close(tmpfd);
X    
X    if ((tmpfd = open(tmpname, S_IREAD)) < 0)
X      return(-1);
X
X    lseek(grfd, 0, 0);
X    while ((Count = readln(tmpfd, tmp, BUFSIZ)) > 0)
X      writeln(grfd, tmp, Count);
X    close(tmpfd);
X    _ss_size(grfd, lseek(grfd, 0, 1));
X    close(grfd);
X
X    unlink(tmpname);
X    return(0);
X  }
X}
END_OF_FILE
if test 3674 -ne `wc -c <'chgrppass.c'`; then
    echo shar: \"'chgrppass.c'\" unpacked with wrong size!
fi
# end of 'chgrppass.c'
fi
if test -f 'chpass.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'chpass.c'\"
else
echo shar: Extracting \"'chpass.c'\" \(3714 characters\)
sed "s/^X//" >'chpass.c' <<'END_OF_FILE'
X/* ------------------------------------------------------------------- *
X |
X | OS9Lib:  change_passwd()
X |
X |
X |     Copyright (c) 1988 by Wolfgang Ocker, Puchheim,
X |                           Ulli Dessauer, Germering and
X |                           Reimer Mellin, Muenchen
X |                           (W-Germany)
X |
X |  This  programm can  be  copied and  distributed freely  for any
X |  non-commercial  purposes.   It can only  be  incorporated  into
X |  commercial software with the written permission of the authors.
X |
X |  If you should modify this program, the authors would appreciate
X |  a notice about the changes. Please send a (context) diff or the
X |  complete source to:
X |
X |  address:     Wolfgang Ocker
X |               Lochhauserstrasse 35a
X |               D-8039 Puchheim
X |               West Germany
X |
X |  e-mail:      weo@altger.UUCP, ud@altger.UUCP, ram@altger.UUCP
X |               pyramid!tmpmbx!recco!weo
X |               pyramid!tmpmbx!nitmar!ud
X |               pyramid!tmpmbx!ramsys!ram
X |
X * ----------------------------------------------------------------- */
X
X#define PATCHLEVEL 1
X
X#include <stdio.h>
X#include <modes.h>
X#include <pwd.h>
X#include <strings.h>
X
Xextern struct passwd *_getpw();
Xextern char          *crypt();
X
Xstatic char          *PASS = "/h0/SYS/password";
Xstatic struct passwd passwd;
Xstatic char	     line[256];
X
X/*
X * c h a n g e _ p a s s w d
X */
Xchange_passwd(name, password)
X  char *name, *password;
X{
X  char          *cryptpw;
X  int           found, pos, Count;
X  struct passwd *pw;
X  int           pwfd, tmpfd;
X  char          tmpname[256], tmp[256];
X  char          *cp1, *cp2;
X
X  /*
X   * Passwort-File fuer Update oeffnen
X   */
X  if ((pwfd = open(PASS, S_IREAD+S_IWRITE)) < 0)
X    return(-1);
X
X  found = 0;
X
X  /*
X   * zunaechst suchen wir im Password-File den Eintrag fuer den User
X   */
X  while (pos = lseek(pwfd, 0, 1), (Count = readln(pwfd, line, BUFSIZ)) > 0) {
X    line[Count] = '\0';
X    pw = _getpw(&passwd, line);
X
X    if (pw && (!_strccmp(name, pw->pw_name))) {
X      found = 1;
X      break;
X    }
X  }
X
X  if (!found)
X    return(-1);
X
X  /*
X   * erstes Komma suchen (danach steht das Passwort)
X   */
X  if (!(cp1 = index(line, ','))) {
X    close(pwfd);
X    return(-1);
X  }
X
X  if (!(cp2 = index(cp1+1, ','))) {
X    close(pwfd);
X    return(-1);
X  }
X
X  if (strlen(password))
X    if (strlen(pw->pw_passwd) < 2)
X      cryptpw = crypt(password, _rnd_salt());
X    else
X      cryptpw = crypt(password, pw->pw_passwd);
X
X  if (cp2-cp1 == 15) {
X    /*
X     * Passwort einkopieren
X     */
X    for (cp1 += 1; cp1 < cp2; cp1++)
X      *cryptpw++ = *cp1;
X
X    lseek(pwfd, -Count, 1);
X    writeln(pwfd, line, strlen(line));
X    close(pwfd);
X    return(0);
X  }
X  else {
X    _ss_lock(pwfd, -1);
X    lseek(pwfd, 0, 0);
X
X    sprintf(tmpname, "/dd/pwXXXXXX");
X    mktemp(tmpname);
X
X    if ((tmpfd = creat(tmpname, S_IREAD+S_IWRITE)) < 0) {
X      close(pwfd);
X      return(-1);
X    }
X
X    while (lseek(pwfd, 0, 1) != pos) {
X      Count = readln(pwfd, tmp, BUFSIZ);
X      writeln(tmpfd, tmp, Count);
X    }
X
X    write(tmpfd, line, cp1-line+1);
X    if (strlen(password))
X      write(tmpfd, cryptpw, strlen(cryptpw));
X
X    /*
X     * ein bisschen trickreich: wir schreiben bis zum CR!!
X     */
X    writeln(tmpfd, cp2, strlen(line));
X 
X    Count = readln(pwfd, tmp, BUFSIZ);
X
X    while ((Count = readln(pwfd, tmp, BUFSIZ)) > 0)
X      writeln(tmpfd, tmp, Count);
X    close(tmpfd);
X    
X    if ((tmpfd = open(tmpname, S_IREAD)) < 0)
X      return(-1);
X
X    lseek(pwfd, 0, 0);
X    while ((Count = readln(tmpfd, tmp, BUFSIZ)) > 0)
X      writeln(pwfd, tmp, Count);
X    close(tmpfd);
X    _ss_size(pwfd, lseek(pwfd, 0, 1));
X    close(pwfd);
X
X    unlink(tmpname);
X    return(0);
X  }
X}
END_OF_FILE
if test 3714 -ne `wc -c <'chpass.c'`; then
    echo shar: \"'chpass.c'\" unpacked with wrong size!
fi
# end of 'chpass.c'
fi
if test -f 'MAN/Group.prf' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MAN/Group.prf'\"
else
echo shar: Extracting \"'MAN/Group.prf'\" \(3933 characters\)
sed "s/^X//" >'MAN/Group.prf' <<'END_OF_FILE'
X.fill
X.justify
X.offset 5
X.rightmargin 55
X.pagesize 48
X.m1 2
X.m2 1
X.m3 2
X.m4 3
X.ec \
X.header /Group/OS9Lib/Group
X.footer /Page #//Printed (%)/
X.in +5
X.define topic
X.bold
X.in -5
X$1 $2 $3 $4 $5
X.in +5
X.en
X.define endtopic
X
X
X.en
X.define noform
X.nojustify
X.nofill
X.en
X.define noformend
X.justify
X.fill
X.en
X.! Manual created with MWB
X.! END-OF-MACRO
X.topic NAME
XGroup - Functions to examine the Groupfile /dd/SYS/group
X.endtopic
X.topic SYNOPSIS
X.noform
X# include	<stdio.h>
X# include	<grp.h>
X
Xint 		_grp_secure;
Xint 		setgrent ()
X
Xint		endgrent ()
X
Xstruct group	*_getgr (group, line)
Xstruct group	*group;
Xchar		*line;
X
Xstruct group	*getgrent ()
X
Xstruct group	*getgrgid (gid)
Xint		gid;
X
Xstruct group	*getgrnam (name)
Xchar		*name;
X
Xstruct group	*fgetgrent(f)
XFILE		*f;
X
Xint 		getgroups (num, gids)
Xint 		num;
Xint		*gids;
X.noformend
X.endtopic
X.topic DESCRIPTION
XThe
X.bold
Xgroup
Xlibrary helps to access the group file which is normally located in
X/dd/SYS/group and on the bootdevice in /SYS/group. A line in the file
Xhas four entries, seperated by a colon ':'. The first entry is the name
Xof the group, the second is a password, the third is the group-ID and
Xthe fourth entry is a list of users who are allowed to change to this
Xgroup via newgrp. To access the group file there are various functions.
XWith
X.ul
Xsetgrent ()
Xyou can open or rewind the groupfile,
X.ul
Xendgrent ()
Xcloses the group file (don't forget this!). You should declare an
Xexternal variable
X.bold
X_grp_secure
Xwhich should be set to a non-zero value if you want to access the group
Xfile on the bootdevice, otherwise the group file is searched on the
Xdefault-disk /dd. Most of the other functions
Xreturn a 
X.ul
Xstruct group
Xwhich is definied in
X.bold
Xgrp.h
Xand loooks like this:
X.br
X.nf
X.nj
X.in +5
Xstruct group {
X  char *gr_name;
X  char *gr_passwd;
X  int  gr_gid;
X  char **gr_mem;
X};
X.in -5
X.fill
X.justify
X
X	struct group *_getgr(group, line)
X  register struct group *group;
X  char                  *line;
X	The internal function _getgr () my be useful if you have a line
Xwhich looks like an entry in the group file and you want to seperate it.
XAs argument the function requires a pointer a struct group where the
Xresult will be copied to and the line, defined as a pointer of char.
X
X	If you just want to scan through the group file the function
X.ul
Xgetgrent ()
Xreturns the next entry in the group file. To determine the entry for a
Xspecified group-ID you can use
X.ul
Xgetgrgid ()
Xwhich looks for the entry with the given ID. If you have the group name,
Xuse
X.ul
Xgetgrnam ()
Xto get the entry in the group file.
X.ul
Xfgetgrent ()
Xis the same function as getgrent (), but you can pass over a file
Xpointer to another file which has the same structure as the group file.
X
X	The  function
X.ul
Xgetgroups
Xglances through the group file and returns all valid group-IDs or
Xmaximum
X.bold
Xnum
Xentries if there are more. The IDs are filled in the area
X.bold
Xgids
Xwhich have to be passed to this function and must be a pointer to int.
X.endtopic
X.topic CAVEATS
X	The functions getgrent(), getgrgid(), getgrnam() and fgetgrent()
Xreturn pointer to static data which will be overwritten by each call of
Xthe function.
X.endtopic
X.topic RETURN VALUE
X	The functions setgrent() and endgrent() return 0 on success and
X-1 on failure.  The functions _getgr(), getgrent(), getgrgid(),
Xgetgrnam() and fgetgrent() returns a pointer to a struct group on
Xsuccess or NULL on failure. Getgroups returns -1 on failure or the number
Xof entries which are returned in the given pointer gids.
X
X.endtopic
X.topic FILES
X.noform
X/dd/SYS/group
X/<bootdrv>/SYS/group
X.noformend
X.endtopic
X.topic EXAMPLES
X.noform
X# include	<grp.h>
X
Xstruct group	*gr;
X
Xif ((gr = getgrnam ("root")) == NULL)
X	return (-1);
Xelse
X	return (gr->gr_gid ? -1 : 0);
X.noformend
X.endtopic
X.topic SEE ALSO
X.noform
Xnewgrp, change_grppasswd
Xin the Top Munich Release and
Xthe Passwd Library, change_grppasswd
Xin the Top OS9Lib Documentation.
X.noformend
X.endtopic
END_OF_FILE
if test 3933 -ne `wc -c <'MAN/Group.prf'`; then
    echo shar: \"'MAN/Group.prf'\" unpacked with wrong size!
fi
# end of 'MAN/Group.prf'
fi
if test -f 'mdir.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'mdir.c'\"
else
echo shar: Extracting \"'mdir.c'\" \(4013 characters\)
sed "s/^X//" >'mdir.c' <<'END_OF_FILE'
X/* ------------------------------------------------------------------- *
X |
X | OS9Lib:  module directory routines
X |
X |
X |     Copyright (c) 1988 by Wolfgang Ocker, Puchheim,
X |                           Ulli Dessauer, Germering and
X |                           Reimer Mellin, Muenchen
X |                           (W-Germany)
X |
X |  This  programm can  be  copied and  distributed freely  for any
X |  non-commercial  purposes.   It can only  be  incorporated  into
X |  commercial software with the written permission of the authors.
X |
X |  If you should modify this program, the authors would appreciate
X |  a notice about the changes. Please send a (context) diff or the
X |  complete source to:
X |
X |  address:     Wolfgang Ocker
X |               Lochhauserstrasse 35a
X |               D-8039 Puchheim
X |               West Germany
X |
X |  e-mail:      weo@altger.UUCP, ud@altger.UUCP, ram@altger.UUCP
X |               pyramid!tmpmbx!recco!weo
X |               pyramid!tmpmbx!nitmar!ud
X |               pyramid!tmpmbx!ramsys!ram
X |
X * ----------------------------------------------------------------- */
X
X#define PATCHLEVEL 1
X
X
X#include <stdio.h>
X#include <mdir.h>
X
X/* Module-Directory entry */
Xtypedef struct {
X  struct modhcom *md_mptr;
X  long           md_group;
X  long           md_static;
X  short          md_link;
X  short          md_mchk;
X} ModDir;
X
X#define TRUE  1
X#define FALSE 0
X
Xstatic mentry  ret;
Xstatic ModDir  *head = NULL;
Xstatic int     pos;
Xstatic int     count, max;
Xstatic int     size;
X
X/*
X * _ m o p e n
X */
Xint _mopen()
X{
X  register int maxcount;
X
X  size     = sizeof(ModDir);
X  maxcount = 0;
X  if (head)
X    _mclose();
X
X  head = NULL;
X
X  do {
X    maxcount += 80;
X    if (!(head = (ModDir *) realloc(head, maxcount * size + 2)))
X      return(-1);
X  } while ((count = _get_module_dir(head, maxcount * size + 2)) >
X           maxcount * size);
X           
X  max = count / size;
X  pos = 0;
X  return(0);
X}
X
X/*
X * _ m c l o s e
X */
Xint _mclose()
X{
X  if (head) {
X    free(head);
X    head = NULL;
X    return(0);
X  }
X  else
X    return(-1);
X}
X
X/*
X * _ m r e a d
X */
Xmentry *_mread()
X{
X  register struct modhcom *md;
X
X  if ((!head) || (pos >= max))
X    return(NULL);
X
X  while ((pos < max) && (head[pos].md_mptr == NULL))
X    ++pos;
X
X  if (pos >= max)
X    return(NULL);
X
X  md         = head[pos].md_mptr;
X  ret.m_ptr  = md;
X  _cpymem(0, sizeof(struct modhcom), md, &ret.m_head);
X  _cpymem(0, sizeof(ret.m_name), (char *) md + ret.m_head._mname, ret.m_name);
X
X  ret.m_link = head[pos].md_link;
X  ++pos;
X  return(&ret);
X}
X
X/*
X * _ m s e e k
X */
Xint _mseek(position, place)
X  int position, place;
X{
X  int t;
X
X  if ((place < 0) || (place > 2) || (!head))
X    return(-1);
X
X  switch (place) {
X    case 0:
X      if ((position >= 0) && (position < max))
X        pos = position;
X      else
X        return(-1);
X      break;
X
X    case 1:
X      t = pos + position;
X      if ((t >= 0) && (t < max))
X        pos = t;
X      else
X        return(-1);
X      break;
X
X    case 2:
X      t = max -1 + position;
X      if ((t >= 0) && (t < max))
X        pos = t;
X      else
X        return(-1);
X      break;
X
X    default:
X      return(-1);
X  }
X  return(pos);
X}
X
X/*
X * _ m t e l l
X */
Xint _mtell()
X{
X  if (!head)
X    return(-1);
X  else
X    return(pos);
X}
X
X/*
X * _ m r e w i n d
X */
Xint _mrewind()
X{
X  if (!head)
X    return(-1);
X
X  pos = 0;
X  return(0);
X}
X
X/*
X * _ m e x i s t
X */
Xmentry *_mexist(name)
X  register char *name;
X{
X  register mentry *scan;
X  register int    siz;
X  int             found;
X
X  found = FALSE;
X  if (_mopen() < 0)
X    return(NULL);
X
X  siz = strlen(name);
X  while (scan = _mread())
X    if (!_cmpnam(scan->m_name, name, siz)) {
X      found = TRUE;
X      break;
X    }
X
X  _mclose();
X  return(found ? scan : NULL);
X}
X
X/*
X * g e t m o d n a m e
X */
Xchar *getmodname(mod_addr)
X  register struct modhcom *mod_addr;
X{
X  register mentry *mentry;
X
X  if (_mopen() == -1)
X    return(NULL);
X
X  while ((mentry = _mread()) != NULL)
X    if (mod_addr == mentry->m_ptr)
X      return(mentry->m_name);
X  
X  return(NULL);
X}
END_OF_FILE
if test 4013 -ne `wc -c <'mdir.c'`; then
    echo shar: \"'mdir.c'\" unpacked with wrong size!
fi
# end of 'mdir.c'
fi
if test -f 'grp.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'grp.c'\"
else
echo shar: Extracting \"'grp.c'\" \(4275 characters\)
sed "s/^X//" >'grp.c' <<'END_OF_FILE'
X/* ------------------------------------------------------------------- *
X |
X | OS9Lib:  group routines
X |
X |
X |     Copyright (c) 1988 by Wolfgang Ocker, Puchheim,
X |                           Ulli Dessauer, Germering and
X |                           Reimer Mellin, Muenchen
X |                           (W-Germany)
X |
X |  This  programm can  be  copied and  distributed freely  for any
X |  non-commercial  purposes.   It can only  be  incorporated  into
X |  commercial software with the written permission of the authors.
X |
X |  If you should modify this program, the authors would appreciate
X |  a notice about the changes. Please send a (context) diff or the
X |  complete source to:
X |
X |  address:     Wolfgang Ocker
X |               Lochhauserstrasse 35a
X |               D-8039 Puchheim
X |               West Germany
X |
X |  e-mail:      weo@altger.UUCP, ud@altger.UUCP, ram@altger.UUCP
X |               pyramid!tmpmbx!recco!weo
X |               pyramid!tmpmbx!nitmar!ud
X |               pyramid!tmpmbx!ramsys!ram
X |
X * ----------------------------------------------------------------- */
X
X#define PATCHLEVEL 1
X
X#include <stdio.h>
X#include <ctype.h>
X#include <grp.h>
X
Xstatic FILE         *grpf = NULL;
Xstatic char         line[BUFSIZ+1];
Xstatic char         *member[MAX_MEM+1];
Xstatic struct group group;
X
X#define TRUE  (-1)
X#define FALSE (0)
X
Xint _grp_secure = 0;
X
Xextern FILE *ddfopen();
X
X/*
X * s e t g r e n t
X */
Xint setgrent()
X{
X  char fn[100];
X
X  if (!grpf) {
X    if (!(grpf = ddfopen(GROUP, fn, "r", _grp_secure)))
X      return(-1);
X  }
X  else
X    rewind(grpf);
X  
X  return(0);
X}
X
X/*
X * e n d g r e n t
X */
Xvoid endgrent()
X{
X  if (grpf) {
X    fclose (grpf);
X    grpf = NULL;
X  }
X}
X
X/*
X * g r s k i p
X */
Xstatic char *grskip(p)
X  register char *p;
X
X{
X  while (*p && *p != ':')
X    ++p;
X  if (*p)
X    *p++ = '\0';
X  return(p);
X}
X
X/*
X * g r s k i p 2
X */
Xstatic char *grskip2 (p)
X  register char *p;
X
X{
X  while (*p && (*p != ',') && (*p != '\n'))
X    ++p;
X
X  if (*p) 
X    if (*p != '\n')
X      *p++ = '\0';
X    else
X      *p = '\0';
X
X  return(p);
X}
X
X/*
X * _ g e t g r
X */
Xstruct group *_getgr(gr, grline)
X  register struct group *gr;
X  char                  *grline;
X
X{
X  register char *p;
X  char          *cp;
X  int           t;
X  static char   tmp[BUFSIZ+1];
X
X  strcpy(tmp, grline);
X  
X  p = tmp;
X  gr->gr_name = p;
X
X  p = grskip(p);
X  gr->gr_passwd = p;
X
X  p = grskip(p);
X  cp = p;
X
X  p = grskip(p);
X  gr->gr_gid = atoi(cp);
X  t = 0;
X  while ((t < MAX_MEM) && *p) {
X    member[t++] = p;
X    p = grskip2(p);
X  }
X
X  member[t] = NULL;
X  gr->gr_mem = member;
X  while(*p && *p != '\n')
X    p++;
X  *p = '\0';
X  return(gr);
X}
X
X/*
X * g e t g r e n t
X */
Xstruct group *getgrent()
X{
X  if (!grpf)
X    if (setgrent() < 0)
X      return(NULL);
X    
X  do {
X    if (!fgets(line, BUFSIZ,grpf))
X      return(NULL);
X  } while (line[0] == '#' || line[0] == '*');
X
X  if (!_getgr(&group, line))
X    return(NULL);
X
X  return(&group);
X}
X
X/*
X * g e t g r g i d
X */
Xstruct group *getgrgid (gid)
X  int gid;
X
X{
X  int found = 0;
X	
X  if (setgrent() < 0)
X    return(NULL);
X
X  while ((!found) && fgets(line, BUFSIZ, grpf)) {
X    if (line[0] == '#' || line[0] == '*')
X      continue;
X    if (_getgr(&group, line))
X      found = (group.gr_gid == gid);
X  }
X
X  if (found)
X    return(&group);
X  else
X    return(NULL);
X}
X
X/*
X * g e t g r n a m
X */
Xstruct group *getgrnam(name)
X  char *name;
X
X{
X  int found = 0;
X	
X  if (setgrent() < 0)
X    return(NULL);
X
X  while ((!found) && fgets(line, BUFSIZ, grpf)) {
X    if (line[0] == '#' || line[0] == '*')
X      continue;
X    if (_getgr(&group, line)) 
X      found = (!_strccmp(group.gr_name, name));
X  }
X
X  if (found)
X    return(&group);
X  else
X    return(NULL);
X}
X
X/*
X * f g e t g r e n t
X */
Xstruct group *fgetgrent(f)
X  FILE *f;
X
X{
X  struct group *gr = NULL;
X	
X  do {
X    if (fgets(line, BUFSIZ, f))
X      gr = _getgr(line, &group);
X    else
X      gr = NULL;
X  } while (gr && (line[0] == '#' || line[0] == '*'));
X
X  return(gr);
X}
X
X/*
X * g e t g r o u p s
X */
Xint getgroups(num, gids)
X  int num;
X  int *gids;
X{
X  struct group *gr;
X  int          i;
X
X  if (setgrent() < 0)
X    return(-1);
X  
X  for (i = 0; i < num; i++)
X    if (!(gr = getgrent())) {
X      endgrent();
X      return(i);
X    }
X    else
X      gids[i] = gr->gr_gid;
X
X  endgrent();
X  return(num);
X}
END_OF_FILE
if test 4275 -ne `wc -c <'grp.c'`; then
    echo shar: \"'grp.c'\" unpacked with wrong size!
fi
# end of 'grp.c'
fi
if test -f 'strings.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'strings.c'\"
else
echo shar: Extracting \"'strings.c'\" \(4370 characters\)
sed "s/^X//" >'strings.c' <<'END_OF_FILE'
X#include <stdio.h>
X#include <strings.h>
X
X/*  strcspn(3)
X *
X *  Author:  Terrence W. Holm          July 1988
X *
X *
X *  This function determines the length of a span from the
X *  beginning of <string> which contains none of the
X *  characters specified in <char_set>. The length of the
X *  span is returned.
X */
X
X
Xint strcspn(string, char_set)
X  char *string;
X  char *char_set;
X{
X  register char *str;
X  register char *chr;
X
X  if (string == NULL)
X    return(0);
X
X  if (char_set == NULL)
X    return(strlen(string));
X
X  for (str = string; *str != '\0'; ++str)
X    for (chr = char_set; *chr != '\0'; ++chr)
X      if (*str == *chr)
X        return(str - string);
X
X  return(str - string);
X}
X
X
X
X/*  strpbrk(3)
X *
X *  Author:  Terrence W. Holm          July 1988
X *
X *
X *  Strpbrk(3) scans <string> for the first occurrence of a
X *  character from the string <char_set>. If a character from
X *  the <char_set> was found then a pointer to it within
X *  <string> is returned, otherwise NULL is returned.
X */
X
Xchar *strpbrk(string, char_set)
X  char *string;
X  char *char_set;
X{
X  register char  c;
X  register char *p;
X
X  if (string == NULL || char_set == NULL)
X    return(NULL);
X
X  while ((c = *string++) != '\0')
X    for (p = char_set; *p != '\0'; ++p)
X      if (c == *p)
X        return(string - 1);
X
X  return(NULL);
X}
X
X
X
X/*  strspn(3)
X *
X *  Author:  Terrence W. Holm          July 1988
X *
X *
X *  This function determines the length of a span from the
X *  beginning of <string> which contains only characters
X *  specified in <char_set>. The length of the span is
X *  returned.
X */
X
Xint strspn(string, char_set)
X  char *string;
X  char *char_set;
X{
X  register char *str;
X  register char *chr;
X
X  if (string == NULL || char_set == NULL)
X    return(0);
X
X  for (str = string; *str != '\0'; ++str) {
X    for (chr = char_set; *chr != '\0'; ++chr)
X      if (*str == *chr)
X        break;
X
X    if (*chr == '\0')
X      return(str - string);
X  }
X
X  return(str - string);
X}
X
X
X/*  strstr(3)
X *
X *  Author: Terrence W. Holm          July 1988
X *
X *
X *  Finds the first occurrence of a substring, pointed to by
X *  <substr>, within a string pointed to by <string>.
X *  If the substring is found then a pointer to it within
X *  <string> is returned, otherwise NULL is returned.
X */
X
X
Xchar *strstr(string, substr)
X  char *string;
X  char *substr;
X{
X  register char head_string;
X  register char head_substr;
X
X  if (string == NULL || substr == NULL)
X    return(NULL);
X
X  head_substr = *substr++;
X
X  while ((head_string = *string++) != '\0')
X    if (head_string == head_substr) {
X      register char *tail_string = string;
X      register char *tail_substr = substr;
X
X      do {
X        if (*tail_substr == '\0')
X          return(string - 1);
X      } while (*tail_string++ == *tail_substr++);
X  }
X
X  return(NULL);
X}
X
X/*  strtok(3)
X *
X *  Author: Terrence W. Holm          July 1988
X *
X *
X *  This function is used to divide up a string into tokens.
X *  Strtok(3) is called with <string> pointing to the string
X *  to be scanned and <char_set> pointing to a string which
X *  consists of the set of separator characters. Tokens are
X *  substrings bordered by separator characters. A pointer to
X *  the first token encountered is returned. If <string> is
X *  NULL then the scan is continued from the last token
X *  returned. Each token is terminated by a '\0'. If there are
X *  no tokens remaining in the string then NULL is returned.
X */
X
Xchar *strtok(string, char_set)
X  char *string;
X  char *char_set;
X{
X  static char   *last_string = "";
X  register char *chr;
X  char          *next_token;
X
X  if (string == NULL)
X    string = last_string;
X
X  if (char_set == NULL)
X    return(NULL);
X
X
X  /*  First skip over any separator characters  */
X
X  while (*string != '\0') {
X    for (chr = char_set; *chr != '\0'; ++chr)
X      if (*string == *chr)
X        break;
X
X      if (*chr == '\0')
X        break;
X
X      ++string;
X  }
X
X
X  /*  Check if we have reached the end of the string  */
X
X  if (*string == '\0')
X    return(NULL);
X
X  /*  If not, then we have found the next token  */
X
X  next_token = string;
X
X
X  /*  Scan for the end of this token  */
X
X  while (*string != '\0') {
X    for (chr = char_set; *chr != '\0'; ++chr)
X      if (*string == *chr) {
X        *string = '\0';
X        last_string = string + 1;
X        return(next_token);
X      }
X
X      ++string;
X  }
X
X  last_string = string;
X  return(next_token);
X }
END_OF_FILE
if test 4370 -ne `wc -c <'strings.c'`; then
    echo shar: \"'strings.c'\" unpacked with wrong size!
fi
# end of 'strings.c'
fi
if test -f 'MAN/Passwd.prf' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'MAN/Passwd.prf'\"
else
echo shar: Extracting \"'MAN/Passwd.prf'\" \(4722 characters\)
sed "s/^X//" >'MAN/Passwd.prf' <<'END_OF_FILE'
X.fill
X.justify
X.offset 5
X.rightmargin 55
X.pagesize 48
X.m1 2
X.m2 1
X.m3 2
X.m4 3
X.ec \
X.header /Passwd/OS9Lib/Passwd
X.footer /Page #//Printed (%)/
X.in +5
X.define topic
X.bold
X.in -5
X$1 $2 $3 $4 $5
X.in +5
X.en
X.define endtopic
X
X
X.en
X.define noform
X.nojustify
X.nofill
X.en
X.define noformend
X.justify
X.fill
X.en
X.! Manual created with MWB
X.! END-OF-MACRO
X.topic NAME
XPasswd - Access the password file
X.endtopic
X.topic SYNOPSIS
X.noform
X# include	<pwd.h>
X
Xint	 	_pw_secure;
X
Xint		setpwent()
X
Xint		endpwent()
X
Xstruct passwd	*_getpw(passwd, line)
Xstruct passwd	*passwd;
Xchar 		*line;
X
Xstruct passwd	*getpwent()
Xstruct passwd	*getpwuid(uid)
Xint		uid;
X
Xint		_strccmp(a, b)
Xchar		*a,*b;
X
Xstruct passwd	*getpwnam(name)
Xchar		*name;
X
Xstruct passwd	*fgetpwent (f)
XFILE		*f;
X
Xint		getpw(uid, name)
Xint		uid;
Xchar		*name;
X
Xint		_cmpuid(uidstr, uid)
Xchar		*uidstr;
Xint		*uid;
X
Xint		getpwopt(junk, buf, opt, max)
Xchar		*junk;
Xchar		*buf;
Xchar		opt;
Xint		max;
X
Xstruct gecos	*getgecos(gecos_field)
Xchar		*gecos_field;
X
X.noformend
X.endtopic
X.topic DESCRIPTION
XThe password library provides some useful functions to access the
Xpassword file. In the include file
X.ul
Xpwd.h
Xthere are two structs defined which help to access the password file.
XThe
X.ul
Xstruct passwd
Xis used by the most function, the
X.ul
Xstruct gecos
Xis only used by one function.
X.nf
X.nj
X.in +5
Xstruct passwd {
X  char *pw_name;
X  char *pw_passwd;
X  int  pw_uid;
X  int  pw_gid;
X  int  pw_prio;       /* OS9: Priority of entry */
X  char *pw_age;
X  char *pw_comment;
X  char *pw_gecos;
X  char *pw_dir;
X  char *pw_xdir;      /* OS9: Execution Directory */
X  char *pw_shell;
X  char *pw_junk;      /* everything else... */
X};
X
Xstruct gecos {
X  char *fullname;
X  char *organization;
X  char *office_phone;
X  char *home_phone;
X};
X.in -5
X.fill
X.justify
X
XBefore examining the password file you open it with
X.bold
Xsetpwent()
Xand after that close it with
X.bold
Xendpwent()
Xplease don't forget this! If you use the routines on security sensitive
Xparts in your programs then you should set _pw_secure (which should be
Xdeclared as extern) to a non-zero value, otherwise to zero.
X.bold
X_getpw
Xis an internal function which may also be useful if you have a line to parse
Xwhich looks like one in the password file. You have to
Xgive a pointer to a struct passwd where the result will be written to and
Xthe string. If you want to scan through the password file you can use
X.bold
Xgetpwent()
Xwhich returns the next entry in the password file. To determine the
Xpassword entry for a given user-ID or username use the functions
X.bold
Xgetpwuid()
Xand
X.bold
Xgetpwnam()
Xwhich requires each one parameter, getpwuid an integer and getpwnam a
Xstring. The internal function
X.bold
X_strccmp()
Xis like the function strcmp() but ignores cases. The function 
X.bold
Xfgetpwent()
Xis like getpwent(), but it works on a given filepointer which should
Xbe opened on a file looking like the password file.
X.bold
XGetwd()
Xcopies the argument name into the username which matches the uid, given
Xas the second parameter.
X.bold
X_compuid()
Xexamines the string uidstr and builds the real uid (as returned by
Xgetuid()) for the user which is stored in *uid.
X
X	In the password file exists a field (the last one) for
Xspecial extensions. To extract an extention call
X.bold
Xgetpwopt() .
XIt requires the (complete) last field, a buffer, the option
Xas a character and the maximum size of the buffer.
X
X	The field gecos in the struct passwd is a special formated
Xstring to get more informations about the "real" person who owns the
Xaccount. The format of this field is
X.ul
X<fullname> : <organisation> : <office-phone> : <home-phone>
Xand these are the entries in the struct gecos. The function
X.bold
Xgetgecos()
Xrequires a line in the specified format and fills up the struct.
X.endtopic
X.topic CAVEATS
XGetpwent(), getpwuid(), getpwnam(), fgetpwent() and getgecos() returns
Xpointer to static data which will be overwritten by each call.
X.endtopic
X.topic RETURN VALUE
XSetpwent() and endpwent() returns 0 on success, and -1 on failure. _getpw
Xreturns a pointer to struct passwd which is given as a parameter on
Xsuccess, NULL on failure. Getpwent(), getpwuid(), getpwnam() and
Xfgetpwent() return a pointer to struct passwd on success, NULL on
Xfailure. _strccmp() returns the same value as strcmp() but ignores case
Xwhile comparing the strings. Getwd() returns -1 on failure and 0 on
Xsuccess. _cmpuid() returns 0 on success and -1 on failure. getpwopt()
Xreturns 0 on success and -1 on failure. Getgecos returns a pointer to
Xstruct gecos on success or NULL on failure.
X.endtopic
X.topic FILES
X.noform
X/<bootdrive>/SYS/password
X/dd/SYS/password
X.noformend
X.endtopic
X.topic SEE ALSO
X.noform
Xthe group library
Xin the TOP OS9Lib Documentation
X.noformend
X.endtopic
END_OF_FILE
if test 4722 -ne `wc -c <'MAN/Passwd.prf'`; then
    echo shar: \"'MAN/Passwd.prf'\" unpacked with wrong size!
fi
# end of 'MAN/Passwd.prf'
fi
if test -f 'popen.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'popen.c'\"
else
echo shar: Extracting \"'popen.c'\" \(4762 characters\)
sed "s/^X//" >'popen.c' <<'END_OF_FILE'
X/* ------------------------------------------------------------------- *
X |
X | OS9Lib:  popen(), xpopen(), pclose()
X |
X |
X |     Copyright (c) 1988 by Wolfgang Ocker, Puchheim,
X |                           Ulli Dessauer, Germering and
X |                           Reimer Mellin, Muenchen
X |                           (W-Germany)
X |
X |  This  programm can  be  copied and  distributed freely  for any
X |  non-commercial  purposes.   It can only  be  incorporated  into
X |  commercial software with the written permission of the authors.
X |
X |  If you should modify this program, the authors would appreciate
X |  a notice about the changes. Please send a (context) diff or the
X |  complete source to:
X |
X |  address:     Wolfgang Ocker
X |               Lochhauserstrasse 35a
X |               D-8039 Puchheim
X |               West Germany
X |
X |  e-mail:      weo@altger.UUCP, ud@altger.UUCP, ram@altger.UUCP
X |               pyramid!tmpmbx!recco!weo
X |               pyramid!tmpmbx!nitmar!ud
X |               pyramid!tmpmbx!ramsys!ram
X |
X * ----------------------------------------------------------------- */
X
X#define PATCHLEVEL 1
X
X#include <stdio.h>
X#include <modes.h>
X#include <strings.h>
X#include <errno.h>
X
Xextern FILE *fdopen();
X
Xextern char **environ;
Xextern int  os9forkc();
X
Xextern char *findmod(), *getenv(), *info_str();
X
Xstatic char  cmd_name[256];
X
Xstruct pid_stat {
X  int used;
X  int pid;
X  int status;
X} ;
X
Xstatic int pids[_NFILE] = { 0, 0, 0, 0, 0, 0, 0, 0,
X                            0, 0, 0, 0, 0, 0, 0, 0,
X                            0, 0, 0, 0, 0, 0, 0, 0,
X                            0, 0, 0, 0, 0, 0, 0, 0 };
X
Xint _popen_secure = 0;
X
X/*
X * c h e c k _ s h e l l
X *
X * check for valid shells
X */
Xstatic int check_shell()
X{
X  char *shell, *cp, *cp2, *cp3, val_shell[200];
X  
X  errno = E_FNA;
X
X  if ((shell = getenv("SHELL")) == NULL)
X    return(0);
X  
X  if (info_str("valid.shells", val_shell, sizeof(val_shell)) == NULL)
X    strcpy(val_shell, "shell,sh,csh");
X  
X  for (cp = val_shell; cp != NULL && *cp != '\0'; ) {
X    cp2 = cp;
X    if ((cp = index(cp, ',')) != NULL)
X      *cp++ = '\0';
X
X    while (*cp2 == ' ')
X      cp2++;
X    if ((cp3 = index(cp2, ' ')) != NULL)
X      *cp3 = '\0';
X
X    if (!strcmp(shell, cp2))
X      return(1);
X  }
X  
X  return(0);
X}
X
X/* 
X * p o p e n
X */
XFILE *popen(name, mode)
X  register char *name, *mode;
X{
X  register int  fd, fd2, fdsav, pid;
X  static char   *argv[] = {NULL, NULL, NULL };
X  static char   cmd[200];
X  static char   cmd_path[200];
X  register char *cp;
X
X  if (_popen_secure)
X    if (!check_shell())
X      return(NULL);
X
X  cp = name;
X  while (*cp == ' ')
X    cp++;
X  strcpy(cmd_path, cp);
X
X  if (cp = index(cmd_path, ' '))
X    *cp++ = '\0';
X
X  strcpy(cmd, "ex ");
X  strcat(cmd, findmod(cmd_path, cmd_path));
X  if (cp) {
X    strcat(cmd, " ");
X    strcat(cmd, cp);
X  }
X
X  argv[1] = cmd;
X
X/*
X * mode kann "r" (stdout) oder "w" (stdin) sein
X */
X  switch(mode[0]) {
X    case 'w':
X      fd = 0;
X      break;
X
X    case 'r':
X      fd = 1;
X      break;
X  }
X
X  if (fd == 1)
X    fflush(stdout);
X
X  fdsav = dup(fd);
X  close(fd);
X 
X  creat("/pipe", S_IWRITE+S_IREAD);
X  argv[0] = findmod("shell", "SYSTEM.SHELL");
X  pid = os9exec(os9forkc, argv[0], argv, environ, 0, 0, 3);
X
X  fd2 = dup(fd);
X  close(fd);
X  dup(fdsav);
X  close(fdsav);
X
X  if (pid > 0) {
X    pids[fd2] = pid;
X    return(fdopen(fd2, mode));
X  }
X  else {
X    close(fd2);
X    return(NULL);
X  }
X}
X
X
X/*
X * x p o p e n
X */
XFILE *xpopen(name, mode)
X  register char *name, *mode;
X{
X  register int fd, fd2, fdsav, pid;
X  char         **argv;
X
X  if (_popen_secure)
X    if (!check_shell())
X      return(NULL);
X
X  strcpy(cmd_name, name);
X
X  if (getargs(cmd_name, &argv) == -1)
X    return(NULL);
X
X/*
X * mode kann "r" (stdout) oder "w" (stdin) sein
X */
X  switch(mode[0]) {
X    case 'w':
X      fd = 0;
X      break;
X
X    case 'r':
X      fd = 1;
X      break;
X  }
X
X  if (fd == 1 && fileno(stdout) == 1)
X    fflush(stdout);
X
X  fdsav = dup(fd);
X  close(fd);
X
X  creat("/pipe", S_IWRITE+S_IREAD);
X  pid = os9exec(os9forkc, findmod(argv[0], argv[0]), argv, environ, 0, 0, 3);
X
X  free(argv);
X
X  fd2 = dup(fd);
X  close(fd);
X  dup(fdsav);
X  close(fdsav);
X
X  if (pid > 0) {
X    pids[fd2] = pid;
X    return(fdopen(fd2, mode));
X  }
X  else {
X    close(fd2);
X    return(NULL);
X  }
X}
X
X/*
X * p c l o s e
X */
Xunsigned int pclose(fp)
X  register FILE *fp;
X{
X  unsigned int status;
X  register int pid;
X  register int fd, i;
X
X  fd = fileno(fp);
X
X  if (pids[fd] == 0)
X    return(-1);
X  fflush(fp);
X  fclose(fp);
X
X  while ((pid = wait(&status)) != -1)
X    if (pid == pids[fd])
X      break;
X    else
X      for (i = 0; i < _NFILE; i++)
X        if (pids[i] == pid) {
X          pids[i] = 0;
X          break;
X        }
X
X  if (pid == -1)
X    status = -1;
X
X  pids[fd] = 0;
X  return(status);
X}
X
X
END_OF_FILE
if test 4762 -ne `wc -c <'popen.c'`; then
    echo shar: \"'popen.c'\" unpacked with wrong size!
fi
# end of 'popen.c'
fi
if test -f 'signal.a' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'signal.a'\"
else
echo shar: Extracting \"'signal.a'\" \(4849 characters\)
sed "s/^X//" >'signal.a' <<'END_OF_FILE'
X* Author:     Reimer Mellin
X* Date:       03/14/87
X* Version:    1.3
X*
X*
X* Revisions:
X* 1.2   _sigini -> _siginit() (weo)
X* 1.3   _siginit() called by signal, if not installed yet
X* 
X*
X*
X* Description:
X* The following UNIX (tm) functions are emulated:
X*
X* - _siginit()
X*
X* to initialize (no more required since 1.3 (weo))
X*
X*
X* - int (signal(signum, sig_handler)) ()
X*     int signum;
X*     int (sig_handler()) ();
X*
X* as the signal() function of UNIX (tm)
X*
X*
X* - _icptexce(excp_handler)
X*     (void) excp_handler();
X*
X* to install the exeception handler function excp_handler()
X*
X* (void) excp_handler(excp_num, reg_frame)
X*   int          exep_num;
X*   registerpack reg_frame;
X*
X*
X
X* Exception Vector address definitions
X org 0
XT_ColdSP: do.l 1 (0) reset initial SSP
XT_ColdPC: do.l 1 (1) reset initial PC
XT_BusErr: do.l 1 (2) bus error
XT_AddErr: do.l 1 (3) address error
XT_IllIns: do.l 1 (4) illegal instruction
XT_ZerDiv: do.l 1 (5) zero divide
XT_CHK: do.l 1 (6) CHK instruction
XT_TRAPV: do.l 1 (7) TRAPV instruction
XT_Priv: do.l 1 (8) privelage violation
XT_Trace: do.l 1 (9) trace
XT_1010: do.l 1 (10) line 1010 emulator
XT_1111: do.l 1 (11) line 1111 emulator
X do.l 3 (12-14) reserved
XT_UnIRQ: do.l 1 (15) unitialized interrupt vector
X do.l 8 (16-23) reserved
XT_SpurIO: do.l 1 (24) spurious interrupt
XT_AutIRQ: do.l 7 (25-31) level 1-7 interrupt autovectors
XT_TRAP: do.l 16 (32-47) TRAP instruction vectors
XT_FPUnordC: do.l 1 (48) FPCP bra or set on unordered condition
XT_FPInxact: do.l 1 (49) FPCP inexact result
XT_FPDivZer: do.l 1 (50) FPCP divide by zero
XT_FPUndrFl: do.l 1 (51) FPCP underflow
XT_FPOprErr: do.l 1 (52) FPCP operand error
XT_FPOverFl: do.l 1 (53) FPCP overflow
XT_FPNotNum: do.l 1 (54) FPCP signaling not a number
X do.l 9 (55-63) reserved
XT_VctIRQ: do.l 192 vectored interrupt vectors
XT_End: equ .
X
X psect signals_a,0,0,0,0,0
X
XSIG_NUM equ 10
X
X vsect
X_siglist ds.w (SIG_NUM*3)+1
X_exerout ds.l 1
X_isinit dc.b 0
X ends
X
X_siginit:
X tst.b _isinit(a6)
X bne.s _siginit99
X
X movem.l d0/d1/a0,-(a7)
X
X lea _siglist(a6),a0 ; Adresse der Signal-Tabelle
X moveq #1,d0 ; Merker fuer ungenutzt
X moveq #SIG_NUM-1,d1 ; Anzahl der Signale
X
Xsig01
X move.w d0,(a0)+ ; markieren als unbenutzt
X clr.l (a0)+ ; Adresse der Routine auf Null
X dbra d1,sig01
X
X clr.w (a0) ; Ende der Tabelle
X lea _sighand(pc),a0 ; die Intercept-Routine ...
X OS9 F$Icpt ; installieren
X
X st _isinit(a6) ; jetzt initialisiert
X
X movem.l (a7)+,d0/d1/a0
X
X_siginit99
X rts
X
Xsignal:
X movem.l a0-a1/d2-d3,-(a7) ; Register retten
X
X tst.b _isinit(a6) ; initialisiert?
X bne.s sig02 ; ja!
X bsr.s _siginit
X
Xsig02
X move.w d0,d3 ; kopiere Signal
X andi.l #$fffe,d3 ; maskiere Bit 1-15
X beq.s sig05
X
X moveq.l #1,d3 ; Default-Aktion ist 1
X bsr.s _siglook ; Signal-Nummer in Tabelle suchen
X tst.l d2 ; Tabelle voll?
X beq.s sig05 ; ja!
X
X tst.l d1 ; Default Aktion verlangt?
X beq.s sig03 ; ja, der Eintrag kann geloescht werden
X
Xsig04
X move.w d0,(a0)+ ; Signal-Nummer
X move.l (a0),d3 ; vorherige Adresse
X move.l d1,(a0)+ ; neue Adresse des Handlers
X
Xsig05
X move.l d3,d0 ; Return-Wert ist die alte Adresse
X movem.l (a7)+,a0-a1/d2-d3 ; Register restaurieren
X rts
X
Xsig03
X move.l 2(a0),d3 ; alte Adresse
X movea.l a0,a1
X addq.l #6,a1
X
Xsig06
X move.w #1,(a0) ; altes Signal loeschen
X move.l #0,2(a0) ; auch alte Adresse loeschen
X tst.w (a1) ; am Ende der Tabelle?
X beq.s sig05 ; ja!
X
X move.w (a1)+,(a0)+ ; Signal-Nummer eintragen
X move.l (a1)+,(a0)+ ; dazugehoerige Handler-Adresse
X bra.s sig06
X
X_siglook
X lea _siglist(a6),a0 ; Signal-Tabelle
X
Xsig07
X move.w (a0),d2 Signal-Nummer
X cmp.w d0,d2 ; die gesuchte?
X beq.s sig08 ; ja!
X
X cmpi.w #1,d2 ; freier Eintrag?
X beq.s sig08 ; ja!
X
X tst.w d2 ; Tabellenende?
X beq.s sig08 ; ja!
X
X addq.l #6,a0 ; naechster Eintrag
X bra.s sig07
X
Xsig08
X ext.l d2
X rts
X
X_sighand
X movem.l a0-a1/d2,-(a7) ; Register retten
X move.l d1,d0 ; Signalnummer ist in d1
X bsr.s _siglook ; Eintrag vorhanden?
X subq.l #1,d2
X ble.s sig09 ; keinen Eintrag gefunden, exit()!
X
X addq.l #2,a0 ; Adresse der Adresse
X
X cmpi.l #1,(a0) ; Signal ignorieren?
X beq.s sig10 ; ja!
X
X movea (a0),a0 ; zu dieser Adresse springen
X jsr (a0)
X
Xsig10
X movem.l (a7)+,a0-a1/d2 Register restaurieren
X OS9 F$RTE ; Ende der Intercept-Routine
X
Xsig09
X move.l d0,d1 ; Signal-Nummer fuer exit
X OS9 F$Exit
X bra.s sig09 ; ???
X
X_exetab
X dc.w T_BusErr,_exehand-*-4 ; Tabelle fuer Exceptions
X dc.w T_AddErr,_exehand-*-4
X dc.w T_IllIns,_exehand-*-4
X dc.w T_ZerDiv,_exehand-*-4
X dc.w T_CHK,_exehand-*-4
X dc.w T_TRAPV,_exehand-*-4
X dc.w T_Priv,_exehand-*-4
X dc.w T_1010,_exehand-*-4
X dc.w T_1111,_exehand-*-4
X dc.w -1
X
X_icptexep:
X move.l d0,_exerout(a6) ; Adresse der Routine
X lea _exetab(pc),a1 ; Trap-Tabelle
X movea.l #0,a0 ; a0 = 0 fuer Default-Stack
X OS9 F$STrap ; Trap installieren
X rts
X
X_exehand
X move.w d7,d0
X ext.l d0
X move.l a5,d1 ; Registerframe
X movea _exerout(a6),a0 ; Handler-Routine
X jsr (a0) ; aufrufen
X rts
X
X ends
X end
END_OF_FILE
if test 4849 -ne `wc -c <'signal.a'`; then
    echo shar: \"'signal.a'\" unpacked with wrong size!
fi
# end of 'signal.a'
fi
echo shar: End of archive 3 \(of 5\).
cp /dev/null ark3isdone
MISSING=""
for I in 1 2 3 4 5 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 5 archives.
    rm -f ark[1-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
  |  Wolfgang Ocker          |  ocker@lan.informatik.tu-muenchen.dbp.de  |
  |  Lochhauserstr. 35a      |      pyramid!tmpmbx!recco!weo (home)      |
  |  D-8039 Puchheim         |     Technische Universitaet Muenchen      |
  |  Voice: +49 89 80 77 02  |          Huh, What? Where am I?           |