new utilities.

the .C files compile but are renamed to avoid building automatically.
This commit is contained in:
rsc 2003-11-23 18:04:47 +00:00
parent f08fdedcee
commit bc7cb1a15a
45 changed files with 16585 additions and 0 deletions

181
src/cmd/ascii.c Normal file
View File

@ -0,0 +1,181 @@
#include <u.h>
#include <libc.h>
#include <bio.h>
#define MAXBASE 36
void usage(void);
void put(int);
void putn(int, int);
void puttext(char *);
void putnum(char *);
int btoi(char *);
int value(int, int);
int isnum(char *);
char *str[256]={
"nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel",
"bs ", "ht ", "nl ", "vt ", "np ", "cr ", "so ", "si ",
"dle", "dc1", "dc2", "dc3", "dc4", "nak", "syn", "etb",
"can", "em ", "sub", "esc", "fs ", "gs ", "rs ", "us ",
"sp ", " ! ", " \" ", " # ", " $ ", " % ", " & ", " ' ",
" ( ", " ) ", " * ", " + ", " , ", " - ", " . ", " / ",
" 0 ", " 1 ", " 2 ", " 3 ", " 4 ", " 5 ", " 6 ", " 7 ",
" 8 ", " 9 ", " : ", " ; ", " < ", " = ", " > ", " ? ",
" @ ", " A ", " B ", " C ", " D ", " E ", " F ", " G ",
" H ", " I ", " J ", " K ", " L ", " M ", " N ", " O ",
" P ", " Q ", " R ", " S ", " T ", " U ", " V ", " W ",
" X ", " Y ", " Z ", " [ ", " \\ ", " ] ", " ^ ", " _ ",
" ` ", " a ", " b ", " c ", " d ", " e ", " f ", " g ",
" h ", " i ", " j ", " k ", " l ", " m ", " n ", " o ",
" p ", " q ", " r ", " s ", " t ", " u ", " v ", " w ",
" x ", " y ", " z ", " { ", " | ", " } ", " ~ ", "del",
"x80", "x81", "x82", "x83", "x84", "x85", "x86", "x87",
"x88", "x89", "x8a", "x8b", "x8c", "x8d", "x8e", "x8f",
"x90", "x91", "x92", "x93", "x94", "x95", "x96", "x97",
"x98", "x99", "x9a", "x9b", "x9c", "x9d", "x9e", "x9f",
"xa0", " ¡ ", " ¢ ", " £ ", " ¤ ", " ¥ ", " ¦ ", " § ",
" ¨ ", " © ", " ª ", " « ", " ¬ ", " ­ ", " ® ", " ¯ ",
" ° ", " ± ", " ² ", " ³ ", " ´ ", " µ ", "", " · ",
" ¸ ", " ¹ ", " º ", " » ", " ¼ ", " ½ ", " ¾ ", " ¿ ",
" À ", " Á ", " Â ", " Ã ", " Ä ", " Å ", " Æ ", " Ç ",
" È ", " É ", " Ê ", " Ë ", " Ì ", " Í ", " Î ", " Ï ",
" Ð ", " Ñ ", " Ò ", " Ó ", " Ô ", " Õ ", " Ö ", " × ",
" Ø ", " Ù ", " Ú ", " Û ", " Ü ", " Ý ", " Þ ", " ß ",
" à ", " á ", " â ", " ã ", " ä ", " å ", " æ ", " ç ",
" è ", " é ", " ê ", " ë ", " ì ", " í ", " î ", " ï ",
" ð ", " ñ ", " ò ", " ó ", " ô ", " õ ", " ö ", " ÷ ",
" ø ", " ù ", " ú ", " û ", " ü ", " ý ", " þ ", " ÿ "
};
char Ncol[]={
0,0,7,5,4,4,3,3,3,3,3,3,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,
};
int nchars=128;
int base=16;
int ncol;
int text=1;
int strip=0;
Biobuf bin;
void
main(int argc, char **argv)
{
int i;
Binit(&bin, 1, OWRITE);
ARGBEGIN{
case '8':
nchars=256; break;
case 'x':
base=16; break;
case 'o':
base=8; break;
case 'd':
base=10; break;
case 'b':
base=strtoul(EARGF(usage()), 0, 0);
if(base<2||base>MAXBASE)
usage();
break;
case 'n':
text=0; break;
case 't':
strip=1;
/* fall through */
case 'c':
text=2; break;
default:
usage();
}ARGEND
ncol=Ncol[base];
if(argc==0){
for(i=0;i<nchars;i++){
put(i);
if((i&7)==7)
Bprint(&bin, "|\n");
}
}else{
if(text==1)
text=isnum(argv[0]);
while(argc--)
if(text)
puttext(*argv++);
else
putnum(*argv++);
}
Bputc(&bin, '\n');
exits(0);
}
void
usage(void)
{
fprint(2, "usage: %s [-8] [-xod | -b8] [-ncst] [--] [text]\n", argv0);
exits("usage");
}
void
put(int i)
{
Bputc(&bin, '|');
putn(i, ncol);
Bprint(&bin, " %s", str[i]);
}
char dig[]="0123456789abcdefghijklmnopqrstuvwxyz";
void
putn(int n, int ndig)
{
if(ndig==0)
return;
putn(n/base, ndig-1);
Bputc(&bin, dig[n%base]);
}
void
puttext(char *s)
{
int n;
n=btoi(s)&0377;
if(strip)
Bputc(&bin, n);
else
Bprint(&bin, "%s\n", str[n]);
}
void
putnum(char *s)
{
while(*s){
putn(*s++&0377, ncol);
Bputc(&bin, '\n');
}
}
int
btoi(char *s)
{
int n;
n=0;
while(*s)
n=n*base+value(*s++, 0);
return(n);
}
int
value(int c, int f)
{
char *s;
for(s=dig; s<dig+base; s++)
if(*s==c)
return(s-dig);
if(f)
return(-1);
fprint(2, "%s: bad input char %c\n", argv0, c);
exits("bad");
return 0; /* to keep ken happy */
}
int
isnum(char *s)
{
while(*s)
if(value(*s++, 1)==-1)
return(0);
return(1);
}

41
src/cmd/basename.c Normal file
View File

@ -0,0 +1,41 @@
#include <u.h>
#include <libc.h>
void
main(int argc, char *argv[])
{
char *pr;
int n, dflag;
dflag = 0;
if(argc>1 && strcmp(argv[1], "-d") == 0){
--argc;
++argv;
dflag = 1;
}
if(argc < 2 || argc > 3){
fprint(2, "usage: basename [-d] string [suffix]\n");
exits("usage");
}
pr = utfrrune(argv[1], '/');
if(dflag){
if(pr){
*pr = 0;
print("%s\n", argv[1]);
exits(0);
}
print(".\n");
exits(0);
}
if(pr)
pr++;
else
pr = argv[1];
if(argc==3){
n = strlen(pr)-strlen(argv[2]);
if(n >= 0 && !strcmp(pr+n, argv[2]))
pr[n] = 0;
}
print("%s\n", pr);
exits(0);
}

313
src/cmd/cal.c Normal file
View File

@ -0,0 +1,313 @@
#include <u.h>
#include <libc.h>
#include <bio.h>
char dayw[] =
{
" S M Tu W Th F S"
};
char *smon[] =
{
"January", "February", "March", "April",
"May", "June", "July", "August",
"September", "October", "November", "December",
};
char mon[] =
{
0,
31, 29, 31, 30,
31, 30, 31, 31,
30, 31, 30, 31,
};
char string[432];
Biobuf bout;
void main(int argc, char *argv[]);
int number(char *str);
void pstr(char *str, int n);
void cal(int m, int y, char *p, int w);
int jan1(int yr);
int curmo(void);
int curyr(void);
void
main(int argc, char *argv[])
{
int y, i, j, m;
if(argc > 3) {
fprint(2, "usage: cal [month] [year]\n");
exits("usage");
}
Binit(&bout, 1, OWRITE);
/*
* no arg, print current month
*/
if(argc == 1) {
m = curmo();
y = curyr();
goto xshort;
}
/*
* one arg
* if looks like a month, print month
* else print year
*/
if(argc == 2) {
y = number(argv[1]);
if(y < 0)
y = -y;
if(y >= 1 && y <= 12) {
m = y;
y = curyr();
goto xshort;
}
goto xlong;
}
/*
* two arg, month and year
*/
m = number(argv[1]);
if(m < 0)
m = -m;
y = number(argv[2]);
goto xshort;
/*
* print out just month
*/
xshort:
if(m < 1 || m > 12)
goto badarg;
if(y < 1 || y > 9999)
goto badarg;
Bprint(&bout, " %s %ud\n", smon[m-1], y);
Bprint(&bout, "%s\n", dayw);
cal(m, y, string, 24);
for(i=0; i<6*24; i+=24)
pstr(string+i, 24);
exits(0);
/*
* print out complete year
*/
xlong:
y = number(argv[1]);
if(y<1 || y>9999)
goto badarg;
Bprint(&bout, "\n\n\n");
Bprint(&bout, " %ud\n", y);
Bprint(&bout, "\n");
for(i=0; i<12; i+=3) {
for(j=0; j<6*72; j++)
string[j] = '\0';
Bprint(&bout, " %.3s", smon[i]);
Bprint(&bout, " %.3s", smon[i+1]);
Bprint(&bout, " %.3s\n", smon[i+2]);
Bprint(&bout, "%s %s %s\n", dayw, dayw, dayw);
cal(i+1, y, string, 72);
cal(i+2, y, string+23, 72);
cal(i+3, y, string+46, 72);
for(j=0; j<6*72; j+=72)
pstr(string+j, 72);
}
Bprint(&bout, "\n\n\n");
exits(0);
badarg:
Bprint(&bout, "cal: bad argument\n");
}
struct
{
char* word;
int val;
} dict[] =
{
"jan", 1,
"january", 1,
"feb", 2,
"february", 2,
"mar", 3,
"march", 3,
"apr", 4,
"april", 4,
"may", 5,
"jun", 6,
"june", 6,
"jul", 7,
"july", 7,
"aug", 8,
"august", 8,
"sep", 9,
"sept", 9,
"september", 9,
"oct", 10,
"october", 10,
"nov", 11,
"november", 11,
"dec", 12,
"december", 12,
0
};
/*
* convert to a number.
* if its a dictionary word,
* return negative number
*/
int
number(char *str)
{
int n, c;
char *s;
for(n=0; s=dict[n].word; n++)
if(strcmp(s, str) == 0)
return -dict[n].val;
n = 0;
s = str;
while(c = *s++) {
if(c<'0' || c>'9')
return 0;
n = n*10 + c-'0';
}
return n;
}
void
pstr(char *str, int n)
{
int i;
char *s;
s = str;
i = n;
while(i--)
if(*s++ == '\0')
s[-1] = ' ';
i = n+1;
while(i--)
if(*--s != ' ')
break;
s[1] = '\0';
Bprint(&bout, "%s\n", str);
}
void
cal(int m, int y, char *p, int w)
{
int d, i;
char *s;
s = p;
d = jan1(y);
mon[2] = 29;
mon[9] = 30;
switch((jan1(y+1)+7-d)%7) {
/*
* non-leap year
*/
case 1:
mon[2] = 28;
break;
/*
* 1752
*/
default:
mon[9] = 19;
break;
/*
* leap year
*/
case 2:
;
}
for(i=1; i<m; i++)
d += mon[i];
d %= 7;
s += 3*d;
for(i=1; i<=mon[m]; i++) {
if(i==3 && mon[m]==19) {
i += 11;
mon[m] += 11;
}
if(i > 9)
*s = i/10+'0';
s++;
*s++ = i%10+'0';
s++;
if(++d == 7) {
d = 0;
s = p+w;
p = s;
}
}
}
/*
* return day of the week
* of jan 1 of given year
*/
int
jan1(int yr)
{
int y, d;
/*
* normal gregorian calendar
* one extra day per four years
*/
y = yr;
d = 4+y+(y+3)/4;
/*
* julian calendar
* regular gregorian
* less three days per 400
*/
if(y > 1800) {
d -= (y-1701)/100;
d += (y-1601)/400;
}
/*
* great calendar changeover instant
*/
if(y > 1752)
d += 3;
return d%7;
}
/*
* system dependent
* get current month and year
*/
int
curmo(void)
{
Tm *tm;
tm = localtime(time(0));
return tm->mon+1;
}
int
curyr(void)
{
Tm *tm;
tm = localtime(time(0));
return tm->year+1900;
}

195
src/cmd/calendar.c Normal file
View File

@ -0,0 +1,195 @@
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <regexp.h>
#include <ctype.h>
typedef struct Date Date;
struct Date {
Reprog *p; /* an RE to match this date */
Date *next; /* pointer to next in list */
};
enum{
Secondsperday = 24*60*60
};
Biobuf in;
int debug, matchyear;
Date *dates(Date**, Tm*);
void upper2lower(char*, char*, int);
void *alloc(unsigned int);
void
main(int argc, char *argv[])
{
int i, fd, ahead;
long now;
char *line;
Tm *tm;
Date *first, *last, *d;
char buf[1024];
ahead = 0;
ARGBEGIN{
case 'y':
matchyear = 1;
break;
case 'd':
debug = 1;
break;
case 'p':
ahead = atoi(ARGF());
break;
default:
fprint(2, "usage: calendar [-y] [-d] [files ...]\n");
exits("usage");
}ARGEND;
/* make a list of dates */
now = time(0);
tm = localtime(now);
last = nil;
first = dates(&last, tm);
now += Secondsperday;
tm = localtime(now);
dates(&last, tm);
if(tm->wday == 6){
now += Secondsperday;
tm = localtime(now);
dates(&last, tm);
}
if(tm->wday == 0){
now += Secondsperday;
tm = localtime(now);
dates(&last, tm);
}
if(ahead){
now = time(0);
now += ahead * Secondsperday;
tm = localtime(now);
dates(&last, tm);
}
for(i=0; i<argc || (i==0 && argc==0); i++){
if(i==0 && argc==0)
snprint(buf, sizeof(buf),
"/usr/%s/lib/calendar", getuser());
else
strcpy(buf, argv[i]);
fd = open(buf, OREAD);
if(fd<0 || Binit(&in, fd, OREAD)<0){
fprint(2, "calendar: can't open %s: %r\n", buf);
exits("open");
}
/* go through the file */
while(line = Brdline(&in, '\n')){
line[Blinelen(&in) - 1] = 0;
upper2lower(buf, line, sizeof buf);
for(d=first; d; d=d->next)
if(regexec(d->p, buf, 0, 0)){
print("%s\n", line);
break;
}
}
close(fd);
}
exits("");
}
char *months[] =
{
"january",
"february",
"march",
"april",
"may",
"june",
"july",
"august",
"september",
"october",
"november",
"december"
};
/*
* Generate two Date structures. First has month followed by day;
* second has day followed by month. Link them into list after
* last, and return the first.
*/
Date*
dates(Date **last, Tm *tm)
{
Date *first;
Date *nd;
char mo[128], buf[128];
if(utflen(months[tm->mon]) > 3)
snprint(mo, sizeof mo, "%3.3s(%s)?",
months[tm->mon], months[tm->mon]+3);
else
snprint(mo, sizeof mo, "%3.3s", months[tm->mon]);
if (matchyear)
snprint(buf, sizeof buf,
"(^| |\t)((%s( |\t)+)|(%d/))%d( |\t|$)(((%d|%d)( |\t|$))|[^0-9]|([0-9]+[^0-9 \t]))",
mo, tm->mon+1, tm->mday, tm->year+1900, tm->year%100);
else
snprint(buf, sizeof buf,
"(^| |\t)((%s( |\t)+)|(%d/))%d( |\t|$)",
mo, tm->mon+1, tm->mday);
if(debug)
print("%s\n", buf);
first = alloc(sizeof(Date));
if(*last)
(*last)->next = first;
first->p = regcomp(buf);
if (matchyear)
snprint(buf, sizeof buf,
"(^| |\t)%d( |\t)+(%s)( |\t|$)(((%d|%d)( |\t|$))|[^0-9]|([0-9]+[^0-9 \t]))",
tm->mday, mo, tm->year+1900, tm->year%100);
else
snprint(buf, sizeof buf,
"(^| |\t)%d( |\t)+(%s)( |\t|$)",
tm->mday, mo);
if(debug)
print("%s\n", buf);
nd = alloc(sizeof(Date));
nd->p = regcomp(buf);
nd->next = 0;
first->next = nd;
*last = nd;
return first;
}
/*
* Copy 'from' to 'to', converting to lower case
*/
void
upper2lower(char *to, char *from, int len)
{
while(--len>0 && *from!='\0')
*to++ = tolower(*from++);
*to = 0;
}
/*
* Call malloc and check for errors
*/
void*
alloc(unsigned int n)
{
void *p;
p = malloc(n);
if(p == 0){
fprint(2, "calendar: malloc failed: %r\n");
exits("malloc");
}
return p;
}

36
src/cmd/cat.c Normal file
View File

@ -0,0 +1,36 @@
#include <u.h>
#include <libc.h>
void
cat(int f, char *s)
{
char buf[8192];
long n;
while((n=read(f, buf, (long)sizeof buf))>0)
if(write(1, buf, n)!=n)
sysfatal("write error copying %s: %r", s);
if(n < 0)
sysfatal("error reading %s: %r", s);
}
void
main(int argc, char *argv[])
{
int f, i;
argv0 = "cat";
if(argc == 1)
cat(0, "<stdin>");
else for(i=1; i<argc; i++){
f = open(argv[i], OREAD);
if(f < 0)
sysfatal("can't open %s: %r", argv[i]);
else{
cat(f, argv[i]);
close(f);
}
}
exits(0);
}

44
src/cmd/cleanname.c Normal file
View File

@ -0,0 +1,44 @@
#include <u.h>
#include <libc.h>
void
main(int argc, char **argv)
{
char *dir;
char *name;
int i;
dir = nil;
ARGBEGIN{
case 'd':
if((dir=ARGF()) == nil)
goto Usage;
break;
default:
goto Usage;
}ARGEND;
if(argc < 1) {
Usage:
fprint(2, "usage: cleanname [-d pwd] name...\n");
exits("usage");
}
for(i=0; i<argc; i++) {
if(dir == nil || argv[i][0] == '/') {
cleanname(argv[i]);
print("%s\n", argv[i]);
} else {
name = malloc(strlen(argv[i])+1+strlen(dir)+1);
if(name == nil) {
fprint(2, "cleanname: out of memory\n");
exits("out of memory");
}
sprint(name, "%s/%s", dir, argv[i]);
cleanname(name);
print("%s\n", name);
free(name);
}
}
exits(0);
}

112
src/cmd/cmp.c Normal file
View File

@ -0,0 +1,112 @@
#include <u.h>
#include <libc.h>
#define BUF 65536
int sflag = 0;
int lflag = 0;
int Lflag = 0;
static void usage(void);
void
main(int argc, char *argv[])
{
int n, i;
uchar *p, *q;
uchar buf1[BUF], buf2[BUF];
int f1, f2;
vlong nc = 1, o, l = 1;
char *name1, *name2;
uchar *b1s, *b1e, *b2s, *b2e;
ARGBEGIN{
case 's': sflag = 1; break;
case 'l': lflag = 1; break;
case 'L': Lflag = 1; break;
default: usage();
}ARGEND
if(argc < 2)
usage();
if((f1 = open(name1 = *argv++, OREAD)) == -1){
if(!sflag) perror(name1);
exits("open");
}
if((f2 = open(name2 = *argv++, OREAD)) == -1){
if(!sflag) perror(name2);
exits("open");
}
if(*argv){
o = strtoll(*argv++, 0, 0);
if(seek(f1, o, 0) < 0){
if(!sflag) perror("cmp: seek by offset1");
exits("seek 1");
}
}
if(*argv){
o = strtoll(*argv++, 0, 0);
if(seek(f2, o, 0) < 0){
if(!sflag) perror("cmp: seek by offset2");
exits("seek 2");
}
}
if(*argv)
usage();
b1s = b1e = buf1;
b2s = b2e = buf2;
for(;;){
if(b1s >= b1e){
if(b1s >= &buf1[BUF])
b1s = buf1;
n = read(f1, b1s, &buf1[BUF] - b1s);
b1e = b1s + n;
}
if(b2s >= b2e){
if(b2s >= &buf2[BUF])
b2s = buf2;
n = read(f2, b2s, &buf2[BUF] - b2s);
b2e = b2s + n;
}
n = b2e - b2s;
if(n > b1e - b1s)
n = b1e - b1s;
if(n <= 0)
break;
if(memcmp((void *)b1s, (void *)b2s, n) != 0){
if(sflag)
exits("differ");
for(p = b1s, q = b2s, i = 0; i < n; p++, q++, i++) {
if(*p == '\n')
l++;
if(*p != *q){
if(!lflag){
print("%s %s differ: char %lld",
name1, name2, nc+i);
print(Lflag?" line %lld\n":"\n", l);
exits("differ");
}
print("%6lld 0x%.2x 0x%.2x\n", nc+i, *p, *q);
}
}
}
if(Lflag)
for(p = b1s; p < b1e;)
if(*p++ == '\n')
l++;
nc += n;
b1s += n;
b2s += n;
}
if(b1e - b1s == b2e - b2s)
exits((char *)0);
if(!sflag)
print("EOF on %s\n", (b1e - b1s > b2e - b2s)? name2 : name1);
exits("EOF");
}
static void
usage(void)
{
print("Usage: cmp [-lsL] file1 file2 [offset1 [offset2] ]\n");
exits("usage");
}

178
src/cmd/comm.c Normal file
View File

