/* $Id: explode.c,v 6.0 2000/04/10 20:18:54 ksb Exp $
* This program burstes M.I.C.E. archieves into common C code. (ksb)
*
* Kevin S Braunsdorf
* ksb@sa.fedex.com
*/
#include <sys/param.h>
#include <sys/file.h>
#include <signal.h>
#include <ctype.h>
#include <stdio.h>
#include <errno.h>
#include <pwd.h>
#include "machine.h"
#include "explode.h"
#include "main.h"
extern struct passwd *getpwnam();
#if HAVE_STRINGS
#include <strings.h>
#else
#include <string.h>
#endif
#if HAVE_STDLIB
#include <stdlib.h>
#else
extern char *malloc(), *realloc();
#endif
/* we have to die because we are out of core (ksb)
*/
static void
OutOfMem()
{
static char acFailMem[] = ": out of memory\n";
write(2, progname, strlen(progname));
write(2, acFailMem, sizeof(acFailMem)-1);
exit(ENOMEM);
}
static char
acNull[]= "/dev/null", /* the bit bucket */
acTty[]= "/dev/tty", /* the users tty */
acAppend[]= "Append",
acHead[]= "Header",
acExp[] = "Explode",
acRem[] = "Remove",
acVersion[] = "Version",
acIns[] = "Insert",
acShell[] = "Shell",
acMsg[] = "Message";
#define MAXLINE 2048 /* max C code line ANSI sez 509 */
static char
*pcTemp, /* the real temp file name */
acTemp[] = /* file name template for header */
"/tmp/explXXXXXX",
acStdin[] = /* internal name for "-" on cmd line */
"stdin";
/* search a path (colon separated) for a directory that has the file (ksb)
* fall back on ./file always first, and full paths are not scanned
*/
static FILE *
SearchOpen(pcPath, pcFile, pcHow)
char *pcPath, *pcFile, *pcHow;
{
register char *pcNext;
static char acColon[] = ":";
register FILE *fpFound;
auto char acTry[MAXPATHLEN+1];
if (acStdin == pcFile) {
if (fPrint) {
printf("-\n");
}
return stdin;
}
if ((FILE *)0 != (fpFound = fopen(pcFile, pcHow)) || '/' == pcFile[0]) {
if (fPrint && (FILE *)0 != fpFound) {
printf("%s\n", pcFile);
}
return fpFound;
}
for (; *pcPath != '\000'; (*pcNext = ':'), pcPath = pcNext+1) {
pcNext = strchr(pcPath, ':');
if ((char *)0 == pcNext)
pcNext = acColon;
*pcNext = '\000';
if ('~' == pcPath[0]) {
register char *pcSlash;
register struct passwd *pwd;
static char acSlash[] = "/";
if ((char *)0 == (pcSlash = strchr(pcPath+1, '/')))
pcSlash = acSlash;
*pcSlash = '\000';
pwd = ('\000' == pcPath[1]) ? getpwuid(getuid()) : getpwnam(pcPath+1);
*pcSlash = '/';
if ((struct passwd *)0 == pwd) {
continue;
}
sprintf(acTry, "%s/%s/%s", pwd->pw_dir, pcSlash+1, pcFile);
} else {
sprintf(acTry, "%s/%s", pcPath, pcFile);
}
if (fVerbose) {
fprintf(stderr, "%s: search for %s as %s\n", progname, pcFile, acTry);
}
if ((FILE *)0 != (fpFound = fopen(acTry, pcHow))) {
*pcNext = ':';
if (fPrint) {
printf("%s\n", acTry);
}
return fpFound;
}
}
return (FILE *)0;
}
/* make sure global flages are consistant (ksb)
* and build temp file name
*/
void
SetGlobals()
{
extern char *mktemp();
if (!fActive)
fVerbose = 1;
pcTemp = mktemp(acTemp);
}
/* zap the temp file (ksb)
*/
void
RemoveTemp()
{
unlink(pcTemp);
}
/* tell if we need this file (ksb)
* We need all files if none are asked for, we need only those
* in the list is any are asked for.
*/
static int
Need(pc)
char *pc;
{
register char *pcCur, *pcNext;
static char acComma[] = ",";
if ((char *)0 == (pcCur = pcUnpack)) {
return 1;
}
for (; *pcCur != '\000'; (*pcNext = ','), pcCur = pcNext+1) {
pcNext = strchr(pcCur, ',');
if ((char *)0 == pcNext)
pcNext = acComma;
*pcNext = '\000';
if (0 == strcmp(pc, pcCur)) {
*pcNext = ',';
return 1;
}
}
return 0;
}
/* qwery the user WRT this file, should we alter it (ksb)
*/
static int
Asked(pcFile)
char *pcFile;
{
static char *pcTold = (char *)0;
auto char acAns[32];
register char *pcCur, *pcNext;
static char acComma[] = ",";
if (!fAsk) {
return 0;
}
/* is this in the list we already asked about?
*/
if ((char *)0 != (pcCur = pcTold)) {
for (pcCur = pcTold; *pcCur != '\000'; (*pcNext = ','), pcCur = pcNext+1) {
pcNext = strchr(pcCur, ',');
if ((char *)0 == pcNext)
pcNext = acComma;
*pcNext = '\000';
if (0 == strcmp(pcFile, pcCur+1)) {
*pcNext = ',';
return 'y' == *pcCur;
}
}
}
fprintf(stdout, "%s: modify %s? [ny] ", progname, pcFile);
fflush(stdout);
if ((char *)0 == fgets(acAns, sizeof(acAns), stdin)) {
fprintf(stdout, "no\n");
acAns[0] = 'n';
}
for (pcCur = acAns; isspace(*pcCur); ++pcCur)
/* nothing */;
acAns[0] = ('Y' == *pcCur || 'y' == *pcCur) ? 'y' : 'n';
if ((char *)0 == pcTold) {
pcTold = pcCur = malloc(1+strlen(pcFile)+1);
if ((char *)0 == pcTold) {
OutOfMem();
}
} else {
register int i;
i = strlen(pcTold);
pcTold = realloc(pcTold, i+1+1+strlen(pcFile)+1);
if ((char *)0 == pcTold) {
OutOfMem();
}
pcCur = pcTold + i;
*pcCur++ = ',';
}
*pcCur++ = acAns[0];
(void)strcpy(pcCur, pcFile);
return 'y' == acAns[0];
}
/* does all the work of unpacking the files from the MICE archive (ksb)
*/
void
UnPack(pcFile, pcBase)
char *pcFile, *pcBase;
{
static char acPath[MAXPATHLEN+1], acWMode[] = "w", acAMode[] = "a";
auto char acLine[MAXLINE+1];
auto char acBase[255];
register FILE *fpIn, *fpOut;
register char *pcMode, *pc;
register FILE *fpHead;
register int fNewHeader;
if (NULL == pcFile || ('-' == pcFile[0] && '\000' == pcFile[1])) {
pcFile = acStdin;
if ((char *)0 == pcBase) {
pcBase = acStdin;
}
} else if (NULL == pcBase) {
pc = strrchr(pcFile, '/');
if (NULL == pc)
pc = pcFile;
else
++pc;
(void)strcpy(acBase, pc);
pc = strrchr(acBase, '.');
if (NULL != pc)
*pc = '\000';
pcBase = acBase;
}
SetDelExt(pcFile);
if (fVerbose) {
if (fTable)
fprintf(stdout, "%s: contents of ", progname);
else
fprintf(stdout, "%s: unpack ", progname);
if ((char *)0 != pcUnpack)
fprintf(stdout, "only %s in ", pcUnpack);
fprintf(stdout, "%s to %s*%s\n", acStdin == pcFile ? "<stdin>" : pcFile, pcBase, pcExt);
}
if (NULL == (fpIn = SearchOpen(pcIncl, pcFile, "r"))) {
fprintf(stderr, "%s: fopen: %s: %s\n", progname, pcFile, strerror(errno));
exit(1);
}
if (fPrint) {
return;
}
fpOut = (FILE *)0;
if (fWhole) {
if ('-' != pcBase[0] || '\000' != pcBase[1]) {
sprintf(acPath, "%s%s", pcBase, pcExt);
if (0 == fOverwrite && 0 == access(acPath, F_OK) && 0 == Asked(acPath)) {
fprintf(stderr, "%s: won't overwrite %s\n", progname, acPath);
exit(9);
}
if (fVerbose) {
fprintf(stdout, "%s: found %s\n", progname, acPath);
}
if (! fActive) {
goto get_out;
}
if (NULL == (fpOut = fopen(acPath, acWMode))) {
fprintf(stderr, "%s: fopen: %s: %s\n", progname, acPath, strerror(errno));
exit(2);
}
} else if (! fActive) {
goto get_out;
} else {
fpOut = stdout;
}
while (NULL != fgets(acLine, sizeof(acLine), fpIn)) {
fputs(acLine, fpOut);
}
goto get_out;
}
if (NULL == (fpHead = fopen(pcTemp, "w"))) {
fprintf(stderr, "%s: fopen: %s: %s\n", progname, pcTemp, strerror(errno));
exit(1);
}
#ifdef DEBUG
fprintf(fpHead, "%s no header given */\n", pcDel);
#endif /* DEBUG */
fclose(fpHead);
if ((FILE *)0 == (fpOut = fopen(acNull, "w"))) {
fprintf(stderr, "%s: fopen: %s: %s\n", progname, acNull, strerror(errno));
exit(1);
}
fNewHeader = 0;
while (NULL != fgets(acLine, sizeof(acLine), fpIn)) {
if (0 != strncmp(pcDel, acLine, iDelLen)) {
fputs(acLine, fpOut);
continue;
}
pc = & acLine[iDelLen];
while (isspace(*pc))
++pc;
pcMode = acWMode;
if (fTable) {
register char *pcFind;
static char acCurVer[2048];
if (0 == strncmp(pc, acVersion, sizeof(acVersion)-1)) {
pc += sizeof(acVersion)-1;
while (isspace(*pc))
++pc;
pcFind = acCurVer;
while (*pc != cClose)
*pcFind++ = *pc++;
*pcFind = '\000';
continue;
} else if (0 == strncmp(pc, acExp, sizeof(acExp)-1)) {
pc += sizeof(acExp);
} else if (0 == strncmp(pc, acHead, sizeof(acHead)-1)) {
pc += sizeof(acHead);
} else {
continue;
}
while (isspace(*pc))
++pc;
pcFind = pc;
while (!isspace(*pc) && *pc != cClose)
++pc;
*pc = '\000';
if ('\000' == *pcFind)
pcFind = "*";
else if ((char *)0 != pcUnpack && ! Need(pcFind))
continue;
printf("%s\t%s%s%s", pcFile, pcBase, pcFind, pcExt);
if ('\000' != acCurVer[0])
printf("\t%s", acCurVer);
printf("\n");
continue;
}
if (0 == strncmp(pc, acExp, sizeof(acExp)-1) ||
(pcMode = acAMode,
0 == strncmp(pc, acAppend, sizeof(acAppend)-1))) {
register char *pcFind;
pc += pcMode == acExp ? sizeof(acExp) : sizeof(acAppend);
while (isspace(*pc))
++pc;
pcFind = pc;
while (!isspace(*pc) && *pc != cClose)
++pc;
*pc = '\000';
if ((char *)0 != pcUnpack && ! Need(pcFind)) {
goto dev_null;
}
if (stdout != fpOut) {
fclose(fpOut);
}
if ('-' != pcBase[0] || '\000' != pcBase[1]) {
sprintf(acPath, "%s%s%s", pcBase, pcFind, pcExt);
if (0 == fOverwrite && acWMode == pcMode &&
0 == access(acPath, F_OK) &&
0 == Asked(acPath)) {
fprintf(stderr, "%s: won't overwrite %s\n", progname, acPath);
exit(9);
}
if (fVerbose) {
fprintf(stdout, "%s: %s %s\n", progname, acWMode == pcMode ? "create" : "append", acPath);
}
if (! fActive) {
continue;
}
if (NULL == (fpOut = fopen(acPath, pcMode))) {
fprintf(stderr, "%s: fopen: %s: %s\n", progname, acPath, strerror(errno));
exit(2);
}
} else if (! fActive) {
continue;
} else {
fpOut = stdout;
if (! fNewHeader) {
continue;
}
}
if (acWMode != pcMode) {
continue;
}
if (NULL == (fpHead = fopen(pcTemp, "r"))) {
fprintf(stderr, "%s: fopen: %s: %s\n", progname, pcTemp, strerror(errno));
exit(3);
}
while (NULL != fgets(acLine, sizeof(acLine), fpHead)) {
fputs(acLine, fpOut);
}
fclose(fpHead);
fNewHeader = 0;
} else if (0 == strncmp(pc, acIns, sizeof(acIns)-1)) {
register int iStop;
if (fVerbose)
fprintf(stdout, "%s: insert text\n", progname);
pc += sizeof(acIns)-1;
while (isspace(*pc))
++pc;
iStop = *pc;
while (iStop != *++pc)
putc(*pc, fpOut);
putc('\n', fpOut);
} else if (0 == strncmp(pc, acShell, sizeof(acShell)-1)) {
register int iStop;
register char *pcCmd;
register FILE *fpShell;
pc += sizeof(acShell)-1;
while (isspace(*pc))
++pc;
iStop = *pc;
pcCmd = pc+1;
while (iStop != *++pc)
;
*pc = '\000';
if (fVerbose)
fprintf(stdout, "%s: shell `%s'\n", progname, pcCmd);
if ((FILE *)0 == (fpShell = popen(pcCmd, "r"))) {
fprintf(stdout, "%s: shell fails\n", progname);
exit(1);
}
while (EOF != (iStop = getc(fpShell))) {
putc(iStop, fpOut);
}
pclose(fpShell);
} else if (0 == strncmp(pc, acHead, sizeof(acHead)-1)) {
if (fVerbose)
fprintf(stdout, "%s: new header\n", progname);
fNewHeader = fHeader;
fflush(fpOut);
if (stdout != fpOut)
fclose(fpOut);
if (fActive && NULL == (fpOut = fopen(pcTemp, "w"))) {
fprintf(stderr, "%s: fopen: %s: %s\n", progname, pcTemp, strerror(errno));
exit(2);
}
} else if (0 == strncmp(pc, acRem, sizeof(acRem)-1)) {
if (fVerbose)
fprintf(stdout, "%s: remove text\n", progname);
fflush(fpOut);
dev_null:
if (stdout != fpOut)
fclose(fpOut);
if (fActive && NULL == (fpOut = fopen(acNull, "w"))) {
fprintf(stderr, "%s: fopen: %s: %s\n", progname, acNull, strerror(errno));
exit(2);
}
} else if (0 == strncmp(pc, acMsg, sizeof(acMsg)-1)) {
if (fVerbose)
fprintf(stdout, "%s: message text\n", progname);
fflush(fpOut);
if (stdout != fpOut)
fclose(fpOut);
if (fActive && NULL == (fpOut = fopen(acTty, "w"))) {
fprintf(stderr, "%s: fopen: %s: %s\n", progname, acTty, strerror(errno));
exit(2);
}
}
}
get_out:
if ((FILE *)0 != fpIn && stdin != fpIn) {
fclose(fpIn);
}
if ((FILE *)0 != fpOut && stdout != fpOut)
fclose(fpOut);
RemoveTemp();
}
syntax highlighted by Code2HTML, v. 0.9.1