1 /****************************************************************
2 * unshar.c: Unpackage one or more shell archive files
3 *
4 * Description: unshar is a filter which removes the front part
5 * of a file and passes the rest to the 'sh' command.
6 * It understands phrases like "cut here", and also
7 * knows about shell comment characters and the Unix
8 * commands "echo", "cat", and "sed".
9 *
10 * HISTORY
11 * 27-July-88 Kim F. Storm (storm@texas.dk) Texas Instruments, Denmark
12 * Adapted to :unshar command in nn
13 * Added static to function declarations
14 * Removed all unused functions, i.e. not useful as stand-alone pgm.
15 * 29-Jan-85 Michael Mauldin (mlm) at Carnegie-Mellon University
16 * Created.
17 ****************************************************************/
18
19 #include "config.h"
20 #include "global.h"
21 #include "nn_term.h"
22
23 /* unshar.c */
24
25 static int stlmatch(char *big, char *small);
26 static int smatch(register char *dat, register char *pat, register char **res);
27
28 extern long ftell();
29
30
31 /*****************************************************************
32 * stlmatch -- match leftmost part of string
33 *
34 * Usage: i = stlmatch (big,small)
35 * int i;
36 * char *small, *big;
37 *
38 * Returns 1 iff initial characters of big match small exactly;
39 * else 0.
40 *
41 * HISTORY
42 * 18-May-82 Michael Mauldin (mlm) at Carnegie-Mellon University
43 * Ripped out of CMU lib for Rog-O-Matic portability
44 * 20-Nov-79 Steven Shafer (sas) at Carnegie-Mellon University
45 * Rewritten for VAX from Ken Greer's routine.
46 *
47 * Originally from klg (Ken Greer) on IUS/SUS UNIX
48 *****************************************************************/
49
50 static int
stlmatch(char * big,char * small)51 stlmatch(char *big, char *small)
52 {
53 register char *s, *b;
54 s = small;
55 b = big;
56 do {
57 if (*s == '\0')
58 return (1);
59 }
60 while (*s++ == *b++);
61 return (0);
62 }
63
64 /*****************************************************************
65 * smatch: Given a data string and a pattern containing one or
66 * more embedded stars (*) (which match any number of characters)
67 * return true if the match succeeds, and set res[i] to the
68 * characters matched by the 'i'th *.
69 *****************************************************************/
70
71 static int
smatch(register char * dat,register char * pat,register char ** res)72 smatch(register char *dat, register char *pat, register char **res)
73 {
74 register char *star = 0, *starend = 0, *resp = 0;
75 int nres = 0;
76
77 while (1) {
78 if (*pat == '*') {
79 star = ++pat; /* Pattern after * */
80 starend = dat; /* Data after * match */
81 resp = res[nres++]; /* Result string */
82 *resp = '\0'; /* Initially null */
83 } else if (*dat == *pat) { /* Characters match */
84 if (*pat == '\0') /* Pattern matches */
85 return (1);
86 pat++; /* Try next position */
87 dat++;
88 } else {
89 if (*dat == '\0') /* Pattern fails - no more */
90 return (0); /* data */
91 if (star == 0) /* Pattern fails - no * to */
92 return (0); /* adjust */
93 pat = star; /* Restart pattern after * */
94 *resp++ = *starend; /* Copy character to result */
95 *resp = '\0'; /* null terminate */
96 dat = ++starend; /* Rescan after copied char */
97 }
98 }
99 }
100
101 /****************************************************************
102 * position: position 'fil' at the start of the shell command
103 * portion of a shell archive file.
104 * Kim Storm: removed static variables
105 ****************************************************************/
106
107 int
unshar_position(FILE * fil)108 unshar_position(FILE * fil)
109 {
110 char buf[BUFSIZ];
111 long pos;
112
113 /* Results from star matcher */
114 char res1[BUFSIZ], res2[BUFSIZ], res3[BUFSIZ], res4[BUFSIZ];
115 char *result[4];
116
117 result[0] = res1, result[1] = res2, result[2] = res3, result[3] = res4;
118
119 /* rewind (fil); */
120
121 while (1) {
122 /* Record position of the start of this line */
123 pos = ftell(fil);
124
125 /* Read next line, fail if no more */
126 if (fgets(buf, BUFSIZ, fil) == NULL) {
127 msg("no shell commands in file");
128 return (0);
129 }
130 /* Bail out if we see C preprocessor commands or C comments */
131 if (stlmatch(buf, "#include") || stlmatch(buf, "# include") ||
132 stlmatch(buf, "#define") || stlmatch(buf, "# define") ||
133 stlmatch(buf, "#ifdef") || stlmatch(buf, "# ifdef") ||
134 stlmatch(buf, "#ifndef") || stlmatch(buf, "# ifndef") ||
135 stlmatch(buf, "/*")) {
136 msg("file looks like raw C code, not a shar file");
137 return (0);
138 }
139 /* Does this line start with a shell command or comment */
140 if (stlmatch(buf, "#") ||
141 stlmatch(buf, ":") ||
142 stlmatch(buf, "echo ") ||
143 stlmatch(buf, "sed ") ||
144 stlmatch(buf, "cat ")) {
145 fseek(fil, pos, 0);
146 return (1);
147 }
148 /* Does this line say "Cut here" */
149 if (smatch(buf, "*CUT*HERE*", result) ||
150 smatch(buf, "*cut*here*", result) ||
151 smatch(buf, "*TEAR*HERE*", result) ||
152 smatch(buf, "*tear*here*", result) ||
153 smatch(buf, "*CUT*CUT*", result) ||
154 smatch(buf, "*cut*cut*", result)) {
155 /* Read next line after "cut here", skipping blank lines */
156 while (1) {
157 pos = ftell(fil);
158
159 if (fgets(buf, BUFSIZ, fil) == NULL) {
160 msg("no shell commands after 'cut'");
161 return (0);
162 }
163 if (*buf != '\n')
164 break;
165 }
166
167 /*
168 * Win if line starts with a comment character of lower case
169 * letter
170 */
171 if (*buf == '#' ||
172 *buf == ':' ||
173 (('a' <= *buf) && ('z' >= *buf))) {
174 fseek(fil, pos, 0);
175 return (1);
176 }
177 /* Cut here message lied to us */
178 msg("invalid data after CUT line");
179 return (0);
180 }
181 }
182 }
183