@ -0,0 +1,178 @@
#include <u.h>
#include <libc.h>
#include <bio.h>
#define LB 2048
int one;
int two;
int three;
char *ldr[3];
Biobuf *ib1;
Biobuf *ib2;
Biobuf *openfil(char*);
int rd(Biobuf*, char*);
void wr(char*, int);
void copy(Biobuf*, char*, int);
int compare(char*, char*);
void
main(int argc, char *argv[])
{
int l;
char lb1[LB],lb2[LB];
ldr[0] = "";
ldr[1] = "\t";
ldr[2] = "\t\t";
l = 2;
ARGBEGIN{
case '1':
if(!one) {
one = 1;
ldr[1][0] =
ldr[2][l--] = '\0';
}
break;
case '2':
if(!two) {
two = 1;
ldr[2][l--] = '\0';
}
break;
case '3':
three = 1;
break;
default:
goto Usage;
}ARGEND
if(argc < 2) {
Usage:
fprint(2, "usage: comm [-123] file1 file2\n");
exits("usage");
}
ib1 = openfil(argv[0]);
ib2 = openfil(argv[1]);
if(rd(ib1,lb1) < 0){
if(rd(ib2,lb2) < 0)
exits(0);
copy(ib2,lb2,2);
}
if(rd(ib2,lb2) < 0)
copy(ib1,lb1,1);
for(;;){
switch(compare(lb1,lb2)) {
case 0:
wr(lb1,3);
if(rd(ib1,lb1) < 0) {
if(rd(ib2,lb2) < 0)
exits(0);
copy(ib2,lb2,2);
}
if(rd(ib2,lb2) < 0)
copy(ib1,lb1,1);
continue;
case 1:
wr(lb1,1);
if(rd(ib1,lb1) < 0)
copy(ib2,lb2,2);
continue;
case 2:
wr(lb2,2);
if(rd(ib2,lb2) < 0)
copy(ib1,lb1,1);
continue;
}
}
exits(0);
}
int
rd(Biobuf *file, char *buf)
{
int i, c;
i = 0;
while((c = Bgetc(file)) != Beof) {
*buf = c;
if(c == '\n' || i > LB-2) {
*buf = '\0';
return 0;
}
i++;
buf++;
}
return -1;
}
void
wr(char *str, int n)
{
switch(n){
case 1:
if(one)
return;
break;
case 2:
if(two)
return;
break;
case 3:
if(three)
return;
}
print("%s%s\n", ldr[n-1],str);
}
void
copy(Biobuf *ibuf, char *lbuf, int n)
{
do
wr(lbuf,n);
while(rd(ibuf,lbuf) >= 0);
exits(0);
}
int
compare(char *a, char *b)
{
while(*a == *b){
if(*a == '\0')
return 0;
a++;
b++;
}
if(*a < *b)
return 1;
return 2;
}
Biobuf*
openfil(char *s)
{
Biobuf *b;
if(s[0]=='-' && s[1]==0)
s = "/fd/0";
b = Bopen(s, OREAD);
if(b)
return b;
fprint(2,"comm: cannot open %s: %r\n",s);
exits("open");
return 0; /* shut up ken */
}

30
src/cmd/date.c Normal file
View File

@ -0,0 +1,30 @@
#include <u.h>
#include <libc.h>
int uflg, nflg;
void
main(int argc, char *argv[])
{
ulong now;
ARGBEGIN{
case 'n': nflg = 1; break;
case 'u': uflg = 1; break;
default: fprint(2, "usage: date [-un] [seconds]\n"); exits("usage");
}ARGEND
if(argc == 1)
now = strtoul(*argv, 0, 0);
else
now = time(0);
if(nflg)
print("%ld\n", now);
else if(uflg)
print("%s", asctime(gmtime(now)));
else
print("%s", ctime(now));
exits(0);
}

2300
src/cmd/dc.c Normal file

File diff suppressed because it is too large Load Diff

660
src/cmd/dd.c Normal file
View File

@ -0,0 +1,660 @@
#include <u.h>
#include <libc.h>
#define BIG 2147483647
#define LCASE (1<<0)
#define UCASE (1<<1)
#define SWAB (1<<2)
#define NERR (1<<3)
#define SYNC (1<<4)
int cflag;
int fflag;
char *string;
char *ifile;
char *ofile;
char *ibuf;
char *obuf;
vlong skip;
vlong oseekn;
vlong iseekn;
vlong count;
long files = 1;
long ibs = 512;
long obs = 512;
long bs;
long cbs;
long ibc;
long obc;
long cbc;
long nifr;
long nipr;
long nofr;
long nopr;
long ntrunc;
int dotrunc = 1;
int ibf;
int obf;
char *op;
int nspace;
uchar etoa[256];
uchar atoe[256];
uchar atoibm[256];
void flsh(void);
int match(char *s);
vlong number(long big);
void cnull(int cc);
void null(int c);
void ascii(int cc);
void unblock(int cc);
void ebcdic(int cc);
void ibm(int cc);
void block(int cc);
void term(void);
void stats(void);
#define iskey(s) ((key[0] == '-') && (strcmp(key+1, s) == 0))
void
main(int argc, char *argv[])
{
void (*conv)(int);
char *ip;
char *key;
int a, c;
conv = null;
for(c=1; c<argc; c++) {
key = argv[c++];
if(c >= argc){
fprint(2, "dd: arg %s needs a value\n", key);
exits("arg");
}
string = argv[c];
if(iskey("ibs")) {
ibs = number(BIG);
continue;
}
if(iskey("obs")) {
obs = number(BIG);
continue;
}
if(iskey("cbs")) {
cbs = number(BIG);
continue;
}
if(iskey("bs")) {
bs = number(BIG);
continue;
}
if(iskey("if")) {
ifile = string;
continue;
}
if(iskey("of")) {
ofile = string;
continue;
}
if(iskey("trunc")) {
dotrunc = number(BIG);
continue;
}
if(iskey("skip")) {
skip = number(BIG);
continue;
}
if(iskey("seek") || iskey("oseek")) {
oseekn = number(BIG);
continue;
}
if(iskey("iseek")) {
iseekn = number(BIG);
continue;
}
if(iskey("count")) {
count = number(BIG);
continue;
}
if(iskey("files")) {
files = number(BIG);
continue;
}
if(iskey("conv")) {
cloop:
if(match(","))
goto cloop;
if(*string == '\0')
continue;
if(match("ebcdic")) {
conv = ebcdic;
goto cloop;
}
if(match("ibm")) {
conv = ibm;
goto cloop;
}
if(match("ascii")) {
conv = ascii;
goto cloop;
}
if(match("block")) {
conv = block;
goto cloop;
}
if(match("unblock")) {
conv = unblock;
goto cloop;
}
if(match("lcase")) {
cflag |= LCASE;
goto cloop;
}
if(match("ucase")) {
cflag |= UCASE;
goto cloop;
}
if(match("swab")) {
cflag |= SWAB;
goto cloop;
}
if(match("noerror")) {
cflag |= NERR;
goto cloop;
}
if(match("sync")) {
cflag |= SYNC;
goto cloop;
}
}
fprint(2, "dd: bad arg: %s\n", key);
exits("arg");
}
if(conv == null && cflag&(LCASE|UCASE))
conv = cnull;
if(ifile)
ibf = open(ifile, 0);
else
ibf = dup(0, -1);
if(ibf < 0) {
fprint(2, "dd: open %s: %r\n", ifile);
exits("open");
}
if(ofile){
if(dotrunc)
obf = create(ofile, 1, 0664);
else
obf = open(ofile, 1);
if(obf < 0) {
fprint(2, "dd: create %s: %r\n", ofile);
exits("create");
}
}else{
obf = dup(1, -1);
if(obf < 0) {
fprint(2, "dd: can't dup file descriptor: %s: %r\n", ofile);
exits("dup");
}
}
if(bs)
ibs = obs = bs;
if(ibs == obs && conv == null)
fflag++;
if(ibs == 0 || obs == 0) {
fprint(2, "dd: counts: cannot be zero\n");
exits("counts");
}
ibuf = sbrk(ibs);
if(fflag)
obuf = ibuf;
else
obuf = sbrk(obs);
sbrk(64); /* For good measure */
if(ibuf == (char *)-1 || obuf == (char *)-1) {
fprint(2, "dd: not enough memory: %r\n");
exits("memory");
}
ibc = 0;
obc = 0;
cbc = 0;
op = obuf;
/*
if(signal(SIGINT, SIG_IGN) != SIG_IGN)
signal(SIGINT, term);
*/
seek(obf, obs*oseekn, 1);
seek(ibf, ibs*iseekn, 1);
while(skip) {
read(ibf, ibuf, ibs);
skip--;
}
ip = 0;
loop:
if(ibc-- == 0) {
ibc = 0;
if(count==0 || nifr+nipr!=count) {
if(cflag&(NERR|SYNC))
for(ip=ibuf+ibs; ip>ibuf;)
*--ip = 0;
ibc = read(ibf, ibuf, ibs);
}
if(ibc == -1) {
perror("read");
if((cflag&NERR) == 0) {
flsh();
term();
}
ibc = 0;
for(c=0; c<ibs; c++)
if(ibuf[c] != 0)
ibc = c;
stats();
}
if(ibc == 0 && --files<=0) {
flsh();
term();
}
if(ibc != ibs) {
nipr++;
if(cflag&SYNC)
ibc = ibs;
} else
nifr++;
ip = ibuf;
c = (ibc>>1) & ~1;
if(cflag&SWAB && c)
do {
a = *ip++;
ip[-1] = *ip;
*ip++ = a;
} while(--c);
ip = ibuf;
if(fflag) {
obc = ibc;
flsh();
ibc = 0;
}
goto loop;
}
c = 0;
c |= *ip++;
c &= 0377;
(*conv)(c);
goto loop;
}
void
flsh(void)
{
int c;
if(obc) {
c = write(obf, obuf, obc);
if(c != obc) {
if(c > 0)
++nopr;
perror("write");
term();
}
if(obc == obs)
nofr++;
else
nopr++;
obc = 0;
}
}
int
match(char *s)
{
char *cs;
cs = string;
while(*cs++ == *s)
if(*s++ == '\0')
goto true;
if(*s != '\0')
return 0;
true:
cs--;
string = cs;
return 1;
}
vlong
number(long big)
{
char *cs;
vlong n;
cs = string;
n = 0;
while(*cs >= '0' && *cs <= '9')
n = n*10 + *cs++ - '0';
for(;;)
switch(*cs++) {
case 'k':
n *= 1024;
continue;
/* case 'w':
n *= sizeof(int);
continue;
*/
case 'b':
n *= 512;
continue;
/* case '*':*/
case 'x':
string = cs;
n *= number(BIG);
case '\0':
if(n>=big || n<0) {
fprint(2, "dd: argument %lld out of range\n", n);
exits("range");
}
return n;
}
/* never gets here */
}
void
cnull(int cc)
{
int c;
c = cc;
if((cflag&UCASE) && c>='a' && c<='z')
c += 'A'-'a';
if((cflag&LCASE) && c>='A' && c<='Z')
c += 'a'-'A';
null(c);
}
void
null(int c)
{
*op = c;
op++;
if(++obc >= obs) {
flsh();
op = obuf;
}
}
void
ascii(int cc)
{
int c;
c = etoa[cc];
if(cbs == 0) {
cnull(c);
return;
}
if(c == ' ') {
nspace++;
goto out;
}
while(nspace > 0) {
null(' ');
nspace--;
}
cnull(c);
out:
if(++cbc >= cbs) {
null('\n');
cbc = 0;
nspace = 0;
}
}
void
unblock(int cc)
{
int c;
c = cc & 0377;
if(cbs == 0) {
cnull(c);
return;
}
if(c == ' ') {
nspace++;
goto out;
}
while(nspace > 0) {
null(' ');
nspace--;
}
cnull(c);
out:
if(++cbc >= cbs) {
null('\n');
cbc = 0;
nspace = 0;
}
}
void
ebcdic(int cc)
{
int c;
c = cc;
if(cflag&UCASE && c>='a' && c<='z')
c += 'A'-'a';
if(cflag&LCASE && c>='A' && c<='Z')
c += 'a'-'A';
c = atoe[c];
if(cbs == 0) {
null(c);
return;
}
if(cc == '\n') {
while(cbc < cbs) {
null(atoe[' ']);
cbc++;
}
cbc = 0;
return;
}
if(cbc == cbs)
ntrunc++;
cbc++;
if(cbc <= cbs)
null(c);
}
void
ibm(int cc)
{
int c;
c = cc;
if(cflag&UCASE && c>='a' && c<='z')
c += 'A'-'a';
if(cflag&LCASE && c>='A' && c<='Z')
c += 'a'-'A';
c = atoibm[c] & 0377;
if(cbs == 0) {
null(c);
return;
}
if(cc == '\n') {
while(cbc < cbs) {
null(atoibm[' ']);
cbc++;
}
cbc = 0;
return;
}
if(cbc == cbs)
ntrunc++;
cbc++;
if(cbc <= cbs)
null(c);
}
void
block(int cc)
{
int c;
c = cc;
if(cflag&UCASE && c>='a' && c<='z')
c += 'A'-'a';
if(cflag&LCASE && c>='A' && c<='Z')
c += 'a'-'A';
c &= 0377;
if(cbs == 0) {
null(c);
return;
}
if(cc == '\n') {
while(cbc < cbs) {
null(' ');
cbc++;
}
cbc = 0;
return;
}
if(cbc == cbs)
ntrunc++;
cbc++;
if(cbc <= cbs)
null(c);
}
void
term(void)
{
stats();
exits(0);
}
void
stats(void)
{
fprint(2, "%lud+%lud records in\n", nifr, nipr);
fprint(2, "%lud+%lud records out\n", nofr, nopr);
if(ntrunc)
fprint(2, "%lud truncated records\n", ntrunc);
}
uchar etoa[] =
{
0000,0001,0002,0003,0234,0011,0206,0177,
0227,0215,0216,0013,0014,0015,0016,0017,
0020,0021,0022,0023,0235,0205,0010,0207,
0030,0031,0222,0217,0034,0035,0036,0037,
0200,0201,0202,0203,0204,0012,0027,0033,
0210,0211,0212,0213,0214,0005,0006,0007,
0220,0221,0026,0223,0224,0225,0226,0004,
0230,0231,0232,0233,0024,0025,0236,0032,
0040,0240,0241,0242,0243,0244,0245,0246,
0247,0250,0133,0056,0074,0050,0053,0041,
0046,0251,0252,0253,0254,0255,0256,0257,
0260,0261,0135,0044,0052,0051,0073,0136,
0055,0057,0262,0263,0264,0265,0266,0267,
0270,0271,0174,0054,0045,0137,0076,0077,
0272,0273,0274,0275,0276,0277,0300,0301,
0302,0140,0072,0043,0100,0047,0075,0042,
0303,0141,0142,0143,0144,0145,0146,0147,
0150,0151,0304,0305,0306,0307,0310,0311,
0312,0152,0153,0154,0155,0156,0157,0160,
0161,0162,0313,0314,0315,0316,0317,0320,
0321,0176,0163,0164,0165,0166,0167,0170,
0171,0172,0322,0323,0324,0325,0326,0327,
0330,0331,0332,0333,0334,0335,0336,0337,
0340,0341,0342,0343,0344,0345,0346,0347,
0173,0101,0102,0103,0104,0105,0106,0107,
0110,0111,0350,0351,0352,0353,0354,0355,
0175,0112,0113,0114,0115,0116,0117,0120,
0121,0122,0356,0357,0360,0361,0362,0363,
0134,0237,0123,0124,0125,0126,0127,0130,
0131,0132,0364,0365,0366,0367,0370,0371,
0060,0061,0062,0063,0064,0065,0066,0067,
0070,0071,0372,0373,0374,0375,0376,0377,
};
uchar atoe[] =
{
0000,0001,0002,0003,0067,0055,0056,0057,
0026,0005,0045,0013,0014,0015,0016,0017,
0020,0021,0022,0023,0074,0075,0062,0046,
0030,0031,0077,0047,0034,0035,0036,0037,
0100,0117,0177,0173,0133,0154,0120,0175,
0115,0135,0134,0116,0153,0140,0113,0141,
0360,0361,0362,0363,0364,0365,0366,0367,
0370,0371,0172,0136,0114,0176,0156,0157,
0174,0301,0302,0303,0304,0305,0306,0307,
0310,0311,0321,0322,0323,0324,0325,0326,
0327,0330,0331,0342,0343,0344,0345,0346,
0347,0350,0351,0112,0340,0132,0137,0155,
0171,0201,0202,0203,0204,0205,0206,0207,
0210,0211,0221,0222,0223,0224,0225,0226,
0227,0230,0231,0242,0243,0244,0245,0246,
0247,0250,0251,0300,0152,0320,0241,0007,
0040,0041,0042,0043,0044,0025,0006,0027,
0050,0051,0052,0053,0054,0011,0012,0033,
0060,0061,0032,0063,0064,0065,0066,0010,
0070,0071,0072,0073,0004,0024,0076,0341,
0101,0102,0103,0104,0105,0106,0107,0110,
0111,0121,0122,0123,0124,0125,0126,0127,
0130,0131,0142,0143,0144,0145,0146,0147,
0150,0151,0160,0161,0162,0163,0164,0165,
0166,0167,0170,0200,0212,0213,0214,0215,
0216,0217,0220,0232,0233,0234,0235,0236,
0237,0240,0252,0253,0254,0255,0256,0257,
0260,0261,0262,0263,0264,0265,0266,0267,
0270,0271,0272,0273,0274,0275,0276,0277,
0312,0313,0314,0315,0316,0317,0332,0333,
0334,0335,0336,0337,0352,0353,0354,0355,
0356,0357,0372,0373,0374,0375,0376,0377,
};
uchar atoibm[] =
{
0000,0001,0002,0003,0067,0055,0056,0057,
0026,0005,0045,0013,0014,0015,0016,0017,
0020,0021,0022,0023,0074,0075,0062,0046,
0030,0031,0077,0047,0034,0035,0036,0037,
0100,0132,0177,0173,0133,0154,0120,0175,
0115,0135,0134,0116,0153,0140,0113,0141,
0360,0361,0362,0363,0364,0365,0366,0367,
0370,0371,0172,0136,0114,0176,0156,0157,
0174,0301,0302,0303,0304,0305,0306,0307,
0310,0311,0321,0322,0323,0324,0325,0326,
0327,0330,0331,0342,0343,0344,0345,0346,
0347,0350,0351,0255,0340,0275,0137,0155,
0171,0201,0202,0203,0204,0205,0206,0207,
0210,0211,0221,0222,0223,0224,0225,0226,
0227,0230,0231,0242,0243,0244,0245,0246,
0247,0250,0251,0300,0117,0320,0241,0007,
0040,0041,0042,0043,0044,0025,0006,0027,
0050,0051,0052,0053,0054,0011,0012,0033,
0060,0061,0032,0063,0064,0065,0066,0010,
0070,0071,0072,0073,0004,0024,0076,0341,
0101,0102,0103,0104,0105,0106,0107,0110,
0111,0121,0122,0123,0124,0125,0126,0127,
0130,0131,0142,0143,0144,0145,0146,0147,
0150,0151,0160,0161,0162,0163,0164,0165,
0166,0167,0170,0200,0212,0213,0214,0215,
0216,0217,0220,0232,0233,0234,0235,0236,
0237,0240,0252,0253,0254,0255,0256,0257,
0260,0261,0262,0263,0264,0265,0266,0267,
0270,0271,0272,0273,0274,0275,0276,0277,
0312,0313,0314,0315,0316,0317,0332,0333,
0334,0335,0336,0337,0352,0353,0354,0355,
0356,0357,0372,0373,0374,0375,0376,0377,
};

969
src/cmd/deroff.c Normal file
View File

