[alt.sources] shar 3.32 part 2/2

wht@n4hgf.Mt-Park.GA.US (Warren Tucker) (07/15/90)

Submitted-by: wht@n4hgf.Mt-Park.GA.US
Archive-name: shar332/part02

#!/bin/sh
# This is part 02 of shar332
# ============= unshar.c ==============
echo "x - extracting unshar.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > unshar.c &&
Xchar *revision = "3.30";
X/****************************************************************
X * unshar.c: Unpackage one or more shell archive files
X *
X * Usage:     unshar [-c] [-C exit_line] [ -d directory ] [ file ] ...
X *
X * Description:	unshar is a filter which removes the front part
X *		of a file and passes the rest to the 'sh' command.
X *		It understands phrases like "cut here", and also
X *		knows about shell comment characters and the Unix
X *		commands "echo", "cat", and "sed".
X *
X *      It can unshar shar files concatenated in one file, with the
X *      the "-c" command, which separates files by recognizing the
X *      "exit 0" string at the beginning of a line
X *
X *      (The -C string option allows you to specify this string, thus
X *      -c is equivalent to -C "exit 0")
X *
X *      The -d flag tells unshar to change directory before unsharing
X *
X * HISTORY
X * 19-Apr-90  Colas Nahaboo (colas@mirsa.inria.fr)
X *      added -c and -C flags to read from concatenated archives
X *  1-Feb-85  Guido van Rossum (guido@mcvax) at CWI, Amsterdam
X *	Added missing 'quit' routine;
X *	added -d flag to change to directory first;
X *	added filter mode (read stdin when no arguments);
X *	added 'getopt' to get flags (makes it self-contained).
X * 29-Jan-85  Michael Mauldin (mlm) at Carnegie-Mellon University
X *	Created.
X ****************************************************************/
X/*+:EDITS:*/
X/*:05-05-1990-01:37-relay.EU.net!rivm!a3-dont assume vax is running BSD */
X/*:04-19-1990-15:20-wht@n4hgf-fix so -d doesnt make argv files unreachable */
X/*:04-19-1990-15:06-wht@n4hgf-colas@mirsa patches had expanded tabs */
X/*:04-10-1990-22:02-wht@n4hgf-stdin failed sometimes-can not seek on pipe */
X
X#include <stdio.h>
X#define EOL '\n'
X
X#if (defined(pyr) || defined(sun) || defined(BSD42) || \
X defined(vax) || defined(sequent)) && !defined(SYS5)
X#define strchr	index
X#undef USE_GETCWD
Xchar *getwd();
X#else
X#define USE_GETCWD
Xchar *getcwd();
X#endif
X
Xchar *strchr();
X
Xextern char *optarg;
Xextern int optind;
X
Xint continue_reading = 0;
Xchar *exit_string = "exit 0";
Xint exit_string_length;
Xchar argvdir[1024];
X
Xmain(argc,argv)
Xint argc;
Xchar *argv[];
X{
X	int i,ch;
X	FILE *in;
X	char s1024[1024];
X
X	setbuf(stdout,NULL);
X	setbuf(stderr,NULL);
X
X#ifdef USE_GETCWD
X	if(!getcwd(argvdir,sizeof(argvdir)))
X	{
X		perror("cannot get current directory name");
X		exit(1);
X	}
X#else
X	argvdir[0] = 0;
X	if(!getwd(argvdir))
X	{
X		if(argvdir[0])
X			fprintf(stderr,"%s\n",argvdir);
X		else
X			printf(stderr,"cannot get current directory name\n");
X		exit(1);
X	}
X#endif
X
X
X	/* Process options */
X
X	while((ch = getopt(argc,argv,"d:cC:")) != EOF)
X	{
X		switch(ch)
X		{
X		case 'd':
X			if(chdir(optarg) == -1)
X			{
X				fprintf(stderr,"unshar: cannot chdir to '%s'\n",optarg);
X				exit(2);
X			}
X			break;
X		case 'C':
X			exit_string = optarg;
X		case 'c':
X			continue_reading = 1;
X			exit_string_length = strlen(exit_string);
X			break;
X		default:
X			quit(2,"Usage: unshar [-d directory] [file] ...\n");
X		}
X	}
X
X	if(optind < argc)
X	{
X		for(i= optind; i < argc; ++i)
X		{
X			if(argv[i][0] == '/') {
X				strcpy(s1024,argv[i]);
X			} else {
X				strcpy(s1024,argvdir);
X				strcat(s1024,"/");
X				strcat(s1024,argv[i]);
X			}
X			if(!(in = fopen(s1024,"r")))
X			{
X				perror(s1024);
X				exit(1);
X			}
X			process(s1024,in);
X			fclose(in);
X		}
X	}
X	else
X	{
X		sprintf(s1024,"/tmp/unsh.%05d",getpid());
X		unlink(s1024);
X		if(!(in = fopen(s1024,"w+")))
X		{
X			fprintf(stderr,"cannot open temp file '%s'\n",s1024);
X			exit(1);
X		}
X		unlink(s1024);	/* don't try this with MSDOS, sports fans */
X		while(i = fread(s1024,1,sizeof(s1024),stdin))
X			fwrite(s1024,i,1,in);
X		rewind(in);
X		process("standard input",in);
X		fclose(in);
X	}
X
X	exit(0);
X}
X
X
Xprocess(name,in)
Xchar *name;
XFILE *in;
X{
X	char buffer[8196];
X	char ch;
X	FILE *shpr,*popen();
X	long current_position = 0;
X	char *more_to_read = 0;
X
X	while(position(name,in,current_position))
X	{
X		printf("%s:\n",name);
X		if(!(shpr = popen("sh","w")))
X			quit(1,"unshar: cannot open 'sh' process\n");
X
X		if (!continue_reading) {
X			while((ch = fgetc(in)) != EOF)
X				fputc(ch,shpr);
X			pclose(shpr);
X			break;
X		} else {
X			while (more_to_read = fgets(buffer, 8196, in)) {
X				fputs(buffer, shpr);
X				if (!strncmp(exit_string, buffer, exit_string_length)) {
X					break;
X				}
X			}
X			pclose(shpr);
X			if (more_to_read)
X				current_position = ftell(in);
X			else {
X				break;
X			}
X		}
X	}
X}
X
X/****************************************************************
X * position: position 'fil' at the start of the shell command
X * portion of a shell archive file.
X ****************************************************************/
X
Xposition(fn,fil,start)
Xchar *fn;
XFILE *fil;
Xlong start;                   /* scan file from position */
X{
X	char buf[BUFSIZ];
X	long pos,ftell();
X
X	/* Results from star matcher */
X	static char res1[BUFSIZ],res2[BUFSIZ],res3[BUFSIZ],res4[BUFSIZ];
X	static char *result[] = 
X	{
X		res1,res2,res3,res4 		};
X
X	fseek(fil, start, 0);
X
X	while(1)
X	{ /* Record position of the start of this line */
X		pos = ftell(fil);
X
X		/* Read next line, fail if no more and no previous process */
X		if(!fgets(buf,BUFSIZ,fil))
X		{
X			if(!start)
X				fprintf(stderr,"unshar: found no shell commands in %s\n",fn);
X			return(0);
X		}
X
X		/* Bail out if we see C preprocessor commands or C comments */
X		if(stlmatch(buf,"#include")	|| stlmatch(buf,"# include") ||
X		    stlmatch(buf,"#define")	|| stlmatch(buf,"# define") ||
X		    stlmatch(buf,"#ifdef")	|| stlmatch(buf,"# ifdef") ||
X		    stlmatch(buf,"#ifndef")	|| stlmatch(buf,"# ifndef") ||
X		    stlmatch(buf,"/*"))
X		{
X			fprintf(stderr,
X			    "unshar: %s looks like raw C code, not a shell archive\n",fn);
X			return(0);
X		}
X
X		/* Does this line start with a shell command or comment */
X		if(stlmatch(buf,"#")	|| stlmatch(buf,":") ||
X		    stlmatch(buf,"echo ")	|| stlmatch(buf,"sed ") ||
X		    stlmatch(buf,"cat ") || stlmatch(buf,"if "))
X		{
X			fseek(fil,pos,0);
X			return(1);
X		}
X
X		/* Does this line say "Cut here" */
X		if(smatch(buf,"*CUT*HERE*",result) ||
X		    smatch(buf,"*cut*here*",result) ||
X		    smatch(buf,"*TEAR*HERE*",result) ||
X		    smatch(buf,"*tear*here*",result) ||
X		    smatch(buf,"*CUT*CUT*",result) ||
X		    smatch(buf,"*cut*cut*",result))
X		{
X			/* Read next line after "cut here", skipping blank lines */
X			while(1)
X			{
X				pos = ftell(fil);
X
X				if(!fgets(buf,BUFSIZ,fil))
X				{
X					fprintf(stderr,
X					    "unshar: found no shell commands after 'cut' in %s\n",fn);
X					return(0);
X				}
X
X				if(*buf != '\n') break;
X			}
X
X			/* Win if line starts with a comment character of lower case letter */
X			if(*buf == '#' || *buf == ':' || (('a' <= *buf) && ('z' >= *buf)))
X			{
X				fseek(fil,pos,0);
X				return(1);
X			}
X
X			/* Cut here message lied to us */
X			fprintf(stderr,"unshar: %s is probably not a shell archive,\n",fn);
X			fprintf(stderr,"        the 'cut' line was followed by: %s",buf);
X			return(0);
X		}
X	}
X}
X
X/*****************************************************************
X * stlmatch  --  match leftmost part of string
X *
X * Usage:  i = stlmatch (big,small)
X *	int i;
X *	char *small, *big;
X *
X * Returns 1 iff initial characters of big match small exactly;
X * else 0.
X *
X * HISTORY
X * 18-May-82 Michael Mauldin (mlm) at Carnegie-Mellon University
X *      Ripped out of CMU lib for Rog-O-Matic portability
X * 20-Nov-79  Steven Shafer (sas) at Carnegie-Mellon University
X *	Rewritten for VAX from Ken Greer's routine.
X *
X *  Originally from klg (Ken Greer) on IUS/SUS UNIX
X *****************************************************************/
X
Xint stlmatch(big,small)
Xchar *small,*big;
X{
X	register char *s,*b;
X	s = small;
X	b = big;
X	do
X	{
X		if(*s == '\0')
X			return(1);
X	}  while(*s++ == *b++);
X	return(0);
X}
X
X/*****************************************************************
X * smatch: Given a data string and a pattern containing one or
X * more embedded stars (*) (which match any number of characters)
X * return true if the match succeeds, and set res[i] to the
X * characters matched by the 'i'th *.
X *****************************************************************/
X
Xsmatch(dat,pat,res)
Xregister char *dat,*pat,**res;
X{
X	register char *star = 0,*starend,*resp;
X	int nres = 0;
X
X	while(1)
X	{
X		if(*pat == '*')
X		{
X			star = ++pat; 			     /* Pattern after * */
X			starend = dat; 			     /* Data after * match */
X			resp = res[nres++]; 		     /* Result string */
X			*resp = '\0'; 			     /* Initially null */
X		}
X		else if(*dat == *pat) 		     /* Characters match */
X		{
X			if(*pat == '\0') 		     /* Pattern matches */
X				return(1);
X			pat++; 				     /* Try next position */
X			dat++;
X		}
X		else
X		{
X			if(*dat == '\0') 		     /* Pattern fails - no more */
X				return(0); 			     /* data */
X			if(star == 0) 			     /* Pattern fails - no * to */
X				return(0); 			     /* adjust */
X			pat = star; 			     /* Restart pattern after * */
X			*resp++ = *starend; 		     /* Copy character to result */
X			*resp = '\0'; 			     /* null terminate */
X			dat = ++starend; 			     /* Rescan after copied char */
X		}
X	}
X}
X
X/*****************************************************************
X * Addendum: quit subroutine (print a message and exit)
X *****************************************************************/
X
Xquit(status,message)
Xint status;
Xchar *message;
X{
X	fprintf(stderr,message);
X	exit(status);
X}
X
X/*****************************************************************
X * Public Domain getopt routine
X *****************************************************************/
X
X/*
X * get option letter from argument vector
X */
Xint opterr = 1;		/* useless, never set or used */
Xint optind = 1;		/* index into parent argv vector */
Xint optopt;			/* character checked for validity */
Xchar *optarg;		/* argument associated with option */
X
X#define BADCH	(int)'?'
X#define EMSG	""
X#define tell(s)	fputs(*nargv,stderr);fputs(s,stderr); \
X		fputc(optopt,stderr);fputc('\n',stderr);return(BADCH);
X
Xgetopt(nargc,nargv,ostr)
Xint nargc;
Xchar **nargv,*ostr;
X{
X	static char *place = EMSG;	/* option letter processing */
X	register char *oli;		/* option letter list index */
X	char *strchr();
X
X	if(!*place)
X	{			/* update scanning pointer */
X		if(optind >= nargc || *(place = nargv[optind]) != '-' || !*++place)
X			return(EOF);
X		if(*place == '-')
X		{	/* found "--" */
X			++optind;
X			return(EOF);
X		}
X	}				/* option letter okay? */
X	if((optopt = (int)*place++) == (int)':' || !(oli = strchr(ostr,optopt)))
X	{
X		if(!*place) ++optind;
X		tell(": illegal option -- ");
X	}
X	if(*++oli != ':')
X	{		/* don't need argument */
X		optarg = (char *)0;
X		if(!*place) ++optind;
X	}
X	else 
X	{				/* need an argument */
X		if(*place) optarg = place;	/* no white space */
X		else if(nargc <= ++optind)
X		{	/* no arg */
X			place = EMSG;
X			tell(": option requires an argument -- ");
X		}
X		else optarg = nargv[optind];	/* white space */
X		place = EMSG;
X		++optind;
X	}
X	return(optopt);			/* dump back option letter */
X}
X/* vi: set tabstop=4 shiftwidth=4: */
SHAR_EOF
# ============= uushar.c ==============
echo "x - extracting uushar.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > uushar.c &&
X#include <stdio.h>
X#include <sys/types.h>
X#include <sys/stat.h>
X
X/* ENC is the basic 1 character encoding function to make a char printing */
X#define ENC(c) ((((c) & 077) + ' ') | ((c & 077) == 0 ? 0100 : 0))
X
Xencode (in, out)
X    FILE *in;
X    FILE *out;
X{
X    char  buf[80];
X    int  i, n;
X
X    for (;;)
X    {
X    /* 1 (up to) 45 character line */
X	n = fr (in, buf, 45);
X	putc (ENC (n), out);
X
X	for (i = 0; i < n; i += 3)
X	    outdec (&buf[i], out);
X
X	putc ('\n', out);
X	if (n <= 0)
X	    break;
X    }
X}
X
X/*
X * output one group of 3 bytes, pointed at by p, on file f.
X */
Xoutdec (p, f)
X    char *p;
X    FILE *f;
X{
X    int  c1, c2, c3, c4;
X
X    c1 = *p >> 2;
X    c2 = (*p << 4) & 060 | (p[1] >> 4) & 017;
X    c3 = (p[1] << 2) & 074 | (p[2] >> 6) & 03;
X    c4 = p[2] & 077;
X    putc (ENC (c1), f);
X    putc (ENC (c2), f);
X    putc (ENC (c3), f);
X    putc (ENC (c4), f);
X}
X
X/* fr: like read but stdio */
Xint
X     fr (fp, buf, cnt)
X    FILE *fp;
X    char *buf;
X    int  cnt;
X{
X    int  c, i;
X
X    for (i = 0; i < cnt; i++)
X    {
X	c = getc (fp);
X	if (c == EOF)
X	    return (i);
X	buf[i] = c;
X    }
X    return (cnt);
X}
X/* vi: set tabstop=4 shiftwidth=4: */
SHAR_EOF
# ============= who@where.c ==============
echo "x - extracting who@where.c (Text)"
sed 's/^X//' << 'SHAR_EOF' > who@where.c &&
X/*+-------------------------------------------------------------------------
X	who@where.c - find out who i am & where i am
X	...!gatech!kd4nc!n4hgf!wht (wht%n4hgf@gatech.edu)
X--------------------------------------------------------------------------*/
X/*+:EDITS:*/
X/*:04-03-1990-19:55-wht@n4hgf-get rid of complicated who_am_i */
X/*:04-01-1990-13:30-pat@rwing-use utsname.nodename instead of sysname */
X/*:04-02-1990-12:12-wht@n4hgf-sigh... some pwd.h dont declare functions */
X/*:03-29-1990-18:23-wht@n4hgf-add automatic sequent support */
X/*:03-28-1990-15:24-wht@n4hgf-creation */
X
X#include <stdio.h>
X#include <sys/types.h>
X#include <pwd.h>
X
X/* assume system v unless otherwise fixed */
X#if (defined(pyr) || defined(vax) || defined(sequent)) && !defined(BSD42) && !defined(SYS5)
X#define BSD42
X#endif
X#if defined(sun)	/* this miscreant doesn't exactly fit BSD or SYSV */
X#undef BSD42
X#undef SYS5
X#endif
X#if !defined(BSD42) && !defined(sun) && !defined(SYS5)
X#define SYS5
X#endif
X
X#if defined(sun) || defined(BSD42)
X#define strchr	index
X#define strrchr	rindex
X#endif
X
X#if !defined(SYS5) || defined(sun)
X#include <sys/time.h>
Xextern int errno;
X#else
X#include <sys/utsname.h>
X#include <time.h>
X#endif	/* system dependencies */
X
X/*+-------------------------------------------------------------------------
X	who_am_i() - get user name
X--------------------------------------------------------------------------*/
Xchar *
Xwho_am_i()
X{
X	struct passwd *getpwuid();
X	struct passwd *passwd;
X	passwd = getpwuid(getuid());
X	(void)endpwent();
X	if(passwd == (struct passwd *)0)
X		return("???");
X	return(passwd->pw_name);
X
X}	/* end of who_am_i */
X
X/*+-------------------------------------------------------------------------
X	where_am_i() - do uname, gethostname, or read file (/etc/systemid)
X--------------------------------------------------------------------------*/
Xchar *
Xwhere_am_i()
X{
X#if defined(M_SYS5)	/* SCO UNIX or XENIX */
XFILE *fpsid = fopen("/etc/systemid","r");
Xstatic char s20[20];
X	if(!fpsid)
X		return("???");
X	fgets(s20,sizeof(s20),fpsid);
X	fclose(fpsid);
X	s20[strlen(s20) - 1] = 0;
X	return(s20);
X#else /* M_SYS5 */
X#if defined(SYS5)
Xstatic struct utsname where_i_am;
X	uname(&where_i_am);
X	return(where_i_am.nodename);
X#else /* SYS5 */
Xstatic char where_i_am[64];
X	gethostname(where_i_am,sizeof(where_i_am));
X	return(where_i_am);
X#endif /* SYS5 */
X#endif /* M_SYS5 */
X}	/* end of where_am_i */
X
X/*+-------------------------------------------------------------------------
X	who_where(buf)
X--------------------------------------------------------------------------*/
Xchar *
Xwho_where(buf)
Xchar *buf;
X{
Xstatic char ww[64];
X
X	if(!buf)
X		buf = ww;
X	strcpy(buf,who_am_i());
X	strcat(buf,"@");
X	strcat(buf,where_am_i());
X}	/* end of who_where */
X
X/* vi: set tabstop=4 shiftwidth=4: */
X/* end of who@where.c */
SHAR_EOF
exit 0
 
--------------------------------------------------------------------
Warren Tucker, TuckerWare emory!n4hgf!wht or wht@n4hgf.Mt-Park.GA.US
Sforzando (It., sfohr-tsahn'-doh).   A direction to perform the tone
or chord with special stress, or marked and sudden emphasis.