| 1 | # |
| 2 | |
| 3 | /* |
| 4 | * glob1 libs command arg ... |
| 5 | * |
| 6 | * Modified by: Bill Joy (UCB) Oct 1976 |
| 7 | * |
| 8 | * takes library name string from the shell |
| 9 | * allows patterns to match directory names, i.e. "/mnt/c*?/.q" |
| 10 | * knows about pascal object and forks px's |
| 11 | */ |
| 12 | |
| 13 | char usagestr[] "usage: glob2 libs command arg ..."; |
| 14 | |
| 15 | char shell[] "/bin/sh"; |
| 16 | char px[] "/bin/px"; |
| 17 | |
| 18 | #define PCXN 0404 |
| 19 | #define E2BIG 7 |
| 20 | #define ENOEXEC 8 |
| 21 | #define ENOENT 2 |
| 22 | |
| 23 | #define STRSIZ 522 |
| 24 | #define PTHSIZ 100 |
| 25 | |
| 26 | char *lib; |
| 27 | |
| 28 | char ab[STRSIZ]; |
| 29 | char *ava[200]; |
| 30 | char **av &ava[1]; |
| 31 | char *string ab; |
| 32 | int ncoll; |
| 33 | |
| 34 | char path[100]; |
| 35 | char *pathp path; |
| 36 | int globbed; |
| 37 | char *entp; |
| 38 | |
| 39 | int errno; |
| 40 | int stbuff[18]; |
| 41 | |
| 42 | main(argc, argv) |
| 43 | char *argv[]; |
| 44 | { |
| 45 | register char *cp1, *cp2, *cpl; |
| 46 | |
| 47 | if (argc < 4) |
| 48 | panic(usagestr); |
| 49 | argv++; |
| 50 | argc--; |
| 51 | lib = *argv++; |
| 52 | argc--; |
| 53 | *av++ = *argv++; |
| 54 | argc--; |
| 55 | while (argc) |
| 56 | { |
| 57 | collect(*argv++); |
| 58 | argc--; |
| 59 | } |
| 60 | if (ncoll==0) |
| 61 | panic("No match"); |
| 62 | cp1 = ava[1]; |
| 63 | while(*cp1 && *cp1 != '/') |
| 64 | cp1++; |
| 65 | if (*cp1 || getuid()) |
| 66 | execute(ava[1], &ava[1]); |
| 67 | if (!*cp1) |
| 68 | { |
| 69 | if (cpl = lib) |
| 70 | for(;;) |
| 71 | { |
| 72 | while ((*cpl & 0177) == ' ') |
| 73 | cpl++; |
| 74 | if (!*cpl) |
| 75 | break; |
| 76 | cp1 = path; |
| 77 | while (*cpl =& 0177) |
| 78 | if (*cpl == ' ') |
| 79 | break; |
| 80 | else if (cp1 >= &path[PTHSIZ-2]) |
| 81 | patherr(); |
| 82 | else |
| 83 | *cp1++ = *cpl++; |
| 84 | *cp1++ = '/'; |
| 85 | cp2 = ava[1]; |
| 86 | while(*cp1++ = *cp2++) |
| 87 | if (cp1 >= &path[PTHSIZ]) |
| 88 | patherr(); |
| 89 | execute(path, &ava[1]); |
| 90 | } |
| 91 | cp1 = path; |
| 92 | cp2 = "/usr/bin/"; |
| 93 | while(*cp1++ = *cp2++) |
| 94 | ; |
| 95 | cp1--; |
| 96 | cp2 = ava[1]; |
| 97 | while(*cp1++ = *cp2++) |
| 98 | if (cp1 >= &path[PTHSIZ]) |
| 99 | patherr(); |
| 100 | execute(path+4, &ava[1]); |
| 101 | execute(path, &ava[1]); |
| 102 | } |
| 103 | prs(ava[1]); |
| 104 | panic(": not found"); |
| 105 | } |
| 106 | |
| 107 | execute(afile, aarg) |
| 108 | char *afile; |
| 109 | char **aarg; |
| 110 | { |
| 111 | register char *file, **arg; |
| 112 | register i; |
| 113 | int w; |
| 114 | |
| 115 | arg = aarg; |
| 116 | file = afile; |
| 117 | execv(file, arg); |
| 118 | if (errno==ENOEXEC) { |
| 119 | arg[0] = file; |
| 120 | *--arg = shell; |
| 121 | i = open(file, 0); |
| 122 | if (i >= 0) { |
| 123 | if (read(i, &w, 2) == 2 && w == PCXN) |
| 124 | *arg = px; |
| 125 | close(i); |
| 126 | } |
| 127 | execv(*arg, arg); |
| 128 | prs("no "); |
| 129 | prs(*arg); |
| 130 | panic("!!"); |
| 131 | } else if (errno==E2BIG) |
| 132 | toolong(); |
| 133 | } |
| 134 | |
| 135 | collect(as) |
| 136 | { |
| 137 | char **oav; |
| 138 | |
| 139 | oav = av; |
| 140 | globbed = 0; |
| 141 | expand(as); |
| 142 | sort(oav); |
| 143 | } |
| 144 | |
| 145 | sort(oav) |
| 146 | char **oav; |
| 147 | { |
| 148 | register char **p1, **p2, **c; |
| 149 | |
| 150 | p1 = oav; |
| 151 | while (p1 < av-1) { |
| 152 | p2 = p1; |
| 153 | while(++p2 < av) { |
| 154 | if (compar(*p1, *p2) > 0) { |
| 155 | c = *p1; |
| 156 | *p1 = *p2; |
| 157 | *p2 = c; |
| 158 | } |
| 159 | } |
| 160 | p1++; |
| 161 | } |
| 162 | } |
| 163 | |
| 164 | expand(as) |
| 165 | char *as; |
| 166 | { |
| 167 | register char *cs; |
| 168 | char *spathp; |
| 169 | register int dirf; |
| 170 | static struct { |
| 171 | int ino; |
| 172 | char name[16]; |
| 173 | } entry; |
| 174 | |
| 175 | spathp = pathp; |
| 176 | cs = as; |
| 177 | while (*cs != '*' && *cs != '?' && *cs != '[') { |
| 178 | if (pathp >= &path[PTHSIZ]) |
| 179 | patherr(); |
| 180 | else if ((*pathp++ = *cs++) == 0) { |
| 181 | if (!globbed) |
| 182 | *av++ = cat(as, ""); |
| 183 | else if (stat(path, &stbuff) >= 0) { |
| 184 | *av++ = cat(path, ""); |
| 185 | ncoll++; |
| 186 | } |
| 187 | goto endit; |
| 188 | } |
| 189 | } |
| 190 | pathp = spathp; |
| 191 | cs--; |
| 192 | while (cs >= as && *cs != '/') |
| 193 | cs--; |
| 194 | while (as <= cs) |
| 195 | if (pathp >= &path[PTHSIZ]) |
| 196 | patherr(); |
| 197 | else |
| 198 | *pathp++ = *as++; |
| 199 | *pathp = 0; |
| 200 | dirf = open(path, 0); |
| 201 | if (dirf<0) |
| 202 | if (globbed) |
| 203 | goto endit; |
| 204 | else { |
| 205 | prs(path); |
| 206 | panic(": cannot open"); |
| 207 | } |
| 208 | globbed++; |
| 209 | cs++; |
| 210 | while (read(dirf, &entry, 16) == 16) { |
| 211 | if (entry.ino==0) |
| 212 | continue; |
| 213 | if (match(entry.name, cs)) { |
| 214 | *av++ = cat(path, entry.name); |
| 215 | ncoll++; |
| 216 | } |
| 217 | } |
| 218 | close(dirf); |
| 219 | endit: |
| 220 | pathp = spathp; |
| 221 | *pathp = 0; |
| 222 | } |
| 223 | |
| 224 | toolong() |
| 225 | { |
| 226 | panic("Arg list too long"); |
| 227 | } |
| 228 | |
| 229 | patherr() |
| 230 | { |
| 231 | prs("Path too long: "); |
| 232 | panic(path); |
| 233 | } |
| 234 | |
| 235 | match(s, p) |
| 236 | char *s, *p; |
| 237 | { |
| 238 | register c, sentp; |
| 239 | |
| 240 | if (*s == '.' && *p != '.') |
| 241 | return(0); |
| 242 | sentp = entp; |
| 243 | entp = s; |
| 244 | c = amatch(s, p); |
| 245 | entp = sentp; |
| 246 | return(c); |
| 247 | } |
| 248 | |
| 249 | amatch(as, ap) |
| 250 | char *as, *ap; |
| 251 | { |
| 252 | register char *s, *p; |
| 253 | register scc; |
| 254 | int c, cc, ok, lc; |
| 255 | char *spathp; |
| 256 | |
| 257 | s = as; |
| 258 | p = ap; |
| 259 | nextc: |
| 260 | if(scc = *s++ & 0177) |
| 261 | if ((scc =& 0177) == 0) |
| 262 | scc = 0200; |
| 263 | switch (c = *p++) { |
| 264 | case '[': |
| 265 | ok = 0; |
| 266 | lc = 077777; |
| 267 | while (cc = *p++) { |
| 268 | if (cc == ']') { |
| 269 | if (ok) |
| 270 | goto nextc; |
| 271 | else |
| 272 | return(0); |
| 273 | } else if (cc == '-') { |
| 274 | if (lc <= scc && scc <= *p++) |
| 275 | ok++; |
| 276 | } else |
| 277 | if (scc == (lc = cc)) |
| 278 | ok++; |
| 279 | } |
| 280 | panic("missing ]"); |
| 281 | case '*': |
| 282 | if(*p == '\0') |
| 283 | return(1); |
| 284 | else if (*p == '/') { |
| 285 | p++; |
| 286 | goto slash; |
| 287 | } |
| 288 | s--; |
| 289 | while(*s) |
| 290 | if (amatch(s, p)) |
| 291 | return(1); |
| 292 | else |
| 293 | s++; |
| 294 | return(0); |
| 295 | case '\0': |
| 296 | return(scc == '\0'); |
| 297 | default: |
| 298 | if (c == scc) |
| 299 | goto nextc; |
| 300 | else |
| 301 | return(0); |
| 302 | case '?': |
| 303 | if (scc != '\0') |
| 304 | goto nextc; |
| 305 | else |
| 306 | return(0); |
| 307 | case '/': |
| 308 | if (scc == '\0') { |
| 309 | slash: |
| 310 | s = entp; |
| 311 | spathp = pathp; |
| 312 | while (*pathp = *s++) |
| 313 | pathp++; |
| 314 | *pathp++ = '/'; |
| 315 | *pathp = 0; |
| 316 | if (stat(path, &stbuff) == 0) |
| 317 | if ((stbuff[2] & 060000) == 040000) |
| 318 | if (*p == 0) { |
| 319 | *av++ = cat(path, ""); |
| 320 | ncoll++; |
| 321 | } else |
| 322 | expand(p); |
| 323 | pathp = spathp; |
| 324 | *pathp = 0; |
| 325 | } |
| 326 | return(0); |
| 327 | } |
| 328 | } |
| 329 | |
| 330 | compar(as1, as2) |
| 331 | char *as1, *as2; |
| 332 | { |
| 333 | register char *s1, *s2; |
| 334 | |
| 335 | s1 = as1; |
| 336 | s2 = as2; |
| 337 | while (*s1++ == *s2) |
| 338 | if (*s2++ == 0) |
| 339 | return(0); |
| 340 | if (*--s1 == '/') |
| 341 | return(-1); |
| 342 | else if (*s2 == '/') |
| 343 | return(1); |
| 344 | else |
| 345 | return (*s1 - *s2); |
| 346 | } |
| 347 | |
| 348 | cat(as1, as2) |
| 349 | char *as1, *as2; |
| 350 | { |
| 351 | register char *s1, *s2; |
| 352 | |
| 353 | s2 = string; |
| 354 | s1 = as1; |
| 355 | while (*s2++ = (*s1++ & 0177)) |
| 356 | if (s2 >= &ab[STRSIZ]) |
| 357 | toolong(); |
| 358 | s1 = as2; |
| 359 | s2--; |
| 360 | while (*s2++ = *s1++) |
| 361 | if (s2 > &ab[STRSIZ]) |
| 362 | toolong(); |
| 363 | s1 = string; |
| 364 | string = s2; |
| 365 | return(s1); |
| 366 | } |
| 367 | |
| 368 | prs(str) |
| 369 | char *str; |
| 370 | { |
| 371 | register char *cp; |
| 372 | |
| 373 | cp = str; |
| 374 | while(*cp) |
| 375 | cp++; |
| 376 | write(2, str, cp-str); |
| 377 | } |
| 378 | |
| 379 | panic(str) |
| 380 | { |
| 381 | prs(str); |
| 382 | write(2, &"\n", 1); |
| 383 | exit(1); |
| 384 | } |