@ -0,0 +1,969 @@
#include <u.h>
#include <libc.h>
#include <bio.h>
/*
* Deroff command -- strip troff, eqn, and tbl sequences from
* a file. Has three flags argument, -w, to cause output one word per line
* rather than in the original format.
* -mm (or -ms) causes the corresponding macro's to be interpreted
* so that just sentences are output
* -ml also gets rid of lists.
* -i causes deroff to ignore .so and .nx commands.
* Deroff follows .so and .nx commands, removes contents of macro
* definitions, equations (both .EQ ... .EN and $...$),
* Tbl command sequences, and Troff backslash vconstructions.
*
* All input is through the C macro; the most recently read character is in c.
*/
/*
#define C ((c = Bgetrune(infile)) < 0?\
eof():\
((c == ldelim) && (filesp == files)?\
skeqn():\
(c == '\n'?\
(linect++,c):\
c)))
#define C1 ((c = Bgetrune(infile)) == Beof?\
eof():\
(c == '\n'?\
(linect++,c):\
c))
*/
/* lose those macros! */
#define C fC()
#define C1 fC1()
#define SKIP while(C != '\n')
#define SKIP1 while(C1 != '\n')
#define SKIP_TO_COM SKIP;\
SKIP;\
pc=c;\
while(C != '.' || pc != '\n' || C > 'Z')\
pc=c
#define YES 1
#define NO 0
#define MS 0
#define MM 1
#define ONE 1
#define TWO 2
#define NOCHAR -2
#define EXTENDED -1 /* All runes above 0x7F */
#define SPECIAL 0
#define APOS 1
#define PUNCT 2
#define DIGIT 3
#define LETTER 4
int linect = 0;
int wordflag= NO;
int underscoreflag = NO;
int msflag = NO;
int iflag = NO;
int mac = MM;
int disp = 0;
int inmacro = NO;
int intable = NO;
int eqnflag = 0;
#define MAX_ASCII 0X80
char chars[MAX_ASCII]; /* SPECIAL, PUNCT, APOS, DIGIT, or LETTER */
Rune line[30000];
Rune* lp;
long c;
long pc;
int ldelim = NOCHAR;
int rdelim = NOCHAR;
char** argv;
char fname[50];
Biobuf* files[15];
Biobuf**filesp;
Biobuf* infile;
char* devnull = "/dev/null";
Biobuf *infile;
Biobuf bout;
long skeqn(void);
Biobuf* opn(char *p);
int eof(void);
int charclass(int);
void getfname(void);
void fatal(char *s, char *p);
void usage(void);
void work(void);
void putmac(Rune *rp, int vconst);
void regline(int macline, int vconst);
void putwords(void);
void comline(void);
void macro(void);
void eqn(void);
void tbl(void);
void stbl(void);
void sdis(char a1, char a2);
void sce(void);
void backsl(void);
char* copys(char *s);
void refer(int c1);
void inpic(void);
int
fC(void)
{
c = Bgetrune(infile);
if(c < 0)
return eof();
if(c == ldelim && filesp == files)
return skeqn();
if(c == '\n')
linect++;
return c;
}
int
fC1(void)
{
c = Bgetrune(infile);
if(c == Beof)
return eof();
if(c == '\n')
linect++;
return c;
}
void
main(int argc, char *av[])
{
int i;
char *f;
argv = av;
Binit(&bout, 1, OWRITE);
ARGBEGIN{
case 'w':
wordflag = YES;
break;
case '_':
wordflag = YES;
underscoreflag = YES;
break;
case 'm':
msflag = YES;
if(f = ARGF())
switch(*f)
{
case 'm': mac = MM; break;
case 's': mac = MS; break;
case 'l': disp = 1; break;
default: usage();
}
else
usage();
break;
case 'i':
iflag = YES;
break;
default:
usage();
}ARGEND
if(*argv)
infile = opn(*argv++);
else{
infile = malloc(sizeof(Biobuf));
Binit(infile, 0, OREAD);
}
files[0] = infile;
filesp = &files[0];
for(i='a'; i<='z' ; ++i)
chars[i] = LETTER;
for(i='A'; i<='Z'; ++i)
chars[i] = LETTER;
for(i='0'; i<='9'; ++i)
chars[i] = DIGIT;
chars['\''] = APOS;
chars['&'] = APOS;
chars['\b'] = APOS;
chars['.'] = PUNCT;
chars[','] = PUNCT;
chars[';'] = PUNCT;
chars['?'] = PUNCT;
chars[':'] = PUNCT;
work();
}
long
skeqn(void)
{
while(C1 != rdelim)
if(c == '\\')
c = C1;
else if(c == '"')
while(C1 != '"')
if(c == '\\')
C1;
if (msflag)
eqnflag = 1;
return(c = ' ');
}
Biobuf*
opn(char *p)
{
Biobuf *fd;
while ((fd = Bopen(p, OREAD)) == 0) {
if(msflag || p == devnull)
fatal("Cannot open file %s - quitting\n", p);
else {
fprint(2, "Deroff: Cannot open file %s - continuing\n", p);
p = devnull;
}
}
linect = 0;
return(fd);
}
int
eof(void)
{
if(Bfildes(infile) != 0)
Bterm(infile);
if(filesp > files)
infile = *--filesp;
else
if(*argv)
infile = opn(*argv++);
else
exits(0);
return(C);
}
void
getfname(void)
{
char *p;
Rune r;
Dir *dir;
struct chain
{
struct chain* nextp;
char* datap;
} *q;
static struct chain *namechain= 0;
while(C == ' ')
;
for(p = fname; (r=c) != '\n' && r != ' ' && r != '\t' && r != '\\'; C)
p += runetochar(p, &r);
*p = '\0';
while(c != '\n')
C;
if(!strcmp(fname, "/sys/lib/tmac/tmac.cs")
|| !strcmp(fname, "/sys/lib/tmac/tmac.s")) {
fname[0] = '\0';
return;
}
dir = dirstat(fname);
if(dir!=nil && ((dir->mode & DMDIR) || dir->type != 'M')) {
free(dir);
fname[0] = '\0';
return;
}
free(dir);
/*
* see if this name has already been used
*/
for(q = namechain; q; q = q->nextp)
if( !strcmp(fname, q->datap)) {
fname[0] = '\0';
return;
}
q = (struct chain*)malloc(sizeof(struct chain));
q->nextp = namechain;
q->datap = copys(fname);
namechain = q;
}
void
usage(void)
{
fprint(2,"usage: deroff [-nw_pi] [-m (m s l)] [file ...] \n");
exits("usage");
}
void
fatal(char *s, char *p)
{
fprint(2, "deroff: ");
fprint(2, s, p);
exits(s);
}
void
work(void)
{
for(;;) {
eqnflag = 0;
if(C == '.' || c == '\'')
comline();
else
regline(NO, TWO);
}
}
void
regline(int macline, int vconst)
{
line[0] = c;
lp = line;
for(;;) {
if(c == '\\') {
*lp = ' ';
backsl();
if(c == '%') /* no blank for hyphenation char */
lp--;
}
if(c == '\n')
break;
if(intable && c=='T') {
*++lp = C;
if(c=='{' || c=='}') {
lp[-1] = ' ';
*lp = C;
}
} else {
if(msflag == 1 && eqnflag == 1) {
eqnflag = 0;
*++lp = 'x';
}
*++lp = C;
}
}
*lp = '\0';
if(lp != line) {
if(wordflag)
putwords();
else
if(macline)
putmac(line,vconst);
else
Bprint(&bout, "%S\n", line);
}
}
void
putmac(Rune *rp, int vconst)
{
Rune *t;
int found;
Rune last;
found = 0;
last = 0;
while(*rp) {
while(*rp == ' ' || *rp == '\t')
Bputrune(&bout, *rp++);
for(t = rp; *t != ' ' && *t != '\t' && *t != '\0'; t++)
;
if(*rp == '\"')
rp++;
if(t > rp+vconst && charclass(*rp) == LETTER
&& charclass(rp[1]) == LETTER) {
while(rp < t)
if(*rp == '\"')
rp++;
else
Bputrune(&bout, *rp++);
last = t[-1];
found++;
} else
if(found && charclass(*rp) == PUNCT && rp[1] == '\0')
Bputrune(&bout, *rp++);
else {
last = t[-1];
rp = t;
}
}
Bputc(&bout, '\n');
if(msflag && charclass(last) == PUNCT)
Bprint(&bout, " %C\n", last);
}
/*
* break into words for -w option
*/
void
putwords(void)
{
Rune *p, *p1;
int i, nlet;
for(p1 = line;;) {
/*
* skip initial specials ampersands and apostrophes
*/
while((i = charclass(*p1)) != EXTENDED && i < DIGIT)
if(*p1++ == '\0')
return;
nlet = 0;
for(p = p1; (i = charclass(*p)) != SPECIAL || (underscoreflag && *p=='_'); p++)
if(i == LETTER || (underscoreflag && *p == '_'))
nlet++;
/*
* MDM definition of word
*/
if(nlet > 1) {
/*
* delete trailing ampersands and apostrophes
*/
while(*--p == '\'' || *p == '&'
|| charclass(*p) == PUNCT)
;
while(p1 <= p)
Bputrune(&bout, *p1++);
Bputc(&bout, '\n');
} else
p1 = p;
}
}
void
comline(void)
{
long c1, c2;
while(C==' ' || c=='\t')
;
comx:
if((c1=c) == '\n')
return;
c2 = C;
if(c1=='.' && c2!='.')
inmacro = NO;
if(msflag && c1 == '['){
refer(c2);
return;
}
if(c2 == '\n')
return;
if(c1 == '\\' && c2 == '\"')
SKIP;
else
if (filesp==files && c1=='E' && c2=='Q')
eqn();
else
if(filesp==files && c1=='T' && (c2=='S' || c2=='C' || c2=='&')) {
if(msflag)
stbl();
else
tbl();
}
else
if(c1=='T' && c2=='E')
intable = NO;
else if (!inmacro &&
((c1 == 'd' && c2 == 'e') ||
(c1 == 'i' && c2 == 'g') ||
(c1 == 'a' && c2 == 'm')))
macro();
else
if(c1=='s' && c2=='o') {
if(iflag)
SKIP;
else {
getfname();
if(fname[0]) {
if(infile = opn(fname))
*++filesp = infile;
else infile = *filesp;
}
}
}
else
if(c1=='n' && c2=='x')
if(iflag)
SKIP;
else {
getfname();
if(fname[0] == '\0')
exits(0);
if(Bfildes(infile) != 0)
Bterm(infile);
infile = *filesp = opn(fname);
}
else
if(c1 == 't' && c2 == 'm')
SKIP;
else
if(c1=='h' && c2=='w')
SKIP;
else
if(msflag && c1 == 'T' && c2 == 'L') {
SKIP_TO_COM;
goto comx;
}
else
if(msflag && c1=='N' && c2 == 'R')
SKIP;
else
if(msflag && c1 == 'A' && (c2 == 'U' || c2 == 'I')){
if(mac==MM)SKIP;
else {
SKIP_TO_COM;
goto comx;
}
} else
if(msflag && c1=='F' && c2=='S') {
SKIP_TO_COM;
goto comx;
}
else
if(msflag && (c1=='S' || c1=='N') && c2=='H') {
SKIP_TO_COM;
goto comx;
} else
if(c1 == 'U' && c2 == 'X') {
if(wordflag)
Bprint(&bout, "UNIX\n");
else
Bprint(&bout, "UNIX ");
} else
if(msflag && c1=='O' && c2=='K') {
SKIP_TO_COM;
goto comx;
} else
if(msflag && c1=='N' && c2=='D')
SKIP;
else
if(msflag && mac==MM && c1=='H' && (c2==' '||c2=='U'))
SKIP;
else
if(msflag && mac==MM && c2=='L') {
if(disp || c1=='R')
sdis('L', 'E');
else {
SKIP;
Bprint(&bout, " .");
}
} else
if(!msflag && c1=='P' && c2=='S') {
inpic();
} else
if(msflag && (c1=='D' || c1=='N' || c1=='K'|| c1=='P') && c2=='S') {
sdis(c1, 'E');
} else
if(msflag && (c1 == 'K' && c2 == 'F')) {
sdis(c1,'E');
} else
if(msflag && c1=='n' && c2=='f')
sdis('f','i');
else
if(msflag && c1=='c' && c2=='e')
sce();
else {
if(c1=='.' && c2=='.') {
if(msflag) {
SKIP;
return;
}
while(C == '.')
;
}
inmacro++;
if(c1 <= 'Z' && msflag)
regline(YES,ONE);
else {
if(wordflag)
C;
regline(YES,TWO);
}
inmacro--;
}
}
void
macro(void)
{
if(msflag) {
do {
SKIP1;
} while(C1 != '.' || C1 != '.' || C1 == '.');
if(c != '\n')
SKIP;
return;
}
SKIP;
inmacro = YES;
}
void
sdis(char a1, char a2)
{
int c1, c2;
int eqnf;
int lct;
if(a1 == 'P'){
while(C1 == ' ')
;
if(c == '<') {
SKIP1;
return;
}
}
lct = 0;
eqnf = 1;
if(c != '\n')
SKIP1;
for(;;) {
while(C1 != '.')
if(c == '\n')
continue;
else
SKIP1;
if((c1=C1) == '\n')
continue;
if((c2=C1) == '\n') {
if(a1 == 'f' && (c1 == 'P' || c1 == 'H'))
return;
continue;
}
if(c1==a1 && c2 == a2) {
SKIP1;
if(lct != 0){
lct--;
continue;
}
if(eqnf)
Bprint(&bout, " .");
Bputc(&bout, '\n');
return;
} else
if(a1 == 'L' && c2 == 'L') {
lct++;
SKIP1;
} else
if(a1 == 'D' && c1 == 'E' && c2 == 'Q') {
eqn();
eqnf = 0;
} else
if(a1 == 'f') {
if((mac == MS && c2 == 'P') ||
(mac == MM && c1 == 'H' && c2 == 'U')){
SKIP1;
return;
}
SKIP1;
}
else
SKIP1;
}
}
void
tbl(void)
{
while(C != '.')
;
SKIP;
intable = YES;
}
void
stbl(void)
{
while(C != '.')
;
SKIP_TO_COM;
if(c != 'T' || C != 'E') {
SKIP;
pc = c;
while(C != '.' || pc != '\n' || C != 'T' || C != 'E')
pc = c;
}
}
void
eqn(void)
{
long c1, c2;
int dflg;
char last;
last = 0;
dflg = 1;
SKIP;
for(;;) {
if(C1 == '.' || c == '\'') {
while(C1==' ' || c=='\t')
;
if(c=='E' && C1=='N') {
SKIP;
if(msflag && dflg) {
Bputc(&bout, 'x');
Bputc(&bout, ' ');
if(last) {
Bputc(&bout, last);
Bputc(&bout, '\n');
}
}
return;
}
} else
if(c == 'd') {
if(C1=='e' && C1=='l')
if(C1=='i' && C1=='m') {
while(C1 == ' ')
;
if((c1=c)=='\n' || (c2=C1)=='\n' ||
(c1=='o' && c2=='f' && C1=='f')) {
ldelim = NOCHAR;
rdelim = NOCHAR;
} else {
ldelim = c1;
rdelim = c2;
}
}
dflg = 0;
}
if(c != '\n')
while(C1 != '\n') {
if(chars[c] == PUNCT)
last = c;
else
if(c != ' ')
last = 0;
}
}
}
/*
* skip over a complete backslash vconstruction
*/
void
backsl(void)
{
int bdelim;
sw:
switch(C1)
{
case '"':
SKIP1;
return;
case 's':
if(C1 == '\\')
backsl();
else {
while(C1>='0' && c<='9')
;
Bungetrune(infile);
c = '0';
}
lp--;
return;
case 'f':
case 'n':
case '*':
if(C1 != '(')
return;
case '(':
if(msflag) {
if(C == 'e') {
if(C1 == 'm') {
*lp = '-';
return;
}
} else
if(c != '\n')
C1;
return;
}
if(C1 != '\n')
C1;
return;
case '$':
C1; /* discard argument number */
return;
case 'b':
case 'x':
case 'v':
case 'h':
case 'w':
case 'o':
case 'l':
case 'L':
if((bdelim=C1) == '\n')
return;
while(C1!='\n' && c!=bdelim)
if(c == '\\')
backsl();
return;
case '\\':
if(inmacro)
goto sw;
default:
return;
}
}
char*
copys(char *s)
{
char *t, *t0;
if((t0 = t = malloc((strlen(s)+1))) == 0)
fatal("Cannot allocate memory", (char*)0);
while(*t++ = *s++)
;
return(t0);
}
void
sce(void)
{
int n = 1;
while (C != L'\n' && !(L'0' <= c && c <= L'9'))
;
if (c != L'\n') {
for (n = c-L'0';'0' <= C && c <= L'9';)
n = n*10 + c-L'0';
}
while(n) {
if(C == '.') {
if(C == 'c') {
if(C == 'e') {
while(C == ' ')
;
if(c == '0') {
SKIP;
break;
} else
SKIP;
} else
SKIP;
} else
if(c == 'P' || C == 'P') {
if(c != '\n')
SKIP;
break;
} else
if(c != '\n')
SKIP;
} else {
SKIP;
n--;
}
}
}
void
refer(int c1)
{
int c2;
if(c1 != '\n')
SKIP;
c2 = 0;
for(;;) {
if(C != '.')
SKIP;
else {
if(C != ']')
SKIP;
else {
while(C != '\n')
c2 = c;
if(charclass(c2) == PUNCT)
Bprint(&bout, " %C",c2);
return;
}
}
}
}
void
inpic(void)
{
int c1;
Rune *p1;
/* SKIP1;*/
while(C1 != '\n')
if(c == '<'){
SKIP1;
return;
}
p1 = line;
c = '\n';
for(;;) {
c1 = c;
if(C1 == '.' && c1 == '\n') {
if(C1 != 'P' || C1 != 'E') {
if(c != '\n'){
SKIP1;
c = '\n';
}
continue;
}
SKIP1;
return;
} else
if(c == '\"') {
while(C1 != '\"') {
if(c == '\\') {
if(C1 == '\"')
continue;
Bungetrune(infile);
backsl();
} else
*p1++ = c;
}
*p1++ = ' ';
} else
if(c == '\n' && p1 != line) {
*p1 = '\0';
if(wordflag)
putwords();
else
Bprint(&bout, "%S\n\n", line);
p1 = line;
}
}
}
int
charclass(int c)
{
if(c < MAX_ASCII)
return chars[c];
switch(c){
case 0x2013: case 0x2014: /* en dash, em dash */
return SPECIAL;
}
return EXTENDED;
}

194
src/cmd/du.C Normal file
View File

@ -0,0 +1,194 @@
#include <u.h>
#include <libc.h>
extern vlong du(char*, Dir*);
extern vlong k(vlong);
extern void err(char*);
extern int warn(char*);
extern int seen(Dir*);
int aflag;
int fflag;
int nflag;
int sflag;
int tflag;
int uflag;
int qflag;
char *fmt = "%llud\t%s\n";
vlong blocksize = 1024LL;
void
main(int argc, char *argv[])
{
int i;
char *s, *ss;
ARGBEGIN {
case 'a': /* all files */
aflag = 1;
break;
case 's': /* only top level */
sflag = 1;
break;
case 'f': /* ignore errors */
fflag = 1;
break;
case 'n': /* all files, number of bytes */
aflag = 1;
nflag = 1;
break;
case 't': /* return modified/accessed time */
tflag = 1;
break;
case 'u': /* accessed time */
uflag = 1;
break;
case 'q': /* qid */
fmt = "%.16llux\t%s\n";
qflag = 1;
break;
case 'b': /* block size */
s = ARGF();
if(s) {
blocksize = strtoul(s, &ss, 0);
if(s == ss)
blocksize = 1;
if(*ss == 'k')
blocksize *= 1024;
}
break;
} ARGEND
if(argc==0)
print(fmt, du(".", dirstat(".")), ".");
else
for(i=0; i<argc; i++)
print(fmt, du(argv[i], dirstat(argv[i])), argv[i]);
exits(0);
}
vlong
du(char *name, Dir *dir)
{
int fd, i, n;
Dir *buf, *d;
char file[256];
vlong nk, t;
if(dir == nil)
return warn(name);
fd = open(name, OREAD);
if(fd < 0)
return warn(name);
if((dir->qid.type&QTDIR) == 0)
nk = k(dir->length);
else{
nk = 0;
while((n=dirread(fd, &buf)) > 0) {
d = buf;
for(i=0; i<n; i++, d++) {
if((d->qid.type&QTDIR) == 0) {
t = k(d->length);
nk += t;
if(aflag) {
sprint(file, "%s/%s", name, d->name);
if(tflag) {
t = d->mtime;
if(uflag)
t = d->atime;
}
if(qflag)
t = d->qid.path;
print(fmt, t, file);
}
continue;
}
if(strcmp(d->name, ".") == 0 ||
strcmp(d->name, "..") == 0 ||
seen(d))
continue;
sprint(file, "%s/%s", name, d->name);
t = du(file, d);
nk += t;
if(tflag) {
t = d->mtime;
if(uflag)
t = d->atime;
}
if(qflag)
t = d->qid.path;
if(!sflag)
print(fmt, t, file);
}
free(buf);
}
if(n < 0)
warn(name);
}
close(fd);
if(tflag) {
if(uflag)
return dir->atime;
return dir->mtime;
}
if(qflag)
return dir->qid.path;
return nk;
}
#define NCACHE 128 /* must be power of two */
typedef struct Cache Cache;
struct Cache
{
Dir* cache;
int n;
int max;
} cache[NCACHE];
int
seen(Dir *dir)
{
Dir *dp;
int i;
Cache *c;
c = &cache[dir->qid.path&(NCACHE-1)];
dp = c->cache;
for(i=0; i<c->n; i++, dp++)
if(dir->qid.path == dp->qid.path &&
dir->type == dp->type &&
dir->dev == dp->dev)
return 1;
if(c->n == c->max){
c->cache = realloc(c->cache, (c->max+=20)*sizeof(Dir));
if(cache == 0)
err("malloc failure");
}
c->cache[c->n++] = *dir;
return 0;
}
void
err(char *s)
{
fprint(2, "du: %s: %r\n", s);
exits(s);
}
int
warn(char *s)
{
if(fflag == 0)
fprint(2, "du: %s: %r\n", s);
return 0;
}
vlong
k(vlong n)
{
if(nflag)
return n;
n = (n+blocksize-1)/blocksize;
return n*blocksize/1024LL;
}

38
src/cmd/echo.c Normal file
View File

@ -0,0 +1,38 @@
#include <u.h>
#include <libc.h>
void
main(int argc, char *argv[])
{
int nflag;
int i, len;
char *buf, *p;
nflag = 0;
if(argc > 1 && strcmp(argv[1], "-n") == 0)
nflag = 1;
len = 1;
for(i = 1+nflag; i < argc; i++)
len += strlen(argv[i])+1;
buf = malloc(len);
if(buf == 0)
exits("no memory");
p = buf;
for(i = 1+nflag; i < argc; i++){
strcpy(p, argv[i]);
p += strlen(p);
if(i < argc-1)
*p++ = ' ';
}
if(!nflag)
*p++ = '\n';
if(write(1, buf, p-buf) < 0)
fprint(2, "echo: write error: %r\n");
exits((char *)0);
}

1608
src/cmd/ed.c Normal file

File diff suppressed because it is too large Load Diff

96
src/cmd/factor.c Normal file
View File

