date and time created 88/07/21 17:35:41 by marc
[unix-history] / usr / src / local / local.cmd / cpio.c
CommitLineData
530bfa14
KM
1/* Copyright (c) 1983 Regents of the University of California */
2
3#ifndef lint
02a268e3 4static char sccsid[] = "@(#)cpio.c 4.3 (Berkeley) %G%";
530bfa14
KM
5#endif not lint
6
7/* cpio COMPILE: cc -O cpio.c -s -i -o cpio
8 cpio -- copy file collections
9
10*/
11#include <stdio.h>
12#include <sys/types.h>
13#include <sys/stat.h>
14#include <signal.h>
15#ifdef RT
16#define S_IFEXT 0120000 /* allocated by extents */
17#define S_IF1EXT 0130000 /* one extent */
18#endif
19#define EQ(x,y) (strcmp(x,y)==0)
20/* for VAX, Interdata, ... */
21#define MKSHORT(v,lv) {U.l=1L;if(U.c[0]) U.l=lv,v[0]=U.s[1],v[1]=U.s[0]; else U.l=lv,v[0]=U.s[0],v[1]=U.s[1];}
22#define MAGIC 070707
23#define IN 1
24#define OUT 2
25#define PASS 3
26#define HDRSIZE ((sizeof Hdr)-256)
27#define LINKS 1000
28#define MERT 0
29#define CHARS 76
30#ifdef RT
31#define MERT 1 /* yes = 1 ; no = 0 */
32extern long filespace;
33#endif
34
35struct stat Statb, Xstatb;
36
37struct header {
38 short h_magic,
39 h_dev;
40 unsigned short h_ino,
41 h_mode,
42 h_uid,
43 h_gid;
44 short h_nlink,
45 h_rdev,
46 h_mtime[2],
47 h_namesize,
48 h_filesize[2];
49 char h_name[256];
50} Hdr;
51
52int Bufsize = 512;
53short Buf[256], *Dbuf;
54char BBuf[512];
55char *Cbuf;
56int Wct,Wc;
57short *Wp;
58char *Cp;
59#ifdef RT
60short Actual_size[2]; /* MERT variable */
61struct{
62 long long_size;
63};
64#endif
65
66short Option,
67 Dir,
68 Uncond,
69 Link,
70 Rename,
71 Toc,
72 Verbose,
73 Select,
74 Mod_time,
75 Acc_time,
76 Cflag,
77 Swap;
78
79int Ifile,
80 Ofile,
81 Input = 0,
82 Output = 1;
83long Blocks,
84 Longfile,
85 Longtime;
86
87char Fullname[256],
88 Name[256];
89int Pathend;
90
91FILE *Rtty,
92 *Wtty;
93
94char *Pattern[100];
95char Strhdr[500];
96char *Chdr = Strhdr;
97short Dev,
98 Uid,
99 Gid,
100 A_directory,
101 A_special,
102#ifdef RT
103 One_extent,
104 Multi_extent,
105#endif
106 Filetype = S_IFMT;
107#ifdef RT
108short Remove_mode = 0007777;
109short New_mode;
110#endif
111
112extern errno;
113char *malloc();
114char *cd();
115char *Cd_name;
116FILE *popen();
117
118union { long l; short s[2]; char c[4]; } U;
119
120/* for VAX, Interdata, ... */
121long mklong(v)
122short v[];
123{
124 U.l = 1;
125 if(U.c[0])
126 U.s[0] = v[1], U.s[1] = v[0];
127 else
128 U.s[0] = v[0], U.s[1] = v[1];
129 return U.l;
130}
131
132main(argc, argv)
133char **argv;
134{
135 register ct;
136 long filesz;
137 long lng;
138 register char *fullp;
139 register i;
140
141 signal(SIGSYS, 1);
142 if(*argv[1] != '-')
143 usage();
144 Uid = getuid();
145 umask(0);
146 Gid = getgid();
147 Pattern[0] = "*";
148
149 while(*++argv[1]) {
150 switch(*argv[1]) {
151 case 'a':
152 Acc_time++;
153 break;
154 case 'B':
155 Bufsize = 5120;
156 break;
157 case 'i':
158 Option = IN;
159 if(argc > 2 ) {
160 for(i = 0; (i+2) < argc; ++i)
161 Pattern[i] = argv[i+2];
162 }
163 break;
164 case 'o':
165 if(argc != 2)
166 usage();
167 Option = OUT;
168 break;
169 case 'p':
170 if(argc != 3)
171 usage();
172 if(access(argv[2], 2) == -1) {
173accerr:
174 err("cannot write in <%s>\n", argv[2]);
175 exit(2);
176 }
177 strcpy(Fullname, argv[2]);
178 strcat(Fullname, "/");
179 stat(Fullname, &Xstatb);
180 if((Xstatb.st_mode&S_IFMT) != S_IFDIR)
181 goto accerr;
182 Option = PASS;
183 Dev = Xstatb.st_dev;
184 break;
185 case 'c':
186 Cflag++;
187 break;
188 case 'd':
189 Dir++;
190 break;
191 case 'l':
192 Link++;
193 break;
194 case 'm':
195 Mod_time++;
196 break;
197 case 'r':
198 Rename++;
199 Rtty = fopen("/dev/tty", "r");
200 Wtty = fopen("/dev/tty", "w");
201 if(Rtty==NULL || Wtty==NULL) {
202 err(
203 "Cannot rename (/dev/tty missing)\n");
204 exit(2);
205 }
206 break;
207 case 's':
208 Swap++;
209 break;
210 case 't':
211 Toc++;
212 break;
213 case 'u':
214 Uncond++;
215 break;
216 case 'v':
217 Verbose++;
218 break;
219 case '6':
220 Filetype = 060000;
221 break;
222 default:
223 usage();
224 }
225 }
226 if(!Option) {
227 err("Options must include o|i|p\n");
228 exit(2);
229 }
230
231 if (Cflag && Swap) {
232 err("Swap flag is ignored with Cflag\n");
233 Swap = 0;
234 }
235
236 if(Option != PASS) {
237 Wp = Dbuf = (short *)malloc(Bufsize);
238 Cp = Cbuf = (char *)malloc(Bufsize);
239 }
240 Wct = Bufsize >> 1;
241 Wc = Bufsize;
242
243 if(Option == PASS && Rename) {
244 err("Pass and Rename cannot be used together");
245 exit(2);
246 }
247 switch(Option) {
248
249 case OUT:
250 while(getname()) {
251 if( mklong(Hdr.h_filesize) == 0L) {
252 if ( Cflag )
253 writehdr(Chdr,CHARS+Hdr.h_namesize);
254 else
255 bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);
256#ifdef RT
257 if( (MERT) && (((Hdr.h_mode & Filetype) == S_IF1EXT)
258 || ((Hdr.h_mode & Filetype) == S_IFEXT))) {
259 actsize();
260 bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);
261 }
262#endif
263 continue;
264 }
265 if((Ifile = open(Hdr.h_name, 0)) < 0) {
266 err("<%s> ?\n", Hdr.h_name);
267 continue;
268 }
269 if ( Cflag )
270 writehdr(Chdr,CHARS+Hdr.h_namesize);
271 else
272 bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);
273#ifdef RT
274 if( (MERT) && (((Hdr.h_mode & Filetype) == S_IF1EXT)
275 || ((Hdr.h_mode & Filetype) == S_IFEXT))) {
276 actsize();
277 bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);
278 }
279#endif
280 for(filesz=mklong(Hdr.h_filesize); filesz>0; filesz-= 512){
281 ct = filesz>512? 512: filesz;
282 if(read(Ifile, Cflag? BBuf: (char *)Buf, ct) < 0) {
283 err("Cannot read %s\n", Hdr.h_name);
284 continue;
285 }
286 Cflag? writehdr(BBuf,ct): bwrite(Buf,ct);
287 }
288 close(Ifile);
289 if(Acc_time)
290 utime(Hdr.h_name, &Statb.st_atime);
291 if(Verbose)
292 err("%s\n", Hdr.h_name);
293 }
294 strcpy(Hdr.h_name, "TRAILER!!!");
295 Hdr.h_magic = MAGIC;
296 MKSHORT(Hdr.h_filesize, 0L);
297 Hdr.h_namesize = strlen("TRAILER!!!") + 1;
298 if ( Cflag ) {
299 lng = 0;
300 bintochar(lng);
301 writehdr(Chdr,CHARS+Hdr.h_namesize);
302 }
303 else
304 bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);
305 Cflag? writehdr(Cbuf, Bufsize): bwrite(Dbuf, Bufsize);
306 break;
307
308 case IN:
309 pwd();
310 while(gethdr()) {
311 Ofile = ckname(Hdr.h_name)? openout(Hdr.h_name): 0;
312 for(filesz=mklong(Hdr.h_filesize); filesz>0; filesz-= 512){
313 ct = filesz>512? 512: filesz;
314 Cflag? readhdr(BBuf, ct): bread(Buf, ct);
315 if(Ofile) {
316 if(Swap)
317 swap(Buf, ct);
318 if(write(Ofile, Cflag? BBuf: (char *)Buf, ct) < 0) {
319 err("Cannot write %s\n", Hdr.h_name);
320 continue;
321 }
322 }
323 }
324 if(Ofile) {
325 close(Ofile);
326 set_time(Cd_name, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime));
327 }
328 if(!Select)
329 continue;
330 if(Verbose)
331 if(Toc)
332 pentry(Hdr.h_name);
333 else
334 puts(Hdr.h_name);
335 else if(Toc)
336 puts(Hdr.h_name);
337 }
338 break;
339
340 case PASS:
341 fullp = Fullname + strlen(Fullname);
342
343 while(getname()) {
344 if(!ckname(Hdr.h_name))
345 continue;
346 strcpy(fullp, Hdr.h_name);
347
348 if(Link
349 && !A_directory
350 && Dev == Statb.st_dev) {
351/* ??? && (Uid == Statb.st_uid || !Uid)) {*/
352 if(link(Hdr.h_name, Fullname) < 0) { /* missing dir.? */
353 unlink(Fullname);
354 missdir(Fullname);
355 if(link(Hdr.h_name, Fullname) < 0) {
356 err(
357 "Cannot link <%s> & <%s>\n",
358 Hdr.h_name, Fullname);
359 continue;
360 }
361 }
362 set_time(Hdr.h_name, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime));
363 goto ckverbose;
364 }
365 if(!(Ofile = openout(Fullname)))
366 continue;
367 if((Ifile = open(Hdr.h_name, 0)) < 0) {
368 err("<%s> ?\n", Hdr.h_name);
369 close(Ofile);
370 continue;
371 }
372 filesz = Statb.st_size;
373 for(; filesz > 0; filesz -= 512) {
374 ct = filesz>512? 512: filesz;
375 if(read(Ifile, Buf, ct) < 0) {
376 err("Cannot read %s\n", Hdr.h_name);
377 break;
378 }
379 if(Ofile)
380 if(write(Ofile, Buf, ct) < 0) {
381 err("Cannot write %s\n", Hdr.h_name);
382 break;
383 }
384 ++Blocks;
385 }
386 close(Ifile);
387 if(Acc_time)
388 utime(Hdr.h_name, &Statb.st_atime);
389 if(Ofile) {
390 close(Ofile);
391 set_time(Fullname, Statb.st_atime, mklong(Hdr.h_mtime));
392ckverbose:
393 if(Verbose)
394 puts(Fullname);
395 }
396 }
397 }
398 err("%ld blocks\n", Blocks * (Bufsize>>9));
399 exit(0);
400}
401usage()
402{
403 err("Usage: cpio -o[acvB] <name-list >collection\n%s\n%s\n",
404 " cpio -i[cdmrstuvB6] [pattern ...] <collection",
405 " cpio -p[adlmruv] directory <name-list");
406 exit(2);
407}
408
409getname()
410{
411 register char *namep = Name;
412 long tlong;
413
414 for(;;) {
415 if(gets(namep) == NULL)
416 return 0;
417 if(*namep == '.' && namep[1] == '/')
418 namep += 2;
419 strcpy(Hdr.h_name, namep);
420 if(stat(namep, &Statb) < 0) {
421 err("< %s > ?\n", Hdr.h_name);
422 continue;
423 }
424 A_directory = (Statb.st_mode & Filetype) == S_IFDIR;
425 A_special = ((Statb.st_mode & Filetype) == S_IFBLK)
426 || ((Statb.st_mode & Filetype) == S_IFCHR);
427#ifdef RT
428 if(MERT) {
429 One_extent = (Statb.st_mode & Filetype) == S_IF1EXT;
430 Multi_extent = (Statb.st_mode & Filetype) == S_IFEXT;
431 }
432#endif
433 Hdr.h_magic = MAGIC;
434 Hdr.h_namesize = strlen(Hdr.h_name) + 1;
435 Hdr.h_uid = Statb.st_uid;
436 Hdr.h_gid = Statb.st_gid;
437 Hdr.h_dev = Statb.st_dev;
438 Hdr.h_ino = Statb.st_ino;
439 Hdr.h_mode = Statb.st_mode;
440 MKSHORT(Hdr.h_mtime, Statb.st_mtime);
441 Hdr.h_nlink = Statb.st_nlink;
442 tlong = Hdr.h_mode & S_IFREG? Statb.st_size: 0L;
443 MKSHORT(Hdr.h_filesize, tlong);
444 Hdr.h_rdev = Statb.st_rdev;
445 if(Cflag)
446 bintochar(tlong);
447 return 1;
448 }
449}
450
451bintochar(t)
452long t;
453{
454 sprintf(Chdr,"%.6o%.6ho%.6ho%.6ho%.6ho%.6ho%.6ho%.6ho%.11lo%.6ho%.11lo%s",
455 MAGIC,Statb.st_dev,Statb.st_ino,Statb.st_mode,Statb.st_uid,
456 Statb.st_gid,Statb.st_nlink,Statb.st_rdev & 00000177777,
457 Statb.st_mtime,(short)strlen(Hdr.h_name)+1,t,Hdr.h_name);
458}
459
460chartobin()
461{
02a268e3 462 sscanf(Chdr,"%6ho%6ho%6ho%6ho%6ho%6ho%6ho%6ho%11lo%6ho%11lo",
530bfa14
KM
463 &Hdr.h_magic,&Hdr.h_dev,&Hdr.h_ino,&Hdr.h_mode,&Hdr.h_uid,
464 &Hdr.h_gid,&Hdr.h_nlink,&Hdr.h_rdev,&Longtime,&Hdr.h_namesize,
465 &Longfile);
466 MKSHORT(Hdr.h_filesize, Longfile);
467 MKSHORT(Hdr.h_mtime, Longtime);
468}
469
470gethdr()
471{
472
473 if ( Cflag ) {
474 readhdr(Chdr,CHARS);
475 chartobin();
476 }
477 else
478 bread(&Hdr, HDRSIZE);
479
480 if(Hdr.h_magic != MAGIC) {
81fbeb32 481 err("Out of phase--get help\n");
530bfa14
KM
482 exit(2);
483 }
484 if(!Cflag)
485 bread(Hdr.h_name, Hdr.h_namesize);
486 else
487 readhdr(Hdr.h_name, Hdr.h_namesize);
488 if(Swap)
489 swap(Hdr.h_name, Hdr.h_namesize);
490 if(EQ(Hdr.h_name, "TRAILER!!!"))
491 return 0;
492 A_directory = (Hdr.h_mode & Filetype) == S_IFDIR;
493 A_special =((Hdr.h_mode & Filetype) == S_IFBLK)
494 || ((Hdr.h_mode & Filetype) == S_IFCHR);
495#ifdef RT
496 if( (MERT) && (((Hdr.h_mode & Filetype) == S_IF1EXT)
497 || ((Hdr.h_mode & Filetype) == S_IFEXT))) {
498 One_extent = (Hdr.h_mode & Filetype) == S_IF1EXT;
499 Multi_extent = (Hdr.h_mode & Filetype) == S_IFEXT;
500 Actual_size[0] = Hdr.h_filesize[0];
501 Actual_size[1] = Hdr.h_filesize[1];
502 bread(&Hdr, HDRSIZE);
503 if(Hdr.h_magic != MAGIC) {
81fbeb32 504 err("Out of phase--get MERT help\n");
530bfa14
KM
505 exit(2);
506 }
507 bread(Hdr.h_name, Hdr.h_namesize);
508 }
509#endif
510 return 1;
511}
512
513ckname(namep)
514register char *namep;
515{
516 ++Select;
517 if(!nmatch(namep, Pattern)) {
518 Select = 0;
519 return 0;
520 }
521 if(Rename && !A_directory) {
522 fprintf(Wtty, "Rename <%s>\n", namep);
523 fflush(Wtty);
524 fgets(namep, 128, Rtty);
525 if(feof(Rtty))
526 exit(2);
527 namep[strlen(namep) - 1] = '\0';
528 if(EQ(namep, "")) {
529 printf("Skipped\n");
530 return 0;
531 }
532 }
533 return !Toc;
534}
535
536openout(namep)
537register char *namep;
538{
539 register f;
540 register char *np;
541
542 if(!strncmp(namep, "./", 2))
543 namep += 2;
544 np = namep;
545 if(Option == IN)
546 Cd_name = namep = cd(namep);
547 if(A_directory) {
548 if(!Dir
549 || Rename
550 || EQ(namep, ".")
551 || EQ(namep, "..")
552 || stat(namep, &Xstatb) == 0)
553 return 0;
554
555 if(!makdir(namep)) {
556 missdir(namep);
557 }
558ret:
559 chmod(namep, Hdr.h_mode);
560 if(Uid == 0)
561 chown(namep, Hdr.h_uid, Hdr.h_gid);
562 set_time(namep, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime));
563 return 0;
564 }
565 if(Hdr.h_nlink > 1)
566 if(!postml(namep, np))
567 return 0;
568 if(A_special) {
569s_again:
570 if(mknod(namep, Hdr.h_mode, Hdr.h_rdev) < 0) {
571 if(missdir(namep))
572 goto s_again;
573 err("Cannot mknod <%s>\n", namep);
574 return 0;
575 }
576 goto ret;
577 }
578 if(stat(namep, &Xstatb) == 0) {
579 if(Uncond && !(Xstatb.st_mode & S_IWRITE))
580 unlink(namep);
581 if(!Uncond && (mklong(Hdr.h_mtime) < Xstatb.st_mtime)) {
582 err("current <%s> newer\n", namep);
583 return 0;
584 }
585 }
586 if(Option == PASS
587 && Hdr.h_ino == Xstatb.st_ino
588 && Hdr.h_dev == Xstatb.st_dev) {
589 err("Attempt to pass file to self!\n");
590 exit(2);
591 }
592#ifdef RT
593one_again:
594 if(One_extent || Multi_extent) {
595 if((f = falloc(namep, Hdr.h_mode, Hdr.h_filesize[0].long_size)) < 0) {
596 if(missdir(namep))
597 goto one_again;
598 err("Cannot create <%s> (errno:%d)\n", namep, errno);
599 return 0;
600 }
601 if(filespace < Hdr.h_filesize[0].long_size){
602 err("Cannot create contiguous file <%s> proper size\n", namep);
603 err(" <%s> will be created as a regular file\n", namep);
604 if(unlink(Fullname) != 0)
605 err("<%s> not removed\n", namep);
606 New_mode = Hdr.h_mode & Remove_mode;
607 New_mode = New_mode | S_IFREG;
608once_again:
609 if((f = creat(namep, New_mode)) < 0){
610 if(missdir(namep))
611 goto once_again;
612 err("Cannot create <%s> (errno:%d)\n", namep, errno);
613 return (0);
614 }
615 }
616 }
617#endif
618#ifdef RT
619 if(MERT && (One_extent || Multi_extent))
620 goto skip_c;
621#endif
622c_again:
623 if((f = creat(namep, Hdr.h_mode)) < 0) {
624 if(missdir(namep))
625 goto c_again;
626 err("Cannot create <%s> (errno:%d)\n", namep, errno);
627 return 0;
628 }
629#ifdef RT
630skip_c:
631#endif
632 if(Uid == 0)
633 chown(namep, Hdr.h_uid, Hdr.h_gid);
634 return f;
635}
636
637bread(b, c)
638register c;
639register short *b;
640{
641 static nleft = 0;
642 static short *ip;
643 register short *p = ip;
644
645 c = (c+1)>>1;
646 while(c--) {
647 if(!nleft) {
648again:
649 if(read(Input, Dbuf, Bufsize)!=Bufsize) {
650 Input = chgreel(0, Input);
651 goto again;
652 }
653 nleft = Bufsize >> 1;
654 p = Dbuf;
655 ++Blocks;
656 }
657 *b++ = *p++;
658 --nleft;
659 }
660 ip = p;
661}
662
663readhdr(b, c)
664register c;
665register char *b;
666{
667 static nleft = 0;
668 static char *ip;
669 register char *p = ip;
670
671 while(c--) {
672 if(!nleft) {
673again:
674 if(read(Input, Cbuf, Bufsize) != Bufsize) {
675 Input = chgreel(0, Input);
676 goto again;
677 }
678 nleft = Bufsize;
679 p = Cbuf;
680 ++Blocks;
681 }
682 *b++ = *p++;
683 --nleft;
684 }
685 ip = p;
686}
687
688bwrite(rp, c)
689register short *rp;
690register c;
691{
692 register short *wp = Wp;
693
694 c = (c+1) >> 1;
695 while(c--) {
696 if(!Wct) {
697again:
698 if(write(Output, Dbuf, Bufsize)<0) {
699 Output = chgreel(1, Output);
700 goto again;
701 }
702 Wct = Bufsize >> 1;
703 wp = Dbuf;
704 ++Blocks;
705 }
706 *wp++ = *rp++;
707 --Wct;
708 }
709 Wp = wp;
710}
711writehdr(rp,c)
712register char *rp;
713register c;
714{
715 register char *cp = Cp;
716
717 while(c--) {
718 if(!Wc) {
719again:
720 if(write(Output,Cbuf,Bufsize)<0) {
721 Output = chgreel(1, Output);
722 goto again;
723 }
724 Wc = Bufsize;
725 cp = Cbuf;
726 ++Blocks;
727 }
728 *cp++ = *rp++;
729 --Wc;
730 }
731 Cp = cp;
732}
733
734
735postml(namep, np)
736register char *namep, *np;
737{
738 register i;
739 static struct ml {
740 short m_dev,
741 m_ino;
742 char m_name[2];
743 } *ml[LINKS];
744 static mlinks = 0;
745 char *mlp;
746
747 for(i = 0; i < mlinks; ++i) {
748 if(mlinks == LINKS) break;
749 if(ml[i]->m_ino==Hdr.h_ino &&
750 ml[i]->m_dev==Hdr.h_dev) {
751 if(Verbose)
752 printf("%s linked to %s\n", ml[i]->m_name,
753 np);
754 unlink(namep);
755 if(Option == IN) {
756 Fullname[Pathend] = '\0';
757 strcat(Fullname, ml[i]->m_name);
758 mlp = Fullname;
759 } else
760 mlp = ml[i]->m_name;
761l_again:
762 if(link(mlp, namep) < 0) {
763 if(missdir(np))
764 goto l_again;
765 err("Cannot link <%s>&<%s>.\n",
766 ml[i]->m_name, np);
767 }
768 set_time(namep, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime));
769 return 0;
770 }
771 }
772 if(mlinks == LINKS
773 || !(ml[mlinks] = (struct ml *)malloc(strlen(np) + 2 + sizeof(struct ml)))) {
774 static int first=1;
775
776 if(first)
777 if(mlinks == LINKS)
778 err("Too many links\n");
779 else
780 err("No memory for links\n");
781 mlinks = LINKS;
782 first = 0;
783 return 1;
784 }
785 ml[mlinks]->m_dev = Hdr.h_dev;
786 ml[mlinks]->m_ino = Hdr.h_ino;
787 strcpy(ml[mlinks]->m_name, np);
788 ++mlinks;
789 return 1;
790}
791
792pentry(namep)
793register char *namep;
794{
795
796 register i;
797 static short lastid = -1;
798#include <pwd.h>
799 static struct passwd *pw;
800 struct passwd *getpwuid();
801 static char tbuf[32];
802
803 printf("%-7o", Hdr.h_mode & 0177777);
804 if(lastid == Hdr.h_uid)
805 printf("%-6s", pw->pw_name);
806 else {
807 setpwent();
808 if(pw = getpwuid(Hdr.h_uid)) {
809 printf("%-6s", pw->pw_name);
810 lastid = Hdr.h_uid;
811 } else {
812 printf("%-6d", Hdr.h_uid);
813 lastid = -1;
814 }
815 }
816 printf("%7ld ", mklong(Hdr.h_filesize));
817 U.l = mklong(Hdr.h_mtime);
818 strcpy(tbuf, ctime(&U.l));
819 tbuf[24] = '\0';
820 printf(" %s %s\n", &tbuf[4], namep);
821}
822
823nmatch(s, pat)
824char *s, **pat;
825{
826 if(EQ(*pat, "*"))
827 return 1;
828 while(*pat) {
829 if((**pat == '!' && !gmatch(s, *pat+1))
830 || gmatch(s, *pat))
831 return 1;
832 ++pat;
833 }
834 return 0;
835}
836gmatch(s, p)
837register char *s, *p;
838{
839 register int c;
840 register cc, ok, lc, scc;
841
842 scc = *s;
843 lc = 077777;
844 switch (c = *p) {
845
846 case '[':
847 ok = 0;
848 while (cc = *++p) {
849 switch (cc) {
850
851 case ']':
852 if (ok)
853 return(gmatch(++s, ++p));
854 else
855 return(0);
856
857 case '-':
858 ok |= (lc <= scc & scc <= (cc=p[1]));
859 }
860 if (scc==(lc=cc)) ok++;
861 }
862 return(0);
863
864 case '?':
865 caseq:
866 if(scc) return(gmatch(++s, ++p));
867 return(0);
868 case '*':
869 return(umatch(s, ++p));
870 case 0:
871 return(!scc);
872 }
873 if (c==scc) goto caseq;
874 return(0);
875}
876
877umatch(s, p)
878register char *s, *p;
879{
880 if(*p==0) return(1);
881 while(*s)
882 if (gmatch(s++,p)) return(1);
883 return(0);
884}
885
886makdir(namep)
887register char *namep;
888{
889 static status;
890 register pid;
891
892 if(pid = fork())
893 while(wait(&status) != pid);
894 else {
895 close(2);
896 execl("/bin/mkdir", "mkdir", namep, 0);
897 exit(2);
898 }
899 return ((status>>8) & 0377)? 0: 1;
900}
901
902swap(buf, ct)
903register ct;
904register union swp { short shortw; char charv[2]; } *buf;
905{
906 register char c;
907
908 ct = (ct + 1) >> 1;
909
910 while(ct--) {
911 c = buf->charv[0];
912 buf->charv[0] = buf->charv[1];
913 buf->charv[1] = c;
914 ++buf;
915 }
916}
917set_time(namep, atime, mtime)
918register *namep;
919long atime, mtime;
920{
921 static long timevec[2];
922
923 if(!Mod_time)
924 return;
925 timevec[0] = atime;
926 timevec[1] = mtime;
927 utime(namep, timevec);
928}
929chgreel(x, fl)
930{
931 register f;
932 char str[22];
933 FILE *devtty;
934 struct stat statb;
935
936 err("errno: %d, ", errno);
937 err("Can't %s\n", x? "write output": "read input");
938 fstat(fl, &statb);
939#ifdef RT
940 if(!MERT){
941 if((statb.st_mode&S_IFMT) != S_IFCHR)
942 exit(2);
943 }
944 else if((statb.st_mode & (S_IFBLK|S_IFREC))==0)
945 exit(2);
946#endif
947#ifndef RT
948 if((statb.st_mode&S_IFMT) != S_IFCHR)
949 exit(2);
950#endif
951again:
952 err("If you want to go on, type device/file name when ready\n");
953 devtty = fopen("/dev/tty", "r");
954 fgets(str, 20, devtty);
955 str[strlen(str) - 1] = '\0';
956 if(!*str)
957 exit(2);
958 close(fl);
959 if((f = open(str, x? 1: 0)) < 0) {
960 err("That didn't work");
961 fclose(devtty);
962 goto again;
963 }
964 return f;
965}
966missdir(namep)
967register char *namep;
968{
969 register char *np;
970 register ct = 0;
971
972 if(!Dir)
973 return 0;
974 for(np = namep; *np; ++np)
975 if(*np == '/') {
976 *np = '\0';
977 if(stat(namep, &Xstatb) == -1)
978 makdir(namep), ++ct;
979 *np = '/';
980 }
981 return ct;
982}
983err(a, b, c)
984{
985 fprintf(stderr, a, b, c);
986}
987pwd()
988{
989 FILE *dir;
990
991 dir = popen("pwd", "r");
992 fgets(Fullname, 256, dir);
993 if(pclose(dir))
994 exit(2);
995 Pathend = strlen(Fullname);
996 Fullname[Pathend - 1] = '/';
997}
998char * cd(n)
999register char *n;
1000{
1001 char *p_save = Name, *n_save = n, *p_end = 0;
1002 register char *p = Name;
1003 static char dotdot[]="../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../";
1004 int slashes;
1005
1006 if(*n == '/') /* don't try to chdir on full pathnames */
1007 return n;
1008 for(; *p && *n == *p; ++p, ++n) { /* whatever part of strings == */
1009 if(*p == '/')
1010 p_save = p+1, n_save = n+1;
1011 }
1012
1013 p = p_save;
1014 *p++ = '\0';
1015 for(slashes = 0; *p; ++p) { /* if prev is longer, chdir("..") */
1016 if(*p == '/')
1017 ++slashes;
1018 }
1019 p = p_save;
1020 if(slashes) {
1021 slashes = slashes * 3 - 1;
1022 dotdot[slashes] = '\0';
1023 chdir(dotdot);
1024 dotdot[slashes] = '/';
1025 }
1026
1027 n = n_save;
1028 for(; *n; ++n, ++p) {
1029 *p = *n;
1030 if(*n == '/')
1031 p_end = p+1, n_save = n+1;
1032 }
1033 *p = '\0';
1034
1035 if(p_end) {
1036 *p_end = '\0';
1037 if(chdir(p_save) == -1) {
1038 if(!missdir(p_save)) {
1039cd_err:
1040 err("Cannot chdir (no `d' option)\n");
1041 exit(2);
1042 } else if(chdir(p_save) == -1)
1043 goto cd_err;
1044 }
1045 } else
1046 *p_save = '\0';
1047 return n_save;
1048}
1049#ifdef RT
1050actsize()
1051{
1052}
1053#endif