#! /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 shell archive."
# Contents:  Makefile daemon.sh demo.sh lckm.c mktask.sh perform.sh
#   sem-fifo.sh sem-file.sh sem-lckm.sh sumtask.sh taskdir.shar
# Wrapped by martin@mwtech on Tue Feb  8 03:48:47 1994
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f Makefile -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"Makefile\"
else
echo shar: Extracting \"Makefile\" \(251 characters\)
sed "s/^X//" >Makefile <<'END_OF_Makefile'
X#
X# Makefile zum Erzeugen des Lock-Managers (1.1 -- 94/02/08)
X#
XPROGS = lckman lckshut lckstat lckreq
XCFLAGS = -Xp
Xall:	lckm
X	for p in $(PROGS); do ln lckm $$p; done
Xlckm:	lckm.c
X	rm -f lckm $(PROGS)
X	$(CC) $(CFLAGS) $@.c -o $@
Xclean:
X	rm -f $(PROGS)
END_OF_Makefile
if test 251 -ne `wc -c <Makefile`; then
    echo shar: \"Makefile\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f daemon.sh -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"daemon.sh\"
else
echo shar: Extracting \"daemon.sh\" \(468 characters\)
sed "s/^X//" >daemon.sh <<'END_OF_daemon.sh'
X#
X# Manager-Prozess fuer FIFO-Semaphoren (1.1 -- 94/02/08)
X#
Xprocs=
Xfiles=
Xfor parm
Xdo	(
X		rm -f $parm.lck
X		/etc/mknod $parm.lck p || exit
X		while 
X			sleep 3600 &
X			trap 'exec kill $!' 1 2 3
X			wait
X		do :
X		done < $parm.lck &
X		trap 'exec kill -1 $!' 1 2 3
X		exec >> $parm.lck
X		echo
X		wait
X	) &
X	procs="$procs $!"
X	files="$files $parm.lck"
Xdone
Xtrap '
X	test -n "$procs" && kill -1 $procs
X	procs=
X	test -n "$files" && rm -f $files
X	files=
X	exit 129
X' 0 1 2 3
Xwait
END_OF_daemon.sh
if test 468 -ne `wc -c <daemon.sh`; then
    echo shar: \"daemon.sh\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f demo.sh -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"demo.sh\"
else
echo shar: Extracting \"demo.sh\" \(1176 characters\)
sed "s/^X//" >demo.sh <<'END_OF_demo.sh'
X#
X# Demo-Programm fuer Shell-Semaphoren (1.1 -- 94/02/08)
X#
XPROG=`basename $0`
XUSAGE="$PROG -{file|fifo} taskdir"
X
X#
X# Aufrufargumente pruefen
X#
Xcase $# in
X2);; *) >&2 echo "Usage: $USAGE"; exit 1
Xesac
X
X#
X# File oder Fifo Semaphoren inkludieren
X#
X. sem$1.sh
Xshift
X
Xtaskdir=$1;
Xshift
Xtest -d "$taskdir" || {
X	>&2 echo "$PROG: keine Taetigkeitsbeschreibung: $taskdir"
X	exit 2
X}
X
Xset x `find "$taskdir" -type f -print | sed 's/[^\/]*\///' | sort`
Xshift
X
X#
X# Meldungsausgabe mit Zeitstempel
X#
Xmessage() {
X	echo "(`date +%H:%M:%S`)	$name:	$*"
X}
X
X#
X# Betriebsmittel anfordern und auf Zuteilung warten
X#
Xrequest() {
X	# Belegungswunsch anmelden
X	message "brauche $resource ..."
X	lock $resource
X	# Belegungswunsch akzeptiert
X	message "	habe $resource ..."
X}
X
X#
X# Betriebsmittel freigeben
X#
Xrelease() {
X	# Freigabe
X	message "		fertig mit $resource"
X	unlock $resource
X}
X
X#
X# Konkurrierende Prozesse starten
X#
Xpids=
Xfor name
Xdo
X	test -f $taskdir/$name && (
X		while
X			read usetime resource
X		do
X			test $resource &&
X				request $resource
X			sleep $usetime
X			test $resource &&
X				release $resource
X		done < $taskdir/$name
X		exit 0
X	) & pids="$pids $!"
Xdone
X
Xtrap 'kill $pids' 1 2 3
Xwait
END_OF_demo.sh
if test 1176 -ne `wc -c <demo.sh`; then
    echo shar: \"demo.sh\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f lckm.c -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"lckm.c\"