@ -0,0 +1,96 @@
#include <u.h>
#include <libc.h>
#include <bio.h>
#define whsiz (sizeof(wheel)/sizeof(wheel[0]))
double wheel[] =
{
2,10, 2, 4, 2, 4, 6, 2, 6, 4,
2, 4, 6, 6, 2, 6, 4, 2, 6, 4,
6, 8, 4, 2, 4, 2, 4, 8, 6, 4,
6, 2, 4, 6, 2, 6, 6, 4, 2, 4,
6, 2, 6, 4, 2, 4, 2,10,
};
Biobuf bin;
void factor(double);
void
main(int argc, char *argv[])
{
double n;
int i;
char *l;
if(argc > 1) {
for(i=1; i<argc; i++) {
n = atof(argv[i]);
factor(n);
}
exits(0);
}
Binit(&bin, 0, OREAD);
for(;;) {
l = Brdline(&bin, '\n');
if(l == 0)
break;
n = atof(l);
if(n <= 0)
break;
factor(n);
}
exits(0);
}
void
factor(double n)
{
double quot, d, s;
int i;
print("%.0f\n", n);
if(n == 0)
return;
s = sqrt(n) + 1;
while(modf(n/2, &quot) == 0) {
print(" 2\n");
n = quot;
s = sqrt(n) + 1;
}
while(modf(n/3, &quot) == 0) {
print(" 3\n");
n = quot;
s = sqrt(n) + 1;
}
while(modf(n/5, &quot) == 0) {
print(" 5\n");
n = quot;
s = sqrt(n) + 1;
}
while(modf(n/7, &quot) == 0) {
print(" 7\n");
n = quot;
s = sqrt(n) + 1;
}
d = 1;
for(i=1;;) {
d += wheel[i];
while(modf(n/d, &quot) == 0) {
print(" %.0f\n", d);
n = quot;
s = sqrt(n) + 1;
}
i++;
if(i >= whsiz) {
i = 0;
if(d > s)
break;
}
}
if(n > 1)
print(" %.0f\n",n);
print("\n");
}

111
src/cmd/freq.c Normal file
View File

@ -0,0 +1,111 @@
#include <u.h>
#include <libc.h>
#include <bio.h>
long count[1<<16];
Biobuf bout;
void freq(int, char*);
long flag;
enum
{
Fdec = 1<<0,
Fhex = 1<<1,
Foct = 1<<2,
Fchar = 1<<3,
Frune = 1<<4,
};
void
main(int argc, char *argv[])
{
int f, i;
flag = 0;
Binit(&bout, 1, OWRITE);
ARGBEGIN{
default:
fprint(2, "freq: unknown option %c\n", ARGC());
exits("usage");
case 'd':
flag |= Fdec;
break;
case 'x':
flag |= Fhex;
break;
case 'o':
flag |= Foct;
break;
case 'c':
flag |= Fchar;
break;
case 'r':
flag |= Frune;
break;
}ARGEND
if((flag&(Fdec|Fhex|Foct|Fchar)) == 0)
flag |= Fdec | Fhex | Foct | Fchar;
if(argc < 1) {
freq(0, "-");
exits(0);
}
for(i=0; i<argc; i++) {
f = open(argv[i], 0);
if(f < 0) {
fprint(2, "cannot open %s\n", argv[i]);
continue;
}
freq(f, argv[i]);
close(f);
}
exits(0);
}
void
freq(int f, char *s)
{
Biobuf bin;
long c, i;
memset(count, 0, sizeof(count));
Binit(&bin, f, OREAD);
if(flag & Frune) {
for(;;) {
c = Bgetrune(&bin);
if(c < 0)
break;
count[c]++;
}
} else {
for(;;) {
c = Bgetc(&bin);
if(c < 0)
break;
count[c]++;
}
}
Bterm(&bin);
if(c != Beof)
fprint(2, "freq: read error on %s\n", s);
for(i=0; i<nelem(count); i++) {
if(count[i] == 0)
continue;
if(flag & Fdec)
Bprint(&bout, "%3ld ", i);
if(flag & Foct)
Bprint(&bout, "%.3lo ", i);
if(flag & Fhex)
Bprint(&bout, "%.2lx ", i);
if(flag & Fchar) {
if(i <= 0x20 ||
i >= 0x7f && i < 0xa0 ||
i > 0xff && !(flag & Frune))
Bprint(&bout, "- ");
else
Bprint(&bout, "%C ", (int)i);
}
Bprint(&bout, "%8ld\n", count[i]);
}
Bflush(&bout);
}

32
src/cmd/fsize.c Normal file
View File

@ -0,0 +1,32 @@
#include <u.h>
#include <libc.h>
void
usage(void)
{
fprint(2, "usage: fsize file...\n");
exits("usage");
}
void
main(int argc, char **argv)
{
int i;
Dir *d;
ARGBEGIN{
default:
usage();
}ARGEND
if(argc == 0)
usage();
for(i=0; i<argc; i++){
if((d = dirstat(argv[i])) == nil)
fprint(2, "dirstat %s: %r", argv[i]);
else{
print("%s: %lld\n", argv[i], d->length);
free(d);
}
}
}

335
src/cmd/idiff.c Normal file
View File

@ -0,0 +1,335 @@
/*
* interactive diff, inspired/stolen from
* kernighan and pike, _unix programming environment_.
*/
#include <u.h>
#include <libc.h>
#include <bio.h>
int diffbflag;
int diffwflag;
void copy(Biobuf*, char*, Biobuf*, char*);
void idiff(Biobuf*, char*, Biobuf*, char*, Biobuf*, char*, Biobuf*, char*);
int opentemp(char*, int, long);
void rundiff(char*, char*, int);
void
usage(void)
{
fprint(2, "usage: idiff [-bw] file1 file2\n");
exits("usage");
}
void
main(int argc, char **argv)
{
int fd, ofd;
char diffout[40], idiffout[40];
Biobuf *b1, *b2, bdiff, bout, bstdout;
Dir *d;
ARGBEGIN{
default:
usage();
case 'b':
diffbflag++;
break;
case 'w':
diffwflag++;
break;
}ARGEND
if(argc != 2)
usage();
if((d = dirstat(argv[0])) == nil)
sysfatal("stat %s: %r", argv[0]);
if(d->mode&DMDIR)
sysfatal("%s is a directory", argv[0]);
free(d);
if((d = dirstat(argv[1])) == nil)
sysfatal("stat %s: %r", argv[1]);
if(d->mode&DMDIR)
sysfatal("%s is a directory", argv[1]);
free(d);
if((b1 = Bopen(argv[0], OREAD)) == nil)
sysfatal("open %s: %r", argv[0]);
if((b2 = Bopen(argv[1], OREAD)) == nil)
sysfatal("open %s: %r", argv[1]);
strcpy(diffout, "/tmp/idiff.XXXXXX");
fd = opentemp(diffout, ORDWR|ORCLOSE, 0);
strcpy(idiffout, "/tmp/idiff.XXXXXX");
ofd = opentemp(idiffout, ORDWR|ORCLOSE, 0);
rundiff(argv[0], argv[1], fd);
seek(fd, 0, 0);
Binit(&bdiff, fd, OREAD);
Binit(&bout, ofd, OWRITE);
idiff(b1, argv[0], b2, argv[1], &bdiff, diffout, &bout, idiffout);
Bterm(&bdiff);
Bflush(&bout);
seek(ofd, 0, 0);
Binit(&bout, ofd, OREAD);
Binit(&bstdout, 1, OWRITE);
copy(&bout, idiffout, &bstdout, "<stdout>");
exits(nil);
}
int
opentemp(char *template, int mode, long perm)
{
int fd, i;
char *p;
p = strdup(template);
if(p == nil)
sysfatal("strdup out of memory");
fd = -1;
for(i=0; i<10; i++){
mktemp(p);
if(access(p, 0) < 0 && (fd=create(p, mode, perm)) >= 0)
break;
strcpy(p, template);
}
if(fd < 0)
sysfatal("could not create temporary file");
strcpy(template, p);
free(p);
return fd;
}
void
rundiff(char *arg1, char *arg2, int outfd)
{
char *arg[10], *p;
int narg, pid;
Waitmsg *w;
narg = 0;
arg[narg++] = "/bin/diff";
arg[narg++] = "-n";
if(diffbflag)
arg[narg++] = "-b";
if(diffwflag)
arg[narg++] = "-w";
arg[narg++] = arg1;
arg[narg++] = arg2;
arg[narg] = nil;
switch(pid = fork()){
case -1:
sysfatal("fork: %r");
case 0:
dup(outfd, 1);
close(0);
exec("/bin/diff", arg);
sysfatal("exec: %r");
default:
w = wait();
if(w==nil)
sysfatal("wait: %r");
if(w->pid != pid)
sysfatal("wait got unexpected pid %d", w->pid);
if((p = strchr(w->msg, ':')) && strcmp(p, ": some") != 0)
sysfatal("%s", w->msg);
free(w);
}
}
void
runcmd(char *cmd)
{
char *arg[10];
int narg, pid, wpid;
narg = 0;
arg[narg++] = "/bin/rc";
arg[narg++] = "-c";
arg[narg++] = cmd;
arg[narg] = nil;
switch(pid = fork()){
case -1:
sysfatal("fork: %r");
case 0:
exec("/bin/rc", arg);
sysfatal("exec: %r");
default:
wpid = waitpid();
if(wpid < 0)
sysfatal("wait: %r");
if(wpid != pid)
sysfatal("wait got unexpected pid %d", wpid);
}
}
void
parse(char *s, int *pfrom1, int *pto1, int *pcmd, int *pfrom2, int *pto2)
{
*pfrom1 = *pto1 = *pfrom2 = *pto2 = 0;
s = strchr(s, ':');
if(s == nil)
sysfatal("bad diff output0");
s++;
*pfrom1 = strtol(s, &s, 10);
if(*s == ','){
s++;
*pto1 = strtol(s, &s, 10);
}else
*pto1 = *pfrom1;
if(*s++ != ' ')
sysfatal("bad diff output1");
*pcmd = *s++;
if(*s++ != ' ')
sysfatal("bad diff output2");
s = strchr(s, ':');
if(s == nil)
sysfatal("bad diff output3");
s++;
*pfrom2 = strtol(s, &s, 10);
if(*s == ','){
s++;
*pto2 = strtol(s, &s, 10);
}else
*pto2 = *pfrom2;
}
void
skiplines(Biobuf *b, char *name, int n)
{
int i;
for(i=0; i<n; i++){
while(Brdline(b, '\n')==nil){
if(Blinelen(b) <= 0)
sysfatal("early end of file on %s", name);
Bseek(b, Blinelen(b), 1);
}
}
}
void
copylines(Biobuf *bin, char *nin, Biobuf *bout, char *nout, int n)
{
char buf[4096], *p;
int i, m;
for(i=0; i<n; i++){
while((p=Brdline(bin, '\n'))==nil){
if(Blinelen(bin) <= 0)
sysfatal("early end of file on %s", nin);
m = Blinelen(bin);
if(m > sizeof buf)
m = sizeof buf;
m = Bread(bin, buf, m);
if(Bwrite(bout, buf, m) != m)
sysfatal("error writing %s: %r", nout);
}
if(Bwrite(bout, p, Blinelen(bin)) != Blinelen(bin))
sysfatal("error writing %s: %r", nout);
}
}
void
copy(Biobuf *bin, char *nin, Biobuf *bout, char *nout)
{
char buf[4096];
int m;
USED(nin);
while((m = Bread(bin, buf, sizeof buf)) > 0)
if(Bwrite(bout, buf, m) != m)
sysfatal("error writing %s: %r", nout);
}
void
idiff(Biobuf *b1, char *name1, Biobuf *b2, char *name2, Biobuf *bdiff, char *namediff, Biobuf *bout, char *nameout)
{
char buf[256], *p;
int interactive, defaultanswer, cmd, diffoffset;
int n, from1, to1, from2, to2, nf1, nf2;
Biobuf berr;
nf1 = 1;
nf2 = 1;
interactive = 1;
defaultanswer = 0;
Binit(&berr, 2, OWRITE);
while(diffoffset = Boffset(bdiff), p = Brdline(bdiff, '\n')){
p[Blinelen(bdiff)-1] = '\0';
parse(p, &from1, &to1, &cmd, &from2, &to2);
p[Blinelen(bdiff)-1] = '\n';
n = to1-from1 + to2-from2 + 1; /* #lines from diff */
if(cmd == 'c')
n += 2;
else if(cmd == 'a')
from1++;
else if(cmd == 'd')
from2++;
to1++; /* make half-open intervals */
to2++;
if(interactive){
p[Blinelen(bdiff)-1] = '\0';
fprint(2, "%s\n", p);
p[Blinelen(bdiff)-1] = '\n';
copylines(bdiff, namediff, &berr, "<stderr>", n);
Bflush(&berr);
}else
skiplines(bdiff, namediff, n);
do{
if(interactive){
fprint(2, "? ");
memset(buf, 0, sizeof buf);
if(read(0, buf, sizeof buf - 1) < 0)
sysfatal("read console: %r");
}else
buf[0] = defaultanswer;
switch(buf[0]){
case '>':
copylines(b1, name1, bout, nameout, from1-nf1);
skiplines(b1, name1, to1-from1);
skiplines(b2, name2, from2-nf2);
copylines(b2, name2, bout, nameout, to2-from2);
break;
case '<':
copylines(b1, name1, bout, nameout, to1-nf1);
skiplines(b2, name2, to2-nf2);
break;
case '=':
copylines(b1, name1, bout, nameout, from1-nf1);
skiplines(b1, name1, to1-from1);
skiplines(b2, name2, to2-nf2);
if(Bseek(bdiff, diffoffset, 0) != diffoffset)
sysfatal("seek in diff output: %r");
copylines(bdiff, namediff, bout, nameout, n+1);
break;
case '!':
runcmd(buf+1);
break;
case 'q':
if(buf[1]=='<' || buf[1]=='>' || buf[1]=='='){
interactive = 0;
defaultanswer = buf[1];
}else
fprint(2, "must be q<, q>, or q=\n");
break;
default:
fprint(2, "expect: <, >, =, q<, q>, q=, !cmd\n");
break;
}
}while(buf[0] != '<' && buf[0] != '>' && buf[0] != '=');
nf1 = to1;
nf2 = to2;
}
copy(b1, name1, bout, nameout);
}

369
src/cmd/join.c Normal file
View File

@ -0,0 +1,369 @@
/* join F1 F2 on stuff */
#include <u.h>
#include <libc.h>
#include <stdio.h>
#include <ctype.h>
#define F1 0
#define F2 1
#define F0 3
#define NFLD 100 /* max field per line */
#define comp() runecmp(ppi[F1][j1],ppi[F2][j2])
FILE *f[2];
Rune buf[2][BUFSIZ]; /*input lines */
Rune *ppi[2][NFLD+1]; /* pointers to fields in lines */
Rune *s1,*s2;
#define j1 joinj1
#define j2 joinj2
int j1 = 1; /* join of this field of file 1 */
int j2 = 1; /* join of this field of file 2 */
int olist[2*NFLD]; /* output these fields */
int olistf[2*NFLD]; /* from these files */
int no; /* number of entries in olist */
Rune sep1 = ' '; /* default field separator */
Rune sep2 = '\t';
char *sepstr=" ";
int discard; /* count of truncated lines */
Rune null[BUFSIZ]/* = L""*/;
int a1;
int a2;
char *getoptarg(int*, char***);
void output(int, int);
int input(int);
void oparse(char*);
void error(char*, char*);
void seek1(void), seek2(void);
Rune *strtorune(Rune *, char *);
void
main(int argc, char **argv)
{
int i;
while (argc > 1 && argv[1][0] == '-') {
if (argv[1][1] == '\0')
break;
switch (argv[1][1]) {
case '-':
argc--;
argv++;
goto proceed;
case 'a':
switch(*getoptarg(&argc, &argv)) {
case '1':
a1++;
break;
case '2':
a2++;
break;
default:
error("incomplete option -a","");
}
break;
case 'e':
strtorune(null, getoptarg(&argc, &argv));
break;
case 't':
sepstr=getoptarg(&argc, &argv);
chartorune(&sep1, sepstr);
sep2 = sep1;
break;
case 'o':
if(argv[1][2]!=0 ||
argc>2 && strchr(argv[2],',')!=0)
oparse(getoptarg(&argc, &argv));
else for (no = 0; no<2*NFLD && argc>2; no++){
if (argv[2][0] == '1' && argv[2][1] == '.') {
olistf[no] = F1;
olist[no] = atoi(&argv[2][2]);
} else if (argv[2][0] == '2' && argv[2][1] == '.') {
olist[no] = atoi(&argv[2][2]);
olistf[no] = F2;
} else if (argv[2][0] == '0')
olistf[no] = F0;
else
break;
argc--;
argv++;
}
break;
case 'j':
if(argc <= 2)
break;
if (argv[1][2] == '1')
j1 = atoi(argv[2]);
else if (argv[1][2] == '2')
j2 = atoi(argv[2]);
else
j1 = j2 = atoi(argv[2]);
argc--;
argv++;
break;
case '1':
j1 = atoi(getoptarg(&argc, &argv));
break;
case '2':
j2 = atoi(getoptarg(&argc, &argv));
break;
}
argc--;
argv++;
}
proceed:
for (i = 0; i < no; i++)
if (olist[i]-- > NFLD) /* 0 origin */
error("field number too big in -o","");
if (argc != 3)
error("usage: join [-1 x -2 y] [-o list] file1 file2","");
j1--;
j2--; /* everyone else believes in 0 origin */
s1 = ppi[F1][j1];
s2 = ppi[F2][j2];
if (strcmp(argv[1], "-") == 0)
f[F1] = stdin;
else if ((f[F1] = fopen(argv[1], "r")) == 0)
error("can't open %s", argv[1]);
if(strcmp(argv[2], "-") == 0) {
f[F2] = stdin;
} else if ((f[F2] = fopen(argv[2], "r")) == 0)
error("can't open %s", argv[2]);
if(ftell(f[F2]) >= 0)
seek2();
else if(ftell(f[F1]) >= 0)
seek1();
else
error("neither file is randomly accessible","");
if (discard)
error("some input line was truncated", "");
exits("");
}
int runecmp(Rune *a, Rune *b){
while(*a==*b){
if(*a=='\0') return 0;
a++;
b++;
}
if(*a<*b) return -1;
return 1;
}
char *runetostr(char *buf, Rune *r){
char *s;
for(s=buf;*r;r++) s+=runetochar(s, r);
*s='\0';
return buf;
}
Rune *strtorune(Rune *buf, char *s){
Rune *r;
for(r=buf;*s;r++) s+=chartorune(r, s);
*r='\0';
return buf;
}
/* lazy. there ought to be a clean way to combine seek1 & seek2 */
#define get1() n1=input(F1)
#define get2() n2=input(F2)
void
seek2()
{
int n1, n2;
int top2=0;
int bot2 = ftell(f[F2]);
get1();
get2();
while(n1>0 && n2>0 || (a1||a2) && n1+n2>0) {
if(n1>0 && n2>0 && comp()>0 || n1==0) {
if(a2) output(0, n2);
bot2 = ftell(f[F2]);
get2();
} else if(n1>0 && n2>0 && comp()<0 || n2==0) {
if(a1) output(n1, 0);
get1();
} else /*(n1>0 && n2>0 && comp()==0)*/ {
while(n2>0 && comp()==0) {
output(n1, n2);
top2 = ftell(f[F2]);
get2();
}
fseek(f[F2], bot2, 0);
get2();
get1();
for(;;) {
if(n1>0 && n2>0 && comp()==0) {
output(n1, n2);
get2();
} else if(n1>0 && n2>0 && comp()<0 || n2==0) {
fseek(f[F2], bot2, 0);
get2();
get1();
} else /*(n1>0 && n2>0 && comp()>0 || n1==0)*/{
fseek(f[F2], top2, 0);
bot2 = top2;
get2();
break;
}
}
}
}
}
void
seek1()
{
int n1, n2;
int top1=0;
int bot1 = ftell(f[F1]);
get1();
get2();
while(n1>0 && n2>0 || (a1||a2) && n1+n2>0) {
if(n1>0 && n2>0 && comp()>0 || n1==0) {
if(a2) output(0, n2);
get2();
} else if(n1>0 && n2>0 && comp()<0 || n2==0) {
if(a1) output(n1, 0);
bot1 = ftell(f[F1]);
get1();
} else /*(n1>0 && n2>0 && comp()==0)*/ {
while(n2>0 && comp()==0) {
output(n1, n2);
top1 = ftell(f[F1]);
get1();
}
fseek(f[F1], bot1, 0);
get2();
get1();
for(;;) {
if(n1>0 && n2>0 && comp()==0) {
output(n1, n2);
get1();
} else if(n1>0 && n2>0 && comp()>0 || n1==0) {
fseek(f[F1], bot1, 0);
get2();
get1();
} else /*(n1>0 && n2>0 && comp()<0 || n2==0)*/{
fseek(f[F1], top1, 0);
bot1 = top1;
get1();
break;
}
}
}
}
}
int
input(int n) /* get input line and split into fields */
{
register int i, c;
Rune *bp;
Rune **pp;
char line[BUFSIZ];
bp = buf[n];
pp = ppi[n];
if (fgets(line, BUFSIZ, f[n]) == 0)
return(0);
strtorune(bp, line);
i = 0;
do {
i++;
if (sep1 == ' ') /* strip multiples */
while ((c = *bp) == sep1 || c == sep2)
bp++; /* skip blanks */
*pp++ = bp; /* record beginning */
while ((c = *bp) != sep1 && c != '\n' && c != sep2 && c != '\0')
bp++;
*bp++ = '\0'; /* mark end by overwriting blank */
} while (c != '\n' && c != '\0' && i < NFLD-1);
if (c != '\n')
discard++;
*pp = 0;
return(i);
}
void
output(int on1, int on2) /* print items from olist */
{
int i;
Rune *temp;
char buf[BUFSIZ];
if (no <= 0) { /* default case */
printf("%s", runetostr(buf, on1? ppi[F1][j1]: ppi[F2][j2]));
for (i = 0; i < on1; i++)
if (i != j1)
printf("%s%s", sepstr, runetostr(buf, ppi[F1][i]));
for (i = 0; i < on2; i++)
if (i != j2)
printf("%s%s", sepstr, runetostr(buf, ppi[F2][i]));
printf("\n");
} else {
for (i = 0; i < no; i++) {
if (olistf[i]==F0 && on1>j1)
temp = ppi[F1][j1];
else if (olistf[i]==F0 && on2>j2)
temp = ppi[F2][j2];
else {
temp = ppi[olistf[i]][olist[i]];
if(olistf[i]==F1 && on1<=olist[i] ||
olistf[i]==F2 && on2<=olist[i] ||
*temp==0)
temp = null;
}
printf("%s", runetostr(buf, temp));
if (i == no - 1)
printf("\n");
else
printf("%s", sepstr);
}
}
}
void
error(char *s1, char *s2)
{
fprintf(stderr, "join: ");
fprintf(stderr, s1, s2);
fprintf(stderr, "\n");
exits(s1);
}
char *
getoptarg(int *argcp, char ***argvp)
{
int argc = *argcp;
char **argv = *argvp;
if(argv[1][2] != 0)
return &argv[1][2];
if(argc<=2 || argv[2][0]=='-')
error("incomplete option %s", argv[1]);
*argcp = argc-1;
*argvp = ++argv;
return argv[1];
}
void
oparse(char *s)
{
for (no = 0; no<2*NFLD && *s; no++, s++) {
switch(*s) {
case 0:
return;
case '0':
olistf[no] = F0;
break;
case '1':
case '2':
if(s[1] == '.' && isdigit(s[2])) {
olistf[no] = *s=='1'? F1: F2;
olist[no] = atoi(s += 2);
break;
} /* fall thru */
default:
error("invalid -o list", "");
}
if(s[1] == ',')
s++;
}
}

