[comp.sources.unix] v24i070: Purdue tool to remove old programs

rsalz@uunet.uu.net (Rich Salz) (03/21/91)

Submitted-by: Kevin Braunsdorf <ksb@cc.purdue.edu>
Posting-number: Volume 24, Issue 70
Archive-name: pucc-rmprog

This tool, `rmprog' notifies users of impending system changes; in this
case the removal of a product from a system directory.  After a grace
period it uses install(1L) to de-install the product in question and
reminds the admin that `this was done in your name'. :-)

The sister program `mvprog' is like rmprog, but it moves the program to
a new name (or directory) rather than removing it completely.  This is
used at PUCC to upgrade unsuported programs to supported and such.

#!/bin/sh
# This is pucc-1d, a shell archive (produced by shar 3.49)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# made 11/29/1990 16:01 UTC by ksb@cc.purdue.edu (Kevin Braunsdorf)
# Source directory /ksb/c.s.u-2
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length  mode       name
# ------ ---------- ------------------------------------------
#   1088 -rw-r--r-- INSTALL.04
#  11138 -r--r--r-- rmprog/rmprog.c
#   3360 -r--r--r-- rmprog/util.c
#   2404 -r--r--r-- rmprog/rmprog.8l
#   2623 -rw-r--r-- rmprog/main.c
#   2621 -r--r--r-- mvprog/mvprog.8l
#   2237 -rw-r--r-- mvprog/main.c
#   1809 -rw-r--r-- mvprog/Makefile.mkcmd
#   1630 -rw-r--r-- rmprog/Makefile
#   1716 -rw-r--r-- rmprog/Makefile.mkcmd
#   1720 -rw-r--r-- mvprog/Makefile
#   1139 -r--r--r-- rmprog/rmprog.m
#   1127 -r--r--r-- mvprog/mvprog.m
#    740 -rw-r--r-- rmprog/machine.h
#    562 -r--r--r-- rmprog/README
#    515 -r--r--r-- rmprog/util.h
#    440 -r--r--r-- mvprog/README
#    262 -r--r--r-- rmprog/rmprog.h
#    167 -rw-r--r-- rmprog/main.h
#    166 -rw-r--r-- mvprog/main.h
#
# ============= INSTALL.04 ==============
if test -f 'INSTALL.04' -a X"$1" != X"-c"; then
	echo 'x - skipping INSTALL.04 (File already exists)'
else
echo 'x - extracting INSTALL.04 (Text)'
sed 's/^X//' << 'Purdue' > 'INSTALL.04' &&
Contains:
X	rmprog(8L)	- remove a product with notification
X	mvprog(8L)	- move a product with notification
X
X
Notes on depends:
X	- libopt.a need not be installed, but it would make life easier
X	  if you want other PUCC tools.
X
X	- rmprog needs to be compiled with libopt.a
X
X	- mvprog needs to be compiled with libopt.a
X
X
To install these tools:
X
0\ read the manual pages, see if you want any of them
X
1\ decide where to install all this stuff, change the destinations in
X   the Makefiles {BIN,LIB,ETC,HEADER}
X	vi */Makefile
X	
2\ select a platform in rmprog/machine.h
X	
3\ build rmprog, then mvprog
X	(cd rmprog && make)
X	(cd mvprog && make)
X
4\ install the tools and files
X	su
X	(cd rmprog && make install)			#
X	(cd mvprog && make install)			#
X	exit						# the root shell
X
5\ install the manual pages, turnin/turnin.5l will need lots of site editing
X   (don't install it if you have not edited it)
X	mkcat -v rmprog/rmprog.8l mvprog/mvprog.8l
X
6\ clean up the dirs
X	(cd rmprog && make clean)
X	(cd mvprog && make clean)
X
X
kayessbee
--
Kevin Braunsdorf, ksb@cc.purdue.edu, pur-ee!ksb, purdue!ksb
Purdue
chmod 0644 INSTALL.04 ||
echo 'restore of INSTALL.04 failed'
Wc_c="`wc -c < 'INSTALL.04'`"
test 1088 -eq "$Wc_c" ||
	echo 'INSTALL.04: original size 1088, current size' "$Wc_c"
fi
# ============= rmprog/rmprog.c ==============
if test ! -d 'rmprog'; then
    echo 'x - creating directory rmprog'
    mkdir 'rmprog'
fi
if test -f 'rmprog/rmprog.c' -a X"$1" != X"-c"; then
	echo 'x - skipping rmprog/rmprog.c (File already exists)'
else
echo 'x - extracting rmprog/rmprog.c (Text)'
sed 's/^X//' << 'Purdue' > 'rmprog/rmprog.c' &&
/*
X * rmprog -- use this when a command is going to be deleted.  It moves
X *	the program to a subdirectory, replaces it with a program that
X *	prints a message about it going away and then execs the real one,
X *	and queues an at job to dink it eventually. 
X *
X * Matthew Bradburn, Purdue University Computing Center
X */
#if ! defined lint
static char *rcsid =
X	"$Id: rmprog.c,v 2.6 90/11/28 15:32:20 ksb Exp $";
#endif
#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/dir.h>
X
extern char *getlogin(), *getenv();
extern char *mktemp();
extern char *ctime();
X
#define MVPROG		(!RMPROG)
X
#include "machine.h"
#include "util.h"
#include "rmprog.h"
#include "main.h"
X
static char 
X	*pcMail,		/* who to mail about the removal	*/
X	*pcWhen,		/* date it goes away			*/
X	acRProg[MAXPATHLEN+1],	/* C file to build and compile		*/
X	cmdbuf[2048],		/* for commands to system()		*/
X	acAtJob[MAXPATHLEN+MAXNAMLEN+2],
X	acNewCmd[MAXPATHLEN+1024+1],	/* the new command name, starts with "."*/
X	acPath[MAXPATHLEN+1024+1],	/* the absolute pathname to     pcCmd	*/
X	acTmpDir[] =		/* to hold temporary C work		*/
X		"/tmp/pgXXXXXXX";
#if MVPROG
static int			/* move programs to a dir, else a file	*/
X	fToDir;
X
/*
X * check to be sure the pcTo for a long list is a directory		(ksb)
X */
CheckTo(iCnt)
int iCnt;
{
X	struct stat stTo;
X
X	if (0 != stat(pcTo, &stTo)) {
X		fToDir = 0;
X	} else {
X		fToDir = S_IFDIR == (stTo.st_mode&S_IFMT);
X	}
X	if (iCnt > 1 && !fToDir) {
X		fprintf(stderr, "%s: destination must be a directory to move multiple files\n", progname);
X		exit(2);
X	}
}
#endif
X
/*
X * build the C program to notify the user of the removal		(mjb)
X */
void
mkgenc(fp, pcCmd)
FILE *fp;
char *pcCmd;
{
X	fprintf(fp, "#include <stdio.h>\n");
X	fprintf(fp, "\n");
X	fprintf(fp, "int\n");
X	fprintf(fp, "main(argc, argv, envp)\n");
X	fprintf(fp, "int argc;\n");
X	fprintf(fp, "char **argv, **envp;\n");
X	fprintf(fp, "{\n");
X	fprintf(fp, "\tregister char cNl;\n");
X	fprintf(fp, "\tregister FILE *o, *i;\n\n");
X	fprintf(fp, "\tif (isatty(stdout) || NULL == (o = fopen(\"/dev/tty\", \"w\"))) {\n");
X	fprintf(fp, "\t\to = stdout;\n\t}\n");
X	fprintf(fp, "\tif (isatty(stdin) || NULL == (i = fopen(\"/dev/tty\", \"r\"))) {\n");
X	fprintf(fp, "\t\ti = stdin;\n\t}\n");
X	ttoc(pcCmd, fp, "\tfprintf(o, \"This program, ", ", will be ", TTOC_BLOCK|TTOC_PERCENT, 0);
#if RMPROG
X	ttoc(pcWhen, fp, "deleted ", ".\\n\");\n", TTOC_BLOCK|TTOC_PERCENT, 0);
#else
X	ttoc(acNewCmd, fp, "moved to ", "\\n\");\n", TTOC_BLOCK|TTOC_PERCENT, 0);
X	ttoc(pcWhen, fp, "\tfprintf(o, \"on ", ".\\n\");\n", TTOC_BLOCK|TTOC_PERCENT, 0);
#endif
X	if ((char *)0 != pcWhy && '\000' != *pcWhy) {
X		ttoc(pcWhy, fp, "\tfprintf(o, \"", "\\n\");\n", TTOC_BLOCK|TTOC_PERCENT, 0);
X	}
X	fprintf(fp, "\tfprintf(o, \"Send questions and comments concerning this deletion ");
X	ttoc(pcWho, fp, "to ", "\\n\");\n", TTOC_BLOCK|TTOC_PERCENT, 0);
X	fprintf(fp, "\tif (isatty(fileno(o)) && isatty(fileno(i))){\n");
X	fprintf(fp, "\t\tfprintf(o, \"Press RETURN to continue\");\n");
X	fprintf(fp, "\t\tfflush(o);\n");
X	fprintf(fp, "\t\tcNl = getc(i);\n");
X	fprintf(fp, "\t}\n");
X	fprintf(fp, "\tif (stdout != o) {\n\t\t(void)fclose(o);\n\t}\n");
X	fprintf(fp, "\tif (stdin != i) {\n\t\t(void)fclose(i);\n\t}\n");
X	ttoc(acNewCmd, fp, "\t(void) execve(\"", "\", argv, envp);\n", TTOC_BLOCK, 0);
X	ttoc(acNewCmd, fp, "\tperror(\"execve: ", "\");\n", TTOC_BLOCK, 0);
X	fprintf(fp, "\texit(1);\n");
X	fprintf(fp, "}\n");
}
X
/* build an at(1) job to remove the program and notify the invoker	(ksb)
X */
void
mkatjob(fp, pcCmd)
FILE *fp;
char *pcCmd;
{
#if RMPROG
X	fprintf(fp, "%s -s \"%s: %s removed\" %s <<FRED\n", MAILX, progname, pcCmd, pcMail);
X	fprintf(fp, "You started an at job to delete %s, here is the output:\n", pcCmd);
X	fprintf(fp, "`install -Rv %s`\n", pcCmd);
X	fprintf(fp, "`install -Rv %s`\n", acNewCmd);
X	if ((char *)0 != pcMan) {
X		fprintf(fp, "`mkcat -Dv %s`\n", pcMan);
X	}
X	fprintf(fp, "\nThis would be a good time to think about deleting the source etc.\n");
X	fprintf(fp, "FRED\n");
#else
X	fprintf(fp, "%s -s \"%s: %s moved\" %s <<FRED\n", MAILX, progname, pcCmd, pcMail);
X	fprintf(fp, "You started an at job to move %s to %s.\n", pcCmd, acNewCmd);
X	fprintf(fp, "The notification script was removed today, here is the output:\n");
X	fprintf(fp, "`install -Rv %s`\n", pcCmd);
X	fprintf(fp, "\nThis would be a good time to think about change the manual page etc.\n");
X	fprintf(fp, "FRED\n");
#endif
}
X
/*
X * ProgGoin -- pcCmd is going away.
X * ProgMoved -- pcCmd is moving to a new home
X */
#if MVPROG
#define ProgGoin	ProgMoved
#endif
void
ProgGoin(pcCmd)
char *pcCmd;
{
X	register int iMode;		/* perms of replacment command	*/
X	auto struct stat statbuf;
X	register FILE *fpAtJob, *fpGen;
X	register char *pc;
X	auto int iRet;
X
X	/*
X	 * make sure the command to be removed is a file 
X	 */
X	if (-1 == stat(pcCmd, & statbuf)) {
X		fprintf(stderr, "%s: stat: %s: %s\n", progname, pcCmd, strerror(errno));
X		++iErrs;
X		return;
X	}
X	if (S_IFREG != (statbuf.st_mode&S_IFMT)) {
X		fprintf(stderr, "%s: %s is not a regular file\n", progname, pcCmd);
X		++iErrs;
X		return;
X	}
X	/* we don't have to be setuid, or anything... the target
X	 * program will handle that stuff.
X	 */
X	iMode = statbuf.st_mode & 0775;
X
X	/*
X	 * we need an absolute pathname for the output message;
X	 * get it by appending the relative pathname to the current
X	 * working directory.
X	 */
X	if ('/' != pcCmd[0]) {
X		if (NULL == getwd(acPath)) {
X			fprintf(stderr, "%s: %s\n", progname, acPath);
X			++iErrs;
X			return;
X		}
X		(void)strcat(acPath, "/");
X		(void)strcat(acPath, pcCmd);
X		(void)CompPath(acPath);
X		pcCmd = acPath;
X	}
X
X	pc = strrchr(pcCmd, '/');
X	++pc;
#if RMPROG
X	(void)strcpy(acNewCmd, pcCmd);
X	(void)strcpy(& acNewCmd[pc-pcCmd], ".");
X	(void)strcat(acNewCmd, pc);
#else
X	if (fToDir) {
X		(void)sprintf(acNewCmd, "%s/%s", pcTo, pc);
X	} else {
X		(void)strcpy(acNewCmd, pcTo);
X	}
#endif
X	if (-1 != stat(acNewCmd, & statbuf)) {
X		fprintf(stderr, "%s: %s exists, cannot install replacement\n", progname, acNewCmd);
X		++iErrs;
X		return;
X	}
X
X	/*
X	 * compile the replacement program
X	 */
X	if (fVerbose) {
X		printf("%s: cat - >%s <<\\!\n", progname, acRProg);
X		mkgenc(stdout, pcCmd);
X		printf("!\n");
X	}
X	if (fExec) {
X		if ((FILE *)0 == (fpGen = fopen(acRProg, "w"))) {
X			fprintf(stderr, "%s: fopen: %s: %s\n", progname, acRProg, strerror(errno));
X			exit(1);
X		}
X		mkgenc(fpGen, pcCmd);
X		(void)fclose(fpGen);
X	}
X	sprintf(cmdbuf, "${cc-cc} -O -o %s/a.out %s", acTmpDir, acRProg);
X	if (fVerbose) {
X		printf("%s: %s\n", progname, cmdbuf);
X	}
X	if (fExec && 0 != (iRet = system(cmdbuf))) {
X		fprintf(stderr, "%s: cc: exit: %d\n", progname, iRet);
X		exit(iRet);
X	}
X
X	/*
X	 * move /bin/foo to /bin/.foo and put our new program in
X	 * it's place.
X	 */
X	sprintf(cmdbuf, "mv %s %s", pcCmd, acNewCmd);
X	if (fVerbose) {
X		printf("%s: %s\n", progname, cmdbuf);
X	}
X	if (fExec && 0 != (iRet = system(cmdbuf))) {
X		fprintf(stderr, "%s: mv: exit: %d\n", progname, iRet);
X		exit(1);
X	}
X
X	/*
X	 * install the new command
X	 * To use install(1L) here we have to defeat the checklist
X	 * that might be in place for this file (if it says the file
X	 * should be setuid or some such we would choke).
X	 */
X	sprintf(cmdbuf, "cp %s/a.out %s", acTmpDir, pcCmd);
X	if (fVerbose) {
X		printf("%s: %s\n", progname, cmdbuf);
X	}
X	if (fExec && 0 != (iRet = system(cmdbuf))) {
X		fprintf(stderr, "%s: cp: exit: %d\n", progname, iRet);
X		exit(1);
X	}
X	sprintf(cmdbuf, "chmod %o %s", iMode, pcCmd);
X	if (fVerbose) {
X		printf("%s: %s\n", progname, cmdbuf);
X	}
X	if (fExec && 0 != (iRet = system(cmdbuf))) {
X		fprintf(stderr, "%s: chmod: exit: %d\n", progname, iRet);
X		exit(1);
X	}
X
X	/* find the basename of the command to compute atjob name
X	 */
X	if (NULL == (pc = strrchr(pcCmd, '/'))) {
X	 	pc = pcCmd;
X	} else {
X		++pc;
X	}
#if RMPROG
X	sprintf(acAtJob, "%s/rm_%s", acTmpDir, pc);
#else
X	sprintf(acAtJob, "%s/mv_%s", acTmpDir, pc);
#endif
X
X	/* create an at job to remove the program in iWhen days
X	 */
X	if (fVerbose) {
X		printf("%s: cat - >%s <<\\!\n", progname, acAtJob);
X		mkatjob(stdout, pcCmd);
X		printf("!\n");
X	}
X	if (fExec) {
X		if (NULL == (fpAtJob = fopen(acAtJob, "w"))) {
X			fprintf(stderr, "%s: fopen: %s: %s\n", acAtJob, strerror(errno));
X			++iErrs;
X			return;
X		}
X		mkatjob(fpAtJob, pcCmd);
X		(void)fclose(fpAtJob);
X	}
X
X	/* now spool the at job to remove the program
X	 */
#ifdef SYS_V
X	sprintf(cmdbuf, "at now + %d day <%s 2>/dev/null", iWhen, acAtJob);
#else
#if defined(PUCC)
X	sprintf(cmdbuf, "at -s -o %d.0.0 %s", iWhen, acAtJob);
#else
X				/* Month Day */ /* year == pcWhen+11,*/ 
X	sprintf(cmdbuf, "at 700 %.3s %.2s %s", pcWhen+4, pcWhen+8, acAtJob);
#endif
#endif
X	if (fVerbose) {
X		printf("%s: %s\n", progname, cmdbuf);
X	}
X	if (fExec && 0 != (iRet = system(cmdbuf))) {
X		fprintf(stderr, "%s: at: exit: %d\n", progname, iRet);
X		exit(2);
X	}
}
X
static int iDidInit = 0;
X
/*
X * clean up and exit
X */
Die()
{
X	auto char acDink[MAXPATHLEN+400];
X
X	if (iDidInit) {
X		(void)sprintf(acDink, "rm -rf %s", acTmpDir);
X		if (fVerbose) {
X			printf("%s: %s\n", progname, acDink);
X		}
X		if (fExec && 0 != system(acDink)) {
X			exit(1);
X		}
X	}
X	exit(iErrs);
}
X
/* exit with care, if the user panics us
X */
SIGRET_t
intr_hndlr()
{
X	Die();
}
X
/*
X * some startup code to made life safer while we work			(mjb)
X */
Init()
{
X	auto struct timeval	tv;
X	auto struct timezone	tz;
X	register char *pc;
X
X	(void)signal(SIGINT, intr_hndlr);
X
X	/* find out who's doing this
X	 */
X	if ((char *)0 == pcWho || '\000' == *pcWho) {
X		pcWho = getlogin();
X	}
X	pcMail = getlogin();
X	if ((char *)0 == pcMail || '\000' == *pcMail) {
X		pcMail = getenv("USER");
X	}
X	if ((char *)0 == pcMail || '\000' == *pcMail) {
X		pcMail = getenv("LOGNAME");
X	}
X	if ((char *)0 == pcMail || '\000' == *pcMail) {
X		pcMail = DEFMAIL;
X	}
X
X	/*
X	 * figure out a string that represents when the program in the 
X	 * path will be dinked by the at(1) job we're going to
X	 * submit.  We take the number of days the link will be around
X	 * and add it to today, and convert back to ascii.
X	 */
X	if (-1 == gettimeofday(& tv, & tz)) {
X		fprintf(stderr, "%s: gettimeofday: %s\n", progname, strerror(errno));
X		exit(1);
X	}
X	/* add the number of days hence to count of seconds
X	 * copy the year down over the time and dink the trailing newline
X	 */
X	tv.tv_sec += iWhen * 24 * 60 * 60;
X	pcWhen = ctime(& tv.tv_sec);
X	(void)strcpy(& pcWhen[11], & pcWhen[20]);
X	if (NULL != (pc = strchr(pcWhen, '\n'))) {
X		*pc = '\000';
X	}
X
X	/*
X	 * make a temporary directory and put our substitute program
X	 * there (if it's already made, we assume the binary is there, too)
X	 * We know we've already made the directory if there are no X's left
X	 * in the tmpdir string (mktemp replaces them with digits).
X	 */
X	if ((char *)0 == mktemp(acTmpDir)) {
X		fprintf(stderr, "%s: mktemp failed\n", progname);
X		exit(1);
X	}
X	if (fVerbose) {
X		printf("%s: mkdir %s\n", progname, acTmpDir);
X	}
X	if (fExec && 0 != mkdir(acTmpDir, TDIRMODE)) {
X		fprintf(stderr, "%s: mkdir: %s: %s\n", progname, acTmpDir, strerror(errno));
X		exit(1);
X	}
X	iDidInit = 1;
X
X	sprintf(acRProg, "%s/%s", acTmpDir, GENC);
}
Purdue
chmod 0444 rmprog/rmprog.c ||
echo 'restore of rmprog/rmprog.c failed'
Wc_c="`wc -c < 'rmprog/rmprog.c'`"
test 11138 -eq "$Wc_c" ||
	echo 'rmprog/rmprog.c: original size 11138, current size' "$Wc_c"
fi
# ============= rmprog/util.c ==============
if test -f 'rmprog/util.c' -a X"$1" != X"-c"; then
	echo 'x - skipping rmprog/util.c (File already exists)'
else
echo 'x - extracting rmprog/util.c (Text)'
sed 's/^X//' << 'Purdue' > 'rmprog/util.c' &&
#include <stdio.h>
#include "util.h"
X
X
X
/*
X * CompPath()
X *	Compress a path by assuming the . and .. really point to	(ksb)
X *	what they should (good undef BSD at least :-|), we also
X *	assume the all things used as a directory all directories
X *	(and exist)
X *
X * Remove extra `/', `./', `foo/..'  (in place)
X * also replace a null path with `.'
X */
char *
CompPath(pcFile)
char *pcFile;		/* path to compress				*/
{
X	register char *pcScan, *pcPut;
X	register int bFirst;
X
X	pcScan = pcPut = pcFile;
X	bFirst = 1;
X	for (;;) { switch (*pcPut = *pcScan) {
X	case '/':
X		++pcPut;
X		do
X			++pcScan;
X		while ('/' == *pcScan);
X		bFirst = 1;
X		continue;
X	case '.':
X		if (!bFirst) {
X			++pcPut, ++pcScan;
X			continue;
X		}
X		if ('/' == pcScan[1] || '\000' == pcScan[1]) {
X			do
X				++pcScan;
X			while ('/' == *pcScan);
X			continue;
X		}
X		/* do foo/.., but not /.. or just ..
X		 */
X		if ('.' == pcScan[1] && pcPut != pcFile &&
X		    ('/' == pcScan[2] || '\000' == pcScan[2]) &&
X		    !('/' == pcFile[0] && pcPut == pcFile+1)) {
X			--pcPut;
X			do
X				--pcPut;
X			while ('/' != *pcPut && pcPut != pcFile);
X			if ('/' == *pcPut)
X				++pcPut;
X			pcScan += 2;
X			while ('/' == *pcScan)
X				++pcScan;
X			continue;
X		}
X	default:
X		++pcPut, ++pcScan;
X		bFirst = 0;
X		continue;
X	case '\000':
X		break;
X	} break; }
X
X	/* clean up trailing / and empty path name
X	 */
X	if (pcPut != pcFile) {
X		while (--pcPut != pcFile && '/' == *pcPut)
X			*pcPut = '\000';
X	}
X	if ('\000' == *pcFile) {
X		pcFile[0] = '.';
X		pcFile[1] = '\000';
X	}
X	return pcFile;
}
X
X
/*
X * This routine converts text into C quoted strings			(ksb)
X * It reads from a string and writes to a FILE *; producing code with
X * the input C text between `pcpen` and `pclose`.
X *
X * The iOpts flag provides some options that are handy:
X *	TTOC_NOP		do nothing special
X *	TTOC_PERCENT		this is a printf format string, quote %'s
X *	TTOC_NEWLINE		always break strings at newlines
X *	TTOC_BLOCK		never break the string for newlines
X *
X * The iMax argument is the max lenght of an output string, pass 0 for
X * unlimited
X *
X * pcpen and pclose are output whenever the a new string it started
X * or a string is closed.
X * example:	pcOpen = "\tfprintf(fp, \""
X *		pcClose = "\");\n"
X */
void
ttoc(pcIn, pFIOut, pcOpen, pcClose, iOpts, iMax)
register FILE *pFIOut;
char *pcIn, *pcOpen, *pcClose;
register int iOpts, iMax;
{
X	extern int strlen();
X	register int c;
X	register int bQuote;
X	register int iLen;
X
X	bQuote = iLen = 0;
X
X	if (iMax < 0) {
X		iMax = 0;
X	}
X
X	while ('\000' != (c = *pcIn++)) {
X		if (! bQuote) {
X			fputs(pcOpen, pFIOut);
X			iLen = 0;
X			bQuote = 1;
X		}
X
X		switch (c) {
X		case '\\':
X		case '"':
X			putc('\\', pFIOut);
X			putc(c, pFIOut);
X			iLen += 2;
X			break;
X		case '\t':
X			fputs("\\t", pFIOut);
X			iLen += 2;
X			break;
X		case '\n':
X			fputs("\\n", pFIOut);
X			if (0 != (TTOC_NEWLINE & iOpts) || (0 == (TTOC_BLOCK & iOpts) && iLen > (iMax >> 1))) {
X				iLen = iMax + 2;
X			} else {
X				iLen += 2;
X			}
X			break;
X		case '%':
X			if (0 != (iOpts & TTOC_PERCENT)) {
X				fputs("%%", pFIOut);
X				iLen += 2;
X				break;
X			}
X			/*FALLTHROUGH*/
X		default:
X			if (c < ' ' || c > '~') {
X				fprintf(pFIOut, "\\%03o", c);
X				iLen += 4;
X				break;
X			}
X			putc(c, pFIOut);
X			iLen += 1;
X			break;
X		}
X
X		if (0 != iMax && iLen > iMax) {
X			fputs(pcClose, pFIOut);
X			bQuote = 0;
X		}
X	}
X	if (bQuote) {
X		fputs(pcClose, pFIOut);
X	}
}
Purdue
chmod 0444 rmprog/util.c ||
echo 'restore of rmprog/util.c failed'
Wc_c="`wc -c < 'rmprog/util.c'`"
test 3360 -eq "$Wc_c" ||
	echo 'rmprog/util.c: original size 3360, current size' "$Wc_c"