else
echo shar: Extracting \"lckm.c\" \(19427 characters\)
sed "s/^X//" >lckm.c <<'END_OF_lckm.c'
X/*
X======================================================================
XLOCK-MANAGER:	Version: 1.1 (94/01/19)
X
XCopyright 1994:	Martin Weitzel,
X		Darmstadt, Germany
X		(martin@rent-a-guru.DE)
X======================================================================
X*/
X
X/*
X * ISO-C standard header files
X*/
X#include <assert.h>
X#include <errno.h>
X#include <signal.h>
X#include <stdio.h>
X#include <stdlib.h>
X#include <string.h>
X#include <varargs.h>
X#include <unistd.h>
X
X/*
X * UNIX system header files
X*/
X#include <sys/types.h>
X#include <sys/stat.h>
X#include <sys/fcntl.h>
X#include <sys/wait.h>
X
X/*
X * External definitions (not in a header file)
X*/
Xextern int open();
Xextern unsigned int alarm();
Xextern int setuid();
X
X/*
X * Support for systems without `mkfifo'
X */
X#ifdef HAS_NO_MKFIFO
X#define mkfifo(p, m) (mknod((p), S_IFIFO|(m)))
X#endif
X
X/*
X * Program link names to control functionality (in case
X * of changes, Makefile must be changed accordingly)
X*/
Xchar LCKMAN[] = "lckman";	/* start demon and/or add facility */
Xchar LCKREQ[] = "lckreq";	/* request a lock */
Xchar LCKSHUT[] = "lckshut";	/* shut down demon/remove facility */
Xchar LCKSTAT[] = "lckstat";	/* show status of facilities */
X
X/*
X * Configurable constants
X*/
Xchar FIFO_DIR[] = "/tmp/lckm/";	/* where all the fifos go */
X#define MAX_NAMELEN	12	/* max. length for facility names */
X#define C_TIMEOUT	3	/* timeout for opening C-fifo */
X#define R_TIMEOUT	20	/* timeout for opening R-fifo */
X
X/*
X * Useful definitions
X */
X#define NEW(t) ((t*)malloc(sizeof(t)))
X
X/*
X * Shutup complaints by lint
X*/
X#ifdef lint
Xstatic va_list _va_dummy;
X#define malloc(n) ((void *)0)
X#undef va_start
X#define va_start(x) (x=_va_dummy)
X#undef va_arg
X#define va_arg(x, t) ((t)0)
X#undef va_end
X#define va_end(x) (_va_dummy=x)
X#endif
X
X/*
X * Definitions for command data structures
X*/
Xtypedef struct command {	/* command send to lock manager */
X	int type;			/* type of command */
X#		define CMD_SERV '='		/* start service */
X#		define CMD_REQ  '+'		/* request lock */
X#		define CMD_REL  '-'		/* release lock */
X#		define CMD_STAT '?'		/* show status */
X#		define CMD_SHUT '.'		/* shut down */
X#		define CMD_VERB '$'		/* toggle verbosity */
X	char lockname[MAX_NAMELEN+1];		/* name of lock */
X	int rpid;			/* PID of requestor */
X} COMMAND;
X
X/*
X * Global variables
X*/
Xchar *prog;			/* name of the program */
Xint verbose;			/* verbosity flag */		
Xchar *c_fifo;			/* name of control fifo */
Xint cfd = -1;			/* FD of control fifo */
X
X/*!
X----------------------------------------------------------------------
X	Following are some miscalaneous functions called as
X	necessary from various parts of the program.
X----------------------------------------------------------------------
X*/
X
X/*
X * Print message and optionally terminate program
X*/
X/*VARARGS*/
Xvoid failed(va_alist)
X	va_dcl			/* fixed args "rc" and "fmt" (see below) */
X{
X	int rc;				/* return status of program */
X	char *fmt;			/* printf format for message */
X	va_list ap;			/* arg list iterator */
X
X	/* format error message */
X	va_start(ap);
X	rc = va_arg(ap, int);
X	fmt = va_arg(ap, char *);
X	(void) fprintf(stderr, "%s: %s ", prog,
X		rc ? "[FATAL]" : "[WARNING]");
X	(void) vfprintf(stderr, fmt, ap);
X	(void) fprintf(stderr, "\n");
X	(void) fflush(stderr);
X	va_end(ap);
X
X	/* terminate program if "rc" is not 0 */
X	if (rc > 0) exit(rc);
X	if (rc < 0) abort();
X
X	/* continue if "rc" is 0 */
X}
X
X/*
X * Standard messages
X*/
Xstatic char _F_MALLOC[] = "out of malloc-space in %s";
X#define FAILED_MALLOC(w) failed(-1, _F_MALLOC, w)
X
X/*
X * Print a message only in verbose mode
X*/
X/*VARARGS*/
Xvoid inform(va_alist)
X	va_dcl			/* fixed arg is "fmt" (see below) */
X{
X
X
X	char *fmt;			/* printf format for message */
X	va_list ap;			/* arg list iterator */
X
X	if (verbose) {
X		/* format message */
X		va_start(ap);
X		fmt = va_arg(ap, char *);
X		(void) vprintf(fmt, ap);
X		va_end(ap);
X		(void) fflush(stdout);
X	}
X}
X
X/*
X * Rudimentary string processing support:
X*/
Xchar *mknstr(num)		/* -- static string from */
X	int num;		/* number */
X{
X	static char *cp;		/* pointer to return space */
X	size_t len = 0;			/* length of return space */
X	int v = num;			/* tmp to determine length */
X
X	assert(num >= 0);
X
X	/* determine length */
X	do ++len; while (v /= 10);
X
X	/* free old and allocate new space */
X	if (cp != (char *)0)
X		free(cp);
X	if ((cp = malloc(len+1)) == (char *)0)
X		FAILED_MALLOC("mknstr");
X
X	/* convert number to string */
X	cp[len] = '\0';
X	do {
X		assert(len != 0);
X		cp[--len] = (num % 10) + '0';
X	} while (num /= 10);
X
X	return cp;
X}
X
X/*VARARGS*/
Xchar *pstrcat(va_alist)		/* -- dynamic string from parts */
X	va_dcl			/* char pointer args, (char *)0-terminated */
X{
X	char *cp;			/* tmp to access args */
X	char *res;			/* tmp for result */
X	size_t len = 1;			/* length of all args (plus '\0') */
X	va_list ap;			/* arg list iterator */
X
X	/* determine total length */
X	va_start(ap);
X	while ((cp = va_arg(ap, char *)) != (char *)0)
X		len += strlen(cp);
X	va_end(ap);
X
X	/* allocate space and initialize */
X	if ((res = malloc(len)) == (char *)0)
X		FAILED_MALLOC("pstrcat");
X	res[0] = '\0';
X
X	/* concatenate all arg strings */
X	va_start(ap);
X	while ((cp = va_arg(ap, char *)) != (char *)0)
X		(void) strcat(res, cp);
X	va_end(ap);
X
X	return res;
X}
X
Xvoid pstrfree(strp)		/* -- free dynamic string */
X	char **strp;		/* address(!) of pointer to string */
X{
X	if (*strp)
X		free(*strp);
X	*strp = (char *)0;
X}
X
X/*
X * Build name of R-fifo from PID of requestor
X*/
Xchar *r_fifoname(p)
X	int p;			/* PID */
X{
X	return pstrcat(FIFO_DIR, "R-", mknstr(p), (char *)0);
X}
X
X/*
X * Build name of C-fifo from name of facility
X*/
Xchar *c_fifoname(lockname)
X	char *lockname;		/* name of facitily */
X{
X	return pstrcat(FIFO_DIR, "C-", lockname, (char *)0);
X}
X
X/*
X * Write command to C-fifo:
X*/
Xvoid sendpcmd(cmdp)		/* -- with parameters */
X	COMMAND *cmdp;		/* initialized command structure */
X{
X	assert(cfd != -1);
X
X	if (write(cfd, cmdp, sizeof *cmdp) != sizeof *cmdp)
X		failed(-1, "error %d writing to control fifo", errno);
X}
Xvoid sendscmd(type)		/* -- without parameters */
X	int type;		/* command type */
X{
X	static COMMAND cmd;		/* command structure */
X	cmd.type = type;
X	sendpcmd(&cmd);
X}
X
X/*
X * Check and conditionally truncate name of facility
X*/
Xvoid ckname(lockname)
X	char *lockname;		/* name of facility */
X{
X	if (strlen(lockname) > (unsigned)MAX_NAMELEN) {
X		lockname[MAX_NAMELEN] = '\0';
X		failed(0, "lock name trunctated to %s", lockname);
X	}
X}
X
X/*
X * Open file with time-out
X*/
X/*ARGSUSED*/
Xvoid nothing(sig)
X	int sig;
X{
X	/*empty*/
X}
Xint tmopen(name, mode, tout)	/* -- similar to open(2) */
X	char *name;		/* file name */
X	int mode;		/* open mode */
X	unsigned tout;		/* time-out */
X{
X	int fd;				/* tmp for resulting FD */
X	void (*oldsig)();		/* tmp for old sig handler */
X
X	oldsig = signal(SIGALRM, nothing);
X	(void) alarm(tout);
X	fd = open(name, mode);
X	(void) alarm(0);
X	(void) signal(SIGALRM, oldsig);
X
X	return fd;
X}
X
X/*
X * Request some operation from the demon
X*/
Xvoid requestOP(type, name)
X	int type;		/* type of operation */
X	char *name;		/* (opt.) facility name */
X{
X	assert(c_fifo != (char *)0);
X
X	if (name == (char *)0 || name[0] == '\0')
X		sendscmd(type);
X	else {
X		COMMAND cmd;
X		ckname(name);
X		cmd.type = type;
X		(void) strcpy(cmd.lockname, name);
X		sendpcmd(&cmd);
X	}
X}
X
X/*!
X----------------------------------------------------------------------
X	The following functions implement the lock manager's
X	kernal data structures and algorithms.  This part
X	typically runs in the background waiting for commands
X	to read from the C-fifo.
X----------------------------------------------------------------------
X*/
X
Xtypedef struct request {	/* chain of requests */
X	int rpid;			/* PID of requestor */
X	struct request *next;		/* next request in chain */
X} REQUEST;
X
Xtypedef struct lock {		/* chain of facilities */
X	char lockname[MAX_NAMELEN+1];	/* name of this facility */
X	int serviced;			/* service indicator */
X	int gpid;			/* PID of granter */
X	REQUEST *req;			/* chain of requests */
X	struct lock *next;		/* next lock in chain */
X} LOCK;
X
XLOCK *locklist;			/* anchor of list */
X
X/*
X * Append request to end of queue
X*/
Xvoid addrequest(rpid, rpp)
X	int rpid;		/* PID of requestor */
X	REQUEST **rpp;		/* pointer to anchor of request queue */
X{
X	/* find end of chain */
X	while (*rpp != (REQUEST *)0)
X		rpp = &(*rpp)->next;
X
X	/* allocate space */
X	*rpp = NEW(REQUEST);
X	if (*rpp == (REQUEST *)0)
X		FAILED_MALLOC("addrequest");
X
X	/* initialize data */
X	(*rpp)->rpid = rpid;
X	(*rpp)->next = (REQUEST *)0;
X}
X
X/*
X * Delete request from begin of queue
X*/
Xvoid delrequest(rpp)
X	REQUEST **rpp;		/* pointer to anchor of request queue */
X{
X	REQUEST *rp = *rpp;	/* pointer to entry to free */
X
X	assert(*rpp != (REQUEST *)0);
X
X	/* remove entry and free space */
X	*rpp = rp->next;
X	free(rp);
X}
X
X/*
X * Make entry into the list of facilities
X*/
Xvoid mklock(lockname)
X	char *lockname;		/* name of facility */
X{
X	/* allocate space */
X	LOCK *lp = NEW(LOCK);
X	if (lp == (LOCK *)0)
X		FAILED_MALLOC("mklock");
X
X	/* initialize data */
X	(void) strcpy(lp->lockname, lockname);
X	lp->serviced = 1;
X	lp->gpid = -1;
X	lp->req = (REQUEST *)0;
X
X	/* prepend to existing list */
X	lp->next = locklist;
X	locklist = lp;
X}
X
X/*
X * Locate entry in the list of facilities:
X*/
XLOCK *gtlockn(lockname)		/* -- by */
X	char *lockname;		/* name of facility */
X{
X	LOCK *lp = locklist;
X	while (lp != (LOCK *)0) {
X		if (!strcmp(lockname, lp->lockname))
X			break;
X		lp = lp->next;
X	}
X	return lp;
X}
XLOCK *gtlockp(gpid)		/* -- by */
X	int gpid;		/* PID of grantor */
X{
X	LOCK *lp = locklist;
X	while (lp != (struct  lock *)0) {
X		if (gpid == lp->gpid)
X			break;
X		lp = lp->next;
X	}
X	return lp;
X}
X
X/*
X * Remove entry from the list of facilities
X*/
Xvoid rmlock(lp)
X	LOCK *lp;		/* pointer to entry to remove */
X{
X	LOCK **lpp = &locklist;		/* pointer(!) to entry pointer */
X
X	assert (lp != (LOCK *)0);
X	assert (lp->serviced == 0);
X	assert (lp->gpid == -1);
X	assert (lp->req == (REQUEST *)0);
X
X	/* traverse list to find given entry */
X	while (*lpp != lp) {
X		assert (*lpp != (LOCK *)0);
X		lpp = &((*lpp)->next);
X	}
X
X	/* remove entry and free space */
X	*lpp = lp->next;
X	free(lp);
X}
X
X/*
X * Grant a lock
X*/
Xvoid grantlock(rpid, gpidp)
X	int rpid;		/* PID of requestor */
X	int *gpidp;		/* pointer to PID of grantor */
X{
X	assert(rpid != -1);
X
X	/* fork grantor */
X	if ((*gpidp = fork()) == 0) {
X
X		/* connect to R-fifo */
X		char *r_fifo = r_fifoname(rpid);
X		int rfd = tmopen(r_fifo, O_RDONLY, R_TIMEOUT);
X		(void) unlink(r_fifo);
X		pstrfree(&r_fifo);
X
X		/* wait for requestor to vanish */
X		(void) signal(SIGTERM, nothing);
X		if (rfd != -1) {
X			char dummy;
X			while (read(rfd, &dummy, 1) > 0)
X				; /*empty*/
X			(void) close(rfd);
X		}
X
X		/* message release and terminate */
X		sendscmd(CMD_REL);
X		exit(0);
X		/*NOTREACHED*/
X	}
X	if (*gpidp == -1)
X		failed(0, "error %d on fork", errno);
X}
X
X/*
X * Stop servicing a facility
X*/
Xvoid unservlock(lp)
X	LOCK *lp;		/* pointer to facility */
X{
X	assert(lp != (LOCK *)0);
X
X	inform("stop servicing <%s> -- ", lp->lockname);
X	if (lp->serviced) {
X		char *cs_fifo = c_fifoname(lp->lockname);
X		(void) unlink(cs_fifo);
X		pstrfree(&cs_fifo);
X		lp->serviced = 0;
X		if (lp->gpid != -1)
X			inform("OK (initiated)\n");
X		else {
X			rmlock(lp);
X			inform("OK (shut down)\n");
X		}
X	}
X	else 
X		inform("FAILED (servicing already stopped)");
X}
X
X/*
X * Handle start or re-start of facility
X*/
Xvoid startService(name)
X	char *name;		/* name of facility */
X{
X	LOCK *lp = gtlockn(name);	/* pointer to facility */
X	char *f_fifo = c_fifoname(name);/* name of facility-dependend fifo */
X
X	assert(c_fifo != (char *)0);
X
X	inform("start servicing <%s> -- ", name);
X	if (lp != (LOCK *)0)
X		if (lp->serviced)
X			inform("FAILED (already running)\n");
X		else {
X			lp->serviced = 1;
X			if (link(c_fifo, f_fifo) != -1)
X				inform("OK (shut down canceled)\n");
X			else
X				inform("FAILED (cannot re-link)\n");
X		}
X	else {
X		/* link generic C-fifo to facility-dependend name */
X		if (unlink(f_fifo) != -1)
X			failed(0, "dead(?) control fifo %s removed", f_fifo);
X		if (link(c_fifo, f_fifo) != -1)
X			mklock(name);
X		else
X			failed(0, "error %d linking %s to %s", errno,
X				c_fifo, f_fifo);
X		inform("OK\n");
X	}
X	pstrfree(&f_fifo);
X}
X
X/*
X * Handle request for a lock
X*/
Xvoid doRequest(lockname, rpid)
X	char *lockname;		/* name of facility */
X	int rpid;		/* PID of requestor */
X{
X	LOCK *lp = gtlockn(lockname);	/* pointer to facility */
X
X	inform("request for <%s> by R-%d -- ", lockname, rpid);
X	if (lp == (LOCK *)0)
X		inform("FAILED (no such facility)\n");
X	else if (!lp->serviced)
X		inform("FAILED (not serviced any more)");
X	else if (lp->gpid == -1) {
X		grantlock(rpid, &lp->gpid);
X		inform("OK (G-%d)\n", lp->gpid);
X	}
X	else {
X		addrequest(rpid, &lp->req);
X		inform("OK (queued)\n");
X	}
X}
X
X/*
X * Handle release of a lock
X*/
Xvoid doRelease()
X{
X	int gpid;			/* PID of grantor */
X	LOCK *lp;			/* pointer to released facility */
X
X	while ((gpid = wait((int *)0)) == -1) {
X		if (errno != EINTR)
X			failed(-1, "error %d waiting for child", errno);
X	}
X
X	/* find release facility */
X	lp = gtlockp(gpid);
X	assert(lp != (LOCK *)0);
X	inform("release of <%s> by G-%d -- ",
X		lp->lockname, gpid);
X
X	if (lp->req != (REQUEST *)0) {
X		/* grant to next requestor */
X		grantlock(lp->req->rpid, &lp->gpid);
X		inform("OK (G-%d)\n", lp->gpid);
X		delrequest(&lp->req);
X	}
X	else {
X		/* mark facility as available */
X		lp->gpid = -1;
X
X		if (lp->serviced)
X			inform("OK (available)\n");
X		else {
X			rmlock(lp);
X			inform("OK (finally shut down)\n");
X		}
X	}
X}
X
X/*
X * Handle status display of all facilities
X*/
Xvoid showLocks()
X{
X	LOCK *lp = locklist;		/* iterator for facility list */
X	while (lp != (LOCK *)0) {
X		REQUEST *rp = lp->req;	/* iterator for request list */
X		(void) printf("facility <%s> %s", lp->lockname,
X			lp->serviced ? "serviced" : "shuting down");
X		if (lp->gpid != -1)
X			(void) printf(" (G-%d)", lp->gpid);
X		while (rp != (REQUEST *)0) {
X			(void) printf(" R-%d", rp->rpid);
X			rp = rp->next;
X		}
X		(void) printf("\n");
X		lp = lp->next;
X	}
X	(void) fflush(stdout);
X}
X
X/*
X * Handle shut down of facility
X*/
Xvoid shutService(name)
X	char *name;		/* (begin of) name of facility */
X{
X	LOCK *lp = locklist;
X	while (lp != (LOCK *)0) {
X		LOCK *lpn = lp->next;
X		if (!strncmp(lp->lockname, name, strlen(name)))
X			unservlock(lp);
X		lp = lpn;
X	}
X}
X
Xint run;			/* global run flag */
X
X/*
X * Manage request for and release of locks
X * and administrative commands
X*/
Xvoid stop(sig)			/* -- signal handler */
X	int sig;		/* signal number */
X{
X	requestOP(CMD_SHUT, (char *)0);
X	run = -sig;
X}
Xvoid LockManager()		/* -- command dispatch demon */
X{
X	/* create control fifo */
X	(void) umask(0);
X	if (mkfifo(c_fifo, 0620) == -1)
X		failed(-1, "error %d creating %s", errno, c_fifo);
X
X	/* put demon in the background */
X	switch (fork()) {
X	case -1:
X		failed(201, "error %d forking demon process", errno);
X		/*NOTREACHED*/
X	case 0:
X		/* open control fifo in demon */
X		if ((cfd = open(c_fifo, O_RDWR)) == -1)
X			failed(-1, "error %d opening %s", errno, c_fifo);
X		break;
X	default:
X		/* foreground task continues here */
X		return;
X	}
X
X	/* prepare continuoues operation */
X	run = 1;
X	(void) signal(SIGINT, SIG_IGN);
X	(void) signal(SIGQUIT, SIG_IGN);
X	(void) signal(SIGHUP, stop);
X	(void) signal(SIGTERM, stop);
X	
X	while (run > 0 || locklist != (LOCK *)0) {
X		COMMAND cmd;
X
X		/* wait for command to read from control fifo */
X		if (read(cfd, &cmd, sizeof cmd) != sizeof cmd) {
X			if (errno == EINTR && run < 0) {
X				cmd.type = CMD_SHUT;
X				cmd.lockname[0] = '\0';
X			}
X			else failed(-1, "error %d reading %s", errno,
X				c_fifo);
X		}
X
X		/* dispatch command to handler */
X		switch (cmd.type) {
X		case CMD_SERV:
X			startService(cmd.lockname);
X			break;
X		case CMD_REQ:
X			doRequest(cmd.lockname, cmd.rpid);
X			break;
X		case CMD_REL:
X			doRelease();
X			break;
X		case CMD_STAT:
X			showLocks();
X			break;
X		case CMD_VERB:
X			verbose ^= 1;
X			break;
X		case CMD_SHUT:
X			shutService(cmd.lockname);
X			if (cmd.lockname[0] == '\0' && run > 0)
X				run = 0;
X			break;
X		default:
X			failed(0, "bad command read from %s", c_fifo);
X		}
X	}
X
X	/* remove control fifo */
X	(void) unlink(c_fifo);
X	exit(run ? 128 - run : 0);
X}
X
X/*!
X----------------------------------------------------------------------
X	The following part implement the various commands that
X	typically run in the foreground and connect to the demon
X	via the control fifo.
X----------------------------------------------------------------------
X*/
X
X/*
X * Request a lock from the manager
X*/
Xvoid requestLock(lockname)
X	char *lockname;			/* name of facility */
X{
X	static COMMAND req = {CMD_REQ};	/* command structure to send */
X	char *r_fifo;			/* name of R-fifo */
X	ckname(lockname);
X
X	/* check if facility is serviced */
X	c_fifo = c_fifoname(lockname);
X	if ((cfd = open(c_fifo, O_WRONLY)) == -1)
X		failed(3, "lock %s not serviced", lockname);
X
X	/* complete command structure */
X	req.rpid = getppid();
X	(void) strcpy(req.lockname, lockname);
X	r_fifo = r_fifoname(req.rpid);
X
X	/* create R-fifo */
X	(void) umask(0);
X	if (mkfifo(r_fifo, 0660) == -1)
X		failed(-1, "cannot create R-fifo %s", r_fifo);
X
X	/* send command to manager */
X	sendpcmd(&req);
X
X	/* print name of R-fifo */
X	(void) printf("%s", r_fifo);
X
X	/* miscalaneous cleanup */
X	pstrfree(&r_fifo);
X	pstrfree(&c_fifo);
X}
X
X/*
X * Establish control fifo, optionally start demon
X*/
Xvoid setupChannel(runmgr)
X	int runmgr;		/* indicator to start demon */
X{
X	/* try to connect to control fifo */
X	c_fifo = c_fifoname("");
X	while ((cfd = tmopen(c_fifo, O_WRONLY, C_TIMEOUT)) == -1) {
X		if (runmgr) {
X			if (errno == EINTR) {
X				/* demon not responding in time */
X				failed(0, "demon died, trying restart");
X				(void) unlink(c_fifo);
X				errno = ENOENT;
X			}
X			if (errno == ENOENT) {
X				/* no control fifo, demon not running */
X				runmgr = 0;
X				LockManager();
X				continue;
X			}
X		}
X		if (errno == EINTR || errno == ENOENT)
X			failed(4, "lock manager not running");
X		failed(-1, "error %d opening %s", errno, c_fifo);
X	}
X}
X
X/*
X * Execute functionality depending on program name
X*/
Xint progis(cmpto)		/* -- compare basename of program */
X	char *cmpto;		/* name to compare to */
X{
X	char *cp = prog + strlen(prog);
X	while (cp > prog && cp[-1] != '/')
X		--cp;
X	return !strcmp(cp, cmpto);
X}
Xint main(argc, argv)		/* -- main program */
X	int argc;		/* number of command line args */
X	char **argv;		/* array of command line args */
X{
X	/* store program name */
X	prog = *argv;
X
X	if (progis(LCKREQ)) {
X		if (argc != 2) {
X			(void) fprintf(stderr, "Usage: %s facility\n", prog);
X			return 2;
X		}
X		if (setuid(getuid()) == -1)
X			failed(-1, "error %d on setuid(%d)", errno,
X				getuid());
X		requestLock(*++argv);
X		return 0;
X	}
X
X	/*
X	 * check for priviledged user
X	*/
X	if (getuid() == 0) {
X		 if (setgid(getegid()) == -1)
X			failed(-1, "error %d changing gids", errno);
X	}
X	if (getgid() != getegid())
X		failed(9, "not authorized for this function");
X
X	/*
X	 * access to control fifo / start demon
X	*/
X	setupChannel(progis(LCKMAN));
X
X	if (progis(LCKMAN)) {
X		if (argc > 1 && !strcmp(argv[1], "-v")) {
X			requestOP(CMD_VERB, (char *)0);
X			++argv;
X		}
X		while (*++argv)
X			requestOP(CMD_SERV, *argv);
X		return 0;
X	}
X
X	if (progis(LCKSTAT)) {
X		if (argc != 1) {
X			(void) fprintf(stderr, "Usage: %s (no args)\n", prog);
X			return 2;
X		}
X		requestOP(CMD_STAT, (char *)0);
X		return 0;
X	}
X
X	if (progis(LCKSHUT)) {
X		if (argc == 1)
X			requestOP(CMD_SHUT, (char *)0);
X		else while (*++argv)
X			requestOP(CMD_SHUT, *argv);
X		return 0;
X	}
X
X	failed(1, "no functionality defined");
X	/*NOTREACHED*/
X}
END_OF_lckm.c
if test 19427 -ne `wc -c <lckm.c`; then
    echo shar: \"lckm.c\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f mktask.sh -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"mktask.sh\"