305
src/cmd/ls.C Normal file
View File

@ -0,0 +1,305 @@
#include <u.h>
#include <libc.h>
#include <bio.h>
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 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 'u': uflag++; break;
default: fprint(2, "usage: ls [-dlmnpqrstuFQ] [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; i<argc; i++)
errs |= ls(argv[i], 1);
output();
exits(errs? "errors" : 0);
}
int
ls(char *s, int multi)
{
int fd;
long i, n;
char *p;
Dir *db;
for(;;) {
p = utfrrune(s, '/');
if(p == 0 || p[1] != 0 || p == s)
break;
*p = 0;
}
db = dirstat(s);
if(db == nil){
error:
fprint(2, "ls: %s: %r\n", s);
return 1;
}
if(db->qid.type&QTDIR && dflag==0){
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; i<n; i++){
dirbuf[ndir+i].d = db+i;
dirbuf[ndir+i].prefix = multi? s : 0;
}
ndir += n;
close(fd);
output();
}else{
growto(ndir+1);
dirbuf[ndir].d = db;
dirbuf[ndir].prefix = 0;
p = utfrrune(s, '/');
if(p){
dirbuf[ndir].prefix = s;
*p = 0;
/* restore original name; don't use result of stat */
dirbuf[ndir].d->name = strdup(p+1);
}
ndir++;
}
return 0;
}
void
output(void)
{
int i;
char buf[4096];
char *s;
if(!nflag)
qsort(dirbuf, ndir, sizeof dirbuf[0], (int (*)(const void*, const void*))compar);
for(i=0; i<ndir; i++)
dowidths(dirbuf[i].d);
for(i=0; i<ndir; i++) {
if(!pflag && (s = dirbuf[i].prefix)) {
if(strcmp(s, "/") ==0) /* / is a special case */
s = "";
sprint(buf, "%s/%s", s, dirbuf[i].d->name);
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); i<mwidth; i++)
Bprint(&bin, " ");
}
if(qflag)
Bprint(&bin, "(%.16llux %*lud %.2ux) ",
db->qid.path,
qwidth, db->qid.vers,
db->qid.type);
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<b? -1 : 1);
if(rflag)
i = -i;
return i;
}
char*
asciitime(long l)
{
static char buf[32];
char *t;
t = ctime(l);
/* 6 months in the past or a day in the future */
if(l<clk-180L*24*60*60 || clk+24L*60*60<l){
memmove(buf, t+4, 7); /* month and day */
memmove(buf+7, t+23, 5); /* year */
}else
memmove(buf, t+4, 12); /* skip day of week */
buf[12] = 0;
return buf;
}

61
src/cmd/md5sum.C Normal file
View File

@ -0,0 +1,61 @@
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <libsec.h>
static int
digestfmt(Fmt *fmt)
{
char buf[MD5dlen*2+1];
uchar *p;
int i;
p = va_arg(fmt->args, uchar*);
for(i=0; i<MD5dlen; i++)
sprint(buf+2*i, "%.2ux", p[i]);
return fmtstrcpy(fmt, buf);
}
static void
sum(int fd, char *name)
{
int n;
uchar buf[8192], digest[MD5dlen];
DigestState *s;
s = md5(nil, 0, nil, nil);
while((n = read(fd, buf, sizeof buf)) > 0)
md5(buf, n, nil, s);
md5(nil, 0, digest, s);
if(name == nil)
print("%M\n", digest);
else
print("%M\t%s\n", digest, name);
}
void
main(int argc, char *argv[])
{
int i, fd;
ARGBEGIN{
default:
fprint(2, "usage: md5sum [file...]\n");
exits("usage");
}ARGEND
fmtinstall('M', digestfmt);
if(argc == 0)
sum(0, nil);
else for(i = 0; i < argc; i++){
fd = open(argv[i], OREAD);
if(fd < 0){
fprint(2, "md5sum: can't open %s: %r\n", argv[i]);
continue;
}
sum(fd, argv[i]);
close(fd);
}
exits(nil);
}

26
src/cmd/mkdir.C Normal file
View File

@ -0,0 +1,26 @@
#include <u.h>
#include <libc.h>
void
main(int argc, char *argv[])
{
int i, f;
char *e;
e = nil;
for(i=1; i<argc; i++){
if(access(argv[i], 0) == AEXIST){
fprint(2, "mkdir: %s already exists\n", argv[i]);
e = "error";
continue;
}
f = create(argv[i], OREAD, DMDIR | 0777L);
if(f < 0){
fprint(2, "mkdir: can't create %s: %r\n", argv[i]);
e = "error";
continue;
}
close(f);
}
exits(e);
}

13
src/cmd/mkfile Normal file
View File

@ -0,0 +1,13 @@
PLAN9=../..
<$PLAN9/src/mkhdr
TARG=`ls *.c | sed 's/\.c//'`
LDFLAGS=$LDFLAGS -lsec -lregexp9 -l9 -lbio -lfmt -lutf
<$PLAN9/src/mkmany
BUGGERED='CVS|oplumb|plumb|plumb2|mk|vac'
DIRS=`ls -l |sed -n 's/^d.* //p' |egrep -v "$BUGGERED"`
<$PLAN9/src/mkdirs

104
src/cmd/rm.c Normal file
View File

@ -0,0 +1,104 @@
#include <u.h>
#include <libc.h>
#define rmdir p9rmdir
char errbuf[ERRMAX];
int ignerr = 0;
void
err(char *f)
{
if(!ignerr){
errbuf[0] = '\0';
errstr(errbuf, sizeof errbuf);
fprint(2, "rm: %s: %s\n", f, errbuf);
}
}
/*
* f is a non-empty directory. Remove its contents and then it.
*/
void
rmdir(char *f)
{
char *name;
int fd, i, j, n, ndir, nname;
Dir *dirbuf;
fd = open(f, OREAD);
if(fd < 0){
err(f);
return;
}
n = dirreadall(fd, &dirbuf);
close(fd);
if(n < 0){
err("dirreadall");
return;
}
nname = strlen(f)+1+STATMAX+1; /* plenty! */
name = malloc(nname);
if(name == 0){
err("memory allocation");
return;
}
ndir = 0;
for(i=0; i<n; i++){
snprint(name, nname, "%s/%s", f, dirbuf[i].name);
if(remove(name) != -1)
dirbuf[i].qid.type = QTFILE; /* so we won't recurse */
else{
if(dirbuf[i].qid.type & QTDIR)
ndir++;
else
err(name);
}
}
if(ndir)
for(j=0; j<n; j++)
if(dirbuf[j].qid.type & QTDIR){
snprint(name, nname, "%s/%s", f, dirbuf[j].name);
rmdir(name);
}
if(remove(f) == -1)
err(f);
free(name);
free(dirbuf);
}
void
main(int argc, char *argv[])
{
int i;
int recurse;
char *f;
Dir *db;
ignerr = 0;
recurse = 0;
ARGBEGIN{
case 'r':
recurse = 1;
break;
case 'f':
ignerr = 1;
break;
default:
fprint(2, "usage: rm [-fr] file ...\n");
exits("usage");
}ARGEND
for(i=0; i<argc; i++){
f = argv[i];
if(remove(f) != -1)
continue;
db = nil;
if(recurse && (db=dirstat(f))!=nil && (db->qid.type&QTDIR))
rmdir(f);
else
err(f);
free(db);
}
exits(errbuf);
}

92
src/cmd/seq.c Normal file
View File

@ -0,0 +1,92 @@
#include <u.h>
#include <libc.h>
double min = 1.0;
double max = 0.0;
double incr = 1.0;
int constant = 0;
int nsteps;
char *format;
void
usage(void)
{
fprint(2, "usage: seq [-fformat] [-w] [first [incr]] last\n");
exits("usage");
}
void
buildfmt(void)
{
int i;
char *dp;
int w, p, maxw, maxp;
static char fmt[16];
char buf[32];
format = "%g\n";
if(!constant)
return;
maxw = 0;
maxp = 0;
for(i=0; i<=nsteps; i++){
sprint(buf, "%g", min+i*incr);
if(strchr(buf, 'e')!=0)
return;
dp = strchr(buf,'.');
w = dp==0? strlen(buf): dp-buf;
p = dp==0? 0: strlen(strchr(buf,'.')+1);
if(w>maxw)
maxw = w;
if(p>maxp)
maxp = p;
}
if(maxp > 0)
maxw += maxp+1;
sprint(fmt,"%%%d.%df\n", maxw, maxp);
format = fmt;
}
void
main(int argc, char *argv[]){
int i, j, n;
char buf[256], ffmt[4096];
ARGBEGIN{
case 'w':
constant++;
break;
case 'f':
format = ARGF();
if(format[strlen(format)-1] != '\n'){
sprint(ffmt, "%s\n", format);
format = ffmt;
}
break;
default:
goto out;
}ARGEND
out:
if(argc<1 || argc>3)
usage();
max = atof(argv[argc-1]);
if(argc > 1)
min = atof(argv[0]);
if(argc > 2)
incr = atof(argv[1]);
if(incr == 0){
fprint(2, "seq: zero increment\n");
exits("zero increment");
}
nsteps = (max-min)/incr+.5;
if(!format)
buildfmt();
for(i=0; i<=nsteps; i++){
n = sprint(buf, format, min+i*incr);
if(constant)
for(j=0; buf[j]==' '; j++)
buf[j] ='0';
write(1, buf, n);
}
exits(0);
}

61
src/cmd/sha1sum.c Normal file
View File

@ -0,0 +1,61 @@
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <libsec.h>
static int
digestfmt(Fmt *fmt)
{
char buf[SHA1dlen*2+1];
uchar *p;
int i;
p = va_arg(fmt->args, uchar*);
for(i=0; i<SHA1dlen; i++)
sprint(buf+2*i, "%.2ux", p[i]);
return fmtstrcpy(fmt, buf);
}
static void
sum(int fd, char *name)
{
int n;
uchar buf[8192], digest[SHA1dlen];
DigestState *s;
s = sha1(nil, 0, nil, nil);
while((n = read(fd, buf, sizeof buf)) > 0)
sha1(buf, n, nil, s);
sha1(nil, 0, digest, s);
if(name == nil)
print("%M\n", digest);
else
print("%M\t%s\n", digest, name);
}
void
main(int argc, char *argv[])
{
int i, fd;
ARGBEGIN{
default:
fprint(2, "usage: sha1sum [file...]\n");
exits("usage");
}ARGEND
fmtinstall('M', digestfmt);
if(argc == 0)
sum(0, nil);
else for(i = 0; i < argc; i++){
fd = open(argv[i], OREAD);
if(fd < 0){
fprint(2, "sha1sum: can't open %s: %r\n", argv[i]);
continue;
}
sum(fd, argv[i]);
close(fd);
}
exits(nil);
}

13
src/cmd/sleep.c Normal file
View File

@ -0,0 +1,13 @@
#include <u.h>
#include <libc.h>
void
main(int argc, char *argv[])
{
long secs;
if(argc>1)
for(secs = atol(argv[1]); secs > 0; secs--)
sleep(1000);
exits(0);
}

1767
src/cmd/sort.c Normal file

File diff suppressed because it is too large Load Diff

189
src/cmd/split.c Normal file
View File

@ -0,0 +1,189 @@
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <ctype.h>
#include <regexp.h>
char digit[] = "0123456789";
char *suffix = "";
char *stem = "x";
char suff[] = "aa";
char name[200];
Biobuf bout;
Biobuf *output = &bout;
extern int nextfile(void);
extern int matchfile(Resub*);
extern void openf(void);
extern char *fold(char*,int);
extern void usage(void);
extern void badexp(void);
void
main(int argc, char *argv[])
{
Reprog *exp;
char *pattern = 0;
int n = 1000;
char *line;
int xflag = 0;
int iflag = 0;
Biobuf bin;
Biobuf *b = &bin;
char buf[256];
ARGBEGIN {
case 'l':
case 'n':
n=atoi(EARGF(usage()));
break;
case 'e':
pattern = strdup(EARGF(usage()));
break;
case 'f':
stem = strdup(EARGF(usage()));
break;
case 's':
suffix = strdup(EARGF(usage()));
break;
case 'x':
xflag++;
break;
case 'i':
iflag++;
break;
default:
usage();
break;
} ARGEND;
if(argc < 0 || argc > 1)
usage();
if(argc != 0) {
b = Bopen(argv[0], OREAD);
if(b == nil) {
fprint(2, "split: can't open %s: %r\n", argv[0]);
exits("open");
}
} else
Binit(b, 0, OREAD);
if(pattern) {
if(!(exp = regcomp(iflag? fold(pattern,strlen(pattern)): pattern)))
badexp();
while((line=Brdline(b,'\n')) != 0) {
Resub match[2];
memset(match, 0, sizeof match);
line[Blinelen(b)-1] = 0;
if(regexec(exp,iflag?fold(line,Blinelen(b)-1):line,match,2)) {
if(matchfile(match) && xflag)
continue;
} else if(output == 0)
nextfile(); /* at most once */
Bwrite(output, line, Blinelen(b)-1);
Bputc(output, '\n');
}
} else {
int linecnt = n;
while((line=Brdline(b,'\n')) != 0) {
if(++linecnt > n) {
nextfile();
linecnt = 1;
}
Bwrite(output, line, Blinelen(b));
}
/*
* in case we didn't end with a newline, tack whatever's
* left onto the last file
*/
while((n = Bread(b, buf, sizeof(buf))) > 0)
Bwrite(output, buf, n);
}
if(b != nil)
Bterm(b);
exits(0);
}
int
nextfile(void)
{
static int canopen = 1;
if(suff[0] > 'z') {
if(canopen)
fprint(2, "split: file %szz not split\n",stem);
canopen = 0;
} else {
strcpy(name, stem);
strcat(name, suff);
if(++suff[1] > 'z')
suff[1] = 'a', ++suff[0];
openf();
}
return canopen;
}
int
matchfile(Resub *match)
{
if(match[1].s.sp) {
int len = match[1].e.ep - match[1].s.sp;
strncpy(name, match[1].s.sp, len);
strcpy(name+len, suffix);
openf();
return 1;
}
return nextfile();
}
void
openf(void)
{
static int fd = 0;
Bflush(output);
Bterm(output);
if(fd > 0)
close(fd);
fd = create(name,OWRITE,0666);
if(fd < 0) {
fprint(2, "grep: can't create %s: %r\n", name);
exits("create");
}
Binit(output, fd, OWRITE);
}
char *
fold(char *s, int n)
{
static char *fline;
static int linesize = 0;
char *t;
if(linesize < n+1){
fline = realloc(fline,n+1);
linesize = n+1;
}
for(t=fline; *t++ = tolower(*s++); )
continue;
/* we assume the 'A'-'Z' only appear as themselves
* in a utf encoding.
*/
return fline;
}
void
usage(void)
{
fprint(2, "usage: split [-n num] [-e exp] [-f stem] [-s suff] [-x] [-i] [file]\n");
exits("usage");
}
void
badexp(void)
{
fprint(2, "split: bad regular expression\n");
exits("bad regular expression");
}

88
src/cmd/strings.c Normal file
View File

@ -0,0 +1,88 @@
#include <u.h>
#include <libc.h>
#include <bio.h>
Biobuf *fin;
Biobuf fout;
#define MINSPAN 6 /* Min characters in string */
#define BUFSIZE 70
void stringit(char *);
int isprint(Rune);
void
main(int argc, char **argv)
{
int i;
Binit(&fout, 1, OWRITE);
if(argc < 2) {
stringit("/fd/0");
exits(0);
}
for(i = 1; i < argc; i++) {
if(argc > 2)
print("%s:\n", argv[i]);
stringit(argv[i]);
}
exits(0);
}
void
stringit(char *str)
{
long posn, start;
int cnt = 0;
long c;
Rune buf[BUFSIZE];
if ((fin = Bopen(str, OREAD)) == 0) {
perror("open");
return;
}
start = 0;
posn = Boffset(fin);
while((c = Bgetrune(fin)) >= 0) {
if(isprint(c)) {
if(start == 0)
start = posn;
buf[cnt++] = c;
if(cnt == BUFSIZE-1) {
buf[cnt] = 0;
Bprint(&fout, "%8ld: %S ...\n", start, buf);
start = 0;
cnt = 0;
}
} else {
if(cnt >= MINSPAN) {
buf[cnt] = 0;
Bprint(&fout, "%8ld: %S\n", start, buf);
}
start = 0;
cnt = 0;
}
posn = Boffset(fin);
}
if(cnt >= MINSPAN){
buf[cnt] = 0;
Bprint(&fout, "%8ld: %S\n", start, buf);
}
Bterm(fin);
}
int
isprint(Rune r)
{
if ((r >= ' ' && r <0x7f) || r > 0xA0)
return 1;
else
return 0;
}

215
src/cmd/sum.c Normal file
View File

@ -0,0 +1,215 @@
#include <u.h>
#include <libc.h>
typedef ulong Sumfn(ulong, void*, uvlong);
extern Sumfn sumr, sum5, sum32;
char *sumfile(char*, Sumfn*);
void
usage(void)
{
fprint(2, "Usage: %s [-r5] [files]\n", argv0);
exits("usage");
}
void
main(int argc, char **argv)
{
Sumfn *fn = sum32;
char *exitstr=0, *s;
ARGBEGIN{
case 'r':
fn = sumr;
break;
case '5':
fn = sum5;
break;
default:
usage();
break;
}ARGEND
if(*argv){
while(*argv)
if(s = sumfile(*argv++, fn)) /* assign = */
exitstr = s;
}else
exitstr = sumfile(0, fn);
exits(exitstr);
}
char*
sumfile(char *file, Sumfn *fn)
{
int fd;
int n;
ulong sum;
uvlong fsize;
char buf[8*1024];
if(file){
if((fd = open(file, OREAD)) < 0){
errstr(buf, sizeof buf);
fprint(2, "%s: %s: %s\n", argv0, file, buf);
return "can't open";
}
}else
fd = 0;
fsize = 0;
sum = 0;
while((n=read(fd, buf, sizeof buf)) > 0){
fsize += n;
sum = (*fn)(sum, buf, n);
}
if(n < 0){
errstr(buf, sizeof buf);
fprint(2, "%s: %s: read error: %s\n", argv0, file? file:"<stdin>", buf);
if(file)
close(fd);
return "read error";
}
if(file)
close(fd);
(*fn)(sum, (char*)0, fsize);
if(file)
print(" %s", file);
print("\n");
return 0;
}
#define VBSIZE 512 /* system v */
ulong
sum5(ulong sum, void *buf, uvlong uvn)
{
uchar *s, *send;
int n;
if(buf == 0){
sum = ((sum>>16)+sum) & 0xFFFF;
print("%.5lud%6lld", sum, (uvn+(VBSIZE-1))/VBSIZE);
return 0;
}
n = uvn;
for(s=buf, send=s+n; s<send; s++)
sum += 0xffff & *s;
return sum;
}
#define RBSIZE 1024 /* research */
ulong
sumr(ulong sum, void *buf, uvlong uvn)
{
uchar *s, *send;
int n;
if(buf == 0){
sum &= 0xFFFF;
print("%.5lud%6lld", sum, (uvn+(RBSIZE-1))/RBSIZE);
return 0;
}
n = uvn;
for(s=buf, send=s+n; s<send; s++)
if(sum & 1)
sum = 0xffff & ((sum>>1)+*s+0x8000);
else
sum = 0xffff & ((sum>>1)+*s);
return sum;
}
extern ulong crc_table[256];
ulong
sum32(ulong lcrc, void *buf, uvlong uvn)
{
uchar *s = buf;
ulong crc = lcrc;
int n;
n = uvn;
if(buf == 0){
char x[4];
x[0] = (n>>24)^0xCC; /* encode the length but make n==0 not 0 */
x[1] = (n>>16)^0x55;
x[2] = (n>>8)^0xCC;
x[3] = (n)^0x55;
crc = sum32(lcrc, x, 4);
print("%.8lux %6lld", crc, uvn);
return 0;
}
while(n-- > 0)
crc = crc_table[(crc^*s++)&0xff] ^ (crc>>8);
return crc;
}
/*
* CRC 035556101440
*/
ulong crc_table[256] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
};

362
src/cmd/tail.c Normal file
View File