fi
# ============= rmprog/rmprog.8l ==============
if test -f 'rmprog/rmprog.8l' -a X"$1" != X"-c"; then
	echo 'x - skipping rmprog/rmprog.8l (File already exists)'
else
echo 'x - extracting rmprog/rmprog.8l (Text)'
sed 's/^X//' << 'Purdue' > 'rmprog/rmprog.8l' &&
.\" man page for rmprog
.\" $Compile: ${nroff-nroff} -man %f | ${PAGER-more}
.\" Matthew Bradburn, Purdue University Computing Center
.\" Copyright 1989 Purdue Research Foundation
.\" $Id: rmprog.8l,v 2.0 90/11/28 15:39:50 ksb Exp $
.TH RMPROG 8L PUCC
.SH NAME
rmprog \- inform users that a command is scheduled to go away
.SH SYNOPSIS
\fB/usr/local/etc/rmprog\fP [\fB\-hnvV\fP] [\fB\-t\fP \fIwhen\fP] [\fB\-u\fP \fIwho\fP] [\fB\-w\fP \fIwhy\fP] \fIfiles\fP
.SH DESCRIPTION
\fIRmprog\fP moves
each \fIfile\fP to \fI.file\fR and puts in its place a program which
prints a message about the command being scheduled for deletion,
prompts the invoker to press
.B return
(if the command is invoked from a tty), then invokes \fI.file\fP.
.PP
\fIRmprog\fP also queues an \fIat\fP(1) job which will remove both \fIfile\fP
and \fI.file\fP in \fIwhen\fP days (default 30).
The \fIat\fP job also reminds the invoker to remove the program's source,
manual pages, and \fIwhatis\fP(1) entry via \fImail\fP(1).
.SH OPTIONS
.TP
.B \-h
Print a short help message.
.TP
.B \-n
Don't really do anything, just output detailed shell commands which
mock the actions that would be taken.
.TP
.BI \-t when
Arrange for the command to go away in \fIwhen\fP days, rather than the
default 30.
.TP
.BI \-u who
Print \fIwho\fP as the person to contact regarding the removal.
.TP
.B \-v
Produce verbose output.
.TP
.B \-V
Show which version of \fIrmprog\fP is running.
.TP
.BI \-w why
Print \fIwhy\fP when the command is executed, in addition to the information
that is normally printed.
.SH EXAMPLES
.TP
# rmprog -w "Use /bin/bar instead" /bin/foo
Might be used to cause \fI/bin/foo\fP to go away in a month,
because it has been outdated by \fI/bin/bar\fP.
.TP
$ /bin/foo
will then output:
.sp
.RS
This program, /bin/foo, will be deleted <date inserted here>.
.br
Use /bin/bar instead.
.br
Send questions and comments concerning this deletion to \fIwho\fP.
.RE
.sp
After printing this message, the new \fI/bin/foo\fP invokes
the original command, now named \fI/bin/.foo\fP.
.TP
$ touch /tmp/junque && rmprog -nv /tmp/junque
Use this command to see how \fIrmprog\fP works.
.SH FILES
.TP
/tmp/pgXXXXXXX/* 
temporary directory for compilation of replacement command
.SH AUTHOR
Matthew Bradburn, Purdue University Computing Center
.br
Kevin Braunsdorf, Purdue University Computing Center
.SH SEE ALSO
at(1), mail(1), whatis(1),
mvprog(8L)
Purdue
chmod 0444 rmprog/rmprog.8l ||
echo 'restore of rmprog/rmprog.8l failed'
Wc_c="`wc -c < 'rmprog/rmprog.8l'`"
test 2404 -eq "$Wc_c" ||
	echo 'rmprog/rmprog.8l: original size 2404, current size' "$Wc_c"
fi
# ============= rmprog/main.c ==============
if test -f 'rmprog/main.c' -a X"$1" != X"-c"; then
	echo 'x - skipping rmprog/main.c (File already exists)'
else
echo 'x - extracting rmprog/main.c (Text)'
sed 's/^X//' << 'Purdue' > 'rmprog/main.c' &&
/*
X * machine generated cmd line parser
X * targets for mk
X * $Compile: ${CC-cc} -I/usr/include/local %f -lopt
X * $Depend: ${MAKETD-maketd} -a -d -I/usr/include/local %f
X * $Lint: ${LINT-lint} -hnx -I/usr/include/local %f
X */
X
#include <ctype.h>
#include "getopt.h"
#include <stdio.h>
#include "rmprog.h"
X
char
X	*progname = "$Id$",
X	u_terse[] = " [-Vhnv] [-m manpage] [-t days] [-u who] [-w why] [files]",
X	*u_help[] = {
X		"V         output version information",
X		"h         print this help message",
X		"m manpage manual page to mkcat -D when program is removed",
X		"n         trace execution but do nothing",
X		"t days    days until command goes away",
X		"u who     who to contact about removal",
X		"v         be verbose",
X		"w why     additional message to print",
X		(char *)0
X	},
X	*pcMan = (char *)0;
int
X	iErrs = 0,
X	fExec = 1,
X	iWhen = 30;
char
X	*pcWho = "";
int
X	fVerbose = 0;
char
X	*pcWhy = "";
X
static char sbData[] = "%s: illegal data for %s option `%c\'\n";
X
static void
chkint(opt, pch)
int opt;
char *pch;
{
X	register int c;
X
X	while (isspace(*pch))
X		++pch;
X	c = *pch;
X	if ('+' == c || '-' == c)
X		++pch;
X	while (isdigit(*pch))
X		++pch;
X	if ('\000' != *pch) {
X		fprintf(stderr, sbData, progname, "integer", opt);
X		exit(1);
X	}
}
X
/*
X * parser
X */
int
main(argc, argv)
int argc;
char **argv;
{
X	static char
X		sbOpt[] = "Vhm:nt:u:vw:",
X		*u_pch = (char *)0;
X	static int
X		u_loop = 0;
X	register int curopt;
X	extern int atoi();
X	extern char *strrchr();
X
X	progname = strrchr(argv[0], '/');
X	if ((char *)0 == progname)
X		progname = argv[0];
X	else
X		++progname;
X	while (EOF != (curopt = getopt(argc, argv, sbOpt))) {
X		switch (curopt) {
X		case BADARG:
X			fprintf(stderr, "%s: option %c needs a parameter\n", progname, optopt);
X			exit(1);
X		case BADCH:
X			fprintf(stderr, "%s: usage%s\n", progname, u_terse);
X			exit(1);
X		case 'V':
X			printf("%s: %s\n", progname, "$Id: rmprog.m,v 2.2 90/10/14 21:29:02 ksb Exp $");
X			exit(0);
X		case 'h':
X			fprintf(stdout, "%s: usage%s\n", progname, u_terse);
X			for (u_loop = 0; (char *)0 != (u_pch = u_help[u_loop]); ++u_loop) {
X				fprintf(stdout, "%s\n", u_pch);
X			}
X			exit(0);
X		case 'm':
X			pcMan = optarg;
X			continue;
X		case 'n':
X			fExec ^= 1;
X			continue;
X		case 't':
X			chkint('t', optarg);
X			iWhen = atoi(optarg);
X			continue;
X		case 'u':
X			pcWho = optarg;
X			continue;
X		case 'v':
X			fVerbose = ! 0;
X			continue;
X		case 'w':
X			pcWhy = optarg;
X			continue;
X		}
X		break;
X	}
X	Init();
X
X	curopt = 1;
X	while (EOF != getarg(argc, argv)) {
X		curopt = 0;
X		ProgGoin(optarg);
X	}
X	if (curopt) {
X		fprintf(stderr, "%s: usage%s\n", progname, u_terse);
X	}
X
X	Die();
X	exit(0);
}
Purdue
chmod 0644 rmprog/main.c ||
echo 'restore of rmprog/main.c failed'
Wc_c="`wc -c < 'rmprog/main.c'`"
test 2623 -eq "$Wc_c" ||
	echo 'rmprog/main.c: original size 2623, current size' "$Wc_c"