else
echo shar: Extracting \"mktask.sh\" \(853 characters\)
sed "s/^X//" >mktask.sh <<'END_OF_mktask.sh'
X#
X# Erstellung von "task"-Directories mit Zufallsdaten (1.1 -- 94/02/08)
X#
XPROG=`basename $0`
XUSAGE="$PROG taskdir person[:cycles] ..."
X
X#
X# Aufrufargumente pruefen
X#
Xcase $# in
X0|1) >&2 echo "Usage: $USAGE"; exit 1
Xesac
X
X#
X# Bei Bedarf Taetigkeits-Directory anlegen
X#
Xtaskdir=$1
Xshift
Xtest -d "$taskdir" || mkdir "$taskdir" || exit
X
X#
X# Dateien erzeugen
X#
Xfor name
Xdo
X	sleep 5
X	n=`expr "$name" : '\([^:]*\)'`
X	c=`expr "$name" : '.*:\([0-9]*\)'`
X	rm -f $taskdir/$n
X	while
X		sleep `random 7`
X		sleep 2
X		case `random 3` in
X		1) resource=fax;	usetime=`expr 3 + \`random 4\``;;
X		2) resource=kopierer;	usetime=`expr 4 + \`random 5\``;;
X		3) resource=telefon;	usetime=`expr 1 + \`random 5\``;;
X		*) resource='';		usetime=`expr 1 + \`random 9\``;;
X		esac
X		test ${c:=9} -gt 0
X	do
X		echo "$usetime $resource"
X		c=`expr $c - 1`
X	done > $taskdir/$n &
Xdone
Xwait
END_OF_mktask.sh
if test 853 -ne `wc -c <mktask.sh`; then
    echo shar: \"mktask.sh\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f perform.sh -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"perform.sh\"
