+/* Copyright (c) 1983 Regents of the University of California */
+
+#ifndef lint
+static char sccsid[] = "@(#)cpio.c 4.1 (Berkeley) %G%";
+#endif not lint
+
+/* cpio COMPILE: cc -O cpio.c -s -i -o cpio
+ cpio -- copy file collections
+
+*/
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <signal.h>
+#ifdef RT
+#define S_IFEXT 0120000 /* allocated by extents */
+#define S_IF1EXT 0130000 /* one extent */
+#endif
+#define EQ(x,y) (strcmp(x,y)==0)
+/* for VAX, Interdata, ... */
+#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];}
+#define MAGIC 070707
+#define IN 1
+#define OUT 2
+#define PASS 3
+#define HDRSIZE ((sizeof Hdr)-256)
+#define LINKS 1000
+#define MERT 0
+#define CHARS 76
+#ifdef RT
+#define MERT 1 /* yes = 1 ; no = 0 */
+extern long filespace;
+#endif
+
+struct stat Statb, Xstatb;
+
+struct header {
+ short h_magic,
+ h_dev;
+ unsigned short h_ino,
+ h_mode,
+ h_uid,
+ h_gid;
+ short h_nlink,
+ h_rdev,
+ h_mtime[2],
+ h_namesize,
+ h_filesize[2];
+ char h_name[256];
+} Hdr;
+
+int Bufsize = 512;
+short Buf[256], *Dbuf;
+char BBuf[512];
+char *Cbuf;
+int Wct,Wc;
+short *Wp;
+char *Cp;
+#ifdef RT
+short Actual_size[2]; /* MERT variable */
+struct{
+ long long_size;
+};
+#endif
+
+short Option,
+ Dir,
+ Uncond,
+ Link,
+ Rename,
+ Toc,
+ Verbose,
+ Select,
+ Mod_time,
+ Acc_time,
+ Cflag,
+ Swap;
+
+int Ifile,
+ Ofile,
+ Input = 0,
+ Output = 1;
+long Blocks,
+ Longfile,
+ Longtime;
+
+char Fullname[256],
+ Name[256];
+int Pathend;
+
+FILE *Rtty,
+ *Wtty;
+
+char *Pattern[100];
+char Strhdr[500];
+char *Chdr = Strhdr;
+short Dev,
+ Uid,
+ Gid,
+ A_directory,
+ A_special,
+#ifdef RT
+ One_extent,
+ Multi_extent,
+#endif
+ Filetype = S_IFMT;
+#ifdef RT
+short Remove_mode = 0007777;
+short New_mode;
+#endif
+
+extern errno;
+char *malloc();
+char *cd();
+char *Cd_name;
+FILE *popen();
+
+union { long l; short s[2]; char c[4]; } U;
+
+/* for VAX, Interdata, ... */
+long mklong(v)
+short v[];
+{
+ U.l = 1;
+ if(U.c[0])
+ U.s[0] = v[1], U.s[1] = v[0];
+ else
+ U.s[0] = v[0], U.s[1] = v[1];
+ return U.l;
+}
+
+main(argc, argv)
+char **argv;
+{
+ register ct;
+ long filesz;
+ long lng;
+ register char *fullp;
+ register i;
+
+ signal(SIGSYS, 1);
+ if(*argv[1] != '-')
+ usage();
+ Uid = getuid();
+ umask(0);
+ Gid = getgid();
+ Pattern[0] = "*";
+
+ while(*++argv[1]) {
+ switch(*argv[1]) {
+ case 'a':
+ Acc_time++;
+ break;
+ case 'B':
+ Bufsize = 5120;
+ break;
+ case 'i':
+ Option = IN;
+ if(argc > 2 ) {
+ for(i = 0; (i+2) < argc; ++i)
+ Pattern[i] = argv[i+2];
+ }
+ break;
+ case 'o':
+ if(argc != 2)
+ usage();
+ Option = OUT;
+ break;
+ case 'p':
+ if(argc != 3)
+ usage();
+ if(access(argv[2], 2) == -1) {
+accerr:
+ err("cannot write in <%s>\n", argv[2]);
+ exit(2);
+ }
+ strcpy(Fullname, argv[2]);
+ strcat(Fullname, "/");
+ stat(Fullname, &Xstatb);
+ if((Xstatb.st_mode&S_IFMT) != S_IFDIR)
+ goto accerr;
+ Option = PASS;
+ Dev = Xstatb.st_dev;
+ break;
+ case 'c':
+ Cflag++;
+ break;
+ case 'd':
+ Dir++;
+ break;
+ case 'l':
+ Link++;
+ break;
+ case 'm':
+ Mod_time++;
+ break;
+ case 'r':
+ Rename++;
+ Rtty = fopen("/dev/tty", "r");
+ Wtty = fopen("/dev/tty", "w");
+ if(Rtty==NULL || Wtty==NULL) {
+ err(
+ "Cannot rename (/dev/tty missing)\n");
+ exit(2);
+ }
+ break;
+ case 's':
+ Swap++;
+ break;
+ case 't':
+ Toc++;
+ break;
+ case 'u':
+ Uncond++;
+ break;
+ case 'v':
+ Verbose++;
+ break;
+ case '6':
+ Filetype = 060000;
+ break;
+ default:
+ usage();
+ }
+ }
+ if(!Option) {
+ err("Options must include o|i|p\n");
+ exit(2);
+ }
+
+ if (Cflag && Swap) {
+ err("Swap flag is ignored with Cflag\n");
+ Swap = 0;
+ }
+
+ if(Option != PASS) {
+ Wp = Dbuf = (short *)malloc(Bufsize);
+ Cp = Cbuf = (char *)malloc(Bufsize);
+ }
+ Wct = Bufsize >> 1;
+ Wc = Bufsize;
+
+ if(Option == PASS && Rename) {
+ err("Pass and Rename cannot be used together");
+ exit(2);
+ }
+ switch(Option) {
+
+ case OUT:
+ while(getname()) {
+ if( mklong(Hdr.h_filesize) == 0L) {
+ if ( Cflag )
+ writehdr(Chdr,CHARS+Hdr.h_namesize);
+ else
+ bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);
+#ifdef RT
+ if( (MERT) && (((Hdr.h_mode & Filetype) == S_IF1EXT)
+ || ((Hdr.h_mode & Filetype) == S_IFEXT))) {
+ actsize();
+ bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);
+ }
+#endif
+ continue;
+ }
+ if((Ifile = open(Hdr.h_name, 0)) < 0) {
+ err("<%s> ?\n", Hdr.h_name);
+ continue;
+ }
+ if ( Cflag )
+ writehdr(Chdr,CHARS+Hdr.h_namesize);
+ else
+ bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);
+#ifdef RT
+ if( (MERT) && (((Hdr.h_mode & Filetype) == S_IF1EXT)
+ || ((Hdr.h_mode & Filetype) == S_IFEXT))) {
+ actsize();
+ bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);
+ }
+#endif
+ for(filesz=mklong(Hdr.h_filesize); filesz>0; filesz-= 512){
+ ct = filesz>512? 512: filesz;
+ if(read(Ifile, Cflag? BBuf: (char *)Buf, ct) < 0) {
+ err("Cannot read %s\n", Hdr.h_name);
+ continue;
+ }
+ Cflag? writehdr(BBuf,ct): bwrite(Buf,ct);
+ }
+ close(Ifile);
+ if(Acc_time)
+ utime(Hdr.h_name, &Statb.st_atime);
+ if(Verbose)
+ err("%s\n", Hdr.h_name);
+ }
+ strcpy(Hdr.h_name, "TRAILER!!!");
+ Hdr.h_magic = MAGIC;
+ MKSHORT(Hdr.h_filesize, 0L);
+ Hdr.h_namesize = strlen("TRAILER!!!") + 1;
+ if ( Cflag ) {
+ lng = 0;
+ bintochar(lng);
+ writehdr(Chdr,CHARS+Hdr.h_namesize);
+ }
+ else
+ bwrite(&Hdr, HDRSIZE+Hdr.h_namesize);
+ Cflag? writehdr(Cbuf, Bufsize): bwrite(Dbuf, Bufsize);
+ break;
+
+ case IN:
+ pwd();
+ while(gethdr()) {
+ Ofile = ckname(Hdr.h_name)? openout(Hdr.h_name): 0;
+ for(filesz=mklong(Hdr.h_filesize); filesz>0; filesz-= 512){
+ ct = filesz>512? 512: filesz;
+ Cflag? readhdr(BBuf, ct): bread(Buf, ct);
+ if(Ofile) {
+ if(Swap)
+ swap(Buf, ct);
+ if(write(Ofile, Cflag? BBuf: (char *)Buf, ct) < 0) {
+ err("Cannot write %s\n", Hdr.h_name);
+ continue;
+ }
+ }
+ }
+ if(Ofile) {
+ close(Ofile);
+ set_time(Cd_name, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime));
+ }
+ if(!Select)
+ continue;
+ if(Verbose)
+ if(Toc)
+ pentry(Hdr.h_name);
+ else
+ puts(Hdr.h_name);
+ else if(Toc)
+ puts(Hdr.h_name);
+ }
+ break;
+
+ case PASS:
+ fullp = Fullname + strlen(Fullname);
+
+ while(getname()) {
+ if(!ckname(Hdr.h_name))
+ continue;
+ strcpy(fullp, Hdr.h_name);
+
+ if(Link
+ && !A_directory
+ && Dev == Statb.st_dev) {
+/* ??? && (Uid == Statb.st_uid || !Uid)) {*/
+ if(link(Hdr.h_name, Fullname) < 0) { /* missing dir.? */
+ unlink(Fullname);
+ missdir(Fullname);
+ if(link(Hdr.h_name, Fullname) < 0) {
+ err(
+ "Cannot link <%s> & <%s>\n",
+ Hdr.h_name, Fullname);
+ continue;
+ }
+ }
+ set_time(Hdr.h_name, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime));
+ goto ckverbose;
+ }
+ if(!(Ofile = openout(Fullname)))
+ continue;
+ if((Ifile = open(Hdr.h_name, 0)) < 0) {
+ err("<%s> ?\n", Hdr.h_name);
+ close(Ofile);
+ continue;
+ }
+ filesz = Statb.st_size;
+ for(; filesz > 0; filesz -= 512) {
+ ct = filesz>512? 512: filesz;
+ if(read(Ifile, Buf, ct) < 0) {
+ err("Cannot read %s\n", Hdr.h_name);
+ break;
+ }
+ if(Ofile)
+ if(write(Ofile, Buf, ct) < 0) {
+ err("Cannot write %s\n", Hdr.h_name);
+ break;
+ }
+ ++Blocks;
+ }
+ close(Ifile);
+ if(Acc_time)
+ utime(Hdr.h_name, &Statb.st_atime);
+ if(Ofile) {
+ close(Ofile);
+ set_time(Fullname, Statb.st_atime, mklong(Hdr.h_mtime));
+ckverbose:
+ if(Verbose)
+ puts(Fullname);
+ }
+ }
+ }
+ err("%ld blocks\n", Blocks * (Bufsize>>9));
+ exit(0);
+}
+usage()
+{
+ err("Usage: cpio -o[acvB] <name-list >collection\n%s\n%s\n",
+ " cpio -i[cdmrstuvB6] [pattern ...] <collection",
+ " cpio -p[adlmruv] directory <name-list");
+ exit(2);
+}
+
+getname()
+{
+ register char *namep = Name;
+ long tlong;
+
+ for(;;) {
+ if(gets(namep) == NULL)
+ return 0;
+ if(*namep == '.' && namep[1] == '/')
+ namep += 2;
+ strcpy(Hdr.h_name, namep);
+ if(stat(namep, &Statb) < 0) {
+ err("< %s > ?\n", Hdr.h_name);
+ continue;
+ }
+ A_directory = (Statb.st_mode & Filetype) == S_IFDIR;
+ A_special = ((Statb.st_mode & Filetype) == S_IFBLK)
+ || ((Statb.st_mode & Filetype) == S_IFCHR);
+#ifdef RT
+ if(MERT) {
+ One_extent = (Statb.st_mode & Filetype) == S_IF1EXT;
+ Multi_extent = (Statb.st_mode & Filetype) == S_IFEXT;
+ }
+#endif
+ Hdr.h_magic = MAGIC;
+ Hdr.h_namesize = strlen(Hdr.h_name) + 1;
+ Hdr.h_uid = Statb.st_uid;
+ Hdr.h_gid = Statb.st_gid;
+ Hdr.h_dev = Statb.st_dev;
+ Hdr.h_ino = Statb.st_ino;
+ Hdr.h_mode = Statb.st_mode;
+ MKSHORT(Hdr.h_mtime, Statb.st_mtime);
+ Hdr.h_nlink = Statb.st_nlink;
+ tlong = Hdr.h_mode & S_IFREG? Statb.st_size: 0L;
+ MKSHORT(Hdr.h_filesize, tlong);
+ Hdr.h_rdev = Statb.st_rdev;
+ if(Cflag)
+ bintochar(tlong);
+ return 1;
+ }
+}
+
+bintochar(t)
+long t;
+{
+ sprintf(Chdr,"%.6o%.6ho%.6ho%.6ho%.6ho%.6ho%.6ho%.6ho%.11lo%.6ho%.11lo%s",
+ MAGIC,Statb.st_dev,Statb.st_ino,Statb.st_mode,Statb.st_uid,
+ Statb.st_gid,Statb.st_nlink,Statb.st_rdev & 00000177777,
+ Statb.st_mtime,(short)strlen(Hdr.h_name)+1,t,Hdr.h_name);
+}
+
+chartobin()
+{
+ sscanf(Chdr,"%6o%6ho%6ho%6ho%6ho%6ho%6ho%6ho%11lo%6ho%11lo",
+ &Hdr.h_magic,&Hdr.h_dev,&Hdr.h_ino,&Hdr.h_mode,&Hdr.h_uid,
+ &Hdr.h_gid,&Hdr.h_nlink,&Hdr.h_rdev,&Longtime,&Hdr.h_namesize,
+ &Longfile);
+ MKSHORT(Hdr.h_filesize, Longfile);
+ MKSHORT(Hdr.h_mtime, Longtime);
+}
+
+gethdr()
+{
+
+ if ( Cflag ) {
+ readhdr(Chdr,CHARS);
+ chartobin();
+ }
+ else
+ bread(&Hdr, HDRSIZE);
+
+ if(Hdr.h_magic != MAGIC) {
+ err("Out of phase--get help");
+ exit(2);
+ }
+ if(!Cflag)
+ bread(Hdr.h_name, Hdr.h_namesize);
+ else
+ readhdr(Hdr.h_name, Hdr.h_namesize);
+ if(Swap)
+ swap(Hdr.h_name, Hdr.h_namesize);
+ if(EQ(Hdr.h_name, "TRAILER!!!"))
+ return 0;
+ A_directory = (Hdr.h_mode & Filetype) == S_IFDIR;
+ A_special =((Hdr.h_mode & Filetype) == S_IFBLK)
+ || ((Hdr.h_mode & Filetype) == S_IFCHR);
+#ifdef RT
+ if( (MERT) && (((Hdr.h_mode & Filetype) == S_IF1EXT)
+ || ((Hdr.h_mode & Filetype) == S_IFEXT))) {
+ One_extent = (Hdr.h_mode & Filetype) == S_IF1EXT;
+ Multi_extent = (Hdr.h_mode & Filetype) == S_IFEXT;
+ Actual_size[0] = Hdr.h_filesize[0];
+ Actual_size[1] = Hdr.h_filesize[1];
+ bread(&Hdr, HDRSIZE);
+ if(Hdr.h_magic != MAGIC) {
+ err("Out of phase--get MERT help");
+ exit(2);
+ }
+ bread(Hdr.h_name, Hdr.h_namesize);
+ }
+#endif
+ return 1;
+}
+
+ckname(namep)
+register char *namep;
+{
+ ++Select;
+ if(!nmatch(namep, Pattern)) {
+ Select = 0;
+ return 0;
+ }
+ if(Rename && !A_directory) {
+ fprintf(Wtty, "Rename <%s>\n", namep);
+ fflush(Wtty);
+ fgets(namep, 128, Rtty);
+ if(feof(Rtty))
+ exit(2);
+ namep[strlen(namep) - 1] = '\0';
+ if(EQ(namep, "")) {
+ printf("Skipped\n");
+ return 0;
+ }
+ }
+ return !Toc;
+}
+
+openout(namep)
+register char *namep;
+{
+ register f;
+ register char *np;
+
+ if(!strncmp(namep, "./", 2))
+ namep += 2;
+ np = namep;
+ if(Option == IN)
+ Cd_name = namep = cd(namep);
+ if(A_directory) {
+ if(!Dir
+ || Rename
+ || EQ(namep, ".")
+ || EQ(namep, "..")
+ || stat(namep, &Xstatb) == 0)
+ return 0;
+
+ if(!makdir(namep)) {
+ missdir(namep);
+ }
+ret:
+ chmod(namep, Hdr.h_mode);
+ if(Uid == 0)
+ chown(namep, Hdr.h_uid, Hdr.h_gid);
+ set_time(namep, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime));
+ return 0;
+ }
+ if(Hdr.h_nlink > 1)
+ if(!postml(namep, np))
+ return 0;
+ if(A_special) {
+s_again:
+ if(mknod(namep, Hdr.h_mode, Hdr.h_rdev) < 0) {
+ if(missdir(namep))
+ goto s_again;
+ err("Cannot mknod <%s>\n", namep);
+ return 0;
+ }
+ goto ret;
+ }
+ if(stat(namep, &Xstatb) == 0) {
+ if(Uncond && !(Xstatb.st_mode & S_IWRITE))
+ unlink(namep);
+ if(!Uncond && (mklong(Hdr.h_mtime) < Xstatb.st_mtime)) {
+ err("current <%s> newer\n", namep);
+ return 0;
+ }
+ }
+ if(Option == PASS
+ && Hdr.h_ino == Xstatb.st_ino
+ && Hdr.h_dev == Xstatb.st_dev) {
+ err("Attempt to pass file to self!\n");
+ exit(2);
+ }
+#ifdef RT
+one_again:
+ if(One_extent || Multi_extent) {
+ if((f = falloc(namep, Hdr.h_mode, Hdr.h_filesize[0].long_size)) < 0) {
+ if(missdir(namep))
+ goto one_again;
+ err("Cannot create <%s> (errno:%d)\n", namep, errno);
+ return 0;
+ }
+ if(filespace < Hdr.h_filesize[0].long_size){
+ err("Cannot create contiguous file <%s> proper size\n", namep);
+ err(" <%s> will be created as a regular file\n", namep);
+ if(unlink(Fullname) != 0)
+ err("<%s> not removed\n", namep);
+ New_mode = Hdr.h_mode & Remove_mode;
+ New_mode = New_mode | S_IFREG;
+once_again:
+ if((f = creat(namep, New_mode)) < 0){
+ if(missdir(namep))
+ goto once_again;
+ err("Cannot create <%s> (errno:%d)\n", namep, errno);
+ return (0);
+ }
+ }
+ }
+#endif
+#ifdef RT
+ if(MERT && (One_extent || Multi_extent))
+ goto skip_c;
+#endif
+c_again:
+ if((f = creat(namep, Hdr.h_mode)) < 0) {
+ if(missdir(namep))
+ goto c_again;
+ err("Cannot create <%s> (errno:%d)\n", namep, errno);
+ return 0;
+ }
+#ifdef RT
+skip_c:
+#endif
+ if(Uid == 0)
+ chown(namep, Hdr.h_uid, Hdr.h_gid);
+ return f;
+}
+
+bread(b, c)
+register c;
+register short *b;
+{
+ static nleft = 0;
+ static short *ip;
+ register short *p = ip;
+
+ c = (c+1)>>1;
+ while(c--) {
+ if(!nleft) {
+again:
+ if(read(Input, Dbuf, Bufsize)!=Bufsize) {
+ Input = chgreel(0, Input);
+ goto again;
+ }
+ nleft = Bufsize >> 1;
+ p = Dbuf;
+ ++Blocks;
+ }
+ *b++ = *p++;
+ --nleft;
+ }
+ ip = p;
+}
+
+readhdr(b, c)
+register c;
+register char *b;
+{
+ static nleft = 0;
+ static char *ip;
+ register char *p = ip;
+
+ while(c--) {
+ if(!nleft) {
+again:
+ if(read(Input, Cbuf, Bufsize) != Bufsize) {
+ Input = chgreel(0, Input);
+ goto again;
+ }
+ nleft = Bufsize;
+ p = Cbuf;
+ ++Blocks;
+ }
+ *b++ = *p++;
+ --nleft;
+ }
+ ip = p;
+}
+
+bwrite(rp, c)
+register short *rp;
+register c;
+{
+ register short *wp = Wp;
+
+ c = (c+1) >> 1;
+ while(c--) {
+ if(!Wct) {
+again:
+ if(write(Output, Dbuf, Bufsize)<0) {
+ Output = chgreel(1, Output);
+ goto again;
+ }
+ Wct = Bufsize >> 1;
+ wp = Dbuf;
+ ++Blocks;
+ }
+ *wp++ = *rp++;
+ --Wct;
+ }
+ Wp = wp;
+}
+writehdr(rp,c)
+register char *rp;
+register c;
+{
+ register char *cp = Cp;
+
+ while(c--) {
+ if(!Wc) {
+again:
+ if(write(Output,Cbuf,Bufsize)<0) {
+ Output = chgreel(1, Output);
+ goto again;
+ }
+ Wc = Bufsize;
+ cp = Cbuf;
+ ++Blocks;
+ }
+ *cp++ = *rp++;
+ --Wc;
+ }
+ Cp = cp;
+}
+
+
+postml(namep, np)
+register char *namep, *np;
+{
+ register i;
+ static struct ml {
+ short m_dev,
+ m_ino;
+ char m_name[2];
+ } *ml[LINKS];
+ static mlinks = 0;
+ char *mlp;
+
+ for(i = 0; i < mlinks; ++i) {
+ if(mlinks == LINKS) break;
+ if(ml[i]->m_ino==Hdr.h_ino &&
+ ml[i]->m_dev==Hdr.h_dev) {
+ if(Verbose)
+ printf("%s linked to %s\n", ml[i]->m_name,
+ np);
+ unlink(namep);
+ if(Option == IN) {
+ Fullname[Pathend] = '\0';
+ strcat(Fullname, ml[i]->m_name);
+ mlp = Fullname;
+ } else
+ mlp = ml[i]->m_name;
+l_again:
+ if(link(mlp, namep) < 0) {
+ if(missdir(np))
+ goto l_again;
+ err("Cannot link <%s>&<%s>.\n",
+ ml[i]->m_name, np);
+ }
+ set_time(namep, mklong(Hdr.h_mtime), mklong(Hdr.h_mtime));
+ return 0;
+ }
+ }
+ if(mlinks == LINKS
+ || !(ml[mlinks] = (struct ml *)malloc(strlen(np) + 2 + sizeof(struct ml)))) {
+ static int first=1;
+
+ if(first)
+ if(mlinks == LINKS)
+ err("Too many links\n");
+ else
+ err("No memory for links\n");
+ mlinks = LINKS;
+ first = 0;
+ return 1;
+ }
+ ml[mlinks]->m_dev = Hdr.h_dev;
+ ml[mlinks]->m_ino = Hdr.h_ino;
+ strcpy(ml[mlinks]->m_name, np);
+ ++mlinks;
+ return 1;
+}
+
+pentry(namep)
+register char *namep;
+{
+
+ register i;
+ static short lastid = -1;
+#include <pwd.h>
+ static struct passwd *pw;
+ struct passwd *getpwuid();
+ static char tbuf[32];
+
+ printf("%-7o", Hdr.h_mode & 0177777);
+ if(lastid == Hdr.h_uid)
+ printf("%-6s", pw->pw_name);
+ else {
+ setpwent();
+ if(pw = getpwuid(Hdr.h_uid)) {
+ printf("%-6s", pw->pw_name);
+ lastid = Hdr.h_uid;
+ } else {
+ printf("%-6d", Hdr.h_uid);
+ lastid = -1;
+ }
+ }
+ printf("%7ld ", mklong(Hdr.h_filesize));
+ U.l = mklong(Hdr.h_mtime);
+ strcpy(tbuf, ctime(&U.l));
+ tbuf[24] = '\0';
+ printf(" %s %s\n", &tbuf[4], namep);
+}
+
+nmatch(s, pat)
+char *s, **pat;
+{
+ if(EQ(*pat, "*"))
+ return 1;
+ while(*pat) {
+ if((**pat == '!' && !gmatch(s, *pat+1))
+ || gmatch(s, *pat))
+ return 1;
+ ++pat;
+ }
+ return 0;
+}
+gmatch(s, p)
+register char *s, *p;
+{
+ register int c;
+ register cc, ok, lc, scc;
+
+ scc = *s;
+ lc = 077777;
+ switch (c = *p) {
+
+ case '[':
+ ok = 0;
+ while (cc = *++p) {
+ switch (cc) {
+
+ case ']':
+ if (ok)
+ return(gmatch(++s, ++p));
+ else
+ return(0);
+
+ case '-':
+ ok |= (lc <= scc & scc <= (cc=p[1]));
+ }
+ if (scc==(lc=cc)) ok++;
+ }
+ return(0);
+
+ case '?':
+ caseq:
+ if(scc) return(gmatch(++s, ++p));
+ return(0);
+ case '*':
+ return(umatch(s, ++p));
+ case 0:
+ return(!scc);
+ }
+ if (c==scc) goto caseq;
+ return(0);
+}
+
+umatch(s, p)
+register char *s, *p;
+{
+ if(*p==0) return(1);
+ while(*s)
+ if (gmatch(s++,p)) return(1);
+ return(0);
+}
+
+makdir(namep)
+register char *namep;
+{
+ static status;
+ register pid;
+
+ if(pid = fork())
+ while(wait(&status) != pid);
+ else {
+ close(2);
+ execl("/bin/mkdir", "mkdir", namep, 0);
+ exit(2);
+ }
+ return ((status>>8) & 0377)? 0: 1;
+}
+
+swap(buf, ct)
+register ct;
+register union swp { short shortw; char charv[2]; } *buf;
+{
+ register char c;
+
+ ct = (ct + 1) >> 1;
+
+ while(ct--) {
+ c = buf->charv[0];
+ buf->charv[0] = buf->charv[1];
+ buf->charv[1] = c;
+ ++buf;
+ }
+}
+set_time(namep, atime, mtime)
+register *namep;
+long atime, mtime;
+{
+ static long timevec[2];
+
+ if(!Mod_time)
+ return;
+ timevec[0] = atime;
+ timevec[1] = mtime;
+ utime(namep, timevec);
+}
+chgreel(x, fl)
+{
+ register f;
+ char str[22];
+ FILE *devtty;
+ struct stat statb;
+
+ err("errno: %d, ", errno);
+ err("Can't %s\n", x? "write output": "read input");
+ fstat(fl, &statb);
+#ifdef RT
+ if(!MERT){
+ if((statb.st_mode&S_IFMT) != S_IFCHR)
+ exit(2);
+ }
+ else if((statb.st_mode & (S_IFBLK|S_IFREC))==0)
+ exit(2);
+#endif
+#ifndef RT
+ if((statb.st_mode&S_IFMT) != S_IFCHR)
+ exit(2);
+#endif
+again:
+ err("If you want to go on, type device/file name when ready\n");
+ devtty = fopen("/dev/tty", "r");
+ fgets(str, 20, devtty);
+ str[strlen(str) - 1] = '\0';
+ if(!*str)
+ exit(2);
+ close(fl);
+ if((f = open(str, x? 1: 0)) < 0) {
+ err("That didn't work");
+ fclose(devtty);
+ goto again;
+ }
+ return f;
+}
+missdir(namep)
+register char *namep;
+{
+ register char *np;
+ register ct = 0;
+
+ if(!Dir)
+ return 0;
+ for(np = namep; *np; ++np)
+ if(*np == '/') {
+ *np = '\0';
+ if(stat(namep, &Xstatb) == -1)
+ makdir(namep), ++ct;
+ *np = '/';
+ }
+ return ct;
+}
+err(a, b, c)
+{
+ fprintf(stderr, a, b, c);
+}
+pwd()
+{
+ FILE *dir;
+
+ dir = popen("pwd", "r");
+ fgets(Fullname, 256, dir);
+ if(pclose(dir))
+ exit(2);
+ Pathend = strlen(Fullname);
+ Fullname[Pathend - 1] = '/';
+}
+char * cd(n)
+register char *n;
+{
+ char *p_save = Name, *n_save = n, *p_end = 0;
+ register char *p = Name;
+ static char dotdot[]="../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../";
+ int slashes;
+
+ if(*n == '/') /* don't try to chdir on full pathnames */
+ return n;
+ for(; *p && *n == *p; ++p, ++n) { /* whatever part of strings == */
+ if(*p == '/')
+ p_save = p+1, n_save = n+1;
+ }
+
+ p = p_save;
+ *p++ = '\0';
+ for(slashes = 0; *p; ++p) { /* if prev is longer, chdir("..") */
+ if(*p == '/')
+ ++slashes;
+ }
+ p = p_save;
+ if(slashes) {
+ slashes = slashes * 3 - 1;
+ dotdot[slashes] = '\0';
+ chdir(dotdot);
+ dotdot[slashes] = '/';
+ }
+
+ n = n_save;
+ for(; *n; ++n, ++p) {
+ *p = *n;
+ if(*n == '/')
+ p_end = p+1, n_save = n+1;
+ }
+ *p = '\0';
+
+ if(p_end) {
+ *p_end = '\0';
+ if(chdir(p_save) == -1) {
+ if(!missdir(p_save)) {
+cd_err:
+ err("Cannot chdir (no `d' option)\n");
+ exit(2);
+ } else if(chdir(p_save) == -1)
+ goto cd_err;
+ }
+ } else
+ *p_save = '\0';
+ return n_save;
+}
+#ifdef RT
+actsize()
+{
+}
+#endif