Small 'fixes' to APE to make auto*hell a bit happier. Had to create a fork of ls to better emulate Unix ls: Auto*hell tries to use ls -L because some sort of symlink braindamage which obviously doesn't apply to Plan 9, allow that flag but ignore it. Auto hell does some weird tests comparing the arguments it gives to ls with the output of ls, cleanname() breaks those tests by rewriting parts of the path, so removed the calls to cleanname(). Auto*hell also often calls printf with a single argument and no formating, so I created a really dummy printf that just prints it's first argument. This patch is not of much value, but when trying to wade thru auto*hell land it removes lots of noise. Further patches might follow as I go thru the experience of trying to get a single auto*hell script to run, if I don't go mad first. Notes: Mon Feb 13 09:31:40 EST 2006 rsc I put in a shell script to simulate Unix ls better. I do not want to fork ls. I do not believe that cleanname needs to come out. I used to run ./configure scripts all the time without needing to touch ls. I'd like to at least see an example. Reference: /n/sources/patch/applied/ape-dumb-autohell-fixes Date: Sun Feb 12 22:48:36 CET 2006 Reviewed-by: rsc --- /rc/bin/ape/printf Thu Jan 1 00:00:00 1970 +++ /rc/bin/ape/printf Sun Feb 12 22:30:43 2006 @@ -0,0 +1,4 @@ +#!/bin/rc +# Some programs(auto*hell) use printf when +# they should use echo(1) +echo -n $1 --- /sys/src/ape/cmd/ls.c Thu Jan 1 00:00:00 1970 +++ /sys/src/ape/cmd/ls.c Sun Feb 12 22:30:55 2006 @@ -0,0 +1,305 @@ +#include +#include +#include +#include + +typedef struct NDir NDir; +struct NDir +{ + Dir *d; + char *prefix; +}; + +int errs = 0; +int dflag; +int lflag; +int mflag; +int nflag; +int pflag; +int qflag; +int Qflag; +int rflag; +int sflag; +int tflag; +int Tflag; +int uflag; +int Fflag; +int ndirbuf; +int ndir; +NDir* dirbuf; +int ls(char*, int); +int compar(NDir*, NDir*); +char* asciitime(long); +char* darwx(long); +void rwx(long, char*); +void growto(long); +void dowidths(Dir*); +void format(Dir*, char*); +void output(void); +ulong clk; +int swidth; /* max width of -s size */ +int qwidth; /* max width of -q version */ +int vwidth; /* max width of dev */ +int uwidth; /* max width of userid */ +int mwidth; /* max width of muid */ +int glwidth; /* max width of groupid and length */ +Biobuf bin; + +void +main(int argc, char *argv[]) +{ + int i; + + Binit(&bin, 1, OWRITE); + ARGBEGIN{ + case 'F': Fflag++; break; + case 'd': dflag++; break; + case 'l': lflag++; break; + case 'm': mflag++; break; + case 'n': nflag++; break; + case 'p': pflag++; break; + case 'q': qflag++; break; + case 'Q': Qflag++; break; + case 'r': rflag++; break; + case 's': sflag++; break; + case 't': tflag++; break; + case 'T': Tflag++; break; + case 'u': uflag++; break; + case 'L': break; /* We don't have symlinks, ignored to make auto*hell happy */ + default: fprint(2, "usage: ls [-dlmnpqrstuFQT] [file ...]\n"); + exits("usage"); + }ARGEND + + doquote = needsrcquote; + quotefmtinstall(); + fmtinstall('M', dirmodefmt); + + if(lflag) + clk = time(0); + if(argc == 0) + errs = ls(".", 0); + else for(i=0; iqid.type&QTDIR) && dflag==0){ + free(db); + output(); + fd = open(s, OREAD); + if(fd == -1) + goto error; + n = dirreadall(fd, &db); + if(n < 0) + goto error; + growto(ndir+n); + for(i=0; iname); + format(dirbuf[i].d, buf); + } else + format(dirbuf[i].d, dirbuf[i].d->name); + } + ndir = 0; + Bflush(&bin); +} + +void +dowidths(Dir *db) +{ + char buf[256]; + int n; + + if(sflag) { + n = sprint(buf, "%llud", (db->length+1023)/1024); + if(n > swidth) + swidth = n; + } + if(qflag) { + n = sprint(buf, "%lud", db->qid.vers); + if(n > qwidth) + qwidth = n; + } + if(mflag) { + n = snprint(buf, sizeof buf, "[%s]", db->muid); + if(n > mwidth) + mwidth = n; + } + if(lflag) { + n = sprint(buf, "%ud", db->dev); + if(n > vwidth) + vwidth = n; + n = strlen(db->uid); + if(n > uwidth) + uwidth = n; + n = sprint(buf, "%llud", db->length); + n += strlen(db->gid); + if(n > glwidth) + glwidth = n; + } +} + +char* +fileflag(Dir *db) +{ + if(Fflag == 0) + return ""; + if(QTDIR & db->qid.type) + return "/"; + if(0111 & db->mode) + return "*"; + return ""; +} + +void +format(Dir *db, char *name) +{ + int i; + + if(sflag) + Bprint(&bin, "%*llud ", + swidth, (db->length+1023)/1024); + if(mflag){ + Bprint(&bin, "[%s] ", db->muid); + for(i=2+strlen(db->muid); iqid.path, + qwidth, db->qid.vers, + db->qid.type); + if(Tflag) + Bprint(&bin, "%c ", (db->mode&DMTMP) ? 't' : '-'); + + if(lflag) + Bprint(&bin, + Qflag? "%M %C %*ud %*s %s %*llud %s %s\n" : "%M %C %*ud %*s %s %*llud %s %q\n", + db->mode, db->type, + vwidth, db->dev, + -uwidth, db->uid, + db->gid, + (int)(glwidth-strlen(db->gid)), db->length, + asciitime(uflag? db->atime : db->mtime), name); + else + Bprint(&bin, + Qflag? "%s%s\n" : "%q%s\n", + name, fileflag(db)); +} + +void +growto(long n) +{ + if(n <= ndirbuf) + return; + ndirbuf = n; + dirbuf=(NDir *)realloc(dirbuf, ndirbuf*sizeof(NDir)); + if(dirbuf == 0){ + fprint(2, "ls: malloc fail\n"); + exits("malloc fail"); + } +} + +int +compar(NDir *a, NDir *b) +{ + long i; + Dir *ad, *bd; + + ad = a->d; + bd = b->d; + + if(tflag){ + if(uflag) + i = bd->atime-ad->atime; + else + i = bd->mtime-ad->mtime; + }else{ + if(a->prefix && b->prefix){ + i = strcmp(a->prefix, b->prefix); + if(i == 0) + i = strcmp(ad->name, bd->name); + }else if(a->prefix){ + i = strcmp(a->prefix, bd->name); + if(i == 0) + i = 1; /* a is longer than b */ + }else if(b->prefix){ + i = strcmp(ad->name, b->prefix); + if(i == 0) + i = -1; /* b is longer than a */ + }else + i = strcmp(ad->name, bd->name); + } + if(i == 0) + i = (a