else
echo shar: Extracting \"perform.sh\" \(1007 characters\)
sed "s/^X//" >perform.sh <<'END_OF_perform.sh'
X#
X# Performance-Test fuer File- und Fifo-Semaphoren (1.1 -- 94/02/08)
X# 
XPROG=`basename $1`
XUSAGE="$PROG taskdir"
X
Xcase $# in
X1);; *)	>&2 echo "Usage: $USAGE"; exit 1
Xesac
Xtaskdir=$1;
Xshift
Xtest -d "$taskdir" || {
X	>&2 echo "$PROG: keine Taetigkeitsbeschreibung: $taskdir"
X	exit 2
X}
X
Xsumtask.sh "$taskdir"
Xset x `find "$taskdir" -type f -print | sort`
Xshift
X(
X	ITIME_OFF=`echo | itime +%R/%S/%U`
X	export ITIME_OFF
X
X	for s in 20 10 5 2 1 0
X	do
X	 	echo "sleeptime=$s demo.sh -file $taskdir"
X	done | itime '+%c\t%R\t%U\t%S' -3 >/dev/null
X
X	facilities=`sed 's/^[0-9 ]*//' $* | sort -u`
X
X	daemon.sh $facilities &
X	echo $! >daemon.pid; sleep 4
X	echo "demo.sh -fifo $taskdir" |
X		itime '+%c\t%R\t%U\t%S' -3 >/dev/null
X	kill -1 `cat daemon.pid`
X	rm -f daemon.pid
X
X	lckman $facilities
X	echo "demo.sh -lckm $taskdir" |
X		itime '+%c\t%R\t%U\t%S' -3 >/dev/null
X	lckshut
X) 3>&1 |
Xawk -F'	' '
XBEGIN	{ printf(F = "%34s%12s%12s%12s\n", "", "REAL", "USER", "SYS"); }
X	{ printf(F, $1, $2, $3, $4); }
XEND	{ printf("\n\n"); }'
END_OF_perform.sh
if test 1007 -ne `wc -c <perform.sh`; then
    echo shar: \"perform.sh\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f sem-fifo.sh -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"sem-fifo.sh\"