@ -0,0 +1,362 @@
#include <u.h>
#include <libc.h>
#include <ctype.h>
#include <bio.h>
/*
* tail command, posix plus v10 option -r.
* the simple command tail -c, legal in v10, is illegal
*/
long count;
int anycount;
int follow;
int file = 0;
char* umsg = "usage: tail [-n N] [-c N] [-f] [-r] [+-N[bc][fr]] [file]";
Biobuf bout;
enum
{
BEG,
END
} origin = END;
enum
{
CHARS,
LINES
} units = LINES;
enum
{
FWD,
REV
} dir = FWD;
extern void copy(void);
extern void fatal(char*);
extern int getnumber(char*);
extern void keep(void);
extern void reverse(void);
extern void skip(void);
extern void suffix(char*);
extern long tread(char*, long);
extern void trunc(Dir*, Dir**);
extern long tseek(long, int);
extern void twrite(char*, long);
extern void usage(void);
#define JUMP(o,p) tseek(o,p), copy()
void
main(int argc, char **argv)
{
int seekable, c;
Binit(&bout, 1, OWRITE);
for(; argc > 1 && ((c=*argv[1])=='-'||c=='+'); argc--,argv++ ) {
if(getnumber(argv[1])) {
suffix(argv[1]);
continue;
} else
if(c == '-')
switch(argv[1][1]) {
case 'c':
units = CHARS;
case 'n':
if(getnumber(argv[1]+2))
continue;
else
if(argc > 2 && getnumber(argv[2])) {
argc--, argv++;
continue;
} else
usage();
case 'r':
dir = REV;
continue;
case 'f':
follow++;
continue;
case '-':
argc--, argv++;
}
break;
}
if(dir==REV && (units==CHARS || follow || origin==BEG))
fatal("incompatible options");
if(!anycount)
count = dir==REV? ~0UL>>1: 10;
if(origin==BEG && units==LINES && count>0)
count--;
if(argc > 2)
usage();
if(argc > 1 && (file=open(argv[1],0)) < 0)
fatal(argv[1]);
seekable = seek(file,0L,0) == 0;
if(!seekable && origin==END)
keep();
else
if(!seekable && origin==BEG)
skip();
else
if(units==CHARS && origin==END)
JUMP(-count, 2);
else
if(units==CHARS && origin==BEG)
JUMP(count, 0);
else
if(units==LINES && origin==END)
reverse();
else
if(units==LINES && origin==BEG)
skip();
if(follow && seekable)
for(;;) {
static Dir *sb0, *sb1;
trunc(sb1, &sb0);
copy();
trunc(sb0, &sb1);
sleep(5000);
}
exits(0);
}
void
trunc(Dir *old, Dir **new)
{
Dir *d;
ulong olength;
d = dirfstat(file);
if(d == nil)
return;
olength = 0;
if(old)
olength = old->length;
if(d->length < olength)
d->length = tseek(0L, 0);
free(*new);
*new = d;
}
void
suffix(char *s)
{
while(*s && strchr("0123456789+-", *s))
s++;
switch(*s) {
case 'b':
if((count *= 1024) < 0)
fatal("too big");
case 'c':
units = CHARS;
case 'l':
s++;
}
switch(*s) {
case 'r':
dir = REV;
return;
case 'f':
follow++;
return;
case 0:
return;
}
usage();
}
/*
* read past head of the file to find tail
*/
void
skip(void)
{
int i;
long n;
char buf[Bsize];
if(units == CHARS) {
for( ; count>0; count -=n) {
n = count<Bsize? count: Bsize;
if(!(n = tread(buf, n)))
return;
}
} else /*units == LINES*/ {
n = i = 0;
while(count > 0) {
if(!(n = tread(buf, Bsize)))
return;
for(i=0; i<n && count>0; i++)
if(buf[i]=='\n')
count--;
}
twrite(buf+i, n-i);
}
copy();
}
void
copy(void)
{
long n;
char buf[Bsize];
while((n=tread(buf, Bsize)) > 0) {
twrite(buf, n);
Bflush(&bout); /* for FWD on pipe; else harmless */
}
}
/*
* read whole file, keeping the tail
* complexity is length(file)*length(tail).
* could be linear.
*/
void
keep(void)
{
int len = 0;
long bufsiz = 0;
char *buf = 0;
int j, k, n;
for(n=1; n;) {
if(len+Bsize > bufsiz) {
bufsiz += 2*Bsize;
if(!(buf = realloc(buf, bufsiz+1)))
fatal("out of space");
}
for(; n && len<bufsiz; len+=n)
n = tread(buf+len, bufsiz-len);
if(count >= len)
continue;
if(units == CHARS)
j = len - count;
else {
/* units == LINES */
j = buf[len-1]=='\n'? len-1: len;
for(k=0; j>0; j--)
if(buf[j-1] == '\n')
if(++k >= count)
break;
}
memmove(buf, buf+j, len-=j);
}
if(dir == REV) {
if(len>0 && buf[len-1]!='\n')
buf[len++] = '\n';
for(j=len-1 ; j>0; j--)
if(buf[j-1] == '\n') {
twrite(buf+j, len-j);
if(--count <= 0)
return;
len = j;
}
}
if(count > 0)
twrite(buf, len);
}
/*
* count backward and print tail of file
*/
void
reverse(void)
{
int first;
long len = 0;
long n = 0;
long bufsiz = 0;
char *buf = 0;
long pos = tseek(0L, 2);
for(first=1; pos>0 && count>0; first=0) {
n = pos>Bsize? Bsize: (int)pos;
pos -= n;
if(len+n > bufsiz) {
bufsiz += 2*Bsize;
if(!(buf = realloc(buf, bufsiz+1)))
fatal("out of space");
}
memmove(buf+n, buf, len);
len += n;
tseek(pos, 0);
if(tread(buf, n) != n)
fatal("length error");
if(first && buf[len-1]!='\n')
buf[len++] = '\n';
for(n=len-1 ; n>0 && count>0; n--)
if(buf[n-1] == '\n') {
count--;
if(dir == REV)
twrite(buf+n, len-n);
len = n;
}
}
if(dir == FWD) {
tseek(n==0? 0 : pos+n+1, 0);
copy();
} else
if(count > 0)
twrite(buf, len);
}
long
tseek(long o, int p)
{
o = seek(file, o, p);
if(o == -1)
fatal("");
return o;
}
long
tread(char *buf, long n)
{
int r = read(file, buf, n);
if(r == -1)
fatal("");
return r;
}
void
twrite(char *s, long n)
{
if(Bwrite(&bout, s, n) != n)
fatal("");
}
int
getnumber(char *s)
{
if(*s=='-' || *s=='+')
s++;
if(!isdigit(*s))
return 0;
if(s[-1] == '+')
origin = BEG;
if(anycount++)
fatal("excess option");
count = atol(s);
/* check range of count */
if(count < 0 || (int)count != count)
fatal("too big");
return 1;
}
void
fatal(char *s)
{
char buf[ERRMAX];
errstr(buf, sizeof buf);
fprint(2, "tail: %s: %s\n", s, buf);
exits(s);
}
void
usage(void)
{
fprint(2, "%s\n", umsg);
exits("usage");
}

640
src/cmd/tar.C Normal file
View File

@ -0,0 +1,640 @@
#include <u.h>
#include <libc.h>
#include <bio.h>
#define TBLOCK 512
#define NBLOCK 40 /* maximum blocksize */
#define DBLOCK 20 /* default blocksize */
#define NAMSIZ 100
union hblock
{
char dummy[TBLOCK];
struct header
{
char name[NAMSIZ];
char mode[8];
char uid[8];
char gid[8];
char size[12];
char mtime[12];
char chksum[8];
char linkflag;
char linkname[NAMSIZ];
} dbuf;
} dblock, tbuf[NBLOCK];
Dir *stbuf;
Biobuf bout;
int rflag, xflag, vflag, tflag, mt, cflag, fflag, Tflag, Rflag;
int uflag, gflag;
int chksum, recno, first;
int nblock = DBLOCK;
void usage(void);
void dorep(char **);
int endtar(void);
void getdir(void);
void passtar(void);
void putfile(char*, char *, char *);
void doxtract(char **);
void dotable(void);
void putempty(void);
void longt(Dir *);
int checkdir(char *, int, Qid*);
void tomodes(Dir *);
int checksum(void);
int checkupdate(char *);
int prefix(char *, char *);
int readtar(char *);
int writetar(char *);
void backtar(void);
void flushtar(void);
void affix(int, char *);
int volprompt(void);
void
main(int argc, char **argv)
{
char *usefile;
char *cp, *ap;
if (argc < 2)
usage();
Binit(&bout, 1, OWRITE);
usefile = 0;
argv[argc] = 0;
argv++;
for (cp = *argv++; *cp; cp++)
switch(*cp) {
case 'f':
usefile = *argv++;
if(!usefile)
usage();
fflag++;
break;
case 'u':
ap = *argv++;
if(!ap)
usage();
uflag = strtoul(ap, 0, 0);
break;
case 'g':
ap = *argv++;
if(!ap)
usage();
gflag = strtoul(ap, 0, 0);
break;
case 'c':
cflag++;
rflag++;
break;
case 'r':
rflag++;
break;
case 'v':
vflag++;
break;
case 'x':
xflag++;
break;
case 'T':
Tflag++;
break;
case 't':
tflag++;
break;
case 'R':
Rflag++;
break;
case '-':
break;
default:
fprint(2, "tar: %c: unknown option\n", *cp);
usage();
}
fmtinstall('M', dirmodefmt);
if (rflag) {
if (!usefile) {
if (cflag == 0) {
fprint(2, "tar: can only create standard output archives\n");
exits("arg error");
}
mt = dup(1, -1);
nblock = 1;
}
else if ((mt = open(usefile, ORDWR)) < 0) {
if (cflag == 0 || (mt = create(usefile, OWRITE, 0666)) < 0) {
fprint(2, "tar: cannot open %s: %r\n", usefile);
exits("open");
}
}
dorep(argv);
}
else if (xflag) {
if (!usefile) {
mt = dup(0, -1);
nblock = 1;
}
else if ((mt = open(usefile, OREAD)) < 0) {
fprint(2, "tar: cannot open %s: %r\n", usefile);
exits("open");
}
doxtract(argv);
}
else if (tflag) {
if (!usefile) {
mt = dup(0, -1);
nblock = 1;
}
else if ((mt = open(usefile, OREAD)) < 0) {
fprint(2, "tar: cannot open %s: %r\n", usefile);
exits("open");
}
dotable();
}
else
usage();
exits(0);
}
void
usage(void)
{
fprint(2, "tar: usage tar {txrc}[Rvf] [tarfile] file1 file2...\n");
exits("usage");
}
void
dorep(char **argv)
{
char cwdbuf[2048], *cwd, thisdir[2048];
char *cp, *cp2;
int cd;
if (getwd(cwdbuf, sizeof(cwdbuf)) == 0) {
fprint(2, "tar: can't find current directory: %r\n");
exits("cwd");
}
cwd = cwdbuf;
if (!cflag) {
getdir();
do {
passtar();
getdir();
} while (!endtar());
}
while (*argv) {
cp2 = *argv;
if (!strcmp(cp2, "-C") && argv[1]) {
argv++;
if (chdir(*argv) < 0)
perror(*argv);
cwd = *argv;
argv++;
continue;
}
cd = 0;
for (cp = *argv; *cp; cp++)
if (*cp == '/')
cp2 = cp;
if (cp2 != *argv) {
*cp2 = '\0';
chdir(*argv);
if(**argv == '/')
strncpy(thisdir, *argv, sizeof(thisdir));
else
snprint(thisdir, sizeof(thisdir), "%s/%s", cwd, *argv);
*cp2 = '/';
cp2++;
cd = 1;
} else
strncpy(thisdir, cwd, sizeof(thisdir));
putfile(thisdir, *argv++, cp2);
if(cd && chdir(cwd) < 0) {
fprint(2, "tar: can't cd back to %s: %r\n", cwd);
exits("cwd");
}
}
putempty();
putempty();
flushtar();
}
int
endtar(void)
{
if (dblock.dbuf.name[0] == '\0') {
backtar();
return(1);
}
else
return(0);
}
void
getdir(void)
{
Dir *sp;
readtar((char*)&dblock);
if (dblock.dbuf.name[0] == '\0')
return;
if(stbuf == nil){
stbuf = malloc(sizeof(Dir));
if(stbuf == nil) {
fprint(2, "tar: can't malloc: %r\n");
exits("malloc");
}
}
sp = stbuf;
sp->mode = strtol(dblock.dbuf.mode, 0, 8);
sp->uid = "adm";
sp->gid = "adm";
sp->length = strtol(dblock.dbuf.size, 0, 8);
sp->mtime = strtol(dblock.dbuf.mtime, 0, 8);
chksum = strtol(dblock.dbuf.chksum, 0, 8);
if (chksum != checksum()) {
fprint(2, "directory checksum error\n");
exits("checksum error");
}
sp->qid.type = 0;
/* the mode test is ugly but sometimes necessary */
if (dblock.dbuf.linkflag == '5' || (sp->mode&0170000) == 040000) {
sp->qid.type |= QTDIR;
sp->mode |= DMDIR;
}
}
void
passtar(void)
{
long blocks;
char buf[TBLOCK];
if (dblock.dbuf.linkflag == '1' || dblock.dbuf.linkflag == 's')
return;
blocks = stbuf->length;
blocks += TBLOCK-1;
blocks /= TBLOCK;
while (blocks-- > 0)
readtar(buf);
}
void
putfile(char *dir, char *longname, char *sname)
{
int infile;
long blocks;
char buf[TBLOCK];
char curdir[4096];
char shortname[4096];
char *cp, *cp2;
Dir *db;
int i, n;
if(strlen(sname) > sizeof shortname - 3){
fprint(2, "tar: %s: name too long (max %d)\n", sname, sizeof shortname - 3);
return;
}
snprint(shortname, sizeof shortname, "./%s", sname);
infile = open(shortname, OREAD);
if (infile < 0) {
fprint(2, "tar: %s: cannot open file - %r\n", longname);
return;
}
if(stbuf != nil)
free(stbuf);
stbuf = dirfstat(infile);
if (stbuf->qid.type & QTDIR) {
/* Directory */
for (i = 0, cp = buf; *cp++ = longname[i++];);
*--cp = '/';
*++cp = 0;
if( (cp - buf) >= NAMSIZ) {
fprint(2, "tar: %s: file name too long\n", longname);
close(infile);
return;
}
stbuf->length = 0;
tomodes(stbuf);
strcpy(dblock.dbuf.name,buf);
dblock.dbuf.linkflag = '5'; /* Directory */
sprint(dblock.dbuf.chksum, "%6o", checksum());
writetar( (char *) &dblock);
if (chdir(shortname) < 0) {
fprint(2, "tar: can't cd to %s: %r\n", shortname);
snprint(curdir, sizeof(curdir), "cd %s", shortname);
exits(curdir);
}
sprint(curdir, "%s/%s", dir, sname);
while ((n = dirread(infile, &db)) > 0) {
for(i = 0; i < n; i++){
strncpy(cp, db[i].name, sizeof buf - (cp-buf));
putfile(curdir, buf, db[i].name);
}free(db);
}
close(infile);
if (chdir(dir) < 0 && chdir("..") < 0) {
fprint(2, "tar: can't cd to ..(%s): %r\n", dir);
snprint(curdir, sizeof(curdir), "cd ..(%s)", dir);
exits(curdir);
}
return;
}
tomodes(stbuf);
cp2 = longname;
for (cp = dblock.dbuf.name, i=0; (*cp++ = *cp2++) && i < NAMSIZ; i++);
if (i >= NAMSIZ) {
fprint(2, "%s: file name too long\n", longname);
close(infile);
return;
}
blocks = (stbuf->length + (TBLOCK-1)) / TBLOCK;
if (vflag) {
fprint(2, "a %s ", longname);
fprint(2, "%ld blocks\n", blocks);
}
dblock.dbuf.linkflag = 0; /* Regular file */
sprint(dblock.dbuf.chksum, "%6o", checksum());
writetar( (char *) &dblock);
while ((i = readn(infile, buf, TBLOCK)) > 0 && blocks > 0) {
writetar(buf);
blocks--;
}
close(infile);
if (blocks != 0 || i != 0)
fprint(2, "%s: file changed size\n", longname);
while (blocks-- > 0)
putempty();
}
void
doxtract(char **argv)
{
Dir null;
long blocks, bytes;
char buf[TBLOCK], outname[NAMSIZ+4];
char **cp;
int ofile;
for (;;) {
getdir();
if (endtar())
break;
if (*argv == 0)
goto gotit;
for (cp = argv; *cp; cp++)
if (prefix(*cp, dblock.dbuf.name))
goto gotit;
passtar();
continue;
gotit:
if(checkdir(dblock.dbuf.name, stbuf->mode, &(stbuf->qid)))
continue;
if (dblock.dbuf.linkflag == '1') {
fprint(2, "tar: can't link %s %s\n",
dblock.dbuf.linkname, dblock.dbuf.name);
remove(dblock.dbuf.name);
continue;
}
if (dblock.dbuf.linkflag == 's') {
fprint(2, "tar: %s: cannot symlink\n", dblock.dbuf.name);
continue;
}
if(dblock.dbuf.name[0] != '/' || Rflag)
sprint(outname, "./%s", dblock.dbuf.name);
else
strcpy(outname, dblock.dbuf.name);
if ((ofile = create(outname, OWRITE, stbuf->mode & 0777)) < 0) {
fprint(2, "tar: %s - cannot create: %r\n", outname);
passtar();
continue;
}
blocks = ((bytes = stbuf->length) + TBLOCK-1)/TBLOCK;
if (vflag)
fprint(2, "x %s, %ld bytes\n",
dblock.dbuf.name, bytes);
while (blocks-- > 0) {
readtar(buf);
if (bytes > TBLOCK) {
if (write(ofile, buf, TBLOCK) < 0) {
fprint(2, "tar: %s: HELP - extract write error: %r\n", dblock.dbuf.name);
exits("extract write");
}
} else
if (write(ofile, buf, bytes) < 0) {
fprint(2, "tar: %s: HELP - extract write error: %r\n", dblock.dbuf.name);
exits("extract write");
}
bytes -= TBLOCK;
}
if(Tflag){
nulldir(&null);
null.mtime = stbuf->mtime;
dirfwstat(ofile, &null);
}
close(ofile);
}
}
void
dotable(void)
{
for (;;) {
getdir();
if (endtar())
break;
if (vflag)
longt(stbuf);
Bprint(&bout, "%s", dblock.dbuf.name);
if (dblock.dbuf.linkflag == '1')
Bprint(&bout, " linked to %s", dblock.dbuf.linkname);
if (dblock.dbuf.linkflag == 's')
Bprint(&bout, " -> %s", dblock.dbuf.linkname);
Bprint(&bout, "\n");
passtar();
}
}
void
putempty(void)
{
char buf[TBLOCK];
memset(buf, 0, TBLOCK);
writetar(buf);
}
void
longt(Dir *st)
{
char *cp;
Bprint(&bout, "%M %4d/%1d ", st->mode, 0, 0); /* 0/0 uid/gid */
Bprint(&bout, "%8lld", st->length);
cp = ctime(st->mtime);
Bprint(&bout, " %-12.12s %-4.4s ", cp+4, cp+24);
}
int
checkdir(char *name, int mode, Qid *qid)
{
char *cp;
int f;
Dir *d, null;
if(Rflag && *name == '/')
name++;
cp = name;
if(*cp == '/')
cp++;
for (; *cp; cp++) {
if (*cp == '/') {
*cp = '\0';
if (access(name, 0) < 0) {
f = create(name, OREAD, DMDIR + 0775L);
if(f < 0)
fprint(2, "tar: mkdir %s failed: %r\n", name);
close(f);
}
*cp = '/';
}
}
/* if this is a directory, chmod it to the mode in the tar plus 700 */
if(cp[-1] == '/' || (qid->type&QTDIR)){
if((d=dirstat(name)) != 0){
nulldir(&null);
null.mode = DMDIR | (mode & 0777) | 0700;
dirwstat(name, &null);
free(d);
}
return 1;
} else
return 0;
}
void
tomodes(Dir *sp)
{
char *cp;
for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++)
*cp = '\0';
sprint(dblock.dbuf.mode, "%6lo ", sp->mode & 0777);
sprint(dblock.dbuf.uid, "%6o ", uflag);
sprint(dblock.dbuf.gid, "%6o ", gflag);
sprint(dblock.dbuf.size, "%11llo ", sp->length);
sprint(dblock.dbuf.mtime, "%11lo ", sp->mtime);
}
int
checksum(void)
{
int i;
char *cp;
for (cp = dblock.dbuf.chksum; cp < &dblock.dbuf.chksum[sizeof(dblock.dbuf.chksum)]; cp++)
*cp = ' ';
i = 0;
for (cp = dblock.dummy; cp < &dblock.dummy[TBLOCK]; cp++)
i += *cp & 0xff;
return(i);
}
int
prefix(char *s1, char *s2)
{
while (*s1)
if (*s1++ != *s2++)
return(0);
if (*s2)
return(*s2 == '/');
return(1);
}
int
readtar(char *buffer)
{
int i;
if (recno >= nblock || first == 0) {
if ((i = readn(mt, tbuf, TBLOCK*nblock)) <= 0) {
fprint(2, "tar: archive read error: %r\n");
exits("archive read");
}
if (first == 0) {
if ((i % TBLOCK) != 0) {
fprint(2, "tar: archive blocksize error: %r\n");
exits("blocksize");
}
i /= TBLOCK;
if (i != nblock) {
fprint(2, "tar: blocksize = %d\n", i);
nblock = i;
}
}
recno = 0;
}
first = 1;
memmove(buffer, &tbuf[recno++], TBLOCK);
return(TBLOCK);
}
int
writetar(char *buffer)
{
first = 1;
if (recno >= nblock) {
if (write(mt, tbuf, TBLOCK*nblock) != TBLOCK*nblock) {
fprint(2, "tar: archive write error: %r\n");
exits("write");
}
recno = 0;
}
memmove(&tbuf[recno++], buffer, TBLOCK);
if (recno >= nblock) {
if (write(mt, tbuf, TBLOCK*nblock) != TBLOCK*nblock) {
fprint(2, "tar: archive write error: %r\n");
exits("write");
}
recno = 0;
}
return(TBLOCK);
}
/*
* backup over last tar block
*/
void
backtar(void)
{
seek(mt, -TBLOCK*nblock, 1);
recno--;
}
void
flushtar(void)
{
write(mt, tbuf, TBLOCK*nblock);
}

