|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T u
Length: 8109 (0x1fad)
Types: TextFile
Names: »unshar.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦this⟧ »EUUGD11/euug-87hel/sec1/shar/unshar.c«
/*
** UNSHAR
** Unpack shell archives that might have gone through mail, notes, news, etc.
**
** Options:
** -c dir Change to directory 'dir' before starting
** -d dir Change to directory 'dir' before starting
** -f Don't try to intuit file type
** -s Save pre-shar headers into a file
** -n Don't save pre-shar headers into a file
*/
#include "shar.h"
RCS("$Header: unshar.c,v 1.16 87/03/18 14:03:19 rs Exp $")
/*
** Print error message and die.
*/
static void
Quit(text)
char *text;
{
int e;
e = errno;
fprintf(stderr, "unshar: %s", text);
if (e)
fprintf(stderr, ", %s", Ermsg(e));
fprintf(stderr, ".\n");
exit(1);
}
/*
** Does this look like a mail header line?
*/
static int
IsHeader(p)
register char *p;
{
register int i;
if (*p == '\0' || *p == '\n')
return(FALSE);
if (WHITE(*p))
return(TRUE);
for (i = 0; *p == '-' || *p == '_' || *p == '.' || isalnum(*p); i++)
p++;
return(i && *p == ':');
}
/*
** Is this a /bin/sh comment line? We check that because some shars
** output comments before the CUT line.
*/
static int
IsSHcomment(p)
register char *p;
{
while (isalpha(*p) || WHITE(*p) || *p == '\n' || *p == ',' || *p == '.')
p++;
return(*p == '\0');
}
/*
** Return TRUE if p has wd1 and wd2 as words (i.e., no preceeding or
** following letters).
*/
static int
Has(p, wd1, wd2)
register char *p;
register char *wd1;
register char *wd2;
{
register char *wd;
register int first;
wd = wd1;
first = TRUE;
again:
while (*p) {
if (!isalpha(*p)) {
p++;
continue;
}
while (*p++ == *wd++) {
if (*wd == '\0') {
if (!isalpha(*p)) {
if (!first)
return(TRUE);
first = FALSE;
wd = wd2;
goto again;
}
break;
}
}
while (isalpha(*p))
p++;
wd = first ? wd1 : wd2;
}
return(FALSE);
}
/*
** Here's where the work gets done. Skip headers and try to intuit
** if the file is, e.g., C code, etc.
*/
static int
Found(Name, buff, Forced, Stream, Header)
register char *Name;
register char *buff;
register int Forced;
register FILE *Stream;
register FILE *Header;
{
register char *p;
register int InHeader;
char lower[BUFSIZ];
if (Header)
InHeader = TRUE;
while (TRUE) {
/* Read next line, fail if no more */
if (fgets(buff, BUFSIZ, Stream) == NULL) {
fprintf(stderr, "unshar: No shell commands in %s.\n", Name);
return(FALSE);
}
/* See if it looks like another language. */
if (!Forced) {
if (PREFIX(buff, "#include") || PREFIX(buff, "# include")
|| PREFIX(buff, "#define") || PREFIX(buff, "# define")
|| PREFIX(buff, "#ifdef") || PREFIX(buff, "# ifdef")
|| PREFIX(buff, "#ifndef") || PREFIX(buff, "# ifndef")
|| (PREFIX(buff, "/*")
&& !PREFIX(buff, NOTES1) && !PREFIX(buff, NOTES2)))
p = "C code";
else if (PREFIX(buff, "(*")) /* For vi :-) */
p = "PASCAL code";
else if (buff[0] == '.' && isalpha(buff[1]) && isalpha(buff[2])
&& !isalpha(buff[3]))
p = "TROFF source";
else
p = NULL;
if (p) {
fprintf(stderr, "unshar: %s is %s, not a shell archive.\n",
Name, p);
return(FALSE);
}
}
/* Does this line start with a shell command or comment? */
if ((buff[0] == '#' && !IsSHcomment(buff + 1))
|| buff[0] == ':' || PREFIX(buff, "echo ")
|| PREFIX(buff, "sed ") || PREFIX(buff, "cat ")) {
return(TRUE);
}
/* Does this line say "Cut here"? */
for (p = strcpy(lower, buff); *p; p++)
if (isascii(*p) && islower(*p))
*p = toupper(*p);
if (PREFIX(buff, "-----") || Has(lower, "cut", "here")
|| Has(lower, "cut", "cut") || Has(lower, "tear", "here")) {
/* Get next non-blank line. */
do {
if (fgets(buff, BUFSIZ, Stream) == NULL) {
fprintf(stderr, "unshar: cut line is last line of %s\n",
Name);
return(FALSE);
}
} while (*buff == '\n');
/* If it starts with a comment or lower-case letter we win. */
if (*buff == '#' || *buff == ':' || islower(*buff))
return(TRUE);
/* The cut message lied. */
fprintf(stderr, "unshar: %s is not a shell archive,\n", Name);
fprintf(stderr, " the 'cut' line was followed by: %s", buff);
return(FALSE);
}
if (Header) {
(void)fputs(buff, Header);
if (InHeader && !IsHeader(buff))
InHeader = FALSE;
}
}
}
/*
** Create file for the header, find true start of the archive,
** and send it off to the shell.
*/
static void
Unshar(Name, Stream, Saveit, Forced)
char *Name;
register FILE *Stream;
int Saveit;
int Forced;
{
register FILE *Header;
#ifndef USE_MY_SHELL
register FILE *Pipe;
#endif /* USE_MY_SHELL */
char *p;
char buff[BUFSIZ];
if (Saveit) {
/* Create a name for the saved header. */
if (Name) {
p = RDX(Name, '/');
(void)strncpy(buff, p ? p + 1 : Name, 14);
buff[10] = 0;
(void)strcat(buff, ".hdr");
}
else
(void)strcpy(buff, "UNSHAR.HDR");
/* Tell user, and open the file. */
fprintf(stderr, "unshar: Sending header to %s.\n", buff);
if ((Header = fopen(buff, "a")) == NULL)
Quit("Can't open file for header");
}
else
Header = NULL;
/* If name is NULL, we're being piped into... */
p = Name ? Name : "the standard input";
printf("unshar: Doing %s:\n", p);
if (Found(p, buff, Forced, Stream, Header)) {
#ifdef USE_MY_SHELL
BinSh(Name, Stream, buff);
#else
if ((Pipe = popen("/bin/sh", "w")) == NULL)
Quit("Can't open pipe to /bin/sh process");
(void)fputs(buff, Pipe);
while (fgets(buff, sizeof buff, Stream))
(void)fputs(buff, Pipe);
(void)pclose(Pipe);
#endif /* USE_MY_SHELL */
}
/* Close the headers. */
if (Saveit)
(void)fclose(Header);
}
main(ac, av)
register int ac;
register char *av[];
{
register FILE *Stream;
register int i;
char *p;
char cwd[BUFSIZ];
char dir[BUFSIZ];
char buff[BUFSIZ];
int Saveit;
int Forced;
/* Parse JCL. */
p = getenv("UNSHARDIR");
Saveit = DEF_SAVEIT;
for (Forced = 0; (i = getopt(ac, av, "c:d:fns")) != EOF; )
switch (i) {
default:
Quit("Usage: unshar [-fs] [-c directory] [input files]");
case 'c':
case 'd':
p = optarg;
break;
case 'f':
Forced++;
break;
case 'n':
Saveit = 0;
case 's':
Saveit++;
break;
}
av += optind;
/* Going somewhere? */
if (p) {
if (*p == '?') {
/* Ask for name; go to THE_TTY if we're being piped into. */
Stream = isatty(fileno(stdin)) ? stdin : fopen(THE_TTY, "r");
if (Stream == NULL)
Quit("Can't open tty to ask for directory");
printf("unshar: what directory? ");
(void)fflush(stdout);
if (fgets(buff, sizeof buff, Stream) == NULL
|| buff[0] == '\n' || (p = IDX(buff, '\n')) == NULL)
Quit("Okay, cancelled");
*p = '\0';
p = buff;
if (Stream != stdin)
(void)fclose(Stream);
}
/* If name is ~/blah, he means $HOME/blah. */
if (*p == '~') {
if (getenv("HOME") == NULL)
Quit("You have no $HOME?");
(void)sprintf(dir, "%s/%s", getenv("HOME"), p + 1);
p = dir;
}
/* If we're gonna move, first remember where we were. */
if (Cwd(cwd, sizeof cwd) == NULL) {
fprintf(stderr, "unshar warning: Can't get current directory.\n");
cwd[0] = '\0';
}
/* Got directory; try to go there. */
while (chdir(p) < 0)
if (mkdir(p, 0777) < 0)
Quit("Cannot chdir nor mkdir desired directory");
}
else
cwd[0] = '\0';
/* No buffering. */
(void)setbuf(stdout, (char *)NULL);
(void)setbuf(stderr, (char *)NULL);
/* Process args. */
if (*av)
for (; *av; av++) {
if (cwd[0] && av[0][0] != '/') {
(void)sprintf(buff, "%s/%s", cwd, *av);
*av = buff;
}
if ((Stream = fopen(*av, "r")) == NULL)
fprintf(stderr, "unshar: File '%s' not found.\n", *av);
else {
Unshar(*av, Stream, Saveit, Forced);
(void)fclose(Stream);
}
}
else
Unshar((char *)NULL, stdin, Saveit, Forced);
/* That's all she wrote. */
exit(0);
}