else
echo shar: Extracting \"sem-fifo.sh\" \(123 characters\)
sed "s/^X//" >sem-fifo.sh <<'END_OF_sem-fifo.sh'
X#
X# Semaphoren auf Basis von Named Pipes (1.1 -- 94/02/08)
X#
X
Xlock() {
X	read dummy <$1.lck 
X}
X
Xunlock() {
X	echo >>$1.lck
X}
END_OF_sem-fifo.sh
if test 123 -ne `wc -c <sem-fifo.sh`; then
    echo shar: \"sem-fifo.sh\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f sem-file.sh -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"sem-file.sh\"
else
echo shar: Extracting \"sem-file.sh\" \(282 characters\)
sed "s/^X//" >sem-file.sh <<'END_OF_sem-file.sh'
X#
X# Semaphoren auf Basis von Lock-Files (1.1 -- 94/02/08)
X#
X
Xrm -f *.lck
X: > lockbase
Xtrap '
X	rm -f lockbase
X	exit 129
X' 0 1 2 3
X
Xlock() {
X	until
X		ln lockbase $1.lck 2>/dev/null
X	do
X		case $sleeptime in 0) continue; esac
X		sleep ${sleeptime:-1}
X	done
X}
X
Xunlock() {
X	rm -f $1.lck
X}
END_OF_sem-file.sh
if test 282 -ne `wc -c <sem-file.sh`; then
    echo shar: \"sem-file.sh\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f sem-lckm.sh -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"sem-lckm.sh\"