fi
# ============= mvprog/mvprog.8l ==============
if test ! -d 'mvprog'; then
    echo 'x - creating directory mvprog'
    mkdir 'mvprog'
fi
if test -f 'mvprog/mvprog.8l' -a X"$1" != X"-c"; then
	echo 'x - skipping mvprog/mvprog.8l (File already exists)'
else
echo 'x - extracting mvprog/mvprog.8l (Text)'
sed 's/^X//' << 'Purdue' > 'mvprog/mvprog.8l' &&
.\" man page for mvprog
.\" by Matthew Bradburn, Purdue University Computing Center
.\" Copyright 1989, Purdue Research Foundation
.\" $Compile: nroff -man %f | ${PAGER-more}
.\" $Laser: ltroff -man %f
.\" $Id: mvprog.8l,v 2.0 90/11/28 15:37:57 ksb Exp $
.TH MVPROG 8L PUCC
.SH NAME
mvprog \- move a command and inform users
.SH SYNOPSIS
\fBmvprog\fP [\fB\-hnvV\fP] [\fB\-t\fP \fIwhen\fP] [\fB\-u\fP \fIwho\fP] [\fB\-w\fP \fIwhy\fP] \fIfiles to\fP
.SH DESCRIPTION
A system administrator should use \fImvprog\fP to move a command
from one directory to another.  After moving \fIfiles\fP to \fIto\fP,
it creates a program which
it places in \fIfiles\fP that, when invoked, prints out a message about the new
location of the command and prompts the invoker to hit
.B return
(if the command is run from a tty).  Once return is pressed, this
command executes the command in the \fIto\fP location.
.PP
.I Mvprog
also queues an \fIat\fP(1) job which will remove the \fIfiles\fP command
in \fIwhen\fP (30, by default) days.
System administrators must change the documentation and the makefile
for the source, if necessary.  The \fIat\fP job sends mail to the invoker
as a reminder.
.SH OPTIONS
.TP
.B \-h
Print a short help message.
.TP
.B \-n
Don't really do anything.
.TP
.BI \-t when
Arrange for the link in the old directory to go away in
.I when
days rather than the default 30.
.TP
.BI \-u who
Print
.I who
as the source to conctact about details concerning the command move.
.TP
.B \-v
Produce verbose output.
.TP
.B \-V
Show which version of \fImvprog\fP is running.
.TP
.BI \-w why
Print the string \fIwhy\fP when the command is executed, in addition
to the information that is normally printed.
.SH EXAMPLE
.TP
# \fBmvprog\fP /bin/foo /usr/bin
Would move \fI/bin/foo\fP to \fI/usr/bin/foo\fP, afterward,
.TP
$ /bin/foo
.sp
will then print:
.RS
.sp
This program, /bin/foo, has moved to /usr/bin/foo.
.br
You will no longer be able to invoke it via this path after \fBdate\fP.
.br
Send questions and comments regarding this move to "\fBuser\fP".
.sp
.RE
After printing this message, the \fI/bin/foo\fP invokes the original command,
now in \fI/usr/bin/foo\fP.
.SH BUGS
The program put in the old location may fail to invoke the real program
if it is a shell script without a \*(lqloader card,\*(rq
even though a shell would be able to execute it directly.
.SH FILES
.TP
/tmp/pmXXXXXXX/*
temporary directory for compilation of the replacement command
.SH AUTHORS
Matthew Bradburn, Purdue University Computing Center
.br
Kevin Braunsdorf, Purdue University Computing Center
.SH SEE ALSO
at(1),  atq(1),  atrm(1),
rmprog(8L)
Purdue
chmod 0444 mvprog/mvprog.8l ||
echo 'restore of mvprog/mvprog.8l failed'
Wc_c="`wc -c < 'mvprog/mvprog.8l'`"
test 2621 -eq "$Wc_c" ||
	echo 'mvprog/mvprog.8l: original size 2621, current size' "$Wc_c"
fi
# ============= mvprog/main.c ==============
if test -f 'mvprog/main.c' -a X"$1" != X"-c"; then
	echo 'x - skipping mvprog/main.c (File already exists)'
else
echo 'x - extracting mvprog/main.c (Text)'
sed 's/^X//' << 'Purdue' > 'mvprog/main.c' &&
/*
X * machine generated cmd line parser
X */
X
#include "getopt.h"
#include <stdio.h>
#include "rmprog.h"
X
char
X	*progname = "$Id$",
X	u_terse[] = " [-Vhnv] [-t when] [-u who] [-w why] [files] to",
X	*u_help[] = {
X		"V      output version information",
X		"h      print this help message",
X		"n      trace execution but do nothing",
X		"t when number of days before files are deinstalled",
X		"u who  who to contact for more information",
X		"v      be verbose",
X		"w why  additional message",
X		"files  files to move",
X		"to     file (directory) to move file(s) to",
X		(char *)0
X	},
X	*pcTo = (char *)0;
int
X	iErrs = 0,
X	fExec = 1,
X	iWhen = DEFWHEN;
char
X	*pcWho = (char *)0;
int
X	fVerbose = 0;
char
X	*pcWhy = (char *)0;
X
/*
X * parser
X */
int
main(argc, argv)
int argc;
char **argv;
{
X	static char
X		sbOpt[] = "Vhnt:u:vw:",
X		*u_pch = (char *)0;
X	static int
X		u_loop = 0;
X	register int curopt;
X	extern int atoi();
X	extern char *strrchr();
X
X	progname = strrchr(argv[0], '/');
X	if ((char *)0 == progname)
X		progname = argv[0];
X	else
X		++progname;
X	while (EOF != (curopt = getopt(argc, argv, sbOpt))) {
X		switch (curopt) {
X		case BADARG:
X			fprintf(stderr, "%s: option %c needs a parameter\n", progname, optopt);
X			exit(1);
X		case BADCH:
X			fprintf(stderr, "%s: usage%s\n", progname, u_terse);
X			exit(1);
X		case 'V':
X			printf("%s: %s\n", progname, "$Id: mvprog.m,v 2.0 90/10/15 11:51:12 ksb Exp $");
X			exit(0);
X		case 'h':
X			fprintf(stdout, "%s: usage%s\n", progname, u_terse);
X			for (u_loop = 0; (char *)0 != (u_pch = u_help[u_loop]); ++u_loop) {
X				fprintf(stdout, "%s\n", u_pch);
X			}
X			exit(0);
X		case 'n':
X			fExec = !1;
X			fVerbose = 1;
X			continue;
X		case 't':
X			iWhen = atoi(optarg);
X			continue;
X		case 'u':
X			pcWho = optarg;
X			continue;
X		case 'v':
X			fVerbose = ! 0;
X			continue;
X		case 'w':
X			pcWhy = optarg;
X			continue;
X		}
X		break;
X	}
X	Init();
X	if (argc - optind < 1) {
X		fprintf(stderr, "%s: not enough arguments for justified arguments\n", progname);
X		exit(1);
X	}
X	--argc;
X	pcTo = argv[argc];
X	argv[argc] = (char *)0;
X	if (optind == argc) {
X		fprintf(stderr, "%s: usage%s\n", progname, u_terse);
X		Die();
X	}
X
X	CheckTo(argc-optind);
X
X	while (EOF != getarg(argc, argv)) {
X		ProgMoved(optarg);
X	}
X	Die();
X	exit(iErrs);
}
Purdue
chmod 0644 mvprog/main.c ||
echo 'restore of mvprog/main.c failed'
Wc_c="`wc -c < 'mvprog/main.c'`"
test 2237 -eq "$Wc_c" ||
	echo 'mvprog/main.c: original size 2237, current size' "$Wc_c"
fi
# ============= mvprog/Makefile.mkcmd ==============
if test -f 'mvprog/Makefile.mkcmd' -a X"$1" != X"-c"; then
	echo 'x - skipping mvprog/Makefile.mkcmd (File already exists)'
else
echo 'x - extracting mvprog/Makefile.mkcmd (Text)'
sed 's/^X//' << 'Purdue' > 'mvprog/Makefile.mkcmd' &&
#	$Id: Makefile,v 2.3 90/11/29 08:28:56 ksb Exp $
#
#	Makefile for mvprog
#
X
PROG=	mvprog
BIN=	${DESTDIR}/usr/local/etc
X
RMPROGD=../rmprog
X
L=../libopt
#L=/usr/include/local
I=/usr/include
S=/usr/include/sys
P=
X
INCLUDE= -I$L
DEBUG=	-O
CDEFS=  -DRMPROG=0
CFLAGS= ${DEBUG} ${CDEFS} ${INCLUDE}
X
HDR=	
SRC=	
LINKC=	rmprog.c util.c
LINKH=	rmprog.h machine.h util.h
LINK=	${LINKH} ${LINKC}
GENC=	main.c ${LINKC}
GENH=	main.h ${LINKH}
DEP=	${SRC} ${GENC}
GEN=	${GENC} ${GENH}
OBJ=	main.o rmprog.o util.o
MAN=	mvprog.8l
OTHER=	README mvprog.m
SOURCE=	Makefile Makefile.plain ${HDR} ${SRC} ${MAN} ${OTHER}
X
all: ${PROG}
X
${PROG}:$P ${OBJ}
#	${CC} -o $@ ${CFLAGS} ${OBJ} -lopt
X	${CC} -o $@ ${CFLAGS} ${OBJ} ../libopt/libopt.a
#	${CC} -o $@ ${CFLAGS} ${OBJ} -L /usr/local/lib -lopt
X
main.h: main.c
X
main.c: mvprog.m
X	mkcmd std_help.m mvprog.m
X	-(cmp -s prog.c main.c || (cp prog.c main.c && echo main.c updated))
X	-(cmp -s prog.h main.h || (cp prog.h main.h && echo main.h updated))
X	rm -f prog.[ch]
X
${LINK}:
X	ln -s ${RMPROGD}/$@ ./$@
X
swap: Makefile.plain ${GEN}
X	mv Makefile Makefile.mkcmd
X	mv Makefile.plain Makefile
X
clean: FRC
X	rm -f Makefile.bak ${PROG} ${GEN} *.o a.out core errs tags
X
depend: ${HDR} ${SRC} ${GEN} FRC
X	maketd ${CDEFS} ${INCLUDE} ${DEP}
X
install: all FRC
X	install -cs ${PROG} ${BIN}/${PROG}
X
mkcat: ${MAN} FRC
X	mkcat ${MAN}
X
lint: ${HDR} ${SRC} ${GEN} FRC
X	lint -h ${CDEFS} ${INCLUDE} ${DEP}
X
print: source FRC
X	lpr -J'${PROG} source' ${SOURCE}
X
source: ${SOURCE}
X
spotless: clean
X	rcsclean ${SOURCE}
X
tags: ${HDR} ${SRC} ${GEN}
X	ctags -t ${HDR} ${SRC} ${GEN}
X
${SOURCE}:
X	co -q $@
X
FRC:
X
# DO NOT DELETE THIS LINE - maketd DEPENDS ON IT
X
main.o: main.c rmprog.h
X
rmprog.o: machine.h main.h rmprog.c rmprog.h util.h
X
util.o: util.c util.h
X
# *** Do not add anything here - It will go away. ***
Purdue
chmod 0644 mvprog/Makefile.mkcmd ||
echo 'restore of mvprog/Makefile.mkcmd failed'
Wc_c="`wc -c < 'mvprog/Makefile.mkcmd'`"
test 1809 -eq "$Wc_c" ||
	echo 'mvprog/Makefile.mkcmd: original size 1809, current size' "$Wc_c"
fi
# ============= rmprog/Makefile ==============
if test -f 'rmprog/Makefile' -a X"$1" != X"-c"; then
	echo 'x - skipping rmprog/Makefile (File already exists)'
else
echo 'x - extracting rmprog/Makefile (Text)'
sed 's/^X//' << 'Purdue' > 'rmprog/Makefile' &&
#	$Id: Makefile.plain,v 2.6 90/11/29 08:24:42 ksb Exp $
#
#	Makefile for rmprog
#
X
PROG=	rmprog
BIN=	${DESTDIR}/usr/local/etc
X
L=../libopt
#L=/usr/include/local
I=/usr/include
S=/usr/include/sys
P=
X
INCLUDE=-I$L
DEBUG=	-O
CDEFS=  -DRMPROG=1
CFLAGS= ${DEBUG} ${CDEFS} ${INCLUDE}
X
HDR=	main.h rmprog.h machine.h util.h
SRC=	main.c rmprog.c util.c
OBJ=	rmprog.o util.o main.o
GENH=	
GENC=	
GEN=	${GENC} ${GENH}
DEP=	${SRC} ${GENC}
MAN=	rmprog.8l
OTHER=	README rmprog.m
SOURCE=	Makefile Makefile.mkcmd ${HDR} ${SRC} ${MAN} ${OTHER}
X
all: ${PROG}
X
${PROG}:$P ${OBJ}
#	${CC} -o $@ ${CFLAGS} ${OBJ} -lopt
X	${CC} -o $@ ${CFLAGS} ${OBJ} ../libopt/libopt.a
#	${CC} -o $@ ${CFLAGS} ${OBJ} -L /usr/local/lib -lopt
X
swap: rmprog.m Makefile.mkcmd
X	mkcmd std_help.m std_targets.m rmprog.m
X	-(cmp -s prog.c main.c || echo main.c changed)
X	-(cmp -s prog.h main.h || echo main.h changed)
X	mv Makefile Makefile.plain
X	mv Makefile.mkcmd Makefile
X
clean: FRC
X	rm -f Makefile.bak ${PROG} ${GEN} prog.[ch] *.o a.out core errs tags
X
depend: ${HDR} ${SRC} ${GEN} FRC
X	maketd ${CDEFS} ${INCLUDE} ${DEP}
X
install: all FRC
X	install -cs ${PROG} ${BIN}/${PROG}
X
lint: ${HDR} ${SRC} ${GEN} FRC
X	lint -h ${CDEFS} ${INCLUDE} ${DEP}
X
mkcat: ${MAN}
X	mkcat ${MAN}
X
print: source FRC
X	lpr -J'${PROG} source' ${SOURCE}
X
source: ${SOURCE}
X
spotless: clean
X	rcsclean ${SOURCE}
X
tags: ${HDR} ${SRC} ${GEN}
X	ctags -t ${HDR} ${SRC} ${GEN}
X
${SOURCE}:
X	co -q $@
X
FRC:
X
# DO NOT DELETE THIS LINE - maketd DEPENDS ON IT
X
main.o: main.c rmprog.h
X
rmprog.o: machine.h main.h rmprog.c rmprog.h util.h
X
util.o: util.c util.h
X
# *** Do not add anything here - It will go away. ***
Purdue
chmod 0644 rmprog/Makefile ||
echo 'restore of rmprog/Makefile failed'
Wc_c="`wc -c < 'rmprog/Makefile'`"
test 1630 -eq "$Wc_c" ||
	echo 'rmprog/Makefile: original size 1630, current size' "$Wc_c"
fi
# ============= rmprog/Makefile.mkcmd ==============
if test -f 'rmprog/Makefile.mkcmd' -a X"$1" != X"-c"; then
	echo 'x - skipping rmprog/Makefile.mkcmd (File already exists)'
else
echo 'x - extracting rmprog/Makefile.mkcmd (Text)'
sed 's/^X//' << 'Purdue' > 'rmprog/Makefile.mkcmd' &&
#	$Id: Makefile,v 2.10 90/11/29 08:24:35 ksb Exp $
#
#	Makefile for rmprog
#
X
PROG=	rmprog
BIN=	${DESTDIR}/usr/local/etc
X
L=../libopt
#L=/usr/include/local
I=/usr/include
S=/usr/include/sys
P=
X
INCLUDE=-I$L
DEBUG=	-O
CDEFS=  -DRMPROG=1
CFLAGS= ${DEBUG} ${CDEFS} ${INCLUDE}
X
HDR=	rmprog.h machine.h util.h
SRC=	rmprog.c util.c
OBJ=	rmprog.o util.o main.o
GENH=	main.h
GENC=	main.c
GEN=	${GENC} ${GENH}
DEP=	${SRC} ${GENC}
MAN=	rmprog.8l
OTHER=	README rmprog.m
SOURCE=	Makefile Makefile.plain ${HDR} ${SRC} ${MAN} ${OTHER}
X
all: ${PROG}
X
${PROG}:$P ${OBJ}
#	${CC} -o $@ ${CFLAGS} ${OBJ} -lopt
X	${CC} -o $@ ${CFLAGS} ${OBJ} ../libopt/libopt.a
#	${CC} -o $@ ${CFLAGS} ${OBJ} -L /usr/local/lib -lopt
X
main.h: main.c
X
main.c: rmprog.m
X	mkcmd std_help.m std_targets.m rmprog.m
X	-(cmp -s prog.c main.c || (cp prog.c main.c && echo main.c updated))
X	-(cmp -s prog.h main.h || (cp prog.h main.h && echo main.h updated))
X	rm -f prog.[ch]
X
swap: ${GEN} Makefile.plain
X	mv Makefile Makefile.mkcmd
X	mv Makefile.plain Makefile
X
clean: FRC
X	rm -f Makefile.bak ${PROG} ${GEN} prog.[ch] *.o a.out core errs tags
X
depend: ${HDR} ${SRC} ${GEN} FRC
X	maketd ${CDEFS} ${INCLUDE} ${DEP}
X
install: all FRC
X	install -cs ${PROG} ${BIN}/${PROG}
X
lint: ${HDR} ${SRC} ${GEN} FRC
X	lint -h ${CDEFS} ${INCLUDE} ${DEP}
X
mkcat: ${MAN}
X	mkcat ${MAN}
X
print: source FRC
X	lpr -J'${PROG} source' ${SOURCE}
X
source: ${SOURCE}
X
spotless: clean
X	rcsclean ${SOURCE}
X
tags: ${HDR} ${SRC} ${GEN}
X	ctags -t ${HDR} ${SRC} ${GEN}
X
${SOURCE}:
X	co -q $@
X
FRC:
X
# DO NOT DELETE THIS LINE - maketd DEPENDS ON IT
X
rmprog.o: machine.h main.h rmprog.c rmprog.h util.h
X
util.o: util.c util.h
X
main.o: main.c rmprog.h
X
# *** Do not add anything here - It will go away. ***
Purdue
chmod 0644 rmprog/Makefile.mkcmd ||
echo 'restore of rmprog/Makefile.mkcmd failed'
Wc_c="`wc -c < 'rmprog/Makefile.mkcmd'`"
test 1716 -eq "$Wc_c" ||
	echo 'rmprog/Makefile.mkcmd: original size 1716, current size' "$Wc_c"
fi
# ============= mvprog/Makefile ==============
if test -f 'mvprog/Makefile' -a X"$1" != X"-c"; then
	echo 'x - skipping mvprog/Makefile (File already exists)'
else
echo 'x - extracting mvprog/Makefile (Text)'
sed 's/^X//' << 'Purdue' > 'mvprog/Makefile' &&
#	$Id: Makefile.plain,v 2.3 90/11/29 08:29:02 ksb Exp $
#
#	Makefile for mvprog
#
X
PROG=	mvprog
BIN=	${DESTDIR}/usr/local/etc
X
RMPROGD=../rmprog
X
L=../libopt
#L=/usr/include/local
I=/usr/include
S=/usr/include/sys
P=
X
INCLUDE= -I$L
DEBUG=	-O
CDEFS=  -DRMPROG=0
CFLAGS= ${DEBUG} ${CDEFS} ${INCLUDE}
X
HDR=	main.h 
SRC=	main.c 
LINKC=	rmprog.c util.c
LINKH=	rmprog.h machine.h util.h
LINK=	${LINKH} ${LINKC}
GENC=	${LINKC}
GENH=	${LINKH}
DEP=	${SRC} ${GENC}
GEN=	${GENC} ${GENH}
OBJ=	main.o rmprog.o util.o
MAN=	mvprog.8l
OTHER=	README mvprog.m
SOURCE=	Makefile Makefile.mkcmd ${HDR} ${SRC} ${MAN} ${OTHER}
X
all: ${PROG}
X
${PROG}:$P ${OBJ}
#	${CC} -o $@ ${CFLAGS} ${OBJ} -lopt
X	${CC} -o $@ ${CFLAGS} ${OBJ} ../libopt/libopt.a
#	${CC} -o $@ ${CFLAGS} ${OBJ} -L /usr/local/lib -lopt
X
${LINK}:
X	ln -s ${RMPROGD}/$@ ./$@
X
swap: Makefile.mkcmd ${GEN}
X	mkcmd std_help.m mvprog.m
X	-(cmp -s prog.c main.c || echo main.c changed)
X	-(cmp -s prog.h main.h || echo main.h changed)
X	mv Makefile Makefile.plain
X	mv Makefile.mkcmd Makefile
X
clean: FRC
X	rm -f Makefile.bak ${PROG} ${GEN} *.o a.out core errs tags
X
depend: ${HDR} ${SRC} ${GEN} FRC
X	maketd ${CDEFS} ${INCLUDE} ${DEP}
X
install: all FRC
X	install -cs ${PROG} ${BIN}/${PROG}
X
mkcat: ${MAN} FRC
X	mkcat ${MAN}
X
lint: ${HDR} ${SRC} ${GEN} FRC
X	lint -h ${CDEFS} ${INCLUDE} ${DEP}
X
print: source FRC
X	lpr -J'${PROG} source' ${SOURCE}
X
source: ${SOURCE}
X
spotless: clean
X	rcsclean ${SOURCE}
X
tags: ${HDR} ${SRC} ${GEN}
X	ctags -t ${HDR} ${SRC} ${GEN}
X
${SOURCE}:
X	co -q $@
X
FRC:
X
# DO NOT DELETE THIS LINE - maketd DEPENDS ON IT
X
main.o: main.c rmprog.h
X
rmprog.o: machine.h main.h rmprog.c rmprog.h util.h
X
util.o: util.c util.h
X
# *** Do not add anything here - It will go away. ***
Purdue
chmod 0644 mvprog/Makefile ||
echo 'restore of mvprog/Makefile failed'
Wc_c="`wc -c < 'mvprog/Makefile'`"
test 1720 -eq "$Wc_c" ||
	echo 'mvprog/Makefile: original size 1720, current size' "$Wc_c"
fi
# ============= rmprog/rmprog.m ==============
if test -f 'rmprog/rmprog.m' -a X"$1" != X"-c"; then
	echo 'x - skipping rmprog/rmprog.m (File already exists)'
else
echo 'x - extracting rmprog/rmprog.m (Text)'
sed 's/^X//' << 'Purdue' > 'rmprog/rmprog.m' &&
# mkcmd source for "rmprog"
# $Compile: mkcmd std_help.m std_targets.m %f
# Matthew Bradburn, PUCC UNIX Group
# $Id: rmprog.m,v 2.2 90/10/14 21:29:02 ksb Exp $
X
from '"rmprog.h"'
X
integer variable "iErrs" {
X	init "0"
}
X
after {
X	update "Init();"
}
X
every {
X	named "files"
X	parameter "files"
X	update "ProgGoin(%a);"
}
zero {
X	update 'fprintf(stderr, "%%s: usage%%s\\n", %b, %t);'
}
exit {
X	update "Die();"
}
X
integer "t" {
X	named "iWhen"
X	initializer "30"
X	verify parameter "days"
X	help "days until command goes away"
}
char* "w" {
X	named "pcWhy"
X	initializer '""'
X	parameter "why"
X	help "additional message to print"
}
char* "u" {
X	named "pcWho"
X	initializer '""'
X	parameter "who"
X	help "who to contact about removal"
}
char* "m" {
X	named "pcMan"
X	parameter "manpage"
X	help "manual page to mkcat -D when program is removed"
}
boolean "v" {
X	named "fVerbose"
X	initializer "0"
X	help "be verbose"
}
toggle "n" {
X	named "fExec"
X	initializer "1"
X	help "trace execution but do nothing"
}
action 'V' {
X	update 'printf("%%s: %%s\\n", %b, "$Id: rmprog.m,v 2.2 90/10/14 21:29:02 ksb Exp $");'
X	aborts "exit(0);"
X	help "output version information"
}
Purdue
chmod 0444 rmprog/rmprog.m ||
echo 'restore of rmprog/rmprog.m failed'
Wc_c="`wc -c < 'rmprog/rmprog.m'`"
test 1139 -eq "$Wc_c" ||
	echo 'rmprog/rmprog.m: original size 1139, current size' "$Wc_c"
fi
# ============= mvprog/mvprog.m ==============
if test -f 'mvprog/mvprog.m' -a X"$1" != X"-c"; then
	echo 'x - skipping mvprog/mvprog.m (File already exists)'
else
echo 'x - extracting mvprog/mvprog.m (Text)'
sed 's/^X//' << 'Purdue' > 'mvprog/mvprog.m' &&
X
# cmd line option parser for mvprog (ksb)
from '"rmprog.h"'
X
integer variable "iErrs" {
X	init "0"
}
X
boolean 'n' {
X	named "fExec"
X	init "1"
X	update "%n = !%i;%rvn = 1;"
X	help "trace execution but do nothing"
}
X
boolean 'v' {
X	named "fVerbose"
X	help "be verbose"
}
X
from '"rmprog.h"'
integer 't' {
X	named "iWhen"
X	param "when"
X	init "DEFWHEN"
X	help "number of days before files are deinstalled"
}
X
char* 'u' {
X	named "pcWho"
X	init '(char *)0'
X	param "who"
X	help "who to contact for more information"
}
X
char* 'w' {
X	named "pcWhy"
X	init '(char *)0'
X	param "why"
X	help "additional message"
}
X
X
char* variable "pcTo" {
X	param "to"
X	help "file (directory) to move file(s) to"
}
X
right "pcTo" {
}
X
after {
X	update "Init();"
}
zero {
X	update 'fprintf(stderr, "%%s: usage%%s\\n", %b, %t);'
X	aborts "Die();"
}
list {
X	update 'CheckTo(argc-optind);'
}
every {
X	named "ProgMoved"
X	param "files"
X	help "files to move"
}
exit {
X	named "Die"
X	update "%n();"
X	aborts "exit(iErrs);"
}
action 'V' {
X	update 'printf("%%s: %%s\\n", %b, "$Id: mvprog.m,v 2.0 90/10/15 11:51:12 ksb Exp $");'
X	aborts "exit(0);"
X	help "output version information"
}
Purdue
chmod 0444 mvprog/mvprog.m ||
echo 'restore of mvprog/mvprog.m failed'
Wc_c="`wc -c < 'mvprog/mvprog.m'`"
test 1127 -eq "$Wc_c" ||
	echo 'mvprog/mvprog.m: original size 1127, current size' "$Wc_c"
fi
# ============= rmprog/machine.h ==============
if test -f 'rmprog/machine.h' -a X"$1" != X"-c"; then
	echo 'x - skipping rmprog/machine.h (File already exists)'
else
echo 'x - extracting rmprog/machine.h (Text)'
sed 's/^X//' << 'Purdue' > 'rmprog/machine.h' &&
/*
X * configuration for rmprog and mvprog
X */
/* #define bsd /**/
/* #define HPUX7 /**/
/* #define SYSV /**/
/* #defined sun /**/
X
#if ! defined BSD
#include <local/bsd.h>
#if !defined MAXNAMLEN
#define MAXNAMLEN 15
#endif
#endif
X
#if ! defined MAILX
#if defined HPUX7
#define MAILX	"/usr/bin/mailx"
#else
#define MAILX	"/usr/ucb/mail"
#endif
#endif
X
#if defined bsd
#include <strings.h>
#else
#include <string.h>
#endif
X
#if defined SYSV
extern char *getcwd();
#define getwd(Mpc)	getcwd(Mpc,MAXPATHLEN)
#else
extern char *getwd();
#endif
X
#if defined sun || defined HPUX7
typedef void SIGRET_t;
#else
typedef int SIGRET_t;
#endif
X
#define TDIRMODE	0750
X
extern char *sys_errlist[];
#define strerror(Me) (sys_errlist[Me])
extern int errno;
Purdue
chmod 0644 rmprog/machine.h ||
echo 'restore of rmprog/machine.h failed'
Wc_c="`wc -c < 'rmprog/machine.h'`"
test 740 -eq "$Wc_c" ||
	echo 'rmprog/machine.h: original size 740, current size' "$Wc_c"
fi
# ============= rmprog/README ==============
if test -f 'rmprog/README' -a X"$1" != X"-c"; then
	echo 'x - skipping rmprog/README (File already exists)'
else
echo 'x - extracting rmprog/README (Text)'
sed 's/^X//' << 'Purdue' > 'rmprog/README' &&
# $Id: README,v 2.0 90/11/29 08:25:00 ksb Exp $
X
This tool, `rmprog' notifies users of impending system changes; in this
case the removal of a product from a system directory.  After a grace
period it uses install(1L) to de-install the product in question and
reminds the admin that `this was done in your name'. :-)
X
The sister program `mvprog' is like rmprog, but it moves the program to
a new name (or directory) rather than removing it completely.  This is
used a PUCC to upgrade unsuported programs to supported and such.
X
Kevin Braunsdorf, PUCC UNIX Group
Purdue
chmod 0444 rmprog/README ||
echo 'restore of rmprog/README failed'
Wc_c="`wc -c < 'rmprog/README'`"
test 562 -eq "$Wc_c" ||
	echo 'rmprog/README: original size 562, current size' "$Wc_c"
fi
# ============= rmprog/util.h ==============
if test -f 'rmprog/util.h' -a X"$1" != X"-c"; then
	echo 'x - skipping rmprog/util.h (File already exists)'
else
echo 'x - extracting rmprog/util.h (Text)'
sed 's/^X//' << 'Purdue' > 'rmprog/util.h' &&
/*
X * convert a string of input chars into C code ascii string		(ksb)
X * input	m = "\n";
X * output 	"m = \"\\n\";\n",
X */
#define TTOC_NOP	0x0000	/* do nothing special			*/
#define TTOC_PERCENT	0x0001	/* this is a printf format string	*/
#define TTOC_NEWLINE	0x0002	/* always break strings at newlines	*/
#define TTOC_BLOCK	0x0004	/* never break the string for newlines	*/
X
#if defined(__STDC__)
extern void ttoc(char *, FILE *, char *, char *, int, int);
#else
extern void ttoc();
#endif
X
extern char *CompPath();
Purdue
chmod 0444 rmprog/util.h ||
echo 'restore of rmprog/util.h failed'
Wc_c="`wc -c < 'rmprog/util.h'`"
test 515 -eq "$Wc_c" ||
	echo 'rmprog/util.h: original size 515, current size' "$Wc_c"
fi
# ============= mvprog/README ==============
if test -f 'mvprog/README' -a X"$1" != X"-c"; then
	echo 'x - skipping mvprog/README (File already exists)'
else
echo 'x - extracting mvprog/README (Text)'
sed 's/^X//' << 'Purdue' > 'mvprog/README' &&
# $Id: README,v 2.0 90/11/29 08:29:15 ksb Exp $
X
This tool, `mvprog', notifies users of impending system changes; this
one is used when a product moves from one system directory to another
(or to another name in the same directory).  After a grace period it
uses install(1L) to de-install the message front-end in question and
reminds the admin that `this was done in your name'. :-)
X
See also ../rmprog.
X
Kevin Braunsdorf, PUCC UNIX Group
Purdue
chmod 0444 mvprog/README ||
echo 'restore of mvprog/README failed'
Wc_c="`wc -c < 'mvprog/README'`"
test 440 -eq "$Wc_c" ||
	echo 'mvprog/README: original size 440, current size' "$Wc_c"
fi
# ============= rmprog/rmprog.h ==============
if test -f 'rmprog/rmprog.h' -a X"$1" != X"-c"; then
	echo 'x - skipping rmprog/rmprog.h (File already exists)'
else
echo 'x - extracting rmprog/rmprog.h (Text)'
sed 's/^X//' << 'Purdue' > 'rmprog/rmprog.h' &&
/*
X * include file for rmrog.c
X */
extern int iErrs;
extern void ProgGoin();
X
#if ! defined GENC
#define GENC	"subst.c"	/* C file to put in tmp dir */
#endif
X
#if ! defined DEFMAIL
#define DEFMAIL		"pucc"
#endif
X
#if ! defined DEFWHEN
#define DEFWHEN		30
#endif
Purdue
chmod 0444 rmprog/rmprog.h ||
echo 'restore of rmprog/rmprog.h failed'
Wc_c="`wc -c < 'rmprog/rmprog.h'`"
test 262 -eq "$Wc_c" ||
	echo 'rmprog/rmprog.h: original size 262, current size' "$Wc_c"
fi
# ============= rmprog/main.h ==============
if test -f 'rmprog/main.h' -a X"$1" != X"-c"; then
	echo 'x - skipping rmprog/main.h (File already exists)'
else
echo 'x - extracting rmprog/main.h (Text)'
sed 's/^X//' << 'Purdue' > 'rmprog/main.h' &&
/*
X * parse options
X */
X
extern char *progname, u_terse[], *u_help[];
extern int main();
extern int fExec, iWhen, fVerbose, iErrs;
extern char *pcMan, *pcWho, *pcWhy;
Purdue
chmod 0644 rmprog/main.h ||
echo 'restore of rmprog/main.h failed'
Wc_c="`wc -c < 'rmprog/main.h'`"
test 167 -eq "$Wc_c" ||
	echo 'rmprog/main.h: original size 167, current size' "$Wc_c"
fi
# ============= mvprog/main.h ==============
if test -f 'mvprog/main.h' -a X"$1" != X"-c"; then
	echo 'x - skipping mvprog/main.h (File already exists)'
else
echo 'x - extracting mvprog/main.h (Text)'
sed 's/^X//' << 'Purdue' > 'mvprog/main.h' &&
/*
X * parse options
X */
X
extern char *progname, u_terse[], *u_help[];
extern int main();
extern int fExec, iWhen, fVerbose, iErrs;
extern char *pcWho, *pcWhy, *pcTo;
Purdue
chmod 0644 mvprog/main.h ||
echo 'restore of mvprog/main.h failed'
Wc_c="`wc -c < 'mvprog/main.h'`"
test 166 -eq "$Wc_c" ||
	echo 'mvprog/main.h: original size 166, current size' "$Wc_c"
fi
exit 0

exit 0 # Just in case...
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.