75
src/cmd/tee.c Normal file
View File

@ -0,0 +1,75 @@
/*
* tee-- pipe fitting
*/
#include <u.h>
#include <libc.h>
int uflag;
int aflag;
int openf[100];
char in[8192];
int intignore(void*, char*);
void
main(int argc, char **argv)
{
int i;
int r, n;
ARGBEGIN {
case 'a':
aflag++;
break;
case 'i':
atnotify(intignore, 1);
break;
case 'u':
uflag++;
/* uflag is ignored and undocumented; it's a relic from Unix */
break;
default:
fprint(2, "usage: tee [-ai] [file ...]\n");
exits("usage");
} ARGEND
USED(argc);
n = 0;
while(*argv) {
if(aflag) {
openf[n] = open(argv[0], OWRITE);
if(openf[n] < 0)
openf[n] = create(argv[0], OWRITE, 0666);
seek(openf[n], 0L, 2);
} else
openf[n] = create(argv[0], OWRITE, 0666);
if(openf[n] < 0) {
fprint(2, "tee: cannot open %s: %r\n", argv[0]);
} else
n++;
argv++;
}
openf[n++] = 1;
for(;;) {
r = read(0, in, sizeof in);
if(r <= 0)
exits(nil);
for(i=0; i<n; i++)
write(openf[i], in, r);
}
}
int
intignore(void *a, char *msg)
{
USED(a);
if(strcmp(msg, "interrupt") == 0)
return 1;
return 0;
}

303
src/cmd/test.c Normal file
View File

@ -0,0 +1,303 @@
/*
* POSIX standard
* test expression
* [ expression ]
*
* Plan 9 additions:
* -A file exists and is append-only
* -L file exists and is exclusive-use
*/
#include <u.h>
#include <libc.h>
#define EQ(a,b) ((tmp=a)==0?0:(strcmp(tmp,b)==0))
int ap;
int ac;
char **av;
char *tmp;
void synbad(char *, char *);
int fsizep(char *);
int isdir(char *);
int isreg(char *);
int isatty(int);
int isint(char *, int *);
int hasmode(char *, ulong);
int tio(char *, int);
int e(void), e1(void), e2(void), e3(void);
void
main(int argc, char *argv[])
{
ac = argc; av = argv; ap = 1;
if(EQ(argv[0],"[")) {
if(!EQ(argv[--ac],"]"))
synbad("] missing","");
}
argv[ac] = 0;
if (ac<=1) exits("usage");
exits(e()?0:"false");
}
char *
nxtarg(int mt)
{
if(ap>=ac){
if(mt){
ap++;
return(0);
}
synbad("argument expected","");
}
return(av[ap++]);
}
int
nxtintarg(int *pans)
{
if(ap<ac && isint(av[ap], pans)){
ap++;
return 1;
}
return 0;
}
int
e(void) {
int p1;
p1 = e1();
if (EQ(nxtarg(1), "-o")) return(p1 || e());
ap--;
return(p1);
}
int
e1(void) {
int p1;
p1 = e2();
if (EQ(nxtarg(1), "-a")) return (p1 && e1());
ap--;
return(p1);
}
int
e2(void) {
if (EQ(nxtarg(0), "!"))
return(!e2());
ap--;
return(e3());
}
int
e3(void) {
int p1;
char *a;
char *p2;
int int1, int2;
a = nxtarg(0);
if(EQ(a, "(")) {
p1 = e();
if(!EQ(nxtarg(0), ")")) synbad(") expected","");
return(p1);
}
if(EQ(a, "-A"))
return(hasmode(nxtarg(0), DMAPPEND));
if(EQ(a, "-L"))
return(hasmode(nxtarg(0), DMEXCL));
if(EQ(a, "-f"))
return(isreg(nxtarg(0)));
if(EQ(a, "-d"))
return(isdir(nxtarg(0)));
if(EQ(a, "-r"))
return(tio(nxtarg(0), 4));
if(EQ(a, "-w"))
return(tio(nxtarg(0), 2));
if(EQ(a, "-x"))
return(tio(nxtarg(0), 1));
if(EQ(a, "-e"))
return(tio(nxtarg(0), 0));
if(EQ(a, "-c"))
return(0);
if(EQ(a, "-b"))
return(0);
if(EQ(a, "-u"))
return(0);
if(EQ(a, "-g"))
return(0);
if(EQ(a, "-s"))
return(fsizep(nxtarg(0)));
if(EQ(a, "-t"))
if(ap>=ac || !nxtintarg(&int1))
return(isatty(1));
else
return(isatty(int1));
if(EQ(a, "-n"))
return(!EQ(nxtarg(0), ""));
if(EQ(a, "-z"))
return(EQ(nxtarg(0), ""));
p2 = nxtarg(1);
if (p2==0)
return(!EQ(a,""));
if(EQ(p2, "="))
return(EQ(nxtarg(0), a));
if(EQ(p2, "!="))
return(!EQ(nxtarg(0), a));
if(!isint(a, &int1))
return(!EQ(a,""));
if(nxtintarg(&int2)){
if(EQ(p2, "-eq"))
return(int1==int2);
if(EQ(p2, "-ne"))
return(int1!=int2);
if(EQ(p2, "-gt"))
return(int1>int2);
if(EQ(p2, "-lt"))
return(int1<int2);
if(EQ(p2, "-ge"))
return(int1>=int2);
if(EQ(p2, "-le"))
return(int1<=int2);
}
synbad("unknown operator ",p2);
return 0; /* to shut ken up */
}
int
tio(char *a, int f)
{
return access (a, f) >= 0;
}
/* copy to local memory; clear names for safety */
int
localstat(char *f, Dir *dir)
{
Dir *d;
d = dirstat(f);
if(d == 0)
return(-1);
*dir = *d;
dir->name = 0;
dir->uid = 0;
dir->gid = 0;
dir->muid = 0;
return 0;
}
/* copy to local memory; clear names for safety */
int
localfstat(int f, Dir *dir)
{
Dir *d;
d = dirfstat(f);
if(d == 0)
return(-1);
*dir = *d;
dir->name = 0;
dir->uid = 0;
dir->gid = 0;
dir->muid = 0;
return 0;
}
int
hasmode(char *f, ulong m)
{
Dir dir;
if(localstat(f,&dir)<0)
return(0);
return(dir.mode&m);
}
int
isdir(char *f)
{
Dir dir;
if(localstat(f,&dir)<0)
return(0);
return(dir.mode&DMDIR);
}
int
isreg(char *f)
{
Dir dir;
if(localstat(f,&dir)<0)
return(0);
return(!(dir.mode&DMDIR));
}
int
isatty(int fd)
{
Dir d1, d2;
if(localfstat(fd, &d1) < 0)
return 0;
if(localstat("/dev/cons", &d2) < 0)
return 0;
return d1.type==d2.type && d1.dev==d2.dev && d1.qid.path==d2.qid.path;
}
int
fsizep(char *f)
{
Dir dir;
if(localstat(f,&dir)<0)
return(0);
return(dir.length>0);
}
void
synbad(char *s1, char *s2)
{
int len;
write(2, "test: ", 6);
if ((len = strlen(s1)) != 0)
write(2, s1, len);
if ((len = strlen(s2)) != 0)
write(2, s2, len);
write(2, "\n", 1);
exits("bad syntax");
}
int
isint(char *s, int *pans)
{
char *ep;
*pans = strtol(s, &ep, 0);
return (*ep == 0);
}

101
src/cmd/time.c Normal file
View File

@ -0,0 +1,101 @@
#include <u.h>
#include <libc.h>
char output[4096];
void add(char*, ...);
void error(char*);
void notifyf(void*, char*);
void
main(int argc, char *argv[])
{
int i;
Waitmsg *w;
long l;
char *p;
char err[ERRMAX];
if(argc <= 1){
fprint(2, "usage: time command\n");
exits("usage");
}
switch(fork()){
case -1:
error("fork");
case 0:
exec(argv[1], &argv[1]);
if(argv[1][0] != '/' && strncmp(argv[1], "./", 2) &&
strncmp(argv[1], "../", 3)){
sprint(output, "/bin/%s", argv[1]);
exec(output, &argv[1]);
}
error(argv[1]);
}
notify(notifyf);
loop:
w = wait();
if(w == nil){
errstr(err, sizeof err);
if(strcmp(err, "interrupted") == 0)
goto loop;
error("wait");
}
l = w->time[0];
add("%ld.%.2ldu", l/1000, (l%1000)/10);
l = w->time[1];
add("%ld.%.2lds", l/1000, (l%1000)/10);
l = w->time[2];
add("%ld.%.2ldr", l/1000, (l%1000)/10);
add("\t");
for(i=1; i<argc; i++){
add("%s", argv[i], 0);
if(i>4){
add("...");
break;
}
}
if(w->msg[0]){
p = utfrune(w->msg, ':');
if(p && p[1])
p++;
else
p = w->msg;
add(" # status=%s", p);
}
fprint(2, "%s\n", output);
exits(w->msg);
}
void
add(char *a, ...)
{
static int beenhere=0;
va_list arg;
if(beenhere)
strcat(output, " ");
va_start(arg, a);
vseprint(output+strlen(output), output+sizeof(output), a, arg);
va_end(arg);
beenhere++;
}
void
error(char *s)
{
fprint(2, "time: %s: %r\n", s);
exits(s);
}
void
notifyf(void *a, char *s)
{
USED(a);
if(strcmp(s, "interrupt") == 0)
noted(NCONT);
noted(NDFLT);
}

62
src/cmd/touch.c Normal file
View File

@ -0,0 +1,62 @@
#include <u.h>
#include <libc.h>
int touch(int, char *);
ulong now;
void
usage(void)
{
fprint(2, "usage: touch [-c] [-t time] files\n");
exits("usage");
}
void
main(int argc, char **argv)
{
int nocreate = 0;
int status = 0;
now = time(0);
ARGBEGIN{
case 't':
now = strtoul(EARGF(usage()), 0, 0);
break;
case 'c':
nocreate = 1;
break;
default:
usage();
}ARGEND
if(!*argv)
usage();
while(*argv)
status += touch(nocreate, *argv++);
if(status)
exits("touch");
exits(0);
}
int
touch(int nocreate, char *name)
{
Dir stbuff;
int fd;
nulldir(&stbuff);
stbuff.mtime = now;
if(dirwstat(name, &stbuff) >= 0)
return 0;
if(nocreate){
fprint(2, "touch: %s: cannot wstat: %r\n", name);
return 1;
}
if ((fd = create(name, OREAD, 0666)) < 0) {
fprint(2, "touch: %s: cannot create: %r\n", name);
return 1;
}
dirfwstat(fd, &stbuff);
close(fd);
return 0;
}

356
src/cmd/tr.c Normal file
View File

@ -0,0 +1,356 @@
#include <u.h>
#include <libc.h>
typedef struct PCB /* Control block controlling specification parse */
{
char *base; /* start of specification */
char *current; /* current parse point */
long last; /* last Rune returned */
long final; /* final Rune in a span */
} Pcb;
uchar bits[] = { 1, 2, 4, 8, 16, 32, 64, 128 };
#define SETBIT(a, c) ((a)[(c)/8] |= bits[(c)&07])
#define CLEARBIT(a,c) ((a)[(c)/8] &= ~bits[(c)&07])
#define BITSET(a,c) ((a)[(c)/8] & bits[(c)&07])
#define MAXRUNE 0xFFFF
uchar f[(MAXRUNE+1)/8];
uchar t[(MAXRUNE+1)/8];
char wbuf[4096];
char *wptr;
Pcb pfrom, pto;
int cflag;
int dflag;
int sflag;
void complement(void);
void delete(void);
void squeeze(void);
void translit(void);
void error(char*);
long canon(Pcb*);
char *getrune(char*, Rune*);
void Pinit(Pcb*, char*);
void Prewind(Pcb *p);
int readrune(int, long*);
void wflush(int);
void writerune(int, Rune);
void
main(int argc, char **argv)
{
ARGBEGIN{
case 's': sflag++; break;
case 'd': dflag++; break;
case 'c': cflag++; break;
default: error("bad option");
}ARGEND
if(argc>0)
Pinit(&pfrom, argv[0]);
if(argc>1)
Pinit(&pto, argv[1]);
if(argc>2)
error("arg count");
if(dflag) {
if ((sflag && argc != 2) || (!sflag && argc != 1))
error("arg count");
delete();
} else {
if (argc != 2)
error("arg count");
if (cflag)
complement();
else translit();
}
exits(0);
}
void
delete(void)
{
long c, last;
if (cflag) {
memset((char *) f, 0xff, sizeof f);
while ((c = canon(&pfrom)) >= 0)
CLEARBIT(f, c);
} else {
while ((c = canon(&pfrom)) >= 0)
SETBIT(f, c);
}
if (sflag) {
while ((c = canon(&pto)) >= 0)
SETBIT(t, c);
}
last = 0x10000;
while (readrune(0, &c) > 0) {
if(!BITSET(f, c) && (c != last || !BITSET(t,c))) {
last = c;
writerune(1, (Rune) c);
}
}
wflush(1);
}
void
complement(void)
{
Rune *p;
int i;
long from, to, lastc, high;
lastc = 0;
high = 0;
while ((from = canon(&pfrom)) >= 0) {
if (from > high) high = from;
SETBIT(f, from);
}
while ((to = canon(&pto)) > 0) {
if (to > high) high = to;
SETBIT(t,to);
}
Prewind(&pto);
if ((p = (Rune *) malloc((high+1)*sizeof(Rune))) == 0)
error("can't allocate memory");
for (i = 0; i <= high; i++){
if (!BITSET(f,i)) {
if ((to = canon(&pto)) < 0)
to = lastc;
else lastc = to;
p[i] = to;
}
else p[i] = i;
}
if (sflag){
lastc = 0x10000;
while (readrune(0, &from) > 0) {
if (from > high)
from = to;
else
from = p[from];
if (from != lastc || !BITSET(t,from)) {
lastc = from;
writerune(1, (Rune) from);
}
}
} else {
while (readrune(0, &from) > 0){
if (from > high)
from = to;
else
from = p[from];
writerune(1, (Rune) from);
}
}
wflush(1);
}
void
translit(void)
{
Rune *p;
int i;
long from, to, lastc, high;
lastc = 0;
high = 0;
while ((from = canon(&pfrom)) >= 0)
if (from > high) high = from;
Prewind(&pfrom);
if ((p = (Rune *) malloc((high+1)*sizeof(Rune))) == 0)
error("can't allocate memory");
for (i = 0; i <= high; i++)
p[i] = i;
while ((from = canon(&pfrom)) >= 0) {
if ((to = canon(&pto)) < 0)
to = lastc;
else lastc = to;
if (BITSET(f,from) && p[from] != to)
error("ambiguous translation");
SETBIT(f,from);
p[from] = to;
SETBIT(t,to);
}
while ((to = canon(&pto)) >= 0) {
SETBIT(t,to);
}
if (sflag){
lastc = 0x10000;
while (readrune(0, &from) > 0) {
if (from <= high)
from = p[from];
if (from != lastc || !BITSET(t,from)) {
lastc = from;
writerune(1, (Rune) from);
}
}
} else {
while (readrune(0, &from) > 0) {
if (from <= high)
from = p[from];
writerune(1, (Rune) from);
}
}
wflush(1);
}
int
readrune(int fd, long *rp)
{
Rune r;
int j;
static int i, n;
static char buf[4096];
j = i;
for (;;) {
if (i >= n) {
wflush(1);
if (j != i)
memcpy(buf, buf+j, n-j);
i = n-j;
n = read(fd, &buf[i], sizeof(buf)-i);
if (n < 0)
error("read error");
if (n == 0)
return 0;
j = 0;
n += i;
}
i++;
if (fullrune(&buf[j], i-j))
break;
}
chartorune(&r, &buf[j]);
*rp = r;
return 1;
}
void
writerune(int fd, Rune r)
{
char buf[UTFmax];
int n;
if (!wptr)
wptr = wbuf;
n = runetochar(buf, (Rune*)&r);
if (wptr+n >= wbuf+sizeof(wbuf))
wflush(fd);
memcpy(wptr, buf, n);
wptr += n;
}
void
wflush(int fd)
{
if (wptr && wptr > wbuf)
if (write(fd, wbuf, wptr-wbuf) != wptr-wbuf)
error("write error");
wptr = wbuf;
}
char *
getrune(char *s, Rune *rp)
{
Rune r;
char *save;
int i, n;
s += chartorune(rp, s);
if((r = *rp) == '\\' && *s){
n = 0;
if (*s == 'x') {
s++;
for (i = 0; i < 4; i++) {
save = s;
s += chartorune(&r, s);
if ('0' <= r && r <= '9')
n = 16*n + r - '0';
else if ('a' <= r && r <= 'f')
n = 16*n + r - 'a' + 10;
else if ('A' <= r && r <= 'F')
n = 16*n + r - 'A' + 10;
else {
if (i == 0)
*rp = 'x';
else *rp = n;
return save;
}
}
} else {
for(i = 0; i < 3; i++) {
save = s;
s += chartorune(&r, s);
if('0' <= r && r <= '7')
n = 8*n + r - '0';
else {
if (i == 0)
{
*rp = r;
return s;
}
*rp = n;
return save;
}
}
if(n > 0377)
error("char>0377");
}
*rp = n;
}
return s;
}
long
canon(Pcb *p)
{
Rune r;
if (p->final >= 0) {
if (p->last < p->final)
return ++p->last;
p->final = -1;
}
if (*p->current == '\0')
return -1;
if(*p->current == '-' && p->last >= 0 && p->current[1]){
p->current = getrune(p->current+1, &r);
if (r < p->last)
error ("Invalid range specification");
if (r > p->last) {
p->final = r;
return ++p->last;
}
}
p->current = getrune(p->current, &r);
p->last = r;
return p->last;
}
void
Pinit(Pcb *p, char *cp)
{
p->current = p->base = cp;
p->last = p->final = -1;
}
void
Prewind(Pcb *p)
{
p->current = p->base;
p->last = p->final = -1;
}
void
error(char *s)
{
fprint(2, "%s: %s\n", argv0, s);
exits(s);
}

122
src/cmd/unicode.c Normal file
View File

@ -0,0 +1,122 @@
#include <u.h>
#include <libc.h>
#include <bio.h>
char usage[] = "unicode { [-t] hex hex ... | hexmin-hexmax ... | [-n] char ... }";
char hex[] = "0123456789abcdefABCDEF";
int numout = 0;
int text = 0;
char *err;
Biobuf bout;
char *range(char*[]);
char *nums(char*[]);
char *chars(char*[]);
void
main(int argc, char *argv[])
{
ARGBEGIN{
case 'n':
numout = 1;
break;
case 't':
text = 1;
break;
}ARGEND
Binit(&bout, 1, OWRITE);
if(argc == 0){
fprint(2, "usage: %s\n", usage);
exits("usage");
}
if(!numout && utfrune(argv[0], '-'))
exits(range(argv));
if(numout || strchr(hex, argv[0][0])==0)
exits(nums(argv));
exits(chars(argv));
}
char*
range(char *argv[])
{
char *q;
int min, max;
int i;
while(*argv){
q = *argv;
if(strchr(hex, q[0]) == 0){
err:
fprint(2, "unicode: bad range %s\n", *argv);
return "bad range";
}
min = strtoul(q, &q, 16);
if(min<0 || min>0xFFFF || *q!='-')
goto err;
q++;
if(strchr(hex, *q) == 0)
goto err;
max = strtoul(q, &q, 16);
if(max<0 || max>0xFFFF || max<min || *q!=0)
goto err;
i = 0;
do{
Bprint(&bout, "%.4x %C", min, min);
i++;
if(min==max || (i&7)==0)
Bprint(&bout, "\n");
else
Bprint(&bout, "\t");
min++;
}while(min<=max);
argv++;
}
return 0;
}
char*
nums(char *argv[])
{
char *q;
Rune r;
int w;
while(*argv){
q = *argv;
while(*q){
w = chartorune(&r, q);
if(r==0x80 && (q[0]&0xFF)!=0x80){
fprint(2, "unicode: invalid utf string %s\n", *argv);
return "bad utf";
}
Bprint(&bout, "%.4x\n", r);
q += w;
}
argv++;
}
return 0;
}
char*
chars(char *argv[])
{
char *q;
int m;
while(*argv){
q = *argv;
if(strchr(hex, q[0]) == 0){
err:
fprint(2, "unicode: bad unicode value %s\n", *argv);
return "bad char";
}
m = strtoul(q, &q, 16);
if(m<0 || m>0xFFFF || *q!=0)
goto err;
Bprint(&bout, "%C", m);
if(!text)
Bprint(&bout, "\n");
argv++;
}
return 0;
}

169
src/cmd/uniq.c Normal file
View File