else
echo shar: Extracting \"sem-lckm.sh\" \(306 characters\)
sed "s/^X//" >sem-lckm.sh <<'END_OF_sem-lckm.sh'
X#
X# Semaphoren auf Basis eines Lock-Managers (1.1 -- 94/02/08)
X#
X# Die beiden 'eval'-Kommandos sind nur notwendig, um
X# einen Bug in der Bourne-Shell von SVR4 zu umgehen,
X# und koennen bei Verwendung der Korn-Shell entfallen.
X
Xlock() {
X	eval 'exec 9>>`lckreq $1`' || exit
X}
X
Xunlock() {
X	eval 'exec 9>&-'
X}
END_OF_sem-lckm.sh
if test 306 -ne `wc -c <sem-lckm.sh`; then
    echo shar: \"sem-lckm.sh\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f sumtask.sh -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"sumtask.sh\"
else
echo shar: Extracting \"sumtask.sh\" \(1293 characters\)
sed "s/^X//" >sumtask.sh <<'END_OF_sumtask.sh'
X#
X# Ueberblick ueber Aufgabenbeschreibungen (1.1 -- 94/02/08)
X#
XPROG=`basename $0`
XUSAGE="$PROG taskdir"
X
Xcase $# in
X1);; *)	>&2 echo "Usage: $USAGE"; exit 1
Xesac
Xtaskdir=$1;
Xshift
Xtest -d "$taskdir" || {
X	>&2 echo "$PROG: keine Taetigkeitsbeschreibung: $taskdir"
X	exit 2
X}
X
Xset x `find "$taskdir" -type f -print | sort`
Xshift
Xawk '
X{
X	p = substr(FILENAME, index(FILENAME, "/") + 1);
X	worktime[p] += $1;
X	if (NF == 1)
X		idletime[p] += $1;
X	else {
X		++nrequest[$2];
X		reqtime[$2,p] += $1;
X	}
X}
Xfunc tmfmt(t) {
X	return sprintf("%d:%02d", t/60, t%60);
X}
XEND {
X	printf("%-14s %4s", "Wer|       Was->", "IDLE");
X	nr = 10 + 1 + 10;
X	for (r in nrequest) {
X		nr += 10 + 1;
X		printf("%10s ", r);
X	}
X	printf("%16s\n", "TOTAL");
X	nr += 16;
X	while (length(LINE) < nr) LINE = LINE "-";
X	print LINE;
X	for (p in worktime) {
X		++nperson;
X		printf("%-10s %10s", p, tmfmt(idletime[p]));
X		for (r in nrequest) {
X			printf("%10s ", tmfmt(reqtime[r,p]));
X			reqtime[r] += reqtime[r,p];
X		}
X		printf("%16s\n", tmfmt(worktime[p]));
X		if (mp < worktime[p])
X			mp = worktime[p];
X	}
X	print LINE;
X	printf("GES. %-5s %10s", nperson, "TOTAL");
X	for (r in nrequest) {
X		printf("%10s ", tmfmt(reqtime[r]));
X		if (mr < reqtime[r])
X			mr = reqtime[r];
X	}
X	printf("%16s\n", "MAX. " tmfmt(mr) "/" tmfmt(mp));
X	print LINE;
X}' $*
END_OF_sumtask.sh
if test 1293 -ne `wc -c <sumtask.sh`; then
    echo shar: \"sumtask.sh\" unpacked with wrong size!
