new utilities.
the .C files compile but are renamed to avoid building automatically.
This commit is contained in:
parent
f08fdedcee
commit
bc7cb1a15a
181
src/cmd/ascii.c
Normal file
181
src/cmd/ascii.c
Normal 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
41
src/cmd/basename.c
Normal 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
313
src/cmd/cal.c
Normal 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
195
src/cmd/calendar.c
Normal 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
36
src/cmd/cat.c
Normal 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
44
src/cmd/cleanname.c
Normal 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
112
src/cmd/cmp.c
Normal 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
178
src/cmd/comm.c
Normal 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
30
src/cmd/date.c
Normal 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
2300
src/cmd/dc.c
Normal file
File diff suppressed because it is too large
Load Diff
660
src/cmd/dd.c
Normal file
660
src/cmd/dd.c
Normal 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
969
src/cmd/deroff.c
Normal 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
194
src/cmd/du.C
Normal 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
38
src/cmd/echo.c
Normal 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
1608
src/cmd/ed.c
Normal file
File diff suppressed because it is too large
Load Diff
96
src/cmd/factor.c
Normal file
96
src/cmd/factor.c
Normal 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, ") == 0) {
|
||||
print(" 2\n");
|
||||
n = quot;
|
||||
s = sqrt(n) + 1;
|
||||
}
|
||||
while(modf(n/3, ") == 0) {
|
||||
print(" 3\n");
|
||||
n = quot;
|
||||
s = sqrt(n) + 1;
|
||||
}
|
||||
while(modf(n/5, ") == 0) {
|
||||
print(" 5\n");
|
||||
n = quot;
|
||||
s = sqrt(n) + 1;
|
||||
}
|
||||
while(modf(n/7, ") == 0) {
|
||||
print(" 7\n");
|
||||
n = quot;
|
||||
s = sqrt(n) + 1;
|
||||
}
|
||||
d = 1;
|
||||
for(i=1;;) {
|
||||
d += wheel[i];
|
||||
while(modf(n/d, ") == 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
111
src/cmd/freq.c
Normal 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
32
src/cmd/fsize.c
Normal 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
335
src/cmd/idiff.c
Normal 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
369
src/cmd/join.c
Normal 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
305
src/cmd/ls.C
Normal 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
61
src/cmd/md5sum.C
Normal 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
26
src/cmd/mkdir.C
Normal 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
13
src/cmd/mkfile
Normal 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
104
src/cmd/rm.c
Normal 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
92
src/cmd/seq.c
Normal 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
61
src/cmd/sha1sum.c
Normal 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
13
src/cmd/sleep.c
Normal 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
1767
src/cmd/sort.c
Normal file
File diff suppressed because it is too large
Load Diff
189
src/cmd/split.c
Normal file
189
src/cmd/split.c
Normal 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
88
src/cmd/strings.c
Normal 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
215
src/cmd/sum.c
Normal 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
362
src/cmd/tail.c
Normal 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
640
src/cmd/tar.C
Normal 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
75
src/cmd/tee.c
Normal 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
303
src/cmd/test.c
Normal 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
101
src/cmd/time.c
Normal 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
62
src/cmd/touch.c
Normal 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
356
src/cmd/tr.c
Normal 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
122
src/cmd/unicode.c
Normal 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
169
src/cmd/uniq.c
Normal 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
16
src/cmd/unutf.c
Normal 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
309
src/cmd/wc.c
Normal 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
355
src/cmd/xd.c
Normal 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
2939
src/cmd/yacc.c
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user