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.