@ -0,0 +1,169 @@
/*
* Deal with duplicated lines in a file
*/
#include <u.h>
#include <libc.h>
#include <bio.h>
#include <ctype.h>
#define SIZE 8000
int fields = 0;
int letters = 0;
int linec = 0;
char mode;
int uniq;
char *b1, *b2;
long bsize;
Biobuf fin;
Biobuf fout;
int gline(char *buf);
void pline(char *buf);
int equal(char *b1, char *b2);
char* skip(char *s);
void
main(int argc, char *argv[])
{
int f;
bsize = SIZE;
b1 = malloc(bsize);
b2 = malloc(bsize);
f = 0;
while(argc > 1) {
if(*argv[1] == '-') {
if(isdigit(argv[1][1]))
fields = atoi(&argv[1][1]);
else
mode = argv[1][1];
argc--;
argv++;
continue;
}
if(*argv[1] == '+') {
letters = atoi(&argv[1][1]);
argc--;
argv++;
continue;
}
f = open(argv[1], 0);
if(f < 0) {
fprint(2, "cannot open %s\n", argv[1]);
exits("open");
}
break;
}
if(argc > 2) {
fprint(2, "unexpected argument %s\n", argv[2]);
exits("arg");
}
Binit(&fin, f, OREAD);
Binit(&fout, 1, OWRITE);
if(gline(b1))
exits(0);
for(;;) {
linec++;
if(gline(b2)) {
pline(b1);
exits(0);
}
if(!equal(b1, b2)) {
pline(b1);
linec = 0;
do {
linec++;
if(gline(b1)) {
pline(b2);
exits(0);
}
} while(equal(b2, b1));
pline(b2);
linec = 0;
}
}
}
int
gline(char *buf)
{
char *p;
p = Brdline(&fin, '\n');
if(p == 0)
return 1;
if(fin.rdline >= bsize-1) {
fprint(2, "line too long\n");
exits("too long");
}
memmove(buf, p, fin.rdline);
buf[fin.rdline-1] = 0;
return 0;
}
void
pline(char *buf)
{
switch(mode) {
case 'u':
if(uniq) {
uniq = 0;
return;
}
break;
case 'd':
if(uniq)
break;
return;
case 'c':
Bprint(&fout, "%4d ", linec);
}
uniq = 0;
Bprint(&fout, "%s\n", buf);
}
int
equal(char *b1, char *b2)
{
char c;
if(fields || letters) {
b1 = skip(b1);
b2 = skip(b2);
}
for(;;) {
c = *b1++;
if(c != *b2++) {
if(c == 0 && mode == 's')
return 1;
return 0;
}
if(c == 0) {
uniq++;
return 1;
}
}
}
char*
skip(char *s)
{
int nf, nl;
nf = nl = 0;
while(nf++ < fields) {
while(*s == ' ' || *s == '\t')
s++;
while(!(*s == ' ' || *s == '\t' || *s == 0) )
s++;
}
while(nl++ < letters && *s != 0)
s++;
return s;
}

16
src/cmd/unutf.c Normal file
View File

@ -0,0 +1,16 @@
#include <u.h>
#include <libc.h>
#include <bio.h>
Biobuf bin;
void
main(void)
{
int c;
Binit(&bin, 0, OREAD);
while((c = Bgetrune(&bin)) >= 0)
print("0x%ux\n", c);
exits(0);
}

309
src/cmd/wc.c Normal file
View File

@ -0,0 +1,309 @@
/*
* wc -- count things in utf-encoded text files
* Bugs:
* The only white space characters recognized are ' ', '\t' and '\n', even though
* ISO 10646 has many more blanks scattered through it.
* Should count characters that cannot occur in any rune (hex f0-ff) separately.
* Should count non-canonical runes (e.g. hex c1,80 instead of hex 40).
*/
#include <u.h>
#include <libc.h>
#define NBUF (8*1024)
uvlong nline, tnline, pline;
uvlong nword, tnword, pword;
uvlong nrune, tnrune, prune;
uvlong nbadr, tnbadr, pbadr;
uvlong nchar, tnchar, pchar;
void count(int, char *);
void report(uvlong, uvlong, uvlong, uvlong, uvlong, char *);
void
main(int argc, char *argv[])
{
char *status="";
int i, f;
ARGBEGIN {
case 'l': pline++; break;
case 'w': pword++; break;
case 'r': prune++; break;
case 'b': pbadr++; break;
case 'c': pchar++; break;
default:
fprint(2, "Usage: %s [-lwrbc] [file ...]\n", argv0);
exits("usage");
} ARGEND
if(pline+pword+prune+pbadr+pchar == 0) {
pline = 1;
pword = 1;
pchar = 1;
}
if(argc==0)
count(0, 0);
else{
for(i=0;i<argc;i++){
f=open(argv[i], OREAD);
if(f<0){
perror(argv[i]);
status="can't open";
}
else{
count(f, argv[i]);
tnline+=nline;
tnword+=nword;
tnrune+=nrune;
tnbadr+=nbadr;
tnchar+=nchar;
close(f);
}
}
if(argc>1)
report(tnline, tnword, tnrune, tnbadr, tnchar, "total");
}
exits(status);
}
void
report(uvlong nline, uvlong nword, uvlong nrune, uvlong nbadr, uvlong nchar, char *fname)
{
char line[1024], word[128];
line[0] = '\0';
if(pline){
sprint(word, " %7llud", nline);
strcat(line, word);
}
if(pword){
sprint(word, " %7llud", nword);
strcat(line, word);
}
if(prune){
sprint(word, " %7llud", nrune);
strcat(line, word);
}
if(pbadr){
sprint(word, " %7llud", nbadr);
strcat(line, word);
}
if(pchar){
sprint(word, " %7llud", nchar);
strcat(line, word);
}
if(fname){
sprint(word, " %s", fname);
strcat(line, word);
}
print("%s\n", line+1);
}
/*
* How it works. Start in statesp. Each time we read a character,
* increment various counts, and do state transitions according to the
* following table. If we're not in statesp or statewd when done, the
* file ends with a partial rune.
* | character
* state |09,20| 0a |00-7f|80-bf|c0-df|e0-ef|f0-ff
* -------+-----+-----+-----+-----+-----+-----+-----
* statesp|ASP |ASPN |AWDW |AWDWX|AC2W |AC3W |AWDWX
* statewd|ASP |ASPN |AWD |AWDX |AC2 |AC3 |AWDX
* statec2|ASPX |ASPNX|AWDX |AWDR |AC2X |AC3X |AWDX
* statec3|ASPX |ASPNX|AWDX |AC2R |AC2X |AC3X |AWDX
*/
enum{ /* actions */
AC2, /* enter statec2 */
AC2R, /* enter statec2, don't count a rune */
AC2W, /* enter statec2, count a word */
AC2X, /* enter statec2, count a bad rune */
AC3, /* enter statec3 */
AC3W, /* enter statec3, count a word */
AC3X, /* enter statec3, count a bad rune */
ASP, /* enter statesp */
ASPN, /* enter statesp, count a newline */
ASPNX, /* enter statesp, count a newline, count a bad rune */
ASPX, /* enter statesp, count a bad rune */
AWD, /* enter statewd */
AWDR, /* enter statewd, don't count a rune */
AWDW, /* enter statewd, count a word */
AWDWX, /* enter statewd, count a word, count a bad rune */
AWDX, /* enter statewd, count a bad rune */
};
uchar statesp[256]={ /* looking for the start of a word */
AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, /* 00-07 */
AWDW, ASP, ASPN, AWDW, AWDW, AWDW, AWDW, AWDW, /* 08-0f */
AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, /* 10-17 */
AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, /* 18-1f */
ASP, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, /* 20-27 */
AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, /* 28-2f */
AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, /* 30-37 */
AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, /* 38-3f */
AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, /* 40-47 */
AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, /* 48-4f */
AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, /* 50-57 */
AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, /* 58-5f */
AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, /* 60-67 */
AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, /* 68-6f */
AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, /* 70-77 */
AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, AWDW, /* 78-7f */
AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,/* 80-87 */
AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,/* 88-8f */
AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,/* 90-97 */
AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,/* 98-9f */
AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,/* a0-a7 */
AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,/* a8-af */
AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,/* b0-b7 */
AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,/* b8-bf */
AC2W, AC2W, AC2W, AC2W, AC2W, AC2W, AC2W, AC2W, /* c0-c7 */
AC2W, AC2W, AC2W, AC2W, AC2W, AC2W, AC2W, AC2W, /* c8-cf */
AC2W, AC2W, AC2W, AC2W, AC2W, AC2W, AC2W, AC2W, /* d0-d7 */
AC2W, AC2W, AC2W, AC2W, AC2W, AC2W, AC2W, AC2W, /* d8-df */
AC3W, AC3W, AC3W, AC3W, AC3W, AC3W, AC3W, AC3W, /* e0-e7 */
AC3W, AC3W, AC3W, AC3W, AC3W, AC3W, AC3W, AC3W, /* e8-ef */
AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,/* f0-f7 */
AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,AWDWX,/* f8-ff */
};
uchar statewd[256]={ /* looking for the next character in a word */
AWD, AWD, AWD, AWD, AWD, AWD, AWD, AWD, /* 00-07 */
AWD, ASP, ASPN, AWD, AWD, AWD, AWD, AWD, /* 08-0f */
AWD, AWD, AWD, AWD, AWD, AWD, AWD, AWD, /* 10-17 */
AWD, AWD, AWD, AWD, AWD, AWD, AWD, AWD, /* 18-1f */
ASP, AWD, AWD, AWD, AWD, AWD, AWD, AWD, /* 20-27 */
AWD, AWD, AWD, AWD, AWD, AWD, AWD, AWD, /* 28-2f */
AWD, AWD, AWD, AWD, AWD, AWD, AWD, AWD, /* 30-37 */
AWD, AWD, AWD, AWD, AWD, AWD, AWD, AWD, /* 38-3f */
AWD, AWD, AWD, AWD, AWD, AWD, AWD, AWD, /* 40-47 */
AWD, AWD, AWD, AWD, AWD, AWD, AWD, AWD, /* 48-4f */
AWD, AWD, AWD, AWD, AWD, AWD, AWD, AWD, /* 50-57 */
AWD, AWD, AWD, AWD, AWD, AWD, AWD, AWD, /* 58-5f */
AWD, AWD, AWD, AWD, AWD, AWD, AWD, AWD, /* 60-67 */
AWD, AWD, AWD, AWD, AWD, AWD, AWD, AWD, /* 68-6f */
AWD, AWD, AWD, AWD, AWD, AWD, AWD, AWD, /* 70-77 */
AWD, AWD, AWD, AWD, AWD, AWD, AWD, AWD, /* 78-7f */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* 80-87 */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* 88-8f */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* 90-97 */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* 98-9f */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* a0-a7 */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* a8-af */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* b0-b7 */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* b8-bf */
AC2, AC2, AC2, AC2, AC2, AC2, AC2, AC2, /* c0-c7 */
AC2, AC2, AC2, AC2, AC2, AC2, AC2, AC2, /* c8-cf */
AC2, AC2, AC2, AC2, AC2, AC2, AC2, AC2, /* d0-d7 */
AC2, AC2, AC2, AC2, AC2, AC2, AC2, AC2, /* d8-df */
AC3, AC3, AC3, AC3, AC3, AC3, AC3, AC3, /* e0-e7 */
AC3, AC3, AC3, AC3, AC3, AC3, AC3, AC3, /* e8-ef */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* f0-f7 */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* f8-ff */
};
uchar statec2[256]={ /* looking for 10xxxxxx to complete a rune */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* 00-07 */
AWDX, ASPX, ASPNX,AWDX, AWDX, AWDX, AWDX, AWDX, /* 08-0f */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* 10-17 */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* 18-1f */
ASPX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* 20-27 */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* 28-2f */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* 30-37 */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* 38-3f */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* 40-47 */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* 48-4f */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* 50-57 */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* 58-5f */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* 60-67 */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* 68-6f */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* 70-77 */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* 78-7f */
AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, /* 80-87 */
AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, /* 88-8f */
AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, /* 90-97 */
AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, /* 98-9f */
AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, /* a0-a7 */
AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, /* a8-af */
AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, /* b0-b7 */
AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, AWDR, /* b8-bf */
AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, /* c0-c7 */
AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, /* c8-cf */
AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, /* d0-d7 */
AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, /* d8-df */
AC3X, AC3X, AC3X, AC3X, AC3X, AC3X, AC3X, AC3X, /* e0-e7 */
AC3X, AC3X, AC3X, AC3X, AC3X, AC3X, AC3X, AC3X, /* e8-ef */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* f0-f7 */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* f8-ff */
};
uchar statec3[256]={ /* looking for 10xxxxxx,10xxxxxx to complete a rune */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* 00-07 */
AWDX, ASPX, ASPNX,AWDX, AWDX, AWDX, AWDX, AWDX, /* 08-0f */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* 10-17 */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* 18-1f */
ASPX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* 20-27 */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* 28-2f */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* 30-37 */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* 38-3f */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* 40-47 */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* 48-4f */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* 50-57 */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* 58-5f */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* 60-67 */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* 68-6f */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* 70-77 */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* 78-7f */
AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, /* 80-87 */
AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, /* 88-8f */
AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, /* 90-97 */
AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, /* 98-9f */
AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, /* a0-a7 */
AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, /* a8-af */
AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, /* b0-b7 */
AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, AC2R, /* b8-bf */
AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, /* c0-c7 */
AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, /* c8-cf */
AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, /* d0-d7 */
AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, AC2X, /* d8-df */
AC3X, AC3X, AC3X, AC3X, AC3X, AC3X, AC3X, AC3X, /* e0-e7 */
AC3X, AC3X, AC3X, AC3X, AC3X, AC3X, AC3X, AC3X, /* e8-ef */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* f0-f7 */
AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, AWDX, /* f8-ff */
};
void
count(int f, char *name)
{
int n;
uchar buf[NBUF];
uchar *bufp, *ebuf;
uchar *state=statesp;
nline = 0;
nword = 0;
nrune = 0;
nbadr = 0;
nchar = 0;
for(;;){
n=read(f, buf, NBUF);
if(n<=0)
break;
nchar+=n;
nrune+=n; /* might be too large, gets decreased later */
bufp=buf;
ebuf=buf+n;
do{
switch(state[*bufp]){
case AC2: state=statec2; break;
case AC2R: state=statec2; --nrune; break;
case AC2W: state=statec2; nword++; break;
case AC2X: state=statec2; nbadr++; break;
case AC3: state=statec3; break;
case AC3W: state=statec3; nword++; break;
case AC3X: state=statec3; nbadr++; break;
case ASP: state=statesp; break;
case ASPN: state=statesp; nline++; break;
case ASPNX: state=statesp; nline++; nbadr++; break;
case ASPX: state=statesp; nbadr++; break;
case AWD: state=statewd; break;
case AWDR: state=statewd; --nrune; break;
case AWDW: state=statewd; nword++; break;
case AWDWX: state=statewd; nword++; nbadr++; break;
case AWDX: state=statewd; nbadr++; break;
}
}while(++bufp!=ebuf);
}
if(state!=statesp && state!=statewd)
nbadr++;
if(n<0)
perror(name);
report(nline, nword, nrune, nbadr, nchar, name);
}

355
src/cmd/xd.c Normal file
View File

@ -0,0 +1,355 @@
#include <u.h>
#include <libc.h>
#include <bio.h>
unsigned char odata[16];
unsigned char data[16];
int ndata;
unsigned long addr;
int repeats;
int swizzle;
int flush;
int abase=2;
int xd(char *, int);
void xprint(char *, long);
void initarg(void), swizz(void);
enum{
Narg=10
};
typedef struct Arg Arg;
typedef void fmtfn(char *);
struct Arg
{
int ascii; /* 0==none, 1==ascii */
int loglen; /* 0==1, 1==2, 2==4, 3==8 */
int base; /* 0==8, 1==10, 2==16 */
fmtfn *fn; /* function to call with data */
char *afmt; /* format to use to print address */
char *fmt; /* format to use to print data */
}arg[Narg];
int narg;
fmtfn fmt0, fmt1, fmt2, fmt3, fmtc;
fmtfn *fmt[4] = {
fmt0,
fmt1,
fmt2,
fmt3
};
char *dfmt[4][3] = {
" %.3uo", " %.3ud", " %.2ux",
" %.6uo", " %.5ud", " %.4ux",
" %.11luo", " %.10lud", " %.8lux",
" %.22lluo", " %.20llud", " %.16llux",
};
char *cfmt[3][3] = {
" %c", " %c", " %c",
" %.3s", " %.3s", " %.2s",
" %.3uo", " %.3ud", " %.2ux",
};
char *afmt[2][3] = {
"%.7luo ", "%.7lud ", "%.7lux ",
"%7luo ", "%7lud ", "%7lux ",
};
Biobuf bin;
Biobuf bout;
void
main(int argc, char *argv[])
{
int i, err;
Arg *ap;
Binit(&bout, 1, OWRITE);
err = 0;
ap = 0;
while(argc>1 && argv[1][0]=='-' && argv[1][1]){
--argc;
argv++;
argv[0]++;
if(argv[0][0] == 'r'){
repeats = 1;
if(argv[0][1])
goto Usage;
continue;
}
if(argv[0][0] == 's'){
swizzle = 1;
if(argv[0][1])
goto Usage;
continue;
}
if(argv[0][0] == 'u'){
flush = 1;
if(argv[0][1])
goto Usage;
continue;
}
if(argv[0][0] == 'a'){
argv[0]++;
switch(argv[0][0]){
case 'o':
abase = 0;
break;
case 'd':
abase = 1;
break;
case 'x':
abase = 2;
break;
default:
goto Usage;
}
if(argv[0][1])
goto Usage;
continue;
}
ap = &arg[narg];
initarg();
while(argv[0][0]){
switch(argv[0][0]){
case 'c':
ap->ascii = 1;
ap->loglen = 0;
if(argv[0][1] || argv[0][-1]!='-')
goto Usage;
break;
case 'o':
ap->base = 0;
break;
case 'd':
ap->base = 1;
break;
case 'x':
ap->base = 2;
break;
case 'b':
case '1':
ap->loglen = 0;
break;
case 'w':
case '2':
ap->loglen = 1;
break;
case 'l':
case '4':
ap->loglen = 2;
break;
case 'v':
case '8':
ap->loglen = 3;
break;
default:
Usage:
fprint(2, "usage: xd [-u] [-r] [-s] [-a{odx}] [-c|{b1w2l4v8}{odx}] ... file ...\n");
exits("usage");
}
argv[0]++;
}
if(ap->ascii)
ap->fn = fmtc;
else
ap->fn = fmt[ap->loglen];
ap->fmt = dfmt[ap->loglen][ap->base];
ap->afmt = afmt[ap>arg][abase];
}
if(narg == 0)
initarg();
if(argc == 1)
err = xd(0, 0);
else if(argc == 2)
err = xd(argv[1], 0);
else for(i=1; i<argc; i++)
err |= xd(argv[i], 1);
exits(err? "error" : 0);
}
void
initarg(void)
{
Arg *ap;
ap = &arg[narg++];
if(narg >= Narg){
fprint(2, "xd: too many formats (max %d)\n", Narg);
exits("usage");
}
ap->ascii = 0;
ap->loglen = 2;
ap->base = 2;
ap->fn = fmt2;
ap->fmt = dfmt[ap->loglen][ap->base];
ap->afmt = afmt[narg>1][abase];
}
int
xd(char *name, int title)
{
int fd;
int i, star;
Arg *ap;
Biobuf *bp;
fd = 0;
if(name){
bp = Bopen(name, OREAD);
if(bp == 0){
fprint(2, "xd: can't open %s\n", name);
return 1;
}
}else{
bp = &bin;
Binit(bp, fd, OREAD);
}
if(title)
xprint("%s\n", (long)name);
addr = 0;
star = 0;
while((ndata=Bread(bp, data, 16)) >= 0){
if(ndata < 16)
for(i=ndata; i<16; i++)
data[i] = 0;
if(swizzle)
swizz();
if(ndata==16 && repeats){
if(addr>0 && data[0]==odata[0]){
for(i=1; i<16; i++)
if(data[i] != odata[i])
break;
if(i == 16){
addr += 16;
if(star == 0){
star++;
xprint("*\n", 0);
}
continue;
}
}
for(i=0; i<16; i++)
odata[i] = data[i];
star = 0;
}
for(ap=arg; ap<&arg[narg]; ap++){
xprint(ap->afmt, addr);
(*ap->fn)(ap->fmt);
xprint("\n", 0);
if(flush)
Bflush(&bout);
}
addr += ndata;
if(ndata<16){
xprint(afmt[0][abase], addr);
xprint("\n", 0);
if(flush)
Bflush(&bout);
break;
}
}
Bterm(bp);
return 0;
}
void
swizz(void)
{
uchar *p, *q;
int i;
uchar swdata[16];
p = data;
q = swdata;
for(i=0; i<16; i++)
*q++ = *p++;
p = data;
q = swdata;
for(i=0; i<4; i++){
p[0] = q[3];
p[1] = q[2];
p[2] = q[1];
p[3] = q[0];
p += 4;
q += 4;
}
}
void
fmt0(char *f)
{
int i;
for(i=0; i<ndata; i++)
xprint(f, data[i]);
}
void
fmt1(char *f)
{
int i;
for(i=0; i<ndata; i+=sizeof(unsigned short))
xprint(f, (data[i]<<8)|data[i+1]);
}
void
fmt2(char *f)
{
int i;
for(i=0; i<ndata; i+=sizeof(unsigned long))
xprint(f, (data[i]<<24)|(data[i+1]<<16)|(data[i+2]<<8)|data[i+3]);
}
void
fmt3(char *f)
{
int i;
unsigned long long v;
for(i=0; i<ndata; i+=sizeof(unsigned long long)){
v = (data[i]<<24)|(data[i+1]<<16)|(data[i+2]<<8)|data[i+3];
v <<= 32;
v |= (data[i+4]<<24)|(data[i+1+4]<<16)|(data[i+2+4]<<8)|data[i+3+4];
if(Bprint(&bout, f, v)<0){
fprint(2, "xd: i/o error\n");
exits("i/o error");
}
}
}
void
fmtc(char *f)
{
int i;
USED(f);
for(i=0; i<ndata; i++)
switch(data[i]){
case '\t':
xprint(cfmt[1][2], (long)"\\t");
break;
case '\r':
xprint(cfmt[1][2], (long)"\\r");
break;
case '\n':
xprint(cfmt[1][2], (long)"\\n");
break;
case '\b':
xprint(cfmt[1][2], (long)"\\b");
break;
default:
if(data[i]>=0x7F || ' '>data[i])
xprint(cfmt[2][2], data[i]);
else
xprint(cfmt[0][2], data[i]);
break;
}
}
void
xprint(char *fmt, long d)
{
if(Bprint(&bout, fmt, d)<0){
fprint(2, "xd: i/o error\n");
exits("i/o error");
}
}

2939
src/cmd/yacc.c Normal file

File diff suppressed because it is too large Load Diff