fi
# end of overwriting check
fi
if test -f taskdir.shar -a "${1}" != "-c" ; then 
  echo shar: Will not over-write existing file \"taskdir.shar\"
else
echo shar: Extracting \"taskdir.shar\" \(7251 characters\)
sed "s/^X//" >taskdir.shar <<'END_OF_taskdir.shar'
X#! /bin/sh
X# This is a shell archive.  Remove anything before this line, then unpack
X# it by saving it into a file and typing "sh file".  To overwrite existing
X# files, type "sh file -c".  You can also feed this as standard input via
X# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
X# will see the following message at the end:
X#		"End of shell archive."
X# Contents:  small small/Martin medium medium/Eva medium/Karl
X#   medium/Otto large large/Dieter large/Ewald large/Hartmut
X#   large/Klaus large/Maria large/Paul large/Petra large/Thomas
X# Wrapped by martin@mwtech on Tue Feb  8 03:35:02 1994
XPATH=/bin:/usr/bin:/usr/ucb ; export PATH
Xif test ! -d small ; then
X    echo shar: Creating directory \"small\"
X    mkdir small
Xfi
Xif test -f small/Martin -a "${1}" != "-c" ; then 
X  echo shar: Will not over-write existing file \"small/Martin\"
Xelse
Xecho shar: Extracting \"small/Martin\" \(41 characters\)
Xsed "s/^X//" >small/Martin <<'END_OF_small/Martin'
XX7 kopierer
XX7 telefon
XX3 
XX8 kopierer
XX4 fax
XEND_OF_small/Martin
Xif test 41 -ne `wc -c <small/Martin`; then
X    echo shar: \"small/Martin\" unpacked with wrong size!
Xfi
X# end of overwriting check
Xfi
Xif test ! -d medium ; then
X    echo shar: Creating directory \"medium\"
X    mkdir medium
Xfi
Xif test -f medium/Eva -a "${1}" != "-c" ; then 
X  echo shar: Will not over-write existing file \"medium/Eva\"
Xelse
Xecho shar: Extracting \"medium/Eva\" \(84 characters\)
Xsed "s/^X//" >medium/Eva <<'END_OF_medium/Eva'
XX7 kopierer
XX7 kopierer
XX3 
XX5 telefon
XX6 telefon
XX7 kopierer
XX7 kopierer
XX8 kopierer
XX4 fax
XEND_OF_medium/Eva
Xif test 84 -ne `wc -c <medium/Eva`; then
X    echo shar: \"medium/Eva\" unpacked with wrong size!
Xfi
X# end of overwriting check
Xfi
Xif test -f medium/Karl -a "${1}" != "-c" ; then 
X  echo shar: Will not over-write existing file \"medium/Karl\"
Xelse
Xecho shar: Extracting \"medium/Karl\" \(88 characters\)
Xsed "s/^X//" >medium/Karl <<'END_OF_medium/Karl'
XX6 telefon
XX7 kopierer
XX7 kopierer
XX3 
XX5 telefon
XX6 telefon
XX7 kopierer
XX7 kopierer
XX8 kopierer
XEND_OF_medium/Karl
Xif test 88 -ne `wc -c <medium/Karl`; then
X    echo shar: \"medium/Karl\" unpacked with wrong size!
Xfi
X# end of overwriting check
Xfi
Xif test -f medium/Otto -a "${1}" != "-c" ; then 
X  echo shar: Will not over-write existing file \"medium/Otto\"
Xelse
Xecho shar: Extracting \"medium/Otto\" \(78 characters\)
Xsed "s/^X//" >medium/Otto <<'END_OF_medium/Otto'
XX7 kopierer
XX8 kopierer
XX4 fax
XX4 fax
XX4 fax
XX6 telefon
XX7 kopierer
XX7 kopierer
XX4 fax
XEND_OF_medium/Otto
Xif test 78 -ne `wc -c <medium/Otto`; then
X    echo shar: \"medium/Otto\" unpacked with wrong size!
Xfi
X# end of overwriting check
Xfi
Xif test ! -d large ; then
X    echo shar: Creating directory \"large\"
X    mkdir large
Xfi
Xif test -f large/Dieter -a "${1}" != "-c" ; then 
X  echo shar: Will not over-write existing file \"large/Dieter\"
Xelse
Xecho shar: Extracting \"large/Dieter\" \(157 characters\)
Xsed "s/^X//" >large/Dieter <<'END_OF_large/Dieter'
XX6 telefon
XX7 kopierer
XX7 kopierer
XX8 kopierer
XX8 kopierer
XX4 fax
XX4 fax
XX5 fax
XX6 telefon
XX7 kopierer
XX8 kopierer
XX4 fax
XX4 fax
XX5 fax
XX7 kopierer
XX7 kopierer
XX3 
XX5 telefon
XEND_OF_large/Dieter
Xif test 157 -ne `wc -c <large/Dieter`; then
X    echo shar: \"large/Dieter\" unpacked with wrong size!
Xfi
X# end of overwriting check
Xfi
Xif test -f large/Ewald -a "${1}" != "-c" ; then 
X  echo shar: Will not over-write existing file \"large/Ewald\"
Xelse
Xecho shar: Extracting \"large/Ewald\" \(173 characters\)
Xsed "s/^X//" >large/Ewald <<'END_OF_large/Ewald'
XX1 
XX2 
XX2 
XX5 kopierer
XX4 fax
XX6 telefon
XX6 telefon
XX7 kopierer
XX8 kopierer
XX3 
XX5 telefon
XX6 telefon
XX6 telefon
XX7 kopierer
XX8 kopierer
XX4 fax
XX4 fax
XX4 fax
XX6 telefon
XX7 kopierer
XX8 kopierer
XEND_OF_large/Ewald
Xif test 173 -ne `wc -c <large/Ewald`; then
X    echo shar: \"large/Ewald\" unpacked with wrong size!
Xfi
X# end of overwriting check
Xfi
Xif test -f large/Hartmut -a "${1}" != "-c" ; then 
X  echo shar: Will not over-write existing file \"large/Hartmut\"
Xelse
Xecho shar: Extracting \"large/Hartmut\" \(147 characters\)
Xsed "s/^X//" >large/Hartmut <<'END_OF_large/Hartmut'
XX8 kopierer
XX5 telefon
XX6 telefon
XX7 kopierer
XX2 
XX2 
XX8 kopierer
XX3 
XX5 telefon
XX6 telefon
XX5 fax
XX1 
XX7 kopierer
XX4 fax
XX4 fax
XX4 fax
XX5 fax
XX6 telefon
XX7 kopierer
XEND_OF_large/Hartmut
Xif test 147 -ne `wc -c <large/Hartmut`; then
X    echo shar: \"large/Hartmut\" unpacked with wrong size!
Xfi
X# end of overwriting check
Xfi
Xif test -f large/Klaus -a "${1}" != "-c" ; then 
X  echo shar: Will not over-write existing file \"large/Klaus\"
Xelse
Xecho shar: Extracting \"large/Klaus\" \(176 characters\)
Xsed "s/^X//" >large/Klaus <<'END_OF_large/Klaus'
XX5 telefon
XX6 telefon
XX6 telefon
XX7 kopierer
XX8 kopierer
XX8 kopierer
XX4 fax
XX4 fax
XX5 fax
XX6 telefon
XX7 kopierer
XX8 kopierer
XX4 fax
XX4 fax
XX7 fax
XX7 kopierer
XX7 kopierer
XX3 
XX5 telefon
XX6 telefon
XEND_OF_large/Klaus
Xif test 176 -ne `wc -c <large/Klaus`; then
X    echo shar: \"large/Klaus\" unpacked with wrong size!
Xfi
X# end of overwriting check
Xfi
Xif test -f large/Maria -a "${1}" != "-c" ; then 
X  echo shar: Will not over-write existing file \"large/Maria\"
Xelse
Xecho shar: Extracting \"large/Maria\" \(209 characters\)
Xsed "s/^X//" >large/Maria <<'END_OF_large/Maria'
XX7 kopierer
XX7 kopierer
XX3 
XX5 telefon
XX6 telefon
XX6 telefon
XX7 kopierer
XX5 kopierer
XX3 
XX5 telefon
XX6 telefon
XX5 fax
XX1 
XX7 kopierer
XX4 fax
XX4 fax
XX4 fax
XX5 fax
XX6 telefon
XX7 kopierer
XX3 
XX5 telefon
XX6 telefon
XX6 telefon
XX7 kopierer
XEND_OF_large/Maria
Xif test 209 -ne `wc -c <large/Maria`; then
X    echo shar: \"large/Maria\" unpacked with wrong size!
Xfi
X# end of overwriting check
Xfi
Xif test -f large/Paul -a "${1}" != "-c" ; then 
X  echo shar: Will not over-write existing file \"large/Paul\"
Xelse
Xecho shar: Extracting \"large/Paul\" \(101 characters\)
Xsed "s/^X//" >large/Paul <<'END_OF_large/Paul'
XX5 fax
XX6 telefon
XX7 kopierer
XX5 kopierer
XX4 fax
XX6 telefon
XX6 telefon
XX1 
XX7 kopierer
XX3 
XX5 telefon
XX6 telefon
XEND_OF_large/Paul
Xif test 101 -ne `wc -c <large/Paul`; then
X    echo shar: \"large/Paul\" unpacked with wrong size!
Xfi
X# end of overwriting check
Xfi
Xif test -f large/Petra -a "${1}" != "-c" ; then 
X  echo shar: Will not over-write existing file \"large/Petra\"
Xelse
Xecho shar: Extracting \"large/Petra\" \(124 characters\)
Xsed "s/^X//" >large/Petra <<'END_OF_large/Petra'
XX1 
XX1 
XX2 
XX2 
XX8 kopierer
XX6 fax
XX6 telefon
XX6 telefon
XX7 kopierer
XX5 kopierer
XX4 fax
XX4 fax
XX5 fax
XX7 kopierer
XX7 kopierer
XX3 
XX5 telefon
XEND_OF_large/Petra
Xif test 124 -ne `wc -c <large/Petra`; then
X    echo shar: \"large/Petra\" unpacked with wrong size!
Xfi
X# end of overwriting check
Xfi
Xif test -f large/Thomas -a "${1}" != "-c" ; then 
X  echo shar: Will not over-write existing file \"large/Thomas\"
Xelse
Xecho shar: Extracting \"large/Thomas\" \(172 characters\)
Xsed "s/^X//" >large/Thomas <<'END_OF_large/Thomas'
XX3 
XX5 telefon
XX6 telefon
XX6 telefon
XX7 kopierer
XX8 kopierer
XX8 kopierer
XX4 fax
XX4 fax
XX6 telefon
XX7 kopierer
XX7 kopierer
XX4 fax
XX4 fax
XX4 fax
XX5 fax
XX6 telefon
XX7 kopierer
XX8 kopierer
XX4 fax
XEND_OF_large/Thomas
Xif test 172 -ne `wc -c <large/Thomas`; then
X    echo shar: \"large/Thomas\" unpacked with wrong size!
Xfi
X# end of overwriting check
Xfi
Xecho shar: End of shell archive.
Xexit 0
X# SCCS-ID: 1.1 (94/02/08)
END_OF_taskdir.shar
if test 7251 -ne `wc -c <taskdir.shar`; then
    echo shar: \"taskdir.shar\" unpacked with wrong size!
fi
# end of overwriting check
fi
echo shar: End of shell archive.
exit 0



