summaryrefslogtreecommitdiff
path: root/usr/src/lib/libcmd/common
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libcmd/common')
-rw-r--r--usr/src/lib/libcmd/common/RELEASE33
-rw-r--r--usr/src/lib/libcmd/common/basename.c2
-rw-r--r--usr/src/lib/libcmd/common/cat.c453
-rw-r--r--usr/src/lib/libcmd/common/chgrp.c11
-rw-r--r--usr/src/lib/libcmd/common/chmod.c11
-rw-r--r--usr/src/lib/libcmd/common/chown.c2
-rw-r--r--usr/src/lib/libcmd/common/cksum.c12
-rw-r--r--usr/src/lib/libcmd/common/cmd.h6
-rw-r--r--usr/src/lib/libcmd/common/cmdinit.c21
-rw-r--r--usr/src/lib/libcmd/common/cmp.c15
-rw-r--r--usr/src/lib/libcmd/common/comm.c2
-rw-r--r--usr/src/lib/libcmd/common/cp.c12
-rw-r--r--usr/src/lib/libcmd/common/cut.c2
-rw-r--r--usr/src/lib/libcmd/common/date.c10
-rw-r--r--usr/src/lib/libcmd/common/dirname.c30
-rw-r--r--usr/src/lib/libcmd/common/expr.c2
-rw-r--r--usr/src/lib/libcmd/common/fds.c34
-rw-r--r--usr/src/lib/libcmd/common/features/utsname3
-rw-r--r--usr/src/lib/libcmd/common/fmt.c2
-rw-r--r--usr/src/lib/libcmd/common/fold.c2
-rw-r--r--usr/src/lib/libcmd/common/getconf.c2
-rw-r--r--usr/src/lib/libcmd/common/grep.c876
-rw-r--r--usr/src/lib/libcmd/common/head.c2
-rw-r--r--usr/src/lib/libcmd/common/id.c2
-rw-r--r--usr/src/lib/libcmd/common/join.c10
-rw-r--r--usr/src/lib/libcmd/common/ln.c2
-rw-r--r--usr/src/lib/libcmd/common/logname.c2
-rw-r--r--usr/src/lib/libcmd/common/md5sum.c2
-rw-r--r--usr/src/lib/libcmd/common/mkdir.c38
-rw-r--r--usr/src/lib/libcmd/common/mkfifo.c63
-rw-r--r--usr/src/lib/libcmd/common/mktemp.c164
-rw-r--r--usr/src/lib/libcmd/common/mv.c2
-rw-r--r--usr/src/lib/libcmd/common/paste.c2
-rw-r--r--usr/src/lib/libcmd/common/pathchk.c154
-rw-r--r--usr/src/lib/libcmd/common/pids.c2
-rw-r--r--usr/src/lib/libcmd/common/rev.c2
-rw-r--r--usr/src/lib/libcmd/common/rev.h2
-rw-r--r--usr/src/lib/libcmd/common/revlib.c2
-rw-r--r--usr/src/lib/libcmd/common/rm.c13
-rw-r--r--usr/src/lib/libcmd/common/rmdir.c2
-rw-r--r--usr/src/lib/libcmd/common/shcmd.h80
-rw-r--r--usr/src/lib/libcmd/common/stty.c11
-rw-r--r--usr/src/lib/libcmd/common/sum.c2
-rw-r--r--usr/src/lib/libcmd/common/sync.c2
-rw-r--r--usr/src/lib/libcmd/common/tail.c214
-rw-r--r--usr/src/lib/libcmd/common/tee.c146
-rw-r--r--usr/src/lib/libcmd/common/tty.c2
-rw-r--r--usr/src/lib/libcmd/common/uname.c4
-rw-r--r--usr/src/lib/libcmd/common/uniq.c40
-rw-r--r--usr/src/lib/libcmd/common/wc.c118
-rw-r--r--usr/src/lib/libcmd/common/wc.h6
-rw-r--r--usr/src/lib/libcmd/common/wclib.c424
52 files changed, 2392 insertions, 666 deletions
diff --git a/usr/src/lib/libcmd/common/RELEASE b/usr/src/lib/libcmd/common/RELEASE
index 6300890d12..ebda670177 100644
--- a/usr/src/lib/libcmd/common/RELEASE
+++ b/usr/src/lib/libcmd/common/RELEASE
@@ -1,3 +1,34 @@
+09-09-09 fds.c: add --unit=fd
+09-08-25 tail.c: initialize Tail_t.fifo=0 !!
+09-08-15 tail.c: fix fifo logic
+09-08-11 wc.c: add setlocale(LC_CTYPE,"C") cleanup, add utf8 optimzations
+09-08-10 uniq.c: replace -c 1..9999 sfsprintf() with inline conversion
+09-08-01 join.c: fix empty field null pointer deref
+09-07-23 pathchk.c: add -P,--path and -a,--all
+09-07-02 chgrp.c,chmod.c,cksum.c: fts_flags() default only if not --recursive
+09-06-19 cmd.h,cmdinit.c: add ERROR_CALLBACK for ERROR_NOTIFY main() callback
+09-06-19 mktemp.c: --unsafe now checks and prints path but does create
+09-06-19 tee.c: add ERROR_CALLBACK for tee_cleanup() sfio discipline pop
+09-06-18 rm.c: handle interrupts during interactive query
+09-06-18 cp.c: handle interrupts during interactive query
+09-05-25 tail.c: fix old style option logic to handle --invalid-long-option
+09-05-24 tail.c: -r == +1r
+09-05-01 mktemp.c: handle foo/prefix, add -p dir and -u
+09-03-31 cat.c: handle --no* options
+09-03-15 tail.c: fix --timeout termination logic
+09-03-03 tee.c: clean up sfio disciplines on error
+09-03-03 cat.c: fix -v|-e|-n|-B interaction bugs
+09-02-14 tail.c: fix VSC failures
+09-02-14 join.c: fix VSC failure
+09-02-02 uniq.c: document -number == -fnumber, +number == -snumber
+09-02-02 tail.c: fix usage[] for negative offsets, add sun -b
+09-02-02 mktemp.c: add
+09-02-02 features/utsname: UWIN _UNAME_os_DEFAULT => UWIN
+09-01-31 dirname.c: add experimental { -f -r -x } for pathpath(3)
+09-01-05 cmp.c: fix EOF diagnostic to conform to posix
+09-01-03 mkfifo.c: fix --mode=mode logic
+08-12-07 date.c: add %[_][EO]K for [space pad] [full|long] iso docs
+08-11-10 stty.c: check for -t grouping so -tostop != -t -ostop
08-10-15 rm.c: handle 'rm -f x x' => exit 0
08-09-08 stty.c: #ifdef guard TAB[012] -- freebsd: damn the posix, full speed ahead
08-06-17 shcmd.h: move to libast
@@ -169,7 +200,7 @@
00-10-31 mkdir: handle races by checking EEXIST
00-09-20 cp: copy argv to stack before modifying in place
00-05-18 add setlocale(LC_ALL,"")
-00-04-30 join: drop wierd opt_info.argv reference
+00-04-30 join: drop weird opt_info.argv reference
00-03-17 expr: add == operator -- duh
cp,ln,mv: delay pathcanon() on destination to verify `cp a b/.'
getconf: use astgetconf for proper message control
diff --git a/usr/src/lib/libcmd/common/basename.c b/usr/src/lib/libcmd/common/basename.c
index c5c86aa154..2b59030483 100644
--- a/usr/src/lib/libcmd/common/basename.c
+++ b/usr/src/lib/libcmd/common/basename.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
diff --git a/usr/src/lib/libcmd/common/cat.c b/usr/src/lib/libcmd/common/cat.c
index 76af2f2765..e451998cc2 100644
--- a/usr/src/lib/libcmd/common/cat.c
+++ b/usr/src/lib/libcmd/common/cat.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
@@ -31,7 +31,7 @@
#include <fcntl.h>
static const char usage[] =
-"[-?\n@(#)$Id: cat (AT&T Research) 2007-07-17 $\n]"
+"[-?\n@(#)$Id: cat (AT&T Research) 2009-03-31 $\n]"
USAGE_LICENSE
"[+NAME?cat - concatenate files]"
"[+DESCRIPTION?\bcat\b copies each \afile\a in sequence to the standard"
@@ -62,6 +62,7 @@ USAGE_LICENSE
"[D:dos-output?Output files are opened in \atext\amode which inserts carriage"
" returns in front of new-lines on some systems.]"
"[E:show-ends?Causes a \b$\b to be inserted before each new-line.]"
+"[R:regress?Regression test defaults: \b-v\b buffer size 4.]"
"[S:silent?\bcat\b is silent about non-existent files.]"
"[T:show-blank?Causes tabs to be copied as \b^I\b and formfeeds as \b^L\b.]"
@@ -87,146 +88,306 @@ USAGE_LICENSE
#define d_FLAG (1<<9)
/* character types */
-#define T_ENDBUF 1
-#define T_CONTROL 2
-#define T_NEWLINE 3
-#define T_EIGHTBIT 4
-#define T_CNTL8BIT 5
+#define T_ERROR 1
+#define T_EOF 2
+#define T_ENDBUF 3
+#define T_NEWLINE 4
+#define T_CONTROL 5
+#define T_EIGHTBIT 6
+#define T_CNTL8BIT 7
#define printof(c) ((c)^0100)
+typedef void* (*Reserve_f)(Sfio_t*, ssize_t, int);
+
+#ifndef sfvalue
+#define sfvalue(f) ((f)->_val)
+#endif
+
+static void*
+regress(Sfio_t* sp, ssize_t n, int f)
+{
+ void* r;
+
+ if (!(r = sfreserve(sp, 4, f)))
+ r = sfreserve(sp, n, f);
+ else if (sfvalue(sp) > 4)
+ sfvalue(sp) = 4;
+ return r;
+}
+
/*
* called for any special output processing
*/
static int
-vcat(register char* states, Sfio_t *fdin, Sfio_t *fdout, int flags)
+vcat(register char* states, Sfio_t* ip, Sfio_t* op, Reserve_f reserve, int flags)
{
register unsigned char* cp;
- register unsigned char* cpold;
+ register unsigned char* pp;
+ unsigned char* cur;
+ unsigned char* end;
+ unsigned char* buf;
+ unsigned char* nxt;
register int n;
- register int m;
- register int line = 1;
- register unsigned char* endbuff;
- unsigned char* inbuff;
- int printdefer = (flags&(B_FLAG|N_FLAG));
- int lastchar;
- int lastline;
+ register int line;
+ register int raw;
+ int last;
+ int c;
+ int m;
+ int any;
+ int header;
unsigned char meta[4];
+ unsigned char tmp[32];
meta[0] = 'M';
meta[1] = '-';
+ last = -1;
+ *(cp = buf = end = tmp) = 0;
+ any = 0;
+ header = flags & (B_FLAG|N_FLAG);
+ line = 1;
+ states[0] = T_ENDBUF;
+ raw = !mbwide();
for (;;)
{
- /* read in a buffer full */
- if (!(inbuff = (unsigned char*)sfreserve(fdin, SF_UNBOUND, 0)))
- return sfvalue(fdin) ? -1 : 0;
- if ((n = sfvalue(fdin)) <= 0)
- return n;
- cp = inbuff;
- lastchar = *(endbuff = cp + --n);
- *endbuff = 0;
- if (printdefer)
+ cur = cp;
+ if (raw)
+ while (!(n = states[*cp++]));
+ else
+ for (;;)
+ {
+ while (!(n = states[*cp++]));
+ if (n < T_CONTROL)
+ break;
+ if ((m = mbsize(pp = cp - 1)) > 1)
+ cp += m - 1;
+ else
+ {
+ if (m <= 0)
+ {
+ if (cur == pp)
+ {
+ if (last > 0)
+ {
+ *end = last;
+ last = -1;
+ c = end - pp + 1;
+ if ((m = mbsize(pp)) == c)
+ {
+ any = 1;
+ if (header)
+ {
+ header = 0;
+ sfprintf(op, "%6d\t", line);
+ }
+ sfwrite(op, cur, m);
+ *(cp = cur = end) = 0;
+ }
+ else
+ {
+ memcpy(tmp, pp, c);
+ if (!(nxt = (unsigned char*)(*reserve)(ip, SF_UNBOUND, 0)))
+ {
+ states[0] = sfvalue(ip) ? T_ERROR : T_EOF;
+ *(cp = end = tmp + sizeof(tmp) - 1) = 0;
+ last = -1;
+ }
+ else if ((n = sfvalue(ip)) <= 0)
+ {
+ states[0] = n ? T_ERROR : T_EOF;
+ *(cp = end = tmp + sizeof(tmp) - 1) = 0;
+ last = -1;
+ }
+ else
+ {
+ cp = buf = nxt;
+ end = buf + n - 1;
+ last = *end;
+ *end = 0;
+ }
+ mb:
+ if ((n = end - cp + 1) >= (sizeof(tmp) - c))
+ n = sizeof(tmp) - c - 1;
+ memcpy(tmp + c, cp, n);
+ if ((m = mbsize(tmp)) >= c)
+ {
+ any = 1;
+ if (header)
+ {
+ header = 0;
+ sfprintf(op, "%6d\t", line);
+ }
+ sfwrite(op, tmp, m);
+ cur = cp += m - c;
+ }
+ }
+ continue;
+ }
+ }
+ else
+ {
+ cp = pp + 1;
+ n = 0;
+ }
+ }
+ break;
+ }
+ }
+ c = *--cp;
+ if ((m = cp - cur) || n >= T_CONTROL)
{
- if (states[*cp]!=T_NEWLINE || !(flags&B_FLAG))
- sfprintf(fdout,"%6d\t",line);
- printdefer = 0;
+ flush:
+ any = 1;
+ if (header)
+ {
+ header = 0;
+ sfprintf(op, "%6d\t", line);
+ }
+ if (m)
+ sfwrite(op, cur, m);
}
- while (endbuff)
+ special:
+ switch (n)
{
- cpold = cp;
- /* skip over printable characters */
- if (mbwide())
- while ((n = (m = mbsize(cp)) < 2 ? states[*cp++] : (cp += m, states['a'])) == 0);
+ case T_ERROR:
+ if (cp != end)
+ {
+ n = T_CONTROL;
+ goto flush;
+ }
+ return -1;
+ case T_EOF:
+ if (cp != end)
+ {
+ n = T_CONTROL;
+ goto flush;
+ }
+ return 0;
+ case T_ENDBUF:
+ if (cp != end)
+ {
+ n = T_CONTROL;
+ goto flush;
+ }
+ c = last;
+ if (!(nxt = (unsigned char*)(*reserve)(ip, SF_UNBOUND, 0)))
+ {
+ *(cp = end = tmp) = 0;
+ states[0] = sfvalue(ip) ? T_ERROR : T_EOF;
+ last = -1;
+ }
+ else if ((m = sfvalue(ip)) <= 0)
+ {
+ *(cp = end = tmp) = 0;
+ states[0] = m ? T_ERROR : T_EOF;
+ last = -1;
+ }
else
- while ((n = states[*cp++]) == 0);
- if (n==T_ENDBUF)
{
- if (cp>endbuff)
+ buf = nxt;
+ end = buf + m - 1;
+ last = *end;
+ *end = 0;
+ cp = buf;
+ }
+ if (c >= 0)
+ {
+ if (!(n = states[c]))
{
- if (!(n = states[lastchar]))
- {
- *endbuff = lastchar;
- cp++;
- }
- else
- {
- if (--cp > cpold)
- sfwrite(fdout,(char*)cpold,cp-cpold);
- if (endbuff==inbuff)
- *++endbuff = 0;
- cp = cpold = endbuff;
- cp[-1] = lastchar;
- if (n==T_ENDBUF)
- n = T_CONTROL;
-
- }
- endbuff = 0;
+ *(cur = tmp) = c;
+ m = 1;
+ goto flush;
}
- else n = T_CONTROL;
+ if (raw || n < T_CONTROL)
+ {
+ cp--;
+ goto special;
+ }
+ tmp[0] = c;
+ c = 1;
+ goto mb;
}
- if (--cp>cpold)
- sfwrite(fdout,(char*)cpold,cp-cpold);
- switch(n)
+ break;
+ case T_CONTROL:
+ do
{
- case T_CNTL8BIT:
- meta[2] = '^';
- do
- {
- n = (*cp++)&~0200;
- meta[3] = printof(n);
- sfwrite(fdout,(char*)meta,4);
- }
- while ((n=states[*cp])==T_CNTL8BIT);
- break;
- case T_EIGHTBIT:
- do
- {
- meta[2] = (*cp++)&~0200;
- sfwrite(fdout,(char*)meta,3);
- }
- while ((n=states[*cp])==T_EIGHTBIT);
- break;
- case T_CONTROL:
- do
+ sfputc(op, '^');
+ sfputc(op, printof(c));
+ } while (states[c = *++cp] == T_CONTROL);
+ break;
+ case T_CNTL8BIT:
+ meta[2] = '^';
+ do
+ {
+ n = c & ~0200;
+ meta[3] = printof(n);
+ sfwrite(op, (char*)meta, 4);
+ } while (states[c = *++cp] == T_CNTL8BIT && raw);
+ break;
+ case T_EIGHTBIT:
+ do
+ {
+ meta[2] = c & ~0200;
+ sfwrite(op, (char*)meta, 3);
+ } while (states[c = *++cp] == T_EIGHTBIT && raw);
+ break;
+ case T_NEWLINE:
+ if (header && !(flags & B_FLAG))
+ sfprintf(op, "%6d\t", line);
+ if (flags & E_FLAG)
+ sfputc(op, '$');
+ sfputc(op, '\n');
+ if (!header || !(flags & B_FLAG))
+ line++;
+ header = !(flags & S_FLAG);
+ for (;;)
+ {
+ if ((n = states[*++cp]) == T_ENDBUF)
+ {
+ if (cp != end || last != '\n')
+ break;
+ if (!(nxt = (unsigned char*)(*reserve)(ip, SF_UNBOUND, 0)))
{
- n = *cp++;
- sfputc(fdout,'^');
- sfputc(fdout,printof(n));
+ states[0] = sfvalue(ip) ? T_ERROR : T_EOF;
+ cp = end = tmp;
+ *cp-- = 0;
+ last = -1;
}
- while ((n=states[*cp])==T_CONTROL);
- break;
- case T_NEWLINE:
- lastline = line;
- if (flags&S_FLAG)
+ else if ((n = sfvalue(ip)) <= 0)
{
- while (states[*++cp]==T_NEWLINE)
- line++;
- cp--;
+ states[0] = n ? T_ERROR : T_EOF;
+ cp = end = tmp;
+ *cp-- = 0;
+ last = -1;
}
- do
+ else
{
- cp++;
- if (flags&E_FLAG)
- sfputc(fdout,'$');
- sfputc(fdout,'\n');
- if(line > lastline)
- {
- if (flags&E_FLAG)
- sfputc(fdout,'$');
- sfputc(fdout,'\n');
- }
- if (!(flags&(N_FLAG|B_FLAG)))
- continue;
- line++;
- if (cp < endbuff)
- sfprintf(fdout,"%6d\t",line);
- else printdefer = 1;
+ buf = nxt;
+ end = buf + n - 1;
+ last = *end;
+ *end = 0;
+ cp = buf - 1;
}
- while (states[*cp]==T_NEWLINE);
+ }
+ else if (n != T_NEWLINE)
break;
+ if (!(flags & S_FLAG) || any || header)
+ {
+ any = 0;
+ header = 0;
+ if ((flags & (B_FLAG|N_FLAG)) == N_FLAG)
+ sfprintf(op, "%6d\t", line);
+ if (flags & E_FLAG)
+ sfputc(op, '$');
+ sfputc(op, '\n');
+ }
+ if (!(flags & B_FLAG))
+ line++;
}
+ header = flags & (B_FLAG|N_FLAG);
+ break;
}
}
}
@@ -239,60 +400,65 @@ b_cat(int argc, char** argv, void* context)
register char* cp;
register Sfio_t* fp;
char* mode;
+ Reserve_f reserve = sfreserve;
int att;
- int dovcat=0;
+ int dovcat = 0;
char states[UCHAR_MAX+1];
- NoP(argc);
cmdinit(argc, argv, context, ERROR_CATALOG, 0);
+ setlocale(LC_ALL, "");
att = !strcmp(astconf("UNIVERSE", NiL, NiL), "att");
mode = "r";
for (;;)
{
+ n = 0;
switch (optget(argv, usage))
{
case 'A':
- flags |= T_FLAG|E_FLAG|V_FLAG;
- continue;
+ n = T_FLAG|E_FLAG|V_FLAG;
+ break;
case 'B':
- flags |= S_FLAG;
- continue;
+ n = S_FLAG;
+ break;
case 'b':
- flags |= B_FLAG;
+ n = B_FLAG;
+ break;
+ case 'd':
+ mode = opt_info.num ? "rt" : "r";
continue;
+ case 'D':
+ n = d_FLAG;
+ break;
case 'E':
- flags |= E_FLAG;
- continue;
+ n = E_FLAG;
+ break;
case 'e':
- flags |= E_FLAG|V_FLAG;
- continue;
+ n = E_FLAG|V_FLAG;
+ break;
case 'n':
- flags |= N_FLAG;
+ n = N_FLAG;
+ break;
+ case 'R':
+ reserve = opt_info.num ? regress : sfreserve;
continue;
case 's':
- flags |= att ? F_FLAG : S_FLAG;
- continue;
+ n = att ? F_FLAG : S_FLAG;
+ break;
case 'S':
- flags |= F_FLAG;
- continue;
+ n = F_FLAG;
+ break;
case 'T':
- flags |= T_FLAG;
- continue;
+ n = T_FLAG;
+ break;
case 't':
- flags |= T_FLAG|V_FLAG;
- continue;
+ n = T_FLAG|V_FLAG;
+ break;
case 'u':
- flags |= U_FLAG;
- continue;
+ n = U_FLAG;
+ break;
case 'v':
- flags |= V_FLAG;
- continue;
- case 'd':
- mode = "rt";
- continue;
- case 'D':
- flags |= d_FLAG;
- continue;
+ n = V_FLAG;
+ break;
case ':':
error(2, "%s", opt_info.arg);
break;
@@ -300,7 +466,12 @@ b_cat(int argc, char** argv, void* context)
error(ERROR_usage(2), "%s", opt_info.arg);
break;
}
- break;
+ if (!n)
+ break;
+ if (opt_info.num)
+ flags |= n;
+ else
+ flags &= ~n;
}
argv += opt_info.index;
if (error_info.errors)
@@ -340,15 +511,13 @@ b_cat(int argc, char** argv, void* context)
states['\n'] = T_NEWLINE;
dovcat = 1;
}
- if (flags&B_FLAG)
- flags |= S_FLAG;
if (flags&d_FLAG)
sfopen(sfstdout, NiL, "wt");
if (cp = *argv)
argv++;
do
{
- if (!cp || streq(cp,"-"))
+ if (!cp || streq(cp, "-"))
{
fp = sfstdin;
if (flags&D_FLAG)
@@ -364,7 +533,7 @@ b_cat(int argc, char** argv, void* context)
if (flags&U_FLAG)
sfsetbuf(fp, (void*)fp, -1);
if (dovcat)
- n = vcat(states, fp, sfstdout, flags);
+ n = vcat(states, fp, sfstdout, reserve, flags);
else if (sfmove(fp, sfstdout, SF_UNBOUND, -1) >= 0 && sfeof(fp))
n = 0;
else
diff --git a/usr/src/lib/libcmd/common/chgrp.c b/usr/src/lib/libcmd/common/chgrp.c
index 5525157070..3295f3ab24 100644
--- a/usr/src/lib/libcmd/common/chgrp.c
+++ b/usr/src/lib/libcmd/common/chgrp.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
@@ -28,7 +28,7 @@
*/
static const char usage_1[] =
-"[-?@(#)$Id: chgrp (AT&T Research) 2008-03-28 $\n]"
+"[-?@(#)$Id: chgrp (AT&T Research) 2009-07-02 $\n]"
USAGE_LICENSE
;
@@ -221,6 +221,7 @@ b_chgrp(int argc, char** argv, void* context)
register FTSENT*ent;
register int i;
Dt_t* map = 0;
+ int logical = 1;
int flags;
int uid;
int gid;
@@ -297,16 +298,20 @@ b_chgrp(int argc, char** argv, void* context)
continue;
case 'H':
flags |= FTS_META|FTS_PHYSICAL;
+ logical = 0;
continue;
case 'L':
flags &= ~(FTS_META|FTS_PHYSICAL);
+ logical = 0;
continue;
case 'P':
flags &= ~FTS_META;
flags |= FTS_PHYSICAL;
+ logical = 0;
continue;
case 'R':
flags &= ~FTS_TOP;
+ logical = 0;
continue;
case 'X':
options |= OPT_TEST;
@@ -325,6 +330,8 @@ b_chgrp(int argc, char** argv, void* context)
if (error_info.errors || argc < 2)
error(ERROR_usage(2), "%s", optusage(NiL));
s = *argv;
+ if (logical)
+ flags &= ~(FTS_META|FTS_PHYSICAL);
if (map)
{
if (streq(s, "-"))
diff --git a/usr/src/lib/libcmd/common/chmod.c b/usr/src/lib/libcmd/common/chmod.c
index f8fc03226a..4247446859 100644
--- a/usr/src/lib/libcmd/common/chmod.c
+++ b/usr/src/lib/libcmd/common/chmod.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
@@ -28,7 +28,7 @@
*/
static const char usage[] =
-"[-?\n@(#)$Id: chmod (AT&T Research) 2007-09-10 $\n]"
+"[-?\n@(#)$Id: chmod (AT&T Research) 2009-07-02 $\n]"
USAGE_LICENSE
"[+NAME?chmod - change the access permissions of files]"
"[+DESCRIPTION?\bchmod\b changes the permission of each file "
@@ -158,6 +158,7 @@ b_chmod(int argc, char** argv, void* context)
register FTSENT*ent;
char* last;
int (*chmodf)(const char*, mode_t);
+ int logical = 1;
int notify = 0;
int ignore = 0;
int show = 0;
@@ -206,16 +207,20 @@ b_chmod(int argc, char** argv, void* context)
continue;
case 'H':
flags |= FTS_META|FTS_PHYSICAL;
+ logical = 0;
continue;
case 'L':
flags &= ~(FTS_META|FTS_PHYSICAL);
+ logical = 0;
continue;
case 'P':
flags &= ~FTS_META;
flags |= FTS_PHYSICAL;
+ logical = 0;
continue;
case 'R':
flags &= ~FTS_TOP;
+ logical = 0;
continue;
case '?':
error(ERROR_usage(2), "%s", opt_info.arg);
@@ -226,6 +231,8 @@ b_chmod(int argc, char** argv, void* context)
argv += opt_info.index;
if (error_info.errors || !*argv || !amode && !*(argv + 1))
error(ERROR_usage(2), "%s", optusage(NiL));
+ if (logical)
+ flags &= ~(FTS_META|FTS_PHYSICAL);
if (ignore)
ignore = umask(0);
if (amode)
diff --git a/usr/src/lib/libcmd/common/chown.c b/usr/src/lib/libcmd/common/chown.c
index 83340c346a..cc80ba516f 100644
--- a/usr/src/lib/libcmd/common/chown.c
+++ b/usr/src/lib/libcmd/common/chown.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
diff --git a/usr/src/lib/libcmd/common/cksum.c b/usr/src/lib/libcmd/common/cksum.c
index 56a80131a6..2be23e4a93 100644
--- a/usr/src/lib/libcmd/common/cksum.c
+++ b/usr/src/lib/libcmd/common/cksum.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
@@ -27,7 +27,7 @@
*/
static const char usage[] =
-"[-?\n@(#)$Id: sum (AT&T Research) 2007-11-27 $\n]"
+"[-?\n@(#)$Id: sum (AT&T Research) 2009-07-02 $\n]"
USAGE_LICENSE
"[+NAME?cksum,md5sum,sum - print file checksum and block count]"
"[+DESCRIPTION?\bsum\b lists the checksum, and for most methods the block"
@@ -447,6 +447,7 @@ b_cksum(int argc, register char** argv, void* context)
Sfio_t* sp;
FTS* fts;
FTSENT* ent;
+ int logical;
Optdisc_t optdisc;
State_t state;
@@ -456,6 +457,7 @@ b_cksum(int argc, register char** argv, void* context)
flags = fts_flags() | FTS_TOP | FTS_NOPOSTORDER | FTS_NOSEEDOTDIR;
state.flags = SUM_SIZE;
state.warn = 1;
+ logical = 1;
method = 0;
optinit(&optdisc, optinfo);
for (;;)
@@ -493,6 +495,7 @@ b_cksum(int argc, register char** argv, void* context)
flags &= ~FTS_TOP;
state.recursive = 1;
state.sort = order;
+ logical = 0;
continue;
case 's':
method = "sys5";
@@ -511,13 +514,16 @@ b_cksum(int argc, register char** argv, void* context)
continue;
case 'H':
flags |= FTS_META|FTS_PHYSICAL;
+ logical = 0;
continue;
case 'L':
flags &= ~(FTS_META|FTS_PHYSICAL);
+ logical = 0;
continue;
case 'P':
flags &= ~FTS_META;
flags |= FTS_PHYSICAL;
+ logical = 0;
continue;
case 'T':
state.text = 1;
@@ -548,6 +554,8 @@ b_cksum(int argc, register char** argv, void* context)
* do it
*/
+ if (logical)
+ flags &= ~(FTS_META|FTS_PHYSICAL);
if (state.permissions)
{
state.uid = geteuid();
diff --git a/usr/src/lib/libcmd/common/cmd.h b/usr/src/lib/libcmd/common/cmd.h
index 8fe4094d78..3b054da7dd 100644
--- a/usr/src/lib/libcmd/common/cmd.h
+++ b/usr/src/lib/libcmd/common/cmd.h
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
@@ -35,6 +35,8 @@
#define cmdinit _cmd_init
+#define ERROR_CALLBACK ERROR_SET
+
#if _BLD_cmd && defined(__EXPORT__)
#define extern __EXPORT__
#endif
@@ -86,7 +88,7 @@ cmdinit(int argc, register char** argv, void* context, const char* catalog, int
error_info.catalog = (char*)catalog;
opt_info.index = 0;
if (context)
- error_info.flags |= flags;
+ error_info.flags |= flags & ~(ERROR_CALLBACK|ERROR_NOTIFY);
return 0;
}
diff --git a/usr/src/lib/libcmd/common/cmdinit.c b/usr/src/lib/libcmd/common/cmdinit.c
index bd450ebf47..e0bdfe511e 100644
--- a/usr/src/lib/libcmd/common/cmdinit.c
+++ b/usr/src/lib/libcmd/common/cmdinit.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
@@ -24,14 +24,29 @@
*/
#include <cmd.h>
+#include <shcmd.h>
int
_cmd_init(int argc, char** argv, void* context, const char* catalog, int flags)
{
register char* cp;
- if (argc < 0)
+ if (argc <= 0)
return -1;
+ if (context)
+ {
+ if (flags & ERROR_CALLBACK)
+ {
+ flags &= ~ERROR_CALLBACK;
+ flags |= ERROR_NOTIFY;
+ }
+ else if (flags & ERROR_NOTIFY)
+ {
+ ((Shbltin_t*)(context))->notify = 1;
+ flags &= ~ERROR_NOTIFY;
+ }
+ error_info.flags |= flags;
+ }
if (cp = strrchr(argv[0], '/'))
cp++;
else
@@ -40,8 +55,6 @@ _cmd_init(int argc, char** argv, void* context, const char* catalog, int flags)
if (!error_info.catalog)
error_info.catalog = catalog;
opt_info.index = 0;
- if (context)
- error_info.flags |= flags;
return 0;
}
diff --git a/usr/src/lib/libcmd/common/cmp.c b/usr/src/lib/libcmd/common/cmp.c
index 06223f5695..12b69ee23b 100644
--- a/usr/src/lib/libcmd/common/cmp.c
+++ b/usr/src/lib/libcmd/common/cmp.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
@@ -28,7 +28,7 @@
*/
static const char usage[] =
-"[-?\n@(#)$Id: cmp (AT&T Research) 2004-12-01 $\n]"
+"[-?\n@(#)$Id: cmp (AT&T Research) 2009-01-05 $\n]"
USAGE_LICENSE
"[+NAME?cmp - compare two files]"
"[+DESCRIPTION?\bcmp\b compares two files \afile1\a and \afile2\a. "
@@ -119,7 +119,7 @@ cmp(const char* file1, Sfio_t* f1, const char* file2, Sfio_t* f2, int flags)
{
ret = 1;
if (!(flags & CMP_SILENT))
- error(ERROR_exit(1), "%s: EOF", file1);
+ error(ERROR_exit(1), "EOF on %s", file1);
}
return(ret);
}
@@ -130,7 +130,7 @@ cmp(const char* file1, Sfio_t* f1, const char* file2, Sfio_t* f2, int flags)
if (!(p2 = (unsigned char*)sfreserve(f2, SF_UNBOUND, 0)) || (c2 = sfvalue(f2)) <= 0)
{
if (!(flags & CMP_SILENT))
- error(ERROR_exit(1), "%s: EOF", file2);
+ error(ERROR_exit(1), "EOF on %s", file2);
return(1);
}
e2 = p2 + c2;
@@ -263,14 +263,14 @@ b_cmp(int argc, register char** argv, void* context)
if (o1 && sfseek(f1, o1, SEEK_SET) != o1)
{
if (!(flags & CMP_SILENT))
- error(ERROR_exit(0), "%s: EOF", file1);
+ error(ERROR_exit(0), "EOF on %s", file1);
n = 1;
goto done;
}
if (o2 && sfseek(f2, o2, SEEK_SET) != o2)
{
if (!(flags & CMP_SILENT))
- error(ERROR_exit(0), "%s: EOF", file2);
+ error(ERROR_exit(0), "EOF on %s", file2);
n = 1;
goto done;
}
@@ -280,7 +280,8 @@ b_cmp(int argc, register char** argv, void* context)
error(ERROR_system(0), "%s: cannot stat", file1);
else if (s1.st_ino == s2.st_ino && s1.st_dev == s2.st_dev && o1 == o2)
n = 0;
- else n = ((flags & CMP_SILENT) && S_ISREG(s1.st_mode) && S_ISREG(s2.st_mode) && (s1.st_size - o1) != (s2.st_size - o2)) ? 1 : cmp(file1, f1, file2, f2, flags);
+ else
+ n = ((flags & CMP_SILENT) && S_ISREG(s1.st_mode) && S_ISREG(s2.st_mode) && (s1.st_size - o1) != (s2.st_size - o2)) ? 1 : cmp(file1, f1, file2, f2, flags);
done:
if (f1 && f1 != sfstdin) sfclose(f1);
if (f2 && f2 != sfstdin) sfclose(f2);
diff --git a/usr/src/lib/libcmd/common/comm.c b/usr/src/lib/libcmd/common/comm.c
index 347867d656..f3fee9ef09 100644
--- a/usr/src/lib/libcmd/common/comm.c
+++ b/usr/src/lib/libcmd/common/comm.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
diff --git a/usr/src/lib/libcmd/common/cp.c b/usr/src/lib/libcmd/common/cp.c
index c3484b0cb0..bff4430830 100644
--- a/usr/src/lib/libcmd/common/cp.c
+++ b/usr/src/lib/libcmd/common/cp.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
@@ -27,7 +27,7 @@
*/
static const char usage_head[] =
-"[-?@(#)$Id: cp (AT&T Research) 2007-12-13 $\n]"
+"[-?@(#)$Id: cp (AT&T Research) 2009-06-18 $\n]"
USAGE_LICENSE
;
@@ -142,6 +142,7 @@ static const char usage_tail[] =
typedef struct State_s /* program state */
{
+ void* context; /* builtin context */
int backup; /* BAK_* type */
int directory; /* destination is directory */
int flags; /* FTS_* flags */
@@ -438,7 +439,7 @@ visit(State_t* state, register FTSENT* ent)
/* ok */;
else if (state->interactive)
{
- if (astquery(-1, "%s %s? ", state->opname, state->path))
+ if (astquery(-1, "%s %s? ", state->opname, state->path) < 0 || sh_checksig(state->context))
return 0;
}
else if (state->op == LN)
@@ -459,7 +460,7 @@ visit(State_t* state, register FTSENT* ent)
fmtmode(st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO), 0) + 1;
if (state->interactive)
{
- if (astquery(-1, "override protection %s for %s? ", protection, state->path))
+ if (astquery(-1, "override protection %s for %s? ", protection, state->path) < 0 || sh_checksig(state->context))
return 0;
rm = 1;
}
@@ -659,7 +660,7 @@ b_cp(int argc, register char** argv, void* context)
char** v;
char* backup_type;
FTS* fts;
- FTSENT* ent;
+ FTSENT* ent;
const char* usage;
int path_resolve;
int standard;
@@ -677,6 +678,7 @@ b_cp(int argc, register char** argv, void* context)
}
else
memset(state, 0, offsetof(State_t, INITSTATE));
+ state->context = context;
state->presiz = -1;
backup_type = 0;
state->flags = FTS_NOCHDIR|FTS_NOSEEDOTDIR;
diff --git a/usr/src/lib/libcmd/common/cut.c b/usr/src/lib/libcmd/common/cut.c
index 305ebdaf9d..2be03c3183 100644
--- a/usr/src/lib/libcmd/common/cut.c
+++ b/usr/src/lib/libcmd/common/cut.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
diff --git a/usr/src/lib/libcmd/common/date.c b/usr/src/lib/libcmd/common/date.c
index 1984570b2d..d7895b02d4 100644
--- a/usr/src/lib/libcmd/common/date.c
+++ b/usr/src/lib/libcmd/common/date.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
@@ -27,7 +27,7 @@
*/
static const char usage[] =
-"[-?\n@(#)$Id: date (AT&T Research) 2007-05-21 $\n]"
+"[-?\n@(#)$Id: date (AT&T Research) 2009-03-03 $\n]"
USAGE_LICENSE
"[+NAME?date - set/list/convert dates]"
"[+DESCRIPTION?\bdate\b sets the current date and time (with appropriate"
@@ -106,7 +106,7 @@ USAGE_LICENSE
" [+j?1-offset Julian date]"
" [+J?0-offset Julian date]"
" [+k?\bdate\b(1) style date]"
-" [+K?all numeric date; equivalent to \b%Y-%m-%d+%H:%M:%S\b]"
+" [+K?all numeric date; equivalent to \b%Y-%m-%d+%H:%M:%S\b; \b%_[EO]]K\b for space separator, %OK adds \b.%N\b, \b%EK\b adds \b%.N%z\b, \b%_EK\b adds \b.%N %z\b]"
" [+l?\bls\b(1) \b-l\b date; equivalent to \b%Q/%g/%G/\b]"
" [+L?locale default date format]"
" [+m?month number]"
@@ -212,7 +212,7 @@ settime(void* context, const char* cmd, Time_t now, int adjust, int network)
char* s;
char** argv;
char* args[5];
- char buf[128];
+ char buf[1024];
if (!adjust && !network)
return tmxsettime(now);
@@ -276,7 +276,7 @@ b_date(int argc, register char** argv, void* context)
Time_t ts;
Time_t te;
Time_t e;
- char buf[128];
+ char buf[1024];
Fmt_t* fmts;
Fmt_t fmt;
struct stat st;
diff --git a/usr/src/lib/libcmd/common/dirname.c b/usr/src/lib/libcmd/common/dirname.c
index 71e69d8594..cd6076240b 100644
--- a/usr/src/lib/libcmd/common/dirname.c
+++ b/usr/src/lib/libcmd/common/dirname.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
@@ -29,7 +29,7 @@
*/
static const char usage[] =
-"[-?\n@(#)$Id: dirname (AT&T Research) 2000-03-07 $\n]"
+"[-?\n@(#)$Id: dirname (AT&T Research) 2009-01-31 $\n]"
USAGE_LICENSE
"[+NAME?dirname - return directory portion of file name]"
"[+DESCRIPTION?\bdirname\b treats \astring\a as a file name and returns "
@@ -48,14 +48,17 @@ USAGE_LICENSE
"as \b/\b characters as described above. Otherwise, all "
"trailing slashes are removed and the output will be this string "
"unless this string is empty. If empty the output will be \b.\b.]"
+"[f:file?Print the \b$PATH\b relative regular file path for \astring\a.]"
+"[r:relative?Print the \b$PATH\b relative readable file path for \astring\a.]"
+"[x:executable?Print the \b$PATH\b relative executable file path for \astring\a.]"
"\n"
-"\n string\n"
+"\nstring\n"
"\n"
"[+EXIT STATUS?]{"
"[+0?Successful Completion.]"
"[+>0?An error occurred.]"
"}"
-"[+SEE ALSO?\bbasename\b(1), \bgetconf\b(1), \bdirname\b(3)]"
+"[+SEE ALSO?\bbasename\b(1), \bgetconf\b(1), \bdirname\b(3), \bpathname\b(3)]"
;
#include <cmd.h>
@@ -96,10 +99,22 @@ int
b_dirname(int argc,register char *argv[], void* context)
{
register int n;
+ int mode = 0;
+ char buf[PATH_MAX];
cmdinit(argc, argv, context, ERROR_CATALOG, 0);
while (n = optget(argv, usage)) switch (n)
{
+ case 'f':
+ mode |= PATH_REGULAR;
+ break;
+ case 'r':
+ mode &= ~PATH_REGULAR;
+ mode |= PATH_READ;
+ break;
+ case 'x':
+ mode |= PATH_EXECUTE;
+ break;
case ':':
error(2, "%s", opt_info.arg);
break;
@@ -111,6 +126,11 @@ b_dirname(int argc,register char *argv[], void* context)
argc -= opt_info.index;
if(error_info.errors || argc != 1)
error(ERROR_usage(2),"%s", optusage(NiL));
- l_dirname(sfstdout,argv[0]);
+ if(!mode)
+ l_dirname(sfstdout,argv[0]);
+ else if(pathpath(buf, argv[0], "", mode))
+ sfputr(sfstdout, buf, '\n');
+ else
+ error(1|ERROR_WARNING, "%s: relative path not found", argv[0]);
return(0);
}
diff --git a/usr/src/lib/libcmd/common/expr.c b/usr/src/lib/libcmd/common/expr.c
index ff5d45e039..78749d25ce 100644
--- a/usr/src/lib/libcmd/common/expr.c
+++ b/usr/src/lib/libcmd/common/expr.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
diff --git a/usr/src/lib/libcmd/common/fds.c b/usr/src/lib/libcmd/common/fds.c
index bafa2c09f7..cca4fd22c3 100644
--- a/usr/src/lib/libcmd/common/fds.c
+++ b/usr/src/lib/libcmd/common/fds.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
@@ -21,7 +21,7 @@
#pragma prototyped
static const char usage[] =
-"[-?\n@(#)$Id: fds (AT&T Research) 2008-08-26 $\n]"
+"[-?\n@(#)$Id: fds (AT&T Research) 2009-09-09 $\n]"
USAGE_LICENSE
"[+NAME?fds - list open file descriptor status]"
"[+DESCRIPTION?\bfds\b lists the status for each open file descriptor. "
@@ -29,6 +29,7 @@ USAGE_LICENSE
"calling shell, otherwise it lists the file descriptors passed across "
"\bexec\b(2).]"
"[l:long?List file descriptor details.]"
+"[u:unit?Write output to \afd\a.]#[fd]"
"[+SEE ALSO?\blogname\b(1), \bwho\b(1), \bgetgroups\b(2), \bgetsockname\b(2), \bgetsockopts\b(2)]"
;
@@ -164,6 +165,8 @@ b_fds(int argc, char** argv, void* context)
int flags;
int details;
int open_max;
+ int unit;
+ Sfio_t* sp;
struct stat st;
#ifdef S_IFSOCK
struct sockaddr_in addr;
@@ -175,13 +178,16 @@ b_fds(int argc, char** argv, void* context)
int type;
int port;
int prot;
- char nam[256];
char num[64];
char fam[64];
+#ifdef INET6_ADDRSTRLEN
+ char nam[256];
+#endif
#endif
cmdinit(argc, argv, context, ERROR_CATALOG, 0);
details = 0;
+ unit = 1;
for (;;)
{
switch (optget(argv, usage))
@@ -189,6 +195,9 @@ b_fds(int argc, char** argv, void* context)
case 'l':
details = opt_info.num;
continue;
+ case 'u':
+ unit = opt_info.num;
+ continue;
case '?':
error(ERROR_USAGE|4, "%s", opt_info.arg);
continue;
@@ -203,6 +212,10 @@ b_fds(int argc, char** argv, void* context)
error(ERROR_USAGE|4, "%s", optusage(NiL));
if ((open_max = getconf("OPEN_MAX")) <= 0)
open_max = OPEN_MAX;
+ if (unit == 1)
+ sp = sfstdout;
+ else if (fstat(unit, &st) || !(sp = sfnew(NiL, NiL, SF_UNBOUND, unit, SF_WRITE)))
+ error(ERROR_SYSTEM|3, "%d: cannot write to file descriptor");
for (i = 0; i <= open_max; i++)
{
if (fstat(i, &st))
@@ -212,7 +225,7 @@ b_fds(int argc, char** argv, void* context)
}
if (!details)
{
- sfprintf(sfstdout, "%d\n", i);
+ sfprintf(sp, "%d\n", i);
continue;
}
if ((flags = fcntl(i, F_GETFL, (char*)0)) == -1)
@@ -236,7 +249,7 @@ b_fds(int argc, char** argv, void* context)
x = (fcntl(i, F_GETFD, (char*)0) > 0) ? "x" : "-";
if (isatty(i) && (s = ttyname(i)))
{
- sfprintf(sfstdout, "%02d %s%s %s %s\n", i, m, x, fmtmode(st.st_mode, 0), s);
+ sfprintf(sp, "%02d %s%s %s %s\n", i, m, x, fmtmode(st.st_mode, 0), s);
continue;
}
#ifdef S_IFSOCK
@@ -330,13 +343,18 @@ b_fds(int argc, char** argv, void* context)
a = a == fam ? "0" : fam + 1;
}
if (port)
- sfprintf(sfstdout, "%02d %s%s %s /dev/%s/%s/%d\n", i, m, x, fmtmode(st.st_mode, 0), s, a, port);
+ sfprintf(sp, "%02d %s%s %s /dev/%s/%s/%d\n", i, m, x, fmtmode(st.st_mode, 0), s, a, port);
else
- sfprintf(sfstdout, "%02d %s%s %s /dev/%s/%s\n", i, m, x, fmtmode(st.st_mode, 0), s, a);
+ sfprintf(sp, "%02d %s%s %s /dev/%s/%s\n", i, m, x, fmtmode(st.st_mode, 0), s, a);
continue;
}
#endif
- sfprintf(sfstdout, "%02d %s%s %s /dev/inode/%u/%u\n", i, m, x, fmtmode(st.st_mode, 0), st.st_dev, st.st_ino);
+ sfprintf(sp, "%02d %s%s %s /dev/inode/%u/%u\n", i, m, x, fmtmode(st.st_mode, 0), st.st_dev, st.st_ino);
+ }
+ if (sp != sfstdout)
+ {
+ sfsetfd(sp, -1);
+ sfclose(sp);
}
return 0;
}
diff --git a/usr/src/lib/libcmd/common/features/utsname b/usr/src/lib/libcmd/common/features/utsname
index 5b746ce7ad..7254867181 100644
--- a/usr/src/lib/libcmd/common/features/utsname
+++ b/usr/src/lib/libcmd/common/features/utsname
@@ -6,6 +6,9 @@ sys syscall,systeminfo,syssgi
tst cross{
u=`/bin/uname -o 2>/dev/null`
case $u in
+ UWIN-*) u=UWIN ;;
+ esac
+ case $u in
'') ;;
*) echo "#define _UNAME_os_DEFAULT \"$u\" /* default os name */" ;;
esac
diff --git a/usr/src/lib/libcmd/common/fmt.c b/usr/src/lib/libcmd/common/fmt.c
index 95f5fd4528..ab0db310ea 100644
--- a/usr/src/lib/libcmd/common/fmt.c
+++ b/usr/src/lib/libcmd/common/fmt.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
diff --git a/usr/src/lib/libcmd/common/fold.c b/usr/src/lib/libcmd/common/fold.c
index 6541da8035..01a2cadfb1 100644
--- a/usr/src/lib/libcmd/common/fold.c
+++ b/usr/src/lib/libcmd/common/fold.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
diff --git a/usr/src/lib/libcmd/common/getconf.c b/usr/src/lib/libcmd/common/getconf.c
index bceae0e167..a4509437ab 100644
--- a/usr/src/lib/libcmd/common/getconf.c
+++ b/usr/src/lib/libcmd/common/getconf.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
diff --git a/usr/src/lib/libcmd/common/grep.c b/usr/src/lib/libcmd/common/grep.c
new file mode 100644
index 0000000000..1e857f087c
--- /dev/null
+++ b/usr/src/lib/libcmd/common/grep.c
@@ -0,0 +1,876 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1995-2009 AT&T Knowledge Ventures *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Knowledge Ventures *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+static const char usage[] =
+"[-?\n@(#)$Id: grep (AT&T Research) 2006-06-14 $\n]"
+USAGE_LICENSE
+"[+NAME?grep - search lines in files for matching patterns]"
+"[+DESCRIPTION?The \bgrep\b commands search the named input files"
+" for lines containing a match for the given \apatterns\a."
+" Matching lines are printed by default. The standard input is searched"
+" if no files are given or when the file \b-\b is specified.]"
+"[+?There are six variants of \bgrep\b, each one using a different form of"
+" \apattern\a, controlled either by option or the command path"
+" base name. Details of each variant may be found in \bregex\b(3).]"
+" {"
+" [+grep?The default basic regular expressions (no alternations.)]"
+" [+egrep?Extended regular expressions (alternations, one or more.)]"
+" [+pgrep?\bperl\b(1) regular expressions (lenient extended.)]"
+" [+xgrep?Augmented regular expressions (conjunction, negation.)]"
+" [+fgrep?Fixed string expressions.]"
+" [+agrep?Approximate regular expressions (not implemented.)]"
+" }"
+"[G:basic-regexp?\bgrep\b mode (default): basic regular expression \apatterns\a.]"
+"[E:extended-regexp?\begrep\b mode: extended regular expression \apatterns\a.]"
+"[X:augmented-regexp?\bxgrep\b mode: augmented regular expression \apatterns\a.]"
+"[P:perl-regexp?\bpgrep\b mode: \bperl\b(1) regular expression \apatterns\a.]"
+"[F:fixed-string?\bfgrep\b mode: fixed string \apatterns\a.]"
+"[A:approximate-regexp?\bagrep\b mode: approximate regular expression \apatterns\a (not implemented.)]"
+
+"[C:context?Set the matched line context \abefore\a and \aafter\a count."
+" By default only matched lines are printed.]:?"
+" [before[,after]]:=2,2]"
+"[c:count?Only print a matching line count for each file.]"
+"[e:expression|pattern|regexp?Specify a matching \apattern\a. More than one"
+" \apattern\a implies alternation. If this option is specified"
+" then the command line \apattern\a must be omitted.]:"
+" [pattern]"
+"[f:file?Each line in \apattern-file\a is a \apattern\a, placed into a single"
+" alternating expression.]:"
+" [pattern-file]"
+"[H:filename|with-filename?Prefix each matched line with the containing file name.]"
+"[h:no-filename?Suppress containing file name prefix for each matched line.]"
+"[i:ignore-case?Ignore case when matching.]"
+"[l:files-with-matches?Only print file names with at least one match.]"
+"[L:files-without-matches?Only print file names with no matches.]"
+"[b:highlight?Highlight matches using the ansi terminal bold sequence.]"
+"[v:invert-match|revert-match?Invert the \apattern\a match sense.]"
+"[m:label?All patterns must be of the form \alabel\a:\apattern\a. Match and"
+" count output will be prefixed by the corresponding \alabel\a:.]"
+"[O:lenient?Enable lenient \apattern\a interpretation. This is the default.]"
+"[x:line-match|line-regexp?Force \apatterns\a to match complete lines.]"
+"[n:number|line-number?Prefix each matched line with its line number.]"
+"[N:name?Set the standard input file name prefix to"
+" \aname\a.]:[name:=empty]"
+"[q:quiet|silent?Do not print matching lines.]"
+"[S:strict?Enable strict \apattern\a interpretation with diagnostics.]"
+"[s:suppress|no-messages?Suppress error and warning messages.]"
+"[t:total?Only print a single matching line count for all files.]"
+"[T:test?Enable implementation specific tests.]:"
+" [test]"
+"[w:word-match|word-regexp?Force \apatterns\a to match complete words.]"
+"[a?Ignored for GNU compatibility.]"
+"\n"
+"\n[ pattern ] [ file ... ]\n"
+"\n"
+"[+DIAGNOSTICS?Exit status 0 if matches were found, 1 if no matches were found,"
+" where \b-v\b invertes the exit status. Exit status 2 for other"
+" errors that are accompanied by a message on the standard error.]"
+"[+SEE ALSO?\bed\b(1), \bsed\b(1), \bperl\b(1), \bregex\b(3)]"
+"[+CAVEATS?Some expressions of necessity require exponential space"
+" and/or time.]"
+"[+BUGS?Some expressions may use sub-optimal algorithms. For example,"
+" don't use this implementation to compute primes.]"
+;
+
+#include <ast.h>
+#include <ctype.h>
+#include <ccode.h>
+#include <error.h>
+#include <regex.h>
+
+#ifndef EISDIR
+#define EISDIR (-1)
+#endif
+
+/*
+ * snarfed from Doug McElroy's C++ version
+ *
+ * this grep is based on the Posix re package.
+ * unfortunately it has to have a nonstandard interface.
+ * 1. fgrep does not have usual operators. REG_LITERAL
+ * caters for this.
+ * 2. grep allows null expressions, hence REG_NULL.
+ * 3. it may be possible to combine the multiple
+ * patterns of grep into single patterns. important
+ * special cases are handled by regcomb().
+ * 4. anchoring by -x has to be done separately from
+ * compilation (remember that fgrep has no ^ or $ operator),
+ * hence REG_LEFT|REG_RIGHT. (An honest, but slow alternative:
+ * run regexec with REG_NOSUB off and nmatch=1 and check
+ * whether the match is full length)
+ */
+
+typedef struct Item_s /* list item - sue me for waste */
+{
+ struct Item_s* next; /* next in list */
+ regex_t re; /* compiled re */
+ Sfulong_t hits; /* labeled pattern matches */
+ Sfulong_t total; /* total hits */
+ char string[1]; /* string value */
+} Item_t;
+
+typedef struct List_s /* generic list */
+{
+ Item_t* head; /* list head */
+ Item_t* tail; /* list tail */
+} List_t;
+
+typedef struct State_s /* program state */
+{
+ struct
+ {
+ char* base; /* sfsetbuf buffer */
+ size_t size; /* sfsetbuf size */
+ int noshare; /* turn off SF_SHARE */
+ } buffer;
+
+ List_t file; /* pattern file list */
+ List_t pattern; /* pattern list */
+ List_t re; /* re list */
+
+ regmatch_t posvec[1]; /* match position vector */
+ regmatch_t* pos; /* match position pointer */
+ int posnum; /* number of match positions */
+
+ int any; /* if any pattern hit */
+ int list; /* list files with hits */
+ int notfound; /* some input file not found */
+ int options; /* regex options */
+
+ Sfulong_t hits; /* total matched pattern count */
+
+ unsigned char byline; /* multiple pattern line by line*/
+ unsigned char count; /* count number of hits */
+ unsigned char label; /* all patterns labeled */
+ unsigned char match; /* match sense */
+ unsigned char query; /* return status but no output */
+ unsigned char number; /* line numbers */
+ unsigned char prefix; /* print file prefix */
+ unsigned char suppress; /* no unopenable file messages */
+ unsigned char words; /* word matches only */
+} State_s;
+
+static void
+addre(State_s *state, List_t* p, char* s)
+{
+ int c;
+ char* b;
+ Item_t* x;
+ Sfio_t* t;
+
+ b = s;
+ if (state->label)
+ {
+ if (!(s = strchr(s, ':')))
+ error(3, "%s: label:pattern expected", b);
+ c = s - b;
+ s++;
+ }
+ else
+ c = 0;
+ if (!(x = newof(0, Item_t, 1, c)))
+ error(ERROR_SYSTEM|3, "out of space (pattern `%s')", b);
+ if (c)
+ memcpy(x->string, b, c);
+ if (state->words)
+ {
+ if (!(t = sfstropen()))
+ error(ERROR_SYSTEM|3, "out of space (word pattern `%s')", s);
+ if (!(state->options & REG_AUGMENTED))
+ sfputc(t, '\\');
+ sfputc(t, '<');
+ sfputr(t, s, -1);
+ if (!(state->options & REG_AUGMENTED))
+ sfputc(t, '\\');
+ sfputc(t, '>');
+ if (!(s = sfstruse(t)))
+ error(ERROR_SYSTEM|3, "out of space");
+ }
+ else
+ t = 0;
+ if (c = regcomp(&x->re, s, state->options|REG_MULTIPLE))
+ regfatal(&x->re, 3, c);
+ if (t)
+ sfstrclose(t);
+ if (!p->head)
+ {
+ p->head = p->tail = x;
+ if (state->number || !regrecord(&x->re))
+ state->byline = 1;
+ }
+ else if (state->label || regcomb(&p->tail->re, &x->re))
+ {
+ p->tail = p->tail->next = x;
+ if (!state->byline && (state->number || !state->label || !regrecord(&x->re)))
+ state->byline = 1;
+ }
+ else
+ free(x);
+}
+
+static void
+addstring(State_s *state, List_t* p, char* s)
+{
+ Item_t* x;
+
+ if (!(x = newof(0, Item_t, 1, strlen(s))))
+ error(ERROR_SYSTEM|3, "out of space (string `%s')", s);
+ strcpy(x->string, s);
+ if (p->head)
+ p->tail->next = x;
+ else
+ p->head = x;
+ p->tail = x;
+}
+
+static void
+compile(State_s *state)
+{
+ int line;
+ size_t n;
+ char* s;
+ char* t;
+ char* file;
+ Item_t* x;
+ Sfio_t* f;
+
+ for (x = state->pattern.head; x; x = x->next)
+ addre(state, &state->re, x->string);
+ for (x = state->file.head; x; x = x->next)
+ {
+ s = x->string;
+ if (!(f = sfopen(NiL, s, "r")))
+ error(ERROR_SYSTEM|4, "%s: cannot open", s);
+ else
+ {
+ file = error_info.file;
+ error_info.file = s;
+ line = error_info.line;
+ error_info.line = 0;
+ while (s = (char*)sfreserve(f, SF_UNBOUND, SF_LOCKR))
+ {
+ if (!(n = sfvalue(f)))
+ break;
+ if (s[n - 1] != '\n')
+ {
+ for (t = s + n; t > s && *--t != '\n'; t--);
+ if (t == s)
+ {
+ sfread(f, s, 0);
+ break;
+ }
+ n = t - s + 1;
+ }
+ s[n - 1] = 0;
+ addre(state, &state->re, s);
+ s[n - 1] = '\n';
+ sfread(f, s, n);
+ }
+ while ((s = sfgetr(f, '\n', 1)) || (s = sfgetr(f, '\n', -1)))
+ {
+ error_info.line++;
+ addre(state, &state->re, s);
+ }
+ error_info.file = file;
+ error_info.line = line;
+ sfclose(f);
+ }
+ }
+ if (!state->re.head)
+ error(3, "no pattern");
+}
+
+static void
+highlight(Sfio_t* sp, const char* s, int n, int so, int eo)
+{
+ static const char bold[] = {CC_esc,'[','1','m'};
+ static const char normal[] = {CC_esc,'[','0','m'};
+
+ sfwrite(sp, s, so);
+ sfwrite(sp, bold, sizeof(bold));
+ sfwrite(sp, s + so, eo - so);
+ sfwrite(sp, normal, sizeof(normal));
+ sfwrite(sp, s + eo, n - eo);
+}
+
+typedef struct
+{
+ State_s *state;
+ Item_t *item;
+} record_handle;
+
+static int
+record(void* handle, const char* s, size_t len)
+{
+ record_handle *r_x = (record_handle *)handle;
+ State_s *state = r_x->state;
+ Item_t *item = r_x->item;
+
+ item->hits++;
+ if (state->query || state->list)
+ return -1;
+ if (!state->count)
+ {
+ if (state->prefix)
+ sfprintf(sfstdout, "%s:", error_info.file);
+ if (state->label)
+ sfprintf(sfstdout, "%s:", item->string);
+ if (state->pos)
+ highlight(sfstdout, s, len + 1, state->pos[0].rm_so, state->pos[0].rm_eo);
+ else
+ sfwrite(sfstdout, s, len + 1);
+ }
+ return 0;
+}
+
+static void
+execute(State_s *state, Sfio_t* input, char* name)
+{
+ register char* s;
+ char* file;
+ Item_t* x;
+ size_t len;
+ int result;
+ int line;
+
+ Sfulong_t hits = 0;
+
+ if (state->buffer.noshare)
+ sfset(input, SF_SHARE, 0);
+ if (state->buffer.size)
+ sfsetbuf(input, state->buffer.base, state->buffer.size);
+ if (!name)
+ name = "/dev/stdin";
+ file = error_info.file;
+ error_info.file = name;
+ line = error_info.line;
+ error_info.line = 0;
+ if (state->byline)
+ {
+ for (;;)
+ {
+ error_info.line++;
+ if (s = sfgetr(input, '\n', 0))
+ len = sfvalue(input) - 1;
+ else if (s = sfgetr(input, '\n', -1))
+ {
+ len = sfvalue(input);
+ s[len] = '\n';
+#if _you_like_the_noise
+ error(1, "newline appended");
+#endif
+ }
+ else
+ {
+ if (sferror(input) && errno != EISDIR)
+ error(ERROR_SYSTEM|2, "read error");
+ break;
+ }
+ x = state->re.head;
+ do
+ {
+ if (!(result = regnexec(&x->re, s, len, state->posnum, state->pos, 0)))
+ {
+ if (!state->label)
+ break;
+ x->hits++;
+ if (state->query || state->list)
+ goto done;
+ if (!state->count)
+ {
+ if (state->prefix)
+ sfprintf(sfstdout, "%s:", name);
+ if (state->number)
+ sfprintf(sfstdout, "%d:", error_info.line);
+ sfprintf(sfstdout, "%s:", x->string);
+ if (state->pos)
+ highlight(sfstdout, s, len + 1, state->pos[0].rm_so, state->pos[0].rm_eo);
+ else
+ sfwrite(sfstdout, s, len + 1);
+ }
+ }
+ else if (result != REG_NOMATCH)
+ regfatal(&x->re, 3, result);
+ } while (x = x->next);
+ if (!state->label && (x != 0) == state->match)
+ {
+ hits++;
+ if (state->query || state->list)
+ break;
+ if (!state->count)
+ {
+ if (state->prefix)
+ sfprintf(sfstdout, "%s:", name);
+ if (state->number)
+ sfprintf(sfstdout, "%d:", error_info.line);
+ if (state->pos)
+ highlight(sfstdout, s, len + 1, state->pos[0].rm_so, state->pos[0].rm_eo);
+ else
+ sfwrite(sfstdout, s, len + 1);
+ }
+ }
+ }
+ }
+ else
+ {
+ register char* e;
+ register char* t;
+ char* r;
+
+ static char* span = 0;
+ static size_t spansize = 0;
+
+ s = e = 0;
+ for (;;)
+ {
+ if (s < e)
+ {
+ t = span;
+ for (;;)
+ {
+ len = 2 * (e - s) + t - span + 1;
+ len = roundof(len, SF_BUFSIZE);
+ if (spansize < len)
+ {
+ spansize = len;
+ len = t - span;
+ if (!(span = newof(span, char, spansize, 0)))
+ error(ERROR_SYSTEM|3, "%s: line longer than %lu characters", name, len + e - s);
+ t = span + len;
+ }
+ len = e - s;
+ memcpy(t, s, len);
+ t += len;
+ if (!(s = sfreserve(input, SF_UNBOUND, 0)) || (len = sfvalue(input)) <= 0)
+ {
+ if ((sfvalue(input) || sferror(input)) && errno != EISDIR)
+ error(ERROR_SYSTEM|2, "%s: read error", name);
+ break;
+ }
+ else if (!(e = memchr(s, '\n', len)))
+ e = s + len;
+ else
+ {
+ r = s + len;
+ len = (e - s) + t - span;
+ len = roundof(len, SF_BUFSIZE);
+ if (spansize < len)
+ {
+ spansize = len;
+ len = t - span;
+ if (!(span = newof(span, char, spansize, 0)))
+ error(ERROR_SYSTEM|3, "%s: line longer than %lu characters", name, len + e - s);
+ t = span + len;
+ }
+ len = e - s;
+ memcpy(t, s, len);
+ t += len;
+ s += len + 1;
+ e = r;
+ break;
+ }
+ }
+ *t = '\n';
+ x = state->re.head;
+ do
+ {
+ record_handle r_x = { state, x };
+ if ((result = regrexec(&x->re, span, t - span, state->posnum, state->pos, state->options, '\n', (void*)&r_x, record)) < 0)
+ goto done;
+ if (result && result != REG_NOMATCH)
+ regfatal(&x->re, 3, result);
+ } while (x = x->next);
+ if (!s)
+ break;
+ }
+ else
+ {
+ if (!(s = sfreserve(input, SF_UNBOUND, 0)))
+ {
+ if ((sfvalue(input) || sferror(input)) && errno != EISDIR)
+ error(ERROR_SYSTEM|2, "%s: read error", name);
+ break;
+ }
+ if ((len = sfvalue(input)) <= 0)
+ break;
+ e = s + len;
+ }
+ t = e;
+ while (t > s)
+ if (*--t == '\n')
+ {
+ x = state->re.head;
+ do
+ {
+ record_handle r_x = { state, x };
+ if ((result = regrexec(&x->re, s, t - s, state->posnum, state->pos, state->options, '\n', (void*)&r_x, record)) < 0)
+ goto done;
+ if (result && result != REG_NOMATCH)
+ regfatal(&x->re, 3, result);
+ } while (x = x->next);
+ s = t + 1;
+ break;
+ }
+ }
+ }
+ done:
+ error_info.file = file;
+ error_info.line = line;
+ if (state->byline && !state->label)
+ {
+ if (hits && state->list >= 0)
+ state->any = 1;
+ if (!state->query)
+ {
+ if (!state->list)
+ {
+ if (state->count)
+ {
+ if (state->count & 2)
+ state->hits += hits;
+ else
+ {
+ if (state->prefix)
+ sfprintf(sfstdout, "%s:", name);
+ sfprintf(sfstdout, "%I*u\n", sizeof(hits), hits);
+ }
+ }
+ }
+ else if ((hits != 0) == (state->list > 0))
+ {
+ if (state->list < 0)
+ state->any = 1;
+ sfprintf(sfstdout, "%s\n", name);
+ }
+ }
+ }
+ else
+ {
+ x = state->re.head;
+ do
+ {
+ if (x->hits && state->list >= 0)
+ {
+ state->any = 1;
+ if (state->query)
+ break;
+ }
+ if (!state->query)
+ {
+ if (!state->list)
+ {
+ if (state->count)
+ {
+ if (state->count & 2)
+ {
+ x->total += x->hits;
+ state->hits += x->hits;
+ }
+ else
+ {
+ if (state->prefix)
+ sfprintf(sfstdout, "%s:", name);
+ if (state->label)
+ sfprintf(sfstdout, "%s:", x->string);
+ sfprintf(sfstdout, "%I*u\n", sizeof(x->hits), x->hits);
+ }
+ }
+ }
+ else if ((x->hits != 0) == (state->list > 0))
+ {
+ if (state->list < 0)
+ state->any = 1;
+ if (state->label)
+ sfprintf(sfstdout, "%s:%s\n", name, x->string);
+ else
+ sfprintf(sfstdout, "%s\n", name);
+ }
+ }
+ x->hits = 0;
+ } while (x = x->next);
+ }
+}
+
+
+static
+int grep_main(int argc, char** argv, void *context)
+{
+ int c;
+ char* s;
+ char* h;
+ Sfio_t* f;
+ State_s state;
+ memset(&state, 0, sizeof(state));
+
+ NoP(argc);
+ state.match = 1;
+ state.options = REG_FIRST|REG_NOSUB|REG_NULL;
+ h = 0;
+ if (strcmp(astconf("CONFORMANCE", NiL, NiL), "standard"))
+ state.options |= REG_LENIENT;
+ if (s = strrchr(argv[0], '/'))
+ s++;
+ else
+ s = argv[0];
+ switch (*s)
+ {
+ case 'e':
+ case 'E':
+ s = "egrep";
+ state.options |= REG_EXTENDED;
+ break;
+ case 'f':
+ case 'F':
+ s = "fgrep";
+ state.options |= REG_LITERAL;
+ break;
+ case 'p':
+ case 'P':
+ s = "pgrep";
+ state.options |= REG_EXTENDED|REG_LENIENT;
+ break;
+ case 'x':
+ case 'X':
+ s = "xgrep";
+ state.options |= REG_AUGMENTED;
+ break;
+ default:
+ s = "grep";
+ break;
+ }
+ error_info.id = s;
+ while (c = optget(argv, usage))
+ switch (c)
+ {
+ case 'E':
+ state.options |= REG_EXTENDED;
+ break;
+ case 'F':
+ state.options |= REG_LITERAL;
+ break;
+ case 'G':
+ state.options &= ~(REG_AUGMENTED|REG_EXTENDED);
+ break;
+ case 'H':
+ state.prefix = opt_info.num;
+ break;
+ case 'L':
+ state.list = -opt_info.num;
+ break;
+ case 'N':
+ h = opt_info.arg;
+ break;
+ case 'O':
+ state.options |= REG_LENIENT;
+ break;
+ case 'P':
+ state.options |= REG_EXTENDED|REG_LENIENT;
+ break;
+ case 'S':
+ state.options &= ~REG_LENIENT;
+ break;
+ case 'T':
+ s = opt_info.arg;
+ switch (*s)
+ {
+ case 'b':
+ case 'm':
+ c = *s++;
+ state.buffer.size = strton(s, &s, NiL, 1);
+ if (c == 'b' && !(state.buffer.base = newof(0, char, state.buffer.size, 0)))
+ error(ERROR_SYSTEM|3, "out of space [test buffer]");
+ if (*s)
+ error(3, "%s: invalid characters after test", s);
+ break;
+ case 'f':
+ state.options |= REG_FIRST;
+ break;
+ case 'l':
+ state.options |= REG_LEFT;
+ break;
+ case 'n':
+ state.buffer.noshare = 1;
+ break;
+ case 'r':
+ state.options |= REG_RIGHT;
+ break;
+ default:
+ error(3, "%s: unknown test", s);
+ break;
+ }
+ break;
+ case 'X':
+ state.options |= REG_AUGMENTED;
+ break;
+ case 'a':
+ break;
+ case 'b':
+ state.options &= ~(REG_FIRST|REG_NOSUB);
+ break;
+ case 'c':
+ state.count |= 1;
+ break;
+ case 'e':
+ addstring(&state, &state.pattern, opt_info.arg);
+ break;
+ case 'f':
+ addstring(&state, &state.file, opt_info.arg);
+ break;
+ case 'h':
+ state.prefix = 2;
+ break;
+ case 'i':
+ state.options |= REG_ICASE;
+ break;
+ case 'l':
+ state.list = opt_info.num;
+ break;
+ case 'm':
+ state.label = 1;
+ break;
+ case 'n':
+ state.number = 1;
+ break;
+ case 'q':
+ state.query = 1;
+ break;
+ case 's':
+ state.suppress = opt_info.num;
+ break;
+ case 't':
+ state.count |= 2;
+ break;
+ case 'v':
+ if (state.match = !opt_info.num)
+ state.options &= ~REG_INVERT;
+ else
+ state.options |= REG_INVERT;
+ break;
+ case 'w':
+ state.words = 1;
+ break;
+ case 'x':
+ state.options |= REG_LEFT|REG_RIGHT;
+ break;
+ case '?':
+ error(ERROR_USAGE|4, "%s", opt_info.arg);
+ break;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ default:
+ error(3, "%s: not implemented", opt_info.name);
+ break;
+ }
+ argv += opt_info.index;
+ if ((state.options & REG_LITERAL) && (state.options & (REG_AUGMENTED|REG_EXTENDED)))
+ error(3, "-F and -A or -P or -X are incompatible");
+ if ((state.options & REG_LITERAL) && state.words)
+ error(ERROR_SYSTEM|3, "-F and -w are incompatible");
+ if (!state.file.head && !state.pattern.head)
+ {
+ if (!argv[0])
+ error(3, "no pattern");
+ addstring(&state, &state.pattern, *argv++);
+ }
+ if (!(state.options & (REG_FIRST|REG_NOSUB)))
+ {
+ if (state.count || state.list || state.query || (state.options & REG_INVERT))
+ state.options |= REG_FIRST|REG_NOSUB;
+ else
+ {
+ state.pos = state.posvec;
+ state.posnum = elementsof(state.posvec);
+ }
+ }
+ compile(&state);
+ if (!argv[0])
+ {
+ state.prefix = h ? 1 : 0;
+ execute(&state, sfstdin, h);
+ }
+ else
+ {
+ if (state.prefix > 1)
+ state.prefix = 0;
+ else if (argv[1])
+ state.prefix = 1;
+ while (s = *argv++)
+ {
+ if (f = sfopen(NiL, s, "r"))
+ {
+ execute(&state, f, s);
+ sfclose(f);
+ if (state.query && state.any)
+ break;
+ }
+ else
+ {
+ state.notfound = 1;
+ if (!state.suppress)
+ error(ERROR_SYSTEM|2, "%s: cannot open", s);
+ }
+ }
+ }
+ if ((state.count & 2) && !state.query && !state.list)
+ {
+ if (state.label)
+ {
+ Item_t* x;
+
+ x = state.re.head;
+ do
+ {
+ sfprintf(sfstdout, "%s:%I*u\n", x->string, sizeof(x->total), x->total);
+ } while (x = x->next);
+ }
+ else
+ sfprintf(sfstdout, "%I*u\n", sizeof(state.hits), state.hits);
+ }
+ return (state.notfound && !state.query) ? 2 : !state.any;
+}
+
+
+int b_egrep(int argc, char** argv, void *context)
+{
+ return grep_main(argc, argv, context);
+}
+
+int b_grep(int argc, char** argv, void *context)
+{
+ return grep_main(argc, argv, context);
+}
+
+int b_fgrep(int argc, char** argv, void *context)
+{
+ return grep_main(argc, argv, context);
+}
+
+int b_pgrep(int argc, char** argv, void *context)
+{
+ return grep_main(argc, argv, context);
+}
+
+int b_xgrep(int argc, char** argv, void *context)
+{
+ return grep_main(argc, argv, context);
+}
diff --git a/usr/src/lib/libcmd/common/head.c b/usr/src/lib/libcmd/common/head.c
index cee683e81a..98f7df8e8f 100644
--- a/usr/src/lib/libcmd/common/head.c
+++ b/usr/src/lib/libcmd/common/head.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
diff --git a/usr/src/lib/libcmd/common/id.c b/usr/src/lib/libcmd/common/id.c
index a1820e3bf7..53d8cad830 100644
--- a/usr/src/lib/libcmd/common/id.c
+++ b/usr/src/lib/libcmd/common/id.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
diff --git a/usr/src/lib/libcmd/common/join.c b/usr/src/lib/libcmd/common/join.c
index 12b40bc31b..909a8e8a29 100644
--- a/usr/src/lib/libcmd/common/join.c
+++ b/usr/src/lib/libcmd/common/join.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
@@ -28,7 +28,7 @@
*/
static const char usage[] =
-"[-?\n@(#)$Id: join (AT&T Research) 2006-10-31 $\n]"
+"[-?\n@(#)$Id: join (AT&T Research) 2009-08-01 $\n]"
USAGE_LICENSE
"[+NAME?join - relational database operator]"
"[+DESCRIPTION?\bjoin\b performs an \aequality join\a on the files \afile1\a "
@@ -351,7 +351,7 @@ outfield(Join_t* jp, int index, register int n, int last)
cp = 0;
if ((n=jp->delim)<=0)
{
- if (fp->spaces)
+ if (cp && fp->spaces)
{
/*eliminate leading spaces */
while (jp->state[*(unsigned char*)cp++]==S_SPACE);
@@ -365,7 +365,7 @@ outfield(Join_t* jp, int index, register int n, int last)
size = cpmax-cp;
else
size = 0;
- if (size==0)
+ if (size<=1)
{
if (!jp->nullfield)
sfputc(iop,n);
@@ -800,7 +800,7 @@ b_join(int argc, char** argv, void* context)
if (jp->buffered)
{
sfsetbuf(jp->file[0].iop, jp->file[0].iop, SF_UNBOUND);
- sfsetbuf(jp->file[1].iop, jp->file[0].iop, SF_UNBOUND);
+ sfsetbuf(jp->file[1].iop, jp->file[1].iop, SF_UNBOUND);
}
jp->state['\n'] = S_NL;
jp->outfile = sfstdout;
diff --git a/usr/src/lib/libcmd/common/ln.c b/usr/src/lib/libcmd/common/ln.c
index 90a6190504..94da7be389 100644
--- a/usr/src/lib/libcmd/common/ln.c
+++ b/usr/src/lib/libcmd/common/ln.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
diff --git a/usr/src/lib/libcmd/common/logname.c b/usr/src/lib/libcmd/common/logname.c
index a142653345..6ca5b02e0b 100644
--- a/usr/src/lib/libcmd/common/logname.c
+++ b/usr/src/lib/libcmd/common/logname.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
diff --git a/usr/src/lib/libcmd/common/md5sum.c b/usr/src/lib/libcmd/common/md5sum.c
index f4f7e6ad9b..c4cafa98c7 100644
--- a/usr/src/lib/libcmd/common/md5sum.c
+++ b/usr/src/lib/libcmd/common/md5sum.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
diff --git a/usr/src/lib/libcmd/common/mkdir.c b/usr/src/lib/libcmd/common/mkdir.c
index 596ef2b6b8..5ccce98221 100644
--- a/usr/src/lib/libcmd/common/mkdir.c
+++ b/usr/src/lib/libcmd/common/mkdir.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
@@ -73,22 +73,28 @@ b_mkdir(int argc, char** argv, void* context)
struct stat st;
cmdinit(argc, argv, context, ERROR_CATALOG, 0);
- while (n = optget(argv, usage)) switch (n)
+ for (;;)
{
- case 'p':
- pflag = 1;
- break;
- case 'm':
- mflag = 1;
- mode = strperm(arg = opt_info.arg, &opt_info.arg, mode);
- if (*opt_info.arg)
- error(ERROR_exit(0), "%s: invalid mode", arg);
- break;
- case ':':
- error(2, "%s", opt_info.arg);
- break;
- case '?':
- error(ERROR_usage(2), "%s", opt_info.arg);
+ switch (optget(argv, usage))
+ {
+ case 0:
+ break;
+ case 'p':
+ pflag = 1;
+ continue;
+ case 'm':
+ mflag = 1;
+ mode = strperm(arg = opt_info.arg, &opt_info.arg, mode);
+ if (*opt_info.arg)
+ error(ERROR_exit(0), "%s: invalid mode", arg);
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ continue;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ continue;
+ }
break;
}
argv += opt_info.index;
diff --git a/usr/src/lib/libcmd/common/mkfifo.c b/usr/src/lib/libcmd/common/mkfifo.c
index 7bc56747f7..8692c0702d 100644
--- a/usr/src/lib/libcmd/common/mkfifo.c
+++ b/usr/src/lib/libcmd/common/mkfifo.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
@@ -26,9 +26,8 @@
* mkfifo
*/
-
static const char usage[] =
-"[-?\n@(#)$Id: mkfifo (AT&T Research) 1999-04-20 $\n]"
+"[-?\n@(#)$Id: mkfifo (AT&T Research) 2009-01-02 $\n]"
USAGE_LICENSE
"[+NAME?mkfifo - make FIFOs (named pipes)]"
"[+DESCRIPTION?\bmkfifo\b creates one or more FIFO's. By "
@@ -50,40 +49,50 @@ USAGE_LICENSE
#include <cmd.h>
#include <ls.h>
-#define RWALL (S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)
-
int
b_mkfifo(int argc, char *argv[], void* context)
{
- register char *arg;
- register mode_t mode=RWALL, mask=0;
- register int n;
+ register char* arg;
+ register mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH;
+ register mode_t mask = 0;
+ register int mflag = 0;
cmdinit(argc, argv, context, ERROR_CATALOG, 0);
- while (n = optget(argv, usage)) switch (n)
+ for (;;)
{
- case 'm':
- mode = strperm(arg=opt_info.arg,&opt_info.arg,mode);
- if(*opt_info.arg)
- error(ERROR_exit(0),"%s: invalid mode",arg);
- break;
- case ':':
- error(2, "%s",opt_info.arg);
- break;
- case '?':
- error(ERROR_usage(2), "%s",opt_info.arg);
+ switch (optget(argv, usage))
+ {
+ case 0:
+ break;
+ case 'm':
+ mflag = 1;
+ mode = strperm(arg = opt_info.arg, &opt_info.arg, mode);
+ if (*opt_info.arg)
+ error(ERROR_exit(0), "%s: invalid mode", arg);
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ continue;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ continue;
+ }
break;
}
argv += opt_info.index;
- if(error_info.errors || !*argv)
- error(ERROR_usage(2),"%s",optusage(NiL));
- while(arg = *argv++)
+ if (error_info.errors || !*argv)
+ error(ERROR_usage(2), "%s", optusage(NiL));
+ mask = umask(0);
+ if (!mflag)
{
- if(mkfifo(arg,mode) < 0)
- error(ERROR_system(0),"%s:",arg);
+ mode &= ~mask;
+ umask(mask);
+ mask = 0;
}
- if(mask)
+ while (arg = *argv++)
+ if (mkfifo(arg, mode) < 0)
+ error(ERROR_system(0), "%s:", arg);
+ if (mask)
umask(mask);
- return(error_info.errors!=0);
+ return error_info.errors != 0;
}
-
diff --git a/usr/src/lib/libcmd/common/mktemp.c b/usr/src/lib/libcmd/common/mktemp.c
new file mode 100644
index 0000000000..2936a56e22
--- /dev/null
+++ b/usr/src/lib/libcmd/common/mktemp.c
@@ -0,0 +1,164 @@
+/***********************************************************************
+* *
+* This software is part of the ast package *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Intellectual Property *
+* *
+* A copy of the License is available at *
+* http://www.opensource.org/licenses/cpl1.0.txt *
+* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
+* *
+* Information and Software Systems Research *
+* AT&T Research *
+* Florham Park NJ *
+* *
+* Glenn Fowler <gsf@research.att.com> *
+* David Korn <dgk@research.att.com> *
+* *
+***********************************************************************/
+#pragma prototyped
+
+static const char usage[] =
+"[-?\n@(#)$Id: mktemp (AT&T Research) 2009-06-19 $\n]"
+USAGE_LICENSE
+"[+NAME?mktemp - make temporary file or directory]"
+"[+DESCRIPTION?\bmktemp\b creates a temporary file with optional base "
+ "name prefix \aprefix\a. If \aprefix\a is omitted then \btmp_\b is used "
+ "and \b--tmp\b is implied. If \aprefix\a contains a directory prefix "
+ "then that directory overrides any of the directories described below. A "
+ "temporary file will have mode \brw-------\b and a temporary directory "
+ "will have mode \brwx------\b, subject to \bumask\b(1). Generated paths "
+ "have these attributes:]"
+ "{"
+ "[+*?Lower case to avoid clashes on case ignorant filesystems.]"
+ "[+*?Pseudo-random part to deter denial of service attacks.]"
+ "[+*?Pseudo-random part is \a3-chars\a.\a3-chars\a to accomodate "
+ "8.3 filesystems.]"
+ "}"
+"[+?A consecutive sequence of \bX\b's in \aprefix\a is replaced by the "
+ "pseudo-random part. If there are no \bX\b's then the pseudo-random part "
+ "is appended to the prefix.]"
+"[d:directory?Create a directory instead of a regular file.]"
+"[m:mode]:[mode?Set the mode of the created temporary to \amode\a. "
+ "\amode\a is symbolic or octal mode as in \bchmod\b(1). Relative modes "
+ "assume an initial mode of \bu=rwx\b.]"
+"[p:default?Use \adirectory\a if the \bTMPDIR\b environment variable is "
+ "not defined. Implies \b--tmp\b.]:[directory]"
+"[q:quiet?Suppress file and directory error diagnostics.]"
+"[t:tmp|temporary-directory?Create a path rooted in a temporary "
+ "directory.]"
+"[u:unsafe|dry-run?Check for file/directory existence but do not create. "
+ "Who would want to do that.]"
+"\n"
+"\n[ prefix ]\n"
+"\n"
+"[+SEE ALSO?\bmkdir\b(1), \bpathtemp\b(3), \bmktemp\b(3)]"
+;
+
+#include <cmd.h>
+#include <ls.h>
+
+int
+b_mktemp(int argc, char** argv, void* context)
+{
+ mode_t mode = 0;
+ mode_t mask;
+ int fd;
+ int i;
+ int quiet = 0;
+ int unsafe = 0;
+ int* fdp = &fd;
+ char* dir = "";
+ char* pfx;
+ char* t;
+ char path[PATH_MAX];
+
+ cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_NOTIFY);
+ for (;;)
+ {
+ switch (optget(argv, usage))
+ {
+ case 0:
+ break;
+ case 'd':
+ fdp = 0;
+ continue;
+ case 'm':
+ mode = strperm(pfx = opt_info.arg, &opt_info.arg, S_IRWXU);
+ if (*opt_info.arg)
+ error(ERROR_exit(0), "%s: invalid mode", pfx);
+ continue;
+ case 'p':
+ if ((t = getenv("TMPDIR")) && *t)
+ dir = 0;
+ else
+ dir = opt_info.arg;
+ continue;
+ case 'q':
+ quiet = 1;
+ continue;
+ case 't':
+ dir = 0;
+ continue;
+ case 'u':
+ unsafe = 1;
+ fdp = 0;
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ continue;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ continue;
+ }
+ break;
+ }
+ argv += opt_info.index;
+ if (error_info.errors || (pfx = *argv++) && *argv)
+ error(ERROR_usage(2), "%s", optusage(NiL));
+ mask = umask(0);
+ if (!mode)
+ mode = (fdp ? (S_IRUSR|S_IWUSR) : S_IRWXU) & ~mask;
+ umask(~mode & (S_IRWXU|S_IRWXG|S_IRWXO));
+ if (!pfx)
+ {
+ pfx = "tmp_";
+ if (dir && !*dir)
+ dir = 0;
+ }
+ if (t = strrchr(pfx, '/'))
+ {
+ i = ++t - pfx;
+ dir = fmtbuf(i);
+ memcpy(dir, pfx, i);
+ dir[i] = 0;
+ pfx = t;
+ }
+ for (;;)
+ {
+ if (!pathtemp(path, sizeof(path), dir, pfx, fdp))
+ {
+ if (quiet)
+ error_info.errors++;
+ else
+ error(ERROR_SYSTEM|2, "cannot create temporary path");
+ break;
+ }
+ if (fdp || unsafe || !mkdir(path, mode))
+ {
+ if (fdp)
+ close(*fdp);
+ sfputr(sfstdout, path, '\n');
+ break;
+ }
+ if (sh_checksig(context))
+ {
+ error_info.errors++;
+ break;
+ }
+ }
+ umask(mask);
+ return error_info.errors != 0;
+}
diff --git a/usr/src/lib/libcmd/common/mv.c b/usr/src/lib/libcmd/common/mv.c
index ec08bea2e4..c84c1092bd 100644
--- a/usr/src/lib/libcmd/common/mv.c
+++ b/usr/src/lib/libcmd/common/mv.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
diff --git a/usr/src/lib/libcmd/common/paste.c b/usr/src/lib/libcmd/common/paste.c
index ce1dcef087..71da3f472a 100644
--- a/usr/src/lib/libcmd/common/paste.c
+++ b/usr/src/lib/libcmd/common/paste.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
diff --git a/usr/src/lib/libcmd/common/pathchk.c b/usr/src/lib/libcmd/common/pathchk.c
index 7b0151d69c..ef27bd2788 100644
--- a/usr/src/lib/libcmd/common/pathchk.c
+++ b/usr/src/lib/libcmd/common/pathchk.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
@@ -26,44 +26,50 @@
*/
static const char usage[] =
-"[-?\n@(#)$Id: pathchk (AT&T Research) 2006-09-19 $\n]"
+"[-?\n@(#)$Id: pathchk (AT&T Research) 2009-07-24 $\n]"
USAGE_LICENSE
"[+NAME?pathchk - check pathnames for portability]"
-"[+DESCRIPTION?\bpathchk\b checks each \apathname\a to see if it "
- "is valid and/or portable. A \apathname\a is valid if it "
- "can be used to access or create a file without causing syntax "
- "errors. A file is portable, if no truncation will result on "
- "any conforming POSIX.1 implementation.]"
+"[+DESCRIPTION?\bpathchk\b checks each \apathname\a to see if it is "
+ "valid and/or portable. A \apathname\a is valid if it can be used to "
+ "access or create a file without causing syntax errors. A file is "
+ "portable if no truncation will result on any conforming POSIX.1 "
+ "implementation.]"
"[+?By default \bpathchk\b checks each component of each \apathname\a "
- "based on the underlying file system. A diagnostic is written "
- "to standard error for each pathname that:]{"
- "[+-?Is longer than \b$(getconf PATH_MAX)\b bytes.]"
- "[+-?Contains any component longer than \b$(getconf NAME_MAX)\b bytes.]"
- "[+-?Contains any directory component in a directory that is "
- "not searchable.]"
- "[+-?Contains any character in any component that is not valid in "
- "its containing directory.]"
- "[+-?Is empty.]"
- "}"
-"[p:portability?Instead of performing length checks on the underlying "
- "file system, write a diagnostic for each pathname operand that:]{"
- "[+-?Is longer than \b$(getconf _POSIX_PATH_MAX)\b bytes.]"
- "[+-?Contains any component longer than "
- "\b$(getconf _POSIX_NAME_MAX)\b bytes.]"
+ "based on the underlying file system. A diagnostic is written to "
+ "standard error for each pathname that:]"
+ "{"
+ "[+-?Is longer than \b$(getconf PATH_MAX)\b bytes.]"
+ "[+-?Contains any component longer than \b$(getconf NAME_MAX)\b "
+ "bytes.]"
+ "[+-?Contains any directory component in a directory that is not "
+ "searchable.]"
+ "[+-?Contains any character in any component that is not valid "
+ "in its containing directory.]"
+ "[+-?Is empty.]"
+ "}"
+"[p:components?Instead of performing length checks on the underlying "
+ "file system, write a diagnostic for each pathname operand that:]"
+ "{"
+ "[+-?Is longer than \b$(getconf _POSIX_PATH_MAX)\b bytes.]"
+ "[+-?Contains any component longer than \b$(getconf "
+ "_POSIX_NAME_MAX)\b bytes.]"
"[+-?Contains any character in any component that is not in the "
- "portable filename character set.]"
-#if 0
- "[+-?Contains any component with \b-\b as the first character.]"
-#endif
- "[+-?Is empty.]"
- "}"
+ "portable filename character set.]"
+ "}"
+"[P:path?Write a diagnostic for each pathname operand that:]"
+ "{"
+ "[+-?Contains any component with \b-\b as the first character.]"
+ "[+-?Is empty.]"
+ "}"
+"[a:all|portability?Equivalent to \b--components\b \b--path\b.]"
"\n"
"\npathname ...\n"
"\n"
-"[+EXIT STATUS?]{"
+"[+EXIT STATUS?]"
+ "{"
"[+0?All \apathname\a operands passed all of the checks.]"
"[+>0?An error occurred.]"
-"}"
+ "}"
"[+SEE ALSO?\bgetconf\b(1), \bcreat\b(2), \bpathchk\b(2)]"
;
@@ -71,6 +77,9 @@ USAGE_LICENSE
#include <cmd.h>
#include <ls.h>
+#define COMPONENTS 0x1
+#define PATH 0x2
+
#define isport(c) (((c)>='a' && (c)<='z') || ((c)>='A' && (c)<='Z') || ((c)>='0' && (c)<='9') || (strchr("._-",(c))!=0) )
/*
@@ -82,10 +91,10 @@ static long mypathconf(const char *path, int op)
static const char* const ops[] = { "NAME_MAX", "PATH_MAX" };
- errno=0;
- if((r=strtol(astconf(ops[op], path, NiL), NiL, 0))<0 && errno==0)
- return(LONG_MAX);
- return(r);
+ errno = 0;
+ if ((r = strtol(astconf(ops[op], path, NiL), NiL, 0)) < 0 && !errno)
+ return LONG_MAX;
+ return r;
}
/*
@@ -100,10 +109,11 @@ static int pathchk(char* path, int mode)
if(!*path)
{
- error(2,"path is empty");
- return(0);
+ if (mode & PATH)
+ error(2,"path is empty");
+ return -1;
}
- if(mode)
+ if(mode & COMPONENTS)
{
name_max = _POSIX_NAME_MAX;
path_max = _POSIX_PATH_MAX;
@@ -177,7 +187,7 @@ static int pathchk(char* path, int mode)
else if(errno==ENAMETOOLONG)
{
error(2,"%s: pathname too long",path);
- return(0);
+ return -1;
}
#endif /*ENAMETOOLONG*/
else
@@ -186,18 +196,18 @@ static int pathchk(char* path, int mode)
}
while(*(cpold=cp))
{
- if(mode && *cp == '-')
+ if((mode & PATH) && *cp == '-')
{
error(2,"%s: path component begins with '-'",path,fmtquote(buf, NiL, "'", 1, 0));
- return(0);
+ return -1;
}
while((c= *cp++) && c!='/')
- if(mode && !isport(c))
+ if((mode & COMPONENTS) && !isport(c))
{
buf[0] = c;
buf[1] = 0;
error(2,"%s: '%s' not in portable character set",path,fmtquote(buf, NiL, "'", 1, 0));
- return(0);
+ return -1;
}
if((cp-cpold) > name_max)
goto err;
@@ -208,41 +218,51 @@ static int pathchk(char* path, int mode)
}
if((cp-path) >= path_max)
{
- error(2,"%s: pathname too long",path);
- return(0);
+ error(2, "%s: pathname too long", path);
+ return -1;
}
- return(1);
-err:
- error(2,"%s: component name %.*s too long",path,cp-cpold-1,cpold);
- return(0);
+ return 0;
+ err:
+ error(2, "%s: component name %.*s too long", path, cp-cpold-1, cpold);
+ return -1;
}
int
b_pathchk(int argc, char** argv, void* context)
{
- register int n, mode=0;
- register char *cp;
+ register int n;
+ register int mode = 0;
+ register char* s;
cmdinit(argc, argv, context, ERROR_CATALOG, 0);
- while (n = optget(argv, usage)) switch (n)
+ for (;;)
{
- case 'p':
- mode = 1;
- break;
- case ':':
- error(2, "%s", opt_info.arg);
- break;
- case '?':
- error(ERROR_usage(2), "%s", opt_info.arg);
+ switch (optget(argv, usage))
+ {
+ case 0:
+ break;
+ case 'a':
+ mode |= COMPONENTS|PATH;
+ continue;
+ case 'p':
+ mode |= COMPONENTS;
+ continue;
+ case 'P':
+ mode |= PATH;
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ continue;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ continue;
+ }
break;
}
argv += opt_info.index;
- if(*argv==0 || error_info.errors)
- error(ERROR_usage(2),"%s", optusage((char*)0));
- while(cp = *argv++)
- {
- if(!pathchk(cp,mode))
- error_info.errors=1;
- }
- return(error_info.errors);
+ if (!*argv || error_info.errors)
+ error(ERROR_usage(2),"%s", optusage(NiL));
+ while (s = *argv++)
+ pathchk(s, mode);
+ return error_info.errors != 0;
}
diff --git a/usr/src/lib/libcmd/common/pids.c b/usr/src/lib/libcmd/common/pids.c
index ca419850c1..432b46f345 100644
--- a/usr/src/lib/libcmd/common/pids.c
+++ b/usr/src/lib/libcmd/common/pids.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
diff --git a/usr/src/lib/libcmd/common/rev.c b/usr/src/lib/libcmd/common/rev.c
index 3c63840bdb..c67a6a4c9f 100644
--- a/usr/src/lib/libcmd/common/rev.c
+++ b/usr/src/lib/libcmd/common/rev.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
diff --git a/usr/src/lib/libcmd/common/rev.h b/usr/src/lib/libcmd/common/rev.h
index c23ffb381e..c35fbc4ead 100644
--- a/usr/src/lib/libcmd/common/rev.h
+++ b/usr/src/lib/libcmd/common/rev.h
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
diff --git a/usr/src/lib/libcmd/common/revlib.c b/usr/src/lib/libcmd/common/revlib.c
index d95bbf0c80..a2407f122b 100644
--- a/usr/src/lib/libcmd/common/revlib.c
+++ b/usr/src/lib/libcmd/common/revlib.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
diff --git a/usr/src/lib/libcmd/common/rm.c b/usr/src/lib/libcmd/common/rm.c
index d64d209b9d..fbd21583fb 100644
--- a/usr/src/lib/libcmd/common/rm.c
+++ b/usr/src/lib/libcmd/common/rm.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
@@ -27,7 +27,7 @@
*/
static const char usage[] =
-"[-?\n@(#)$Id: rm (AT&T Research) 2008-10-15 $\n]"
+"[-?\n@(#)$Id: rm (AT&T Research) 2009-06-18 $\n]"
USAGE_LICENSE
"[+NAME?rm - remove files]"
"[+DESCRIPTION?\brm\b removes the named \afile\a arguments. By default it"
@@ -81,6 +81,7 @@ USAGE_LICENSE
typedef struct State_s /* program state */
{
+ void* context; /* builtin context */
int clobber; /* clear out file data first */
int directory; /* remove(dir) not rmdir(dir) */
int force; /* force actions */
@@ -179,7 +180,7 @@ rm(State_t* state, register FTSENT* ent)
{
if (state->interactive)
{
- if ((v = astquery(-1, "remove directory %s? ", ent->fts_path)) < 0)
+ if ((v = astquery(-1, "remove directory %s? ", ent->fts_path)) < 0 || sh_checksig(state->context))
return -1;
if (v > 0)
{
@@ -253,7 +254,7 @@ rm(State_t* state, register FTSENT* ent)
sfputr(sfstdout, ent->fts_path, '\n');
if (state->interactive)
{
- if ((v = astquery(-1, "remove %s? ", ent->fts_path)) < 0)
+ if ((v = astquery(-1, "remove %s? ", ent->fts_path)) < 0 || sh_checksig(state->context))
return -1;
if (v > 0)
{
@@ -277,7 +278,8 @@ rm(State_t* state, register FTSENT* ent)
errno == ETXTBSY ? "``running program''" :
#endif
ent->fts_statp->st_uid != state->uid ? "``not owner''" :
- fmtmode(ent->fts_statp->st_mode & S_IPERM, 0) + 1, ent->fts_path)) < 0)
+ fmtmode(ent->fts_statp->st_mode & S_IPERM, 0) + 1, ent->fts_path)) < 0 ||
+ sh_checksig(state->context))
return -1;
if (v > 0)
{
@@ -343,6 +345,7 @@ b_rm(int argc, register char** argv, void* context)
cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_NOTIFY);
memset(&state, 0, sizeof(state));
+ state.context = context;
state.fs3d = fs3d(FS3D_TEST);
state.terminal = isatty(0);
for (;;)
diff --git a/usr/src/lib/libcmd/common/rmdir.c b/usr/src/lib/libcmd/common/rmdir.c
index e6c370c436..c7acb197f9 100644
--- a/usr/src/lib/libcmd/common/rmdir.c
+++ b/usr/src/lib/libcmd/common/rmdir.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
diff --git a/usr/src/lib/libcmd/common/shcmd.h b/usr/src/lib/libcmd/common/shcmd.h
deleted file mode 100644
index d355c7fd75..0000000000
--- a/usr/src/lib/libcmd/common/shcmd.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/***********************************************************************
-* *
-* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
-* and is licensed under the *
-* Common Public License, Version 1.0 *
-* by AT&T Intellectual Property *
-* *
-* A copy of the License is available at *
-* http://www.opensource.org/licenses/cpl1.0.txt *
-* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
-* *
-* Information and Software Systems Research *
-* AT&T Research *
-* Florham Park NJ *
-* *
-* Glenn Fowler <gsf@research.att.com> *
-* David Korn <dgk@research.att.com> *
-* *
-***********************************************************************/
-#pragma prototyped
-
-/*
- * ksh builtin command api
- */
-
-#ifndef _SHCMD_H
-#define _SHCMD_H 1
-
-#ifndef SH_VERSION
-# define Shell_t void
-#endif
-#ifndef NV_DEFAULT
-# define Namval_t void
-#endif
-#ifndef ERROR_NOTIFY
-# define ERROR_NOTIFY 1
-#endif
-
-typedef int (*Shbltin_f)(int, char**, void*);
-
-#undef Shbltin_t
-typedef struct Shbltin_s
-{
- Shell_t *shp;
- void *ptr;
- int version;
- int (*shrun)(int, char**);
- int (*shtrap)(const char*, int);
- void (*shexit)(int);
- Namval_t *(*shbltin)(const char*, Shbltin_f, void*);
- unsigned char notify;
- unsigned char sigset;
- unsigned char nosfio;
- Namval_t *bnode;
- Namval_t *vnode;
- char *data;
- int flags;
-} Shbltin_t;
-
-#if defined(SH_VERSION) || defined(_SH_PRIVATE)
-# undef Shell_t
-# undef Namval_t
-#else
-# define sh_run(c, ac, av) ((c)?(*((Shbltin_t*)(c))->shrun)(ac,av):-1)
-# define sh_system(c,str) ((c)?(*((Shbltin_t*)(c))->shtrap)(str,0):system(str))
-# define sh_exit(c,n) ((c)?(*((Shbltin_t*)(c))->shexit)(n):exit(n))
-# define sh_checksig(c) ((c) && ((Shbltin_t*)(c))->sigset)
-# if defined(SFIO_VERSION) || defined(_AST_H)
-# define LIB_INIT(c)
-# else
-# define LIB_INIT(c) ((c) && (((Shbltin_t*)(c))->nosfio = 1))
-# endif
-# ifndef _CMD_H
-# define cmdinit(ac,av,c,cat,flg) do { if((ac)<=0) return(0); \
- (((Shbltin_t*)(c))->notify = ((flg)&ERROR_NOTIFY)?1:0);} while(0)
-# endif
-#endif
-
-#endif
diff --git a/usr/src/lib/libcmd/common/stty.c b/usr/src/lib/libcmd/common/stty.c
index 6868d3f326..a7754f447c 100644
--- a/usr/src/lib/libcmd/common/stty.c
+++ b/usr/src/lib/libcmd/common/stty.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
@@ -26,7 +26,7 @@
*/
static const char usage[] =
-"[-?@(#)$Id: stty (AT&T Research) 2008-04-01 $\n]"
+"[-?@(#)$Id: stty (AT&T Research) 2008-11-10 $\n]"
USAGE_LICENSE
"[+NAME?stty - set or get terminal modes]"
"[+DESCRIPTION?\bstty\b sets certain terminal I/O modes for the device "
@@ -913,11 +913,9 @@ b_stty(int argc, char** argv, void* context)
{
switch (n = optget(argv, usage))
{
- case 't':
- flags |= T_FLAG;
- continue;
case 'a':
case 'g':
+ case 't':
if (!opt_info.offset || !argv[opt_info.index][opt_info.offset])
{
switch (n)
@@ -928,6 +926,9 @@ b_stty(int argc, char** argv, void* context)
case 'g':
flags |= G_FLAG;
break;
+ case 't':
+ flags |= T_FLAG;
+ break;
}
continue;
}
diff --git a/usr/src/lib/libcmd/common/sum.c b/usr/src/lib/libcmd/common/sum.c
index da6dc6fa2a..8b16197863 100644
--- a/usr/src/lib/libcmd/common/sum.c
+++ b/usr/src/lib/libcmd/common/sum.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
diff --git a/usr/src/lib/libcmd/common/sync.c b/usr/src/lib/libcmd/common/sync.c
index 8ddc855783..863211c225 100644
--- a/usr/src/lib/libcmd/common/sync.c
+++ b/usr/src/lib/libcmd/common/sync.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
diff --git a/usr/src/lib/libcmd/common/tail.c b/usr/src/lib/libcmd/common/tail.c
index 7eb012af7f..ca128f2938 100644
--- a/usr/src/lib/libcmd/common/tail.c
+++ b/usr/src/lib/libcmd/common/tail.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
@@ -28,7 +28,7 @@
*/
static const char usage[] =
-"+[-?\n@(#)$Id: tail (AT&T Research) 2006-10-18 $\n]"
+"+[-?\n@(#)$Id: tail (AT&T Research) 2009-08-25 $\n]"
USAGE_LICENSE
"[+NAME?tail - output trailing portion of one or more files ]"
"[+DESCRIPTION?\btail\b copies one or more input files to standard output "
@@ -44,21 +44,25 @@ USAGE_LICENSE
"followed by one of the following characters to specify a different "
"unit other than a single byte:]{"
"[+b?512 bytes.]"
- "[+k?1-kilobyte.]"
- "[+m?1-megabyte.]"
+ "[+k?1 KiB.]"
+ "[+m?1 MiB.]"
+ "[+g?1 GiB.]"
"}"
"[+?For backwards compatibility, \b-\b\anumber\a is equivalent to "
"\b-n\b \anumber\a and \b+\b\anumber\a is equivalent to "
- "\b-n -\b\anumber\a.]"
+ "\b-n -\b\anumber\a. \anumber\a may also have these option "
+ "suffixes: \bb c f g k l m r\b.]"
"[n:lines]:[lines:=10?Copy \alines\a lines from each file. A negative value "
- "for \alines\a indicates an offset from the start of the file.]"
+ "for \alines\a indicates an offset from the end of the file.]"
+"[b:blocks?Copy units of 512 bytes.]"
"[c:bytes]:?[chars?Copy \achars\a bytes from each file. A negative value "
- "for \achars\a indicates an offset from the start of the file.]"
+ "for \achars\a indicates an offset from the end of the file.]"
"[f:forever|follow?Loop forever trying to read more characters as the "
"end of each file to copy new data. Ignored if reading from a pipe "
"or fifo.]"
"[h!:headers?Output filename headers.]"
+"[l:lines?Copy units of lines. This is the default.]"
"[L:log?When a \b--forever\b file times out via \b--timeout\b, verify that "
"the curent file has not been renamed and replaced by another file "
"of the same name (a common log file practice) before giving up on "
@@ -83,9 +87,11 @@ USAGE_LICENSE
"[+S?scores]"
"}"
"[v:verbose?Always ouput filename headers.]"
+
"\n"
"\n[file ...]\n"
"\n"
+
"[+EXIT STATUS?]{"
"[+0?All files copied successfully.]"
"[+>0?One or more files did not copy.]"
@@ -103,17 +109,18 @@ USAGE_LICENSE
#define ERROR (1<<1)
#define FOLLOW (1<<2)
#define HEADERS (1<<3)
-#define LOG (1<<4)
-#define NEGATIVE (1<<5)
-#define POSITIVE (1<<6)
-#define REVERSE (1<<7)
-#define SILENT (1<<8)
-#define TIMEOUT (1<<9)
-#define VERBOSE (1<<10)
+#define LINES (1<<4)
+#define LOG (1<<5)
+#define NEGATIVE (1<<6)
+#define POSITIVE (1<<7)
+#define REVERSE (1<<8)
+#define SILENT (1<<9)
+#define TIMEOUT (1<<10)
+#define VERBOSE (1<<11)
#define NOW (unsigned long)time(NiL)
-#define LINES 10
+#define DEFAULT 10
#ifdef S_ISSOCK
#define FIFO(m) (S_ISFIFO(m)||S_ISSOCK(m))
@@ -132,8 +139,11 @@ struct Tail_s
unsigned long expire;
long dev;
long ino;
+ int fifo;
};
+static const char header_fmt[] = "\n==> %s <==\n";
+
/*
* if file is seekable, position file to tail location and return offset
* otherwise, return -1
@@ -159,10 +169,10 @@ tailpos(register Sfio_t* fp, register Sfoff_t number, int delim)
return first;
return offset;
}
- if ((offset = last - SF_BUFSIZE) < first)
- offset = first;
for (;;)
{
+ if ((offset = last - SF_BUFSIZE) < first)
+ offset = first;
sfseek(fp, offset, SEEK_SET);
n = last - offset;
if (!(s = sfreserve(fp, n, SF_LOCKR)))
@@ -178,8 +188,6 @@ tailpos(register Sfio_t* fp, register Sfoff_t number, int delim)
if (offset == first)
break;
last = offset;
- if ((offset = last - SF_BUFSIZE) < first)
- offset = first;
}
return first;
}
@@ -245,11 +253,13 @@ pipetail(Sfio_t* infile, Sfio_t* outfile, Sfoff_t number, int delim)
*/
static int
-init(Tail_t* tp, Sfoff_t number, int delim, int flags)
+init(Tail_t* tp, Sfoff_t number, int delim, int flags, const char** format)
{
Sfoff_t offset;
+ Sfio_t* op;
struct stat st;
+ tp->fifo = 0;
if (tp->sp)
{
offset = 0;
@@ -273,12 +283,46 @@ init(Tail_t* tp, Sfoff_t number, int delim, int flags)
sfset(tp->sp, SF_SHARE, 0);
if (offset)
{
- if ((offset = tailpos(tp->sp, number, delim)) < 0)
+ if (number < 0 || !number && (flags & POSITIVE))
+ {
+ sfset(tp->sp, SF_SHARE, !(flags & FOLLOW));
+ if (number < -1)
+ {
+ sfmove(tp->sp, NiL, -number - 1, delim);
+ offset = sfseek(tp->sp, (Sfoff_t)0, SEEK_CUR);
+ }
+ else
+ offset = 0;
+ }
+ else if ((offset = tailpos(tp->sp, number, delim)) >= 0)
+ sfseek(tp->sp, offset, SEEK_SET);
+ else if (fstat(sffileno(tp->sp), &st))
+ {
+ error(ERROR_system(0), "%s: cannot stat", tp->name);
+ goto bad;
+ }
+ else if (!FIFO(st.st_mode))
{
error(ERROR_SYSTEM|2, "%s: cannot position file to tail", tp->name);
goto bad;
}
- sfseek(tp->sp, offset, SEEK_SET);
+ else
+ {
+ tp->fifo = 1;
+ if (flags & (HEADERS|VERBOSE))
+ {
+ sfprintf(sfstdout, *format, tp->name);
+ *format = header_fmt;
+ }
+ op = (flags & REVERSE) ? sftmp(4*SF_BUFSIZE) : sfstdout;
+ pipetail(tp->sp ? tp->sp : sfstdin, op, number, delim);
+ if (flags & REVERSE)
+ {
+ sfseek(op, (Sfoff_t)0, SEEK_SET);
+ rev_line(op, sfstdout, (Sfoff_t)0);
+ sfclose(op);
+ }
+ }
}
tp->last = offset;
if (flags & LOG)
@@ -325,10 +369,8 @@ num(register const char* s, char** e, int* f, int o)
s++;
errno = 0;
number = strtonll(s, &t, NiL, 0);
- if (!o && t > s && *(t - 1) == 'l')
- t--;
if (t == s)
- number = LINES;
+ number = DEFAULT;
if (o && *t)
{
number = 0;
@@ -346,6 +388,8 @@ num(register const char* s, char** e, int* f, int o)
else
{
*f |= COUNT;
+ if (t > s && isalpha(*(t - 1)))
+ *f &= ~LINES;
if (c == '-')
number = -number;
}
@@ -357,24 +401,23 @@ num(register const char* s, char** e, int* f, int o)
int
b_tail(int argc, char** argv, void* context)
{
- static const char header_fmt[] = "\n==> %s <==\n";
-
register Sfio_t* ip;
register int n;
register int i;
- register int delim = '\n';
- int flags = HEADERS;
+ int delim;
+ int flags = HEADERS|LINES;
+ int blocks = 0;
char* s;
char* t;
char* r;
char* e;
char* file;
Sfoff_t offset;
- Sfoff_t number = LINES;
+ Sfoff_t number = DEFAULT;
unsigned long timeout = 0;
struct stat st;
const char* format = header_fmt+1;
- size_t z;
+ ssize_t z;
Sfio_t* op;
register Tail_t* fp;
register Tail_t* pp;
@@ -386,13 +429,38 @@ b_tail(int argc, char** argv, void* context)
{
switch (n = optget(argv, usage))
{
- case 'c':
- delim = -1;
- if (opt_info.arg && *opt_info.arg=='f' && !*(opt_info.arg+1))
+ case 0:
+ if (!(flags & FOLLOW) && argv[opt_info.index] && (argv[opt_info.index][0] == '-' || argv[opt_info.index][0] == '+') && !argv[opt_info.index][1])
{
- flags |= FOLLOW;
+ number = argv[opt_info.index][0] == '-' ? 10 : -10;
+ flags |= LINES;
+ opt_info.index++;
continue;
}
+ break;
+ case 'b':
+ blocks = 512;
+ flags &= ~LINES;
+ if (opt_info.option[0] == '+')
+ number = -number;
+ continue;
+ case 'c':
+ flags &= ~LINES;
+ if (opt_info.arg == argv[opt_info.index - 1])
+ {
+ strtol(opt_info.arg, &s, 10);
+ if (*s)
+ {
+ opt_info.index--;
+ t = "";
+ goto suffix;
+ }
+ }
+ else if (opt_info.arg && isalpha(*opt_info.arg))
+ {
+ t = opt_info.arg;
+ goto suffix;
+ }
/*FALLTHROUGH*/
case 'n':
flags |= COUNT;
@@ -400,14 +468,14 @@ b_tail(int argc, char** argv, void* context)
number = num(s, &s, &flags, n);
else
{
- number = LINES;
+ number = DEFAULT;
flags &= ~(ERROR|NEGATIVE|POSITIVE);
s = "";
}
- if (n=='c' && *s=='f')
+ if (n != 'n' && s && isalpha(*s))
{
- s++;
- flags |= FOLLOW;
+ t = s;
+ goto suffix;
}
if (flags & ERROR)
continue;
@@ -425,6 +493,11 @@ b_tail(int argc, char** argv, void* context)
else
flags &= ~HEADERS;
continue;
+ case 'l':
+ flags |= LINES;
+ if (opt_info.option[0] == '+')
+ number = -number;
+ continue;
case 'L':
flags |= LOG;
continue;
@@ -448,32 +521,46 @@ b_tail(int argc, char** argv, void* context)
continue;
case ':':
/* handle old style arguments */
- r = s = argv[opt_info.index];
- number = num(s, &t, &flags, 0);
+ if (!(r = argv[opt_info.index]) || !opt_info.offset)
+ {
+ error(2, "%s", opt_info.arg);
+ break;
+ }
+ s = r + opt_info.offset - 1;
+ if (i = *(s - 1) == '-' || *(s - 1) == '+')
+ s--;
+ if ((number = num(s, &t, &flags, 0)) && i)
+ number = -number;
+ goto compatibility;
+ suffix:
+ r = 0;
+ if (opt_info.option[0] == '+')
+ number = -number;
+ compatibility:
for (;;)
{
switch (*t++)
{
case 0:
- opt_info.offset = t - r - 1;
- if (number)
- number = -number;
+ if (r)
+ opt_info.offset = t - r - 1;
break;
case 'c':
- delim = -1;
+ flags &= ~LINES;
continue;
case 'f':
flags |= FOLLOW;
continue;
case 'l':
- delim = '\n';
+ flags |= LINES;
continue;
case 'r':
flags |= REVERSE;
continue;
default:
error(2, "%s: invalid suffix", t - 1);
- opt_info.offset = strlen(r);
+ if (r)
+ opt_info.offset = strlen(r);
break;
}
break;
@@ -496,12 +583,15 @@ b_tail(int argc, char** argv, void* context)
}
else if (!*(argv + 1))
flags &= ~HEADERS;
+ delim = (flags & LINES) ? '\n' : -1;
+ if (blocks)
+ number *= blocks;
if (flags & REVERSE)
{
if (delim < 0)
error(2, "--reverse requires line mode");
- else if (!(flags & COUNT))
- number = 0;
+ if (!(flags & COUNT))
+ number = -1;
flags &= ~FOLLOW;
}
if ((flags & (FOLLOW|TIMEOUT)) == TIMEOUT)
@@ -527,7 +617,7 @@ b_tail(int argc, char** argv, void* context)
{
fp->name = s;
fp->sp = 0;
- if (!init(fp, number, delim, flags))
+ if (!init(fp, number, delim, flags, &format))
{
fp->expire = timeout ? (NOW + timeout + 1) : 0;
if (files)
@@ -542,27 +632,35 @@ b_tail(int argc, char** argv, void* context)
return error_info.errors != 0;
pp->next = 0;
hp = 0;
- for (;;)
+ while (fp = files)
{
if (sfsync(sfstdout))
error(ERROR_system(1), "write error");
+#if 0
sleep(1);
+#else
+ {
+ struct timespec rqt = { 0L, 1000000000L/4L };
+ (void)nanosleep(&rqt, NULL);
+ }
+#endif
n = 0;
pp = 0;
- fp = files;
while (fp)
{
if (fstat(sffileno(fp->sp), &st))
error(ERROR_system(0), "%s: cannot stat", fp->name);
- else if (st.st_size > fp->last)
+ else if (st.st_size > fp->last || fp->fifo)
{
n = 1;
if (timeout)
fp->expire = NOW + timeout;
- z = st.st_size - fp->last;
+ z = fp->fifo ? SF_UNBOUND : st.st_size - fp->last;
i = 0;
if ((s = sfreserve(fp->sp, z, SF_LOCKR)) || (z = sfvalue(fp->sp)) && (s = sfreserve(fp->sp, z, SF_LOCKR)) && (i = 1))
{
+ if (fp->fifo)
+ z = sfvalue(fp->sp);
r = 0;
for (e = (t = s) + z; t < e; t++)
if (*t == '\n')
@@ -594,7 +692,7 @@ b_tail(int argc, char** argv, void* context)
i = 3;
while (--i && stat(fp->name, &st))
sleep(1);
- if (i && (fp->dev != st.st_dev || fp->ino != st.st_ino) && !init(fp, 0, 0, flags))
+ if (i && (fp->dev != st.st_dev || fp->ino != st.st_ino) && !init(fp, 0, 0, flags, &format))
{
if (!(flags & SILENT))
error(ERROR_warn(0), "%s: log file change", fp->name);
@@ -636,11 +734,13 @@ b_tail(int argc, char** argv, void* context)
continue;
}
if (flags & (HEADERS|VERBOSE))
+ {
sfprintf(sfstdout, format, file);
- format = header_fmt;
+ format = header_fmt;
+ }
if (number < 0 || !number && (flags & POSITIVE))
{
- sfset(ip, SF_SHARE, !(flags & FOLLOW));
+ sfset(ip, SF_SHARE, 1);
if (number < -1)
sfmove(ip, NiL, -number - 1, delim);
if (flags & REVERSE)
diff --git a/usr/src/lib/libcmd/common/tee.c b/usr/src/lib/libcmd/common/tee.c
index c1189bade7..246b5af9c3 100644
--- a/usr/src/lib/libcmd/common/tee.c
+++ b/usr/src/lib/libcmd/common/tee.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
@@ -27,7 +27,7 @@
*/
static const char usage[] =
-"[-?\n@(#)$Id: tee (AT&T Research) 2007-11-11 $\n]"
+"[-?\n@(#)$Id: tee (AT&T Research) 2009-06-19 $\n]"
USAGE_LICENSE
"[+NAME?tee - duplicate standard input]"
"[+DESCRIPTION?\btee\b copies standard input to standard output "
@@ -52,7 +52,6 @@ USAGE_LICENSE
"[+SEE ALSO?\bcat\b(1), \bsignal\b(3)]"
;
-
#include <cmd.h>
#include <ls.h>
#include <sig.h>
@@ -60,6 +59,7 @@ USAGE_LICENSE
typedef struct Tee_s
{
Sfdisc_t disc;
+ int line;
int fd[1];
} Tee_t;
@@ -67,7 +67,8 @@ typedef struct Tee_s
* This discipline writes to each file in the list given in handle
*/
-static ssize_t tee_write(Sfio_t* fp, const void* buf, size_t n, Sfdisc_t* handle)
+static ssize_t
+tee_write(Sfio_t* fp, const void* buf, size_t n, Sfdisc_t* handle)
{
register const char* bp;
register const char* ep;
@@ -82,11 +83,27 @@ static ssize_t tee_write(Sfio_t* fp, const void* buf, size_t n, Sfdisc_t* handle
while (bp < ep)
{
if ((r = write(fd, bp, ep - bp)) <= 0)
- return(-1);
+ return -1;
bp += r;
}
} while ((fd = *hp++) >= 0);
- return(n);
+ return n;
+}
+
+static void
+tee_cleanup(register Tee_t* tp)
+{
+ register int* hp;
+ register int n;
+
+ if (tp)
+ {
+ sfdisc(sfstdout, NiL);
+ if (tp->line >= 0)
+ sfset(sfstdout, SF_LINE, tp->line);
+ for (hp = tp->fd; (n = *hp) >= 0; hp++)
+ close(n);
+ }
}
int
@@ -100,32 +117,45 @@ b_tee(int argc, register char** argv, void* context)
int line;
Sfdisc_t tee_disc;
- cmdinit(argc, argv, context, ERROR_CATALOG, 0);
+ if (argc <= 0)
+ {
+ if (context && (tp = (Tee_t*)sh_context(context)->data))
+ {
+ sh_context(context)->data = 0;
+ tee_cleanup(tp);
+ }
+ return 0;
+ }
+ cmdinit(argc, argv, context, ERROR_CATALOG, ERROR_CALLBACK);
line = -1;
- while (n = optget(argv, usage)) switch (n)
+ for (;;)
{
- case 'a':
- oflag &= ~O_TRUNC;
- oflag |= O_APPEND;
- break;
- case 'i':
- signal(SIGINT, SIG_IGN);
- break;
- case 'l':
- line = sfset(sfstdout, 0, 0) & SF_LINE;
- if ((line == 0) == (opt_info.num == 0))
- line = -1;
- else
- sfset(sfstdout, SF_LINE, !!opt_info.num);
- break;
- case ':':
- error(2, "%s", opt_info.arg);
- break;
- case '?':
- error(ERROR_usage(2), "%s", opt_info.arg);
+ switch (optget(argv, usage))
+ {
+ case 'a':
+ oflag &= ~O_TRUNC;
+ oflag |= O_APPEND;
+ continue;
+ case 'i':
+ signal(SIGINT, SIG_IGN);
+ continue;
+ case 'l':
+ line = sfset(sfstdout, 0, 0) & SF_LINE;
+ if ((line == 0) == (opt_info.num == 0))
+ line = -1;
+ else
+ sfset(sfstdout, SF_LINE, !!opt_info.num);
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
break;
}
- if(error_info.errors)
+ if (error_info.errors)
error(ERROR_usage(2), "%s", optusage(NiL));
argv += opt_info.index;
argc -= opt_info.index;
@@ -139,40 +169,36 @@ b_tee(int argc, register char** argv, void* context)
#endif
if (argc > 0)
{
- if (!(tp = (Tee_t*)stakalloc(sizeof(Tee_t) + argc * sizeof(int))))
- error(ERROR_exit(1), "no space");
- memset(&tee_disc, 0, sizeof(tee_disc));
- tee_disc.writef = tee_write;
- tp->disc = tee_disc;
- hp = tp->fd;
- while (cp = *argv++)
+ if (tp = (Tee_t*)stakalloc(sizeof(Tee_t) + argc * sizeof(int)))
{
- if ((*hp = open(cp, oflag, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0)
- error(ERROR_system(0), "%s: cannot create", cp);
- else hp++;
+ memset(&tp->disc, 0, sizeof(tp->disc));
+ tp->disc.writef = tee_write;
+ if (context)
+ sh_context(context)->data = (void*)tp;
+ tp->line = line;
+ hp = tp->fd;
+ while (cp = *argv++)
+ {
+ if ((*hp = open(cp, oflag, S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH)) < 0)
+ error(ERROR_system(0), "%s: cannot create", cp);
+ else
+ hp++;
+ }
+ if (hp == tp->fd)
+ tp = 0;
+ else
+ {
+ *hp = -1;
+ sfdisc(sfstdout, &tp->disc);
+ }
}
- if (hp == tp->fd)
- tp = 0;
else
- {
- *hp = -1;
- sfdisc(sfstdout, &tp->disc);
- }
- }
- if (sfmove(sfstdin, sfstdout, SF_UNBOUND, -1) < 0 || !sfeof(sfstdin) || sfsync(sfstdout))
- error(ERROR_system(1), "cannot copy");
-
- /*
- * close files and free resources
- */
-
- if (tp)
- {
- sfdisc(sfstdout, NiL);
- if (line >= 0)
- sfset(sfstdout, SF_LINE, line);
- for(hp = tp->fd; (n = *hp) >= 0; hp++)
- close(n);
+ error(ERROR_exit(0), "out of space");
}
- return(error_info.errors);
+ if ((sfmove(sfstdin, sfstdout, SF_UNBOUND, -1) < 0 || !sfeof(sfstdin)) && errno != EPIPE)
+ error(ERROR_system(0), "read error");
+ if (sfsync(sfstdout))
+ error(ERROR_system(0), "write error");
+ tee_cleanup(tp);
+ return error_info.errors;
}
diff --git a/usr/src/lib/libcmd/common/tty.c b/usr/src/lib/libcmd/common/tty.c
index 4db11b9185..b257290e50 100644
--- a/usr/src/lib/libcmd/common/tty.c
+++ b/usr/src/lib/libcmd/common/tty.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
diff --git a/usr/src/lib/libcmd/common/uname.c b/usr/src/lib/libcmd/common/uname.c
index 72605200be..74cbd39ebe 100644
--- a/usr/src/lib/libcmd/common/uname.c
+++ b/usr/src/lib/libcmd/common/uname.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
@@ -104,7 +104,7 @@ __STDPP__directive pragma pp:nohide getdomainname gethostid gethostname sethostn
extern int getdomainname(char*, size_t);
#endif
#if _lib_gethostid
-extern int gethostid(void);
+extern long gethostid(void);
#endif
#if _lib_gethostname
extern int gethostname(char*, size_t);
diff --git a/usr/src/lib/libcmd/common/uniq.c b/usr/src/lib/libcmd/common/uniq.c
index d49954a710..bf87a2a15a 100644
--- a/usr/src/lib/libcmd/common/uniq.c
+++ b/usr/src/lib/libcmd/common/uniq.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
@@ -26,17 +26,17 @@
*/
static const char usage[] =
-"[-n?\n@(#)$Id: uniq (AT&T Research) 2008-04-24 $\n]"
+"[-n?\n@(#)$Id: uniq (AT&T Research) 2009-08-10 $\n]"
USAGE_LICENSE
"[+NAME?uniq - Report or filter out repeated lines in a file]"
-"[+DESCRIPTION?\buniq\b reads an input, comparing adjacent lines, and "
- "writing one copy of each input line on the output. The second "
+"[+DESCRIPTION?\buniq\b reads the input, compares adjacent lines, and "
+ "writes one copy of each input line on the output. The second "
"and succeeding copies of the repeated adjacent lines are not "
"written.]"
"[+?If the output file, \aoutfile\a, is not specified, \buniq\b writes "
"to standard output. If no \ainfile\a is given, or if the \ainfile\a "
- "is \b-\b, \buniq\b reads from standard input with the start of "
- "the file is defined as the current offset.]"
+ "is \b-\b, \buniq\b reads from standard input with the start of "
+ "the file defined as the current offset.]"
"[c:count?Output the number of times each line occurred along with "
"the line.]"
"[d:repeated|duplicates?Output the first of each duplicate line.]"
@@ -49,13 +49,15 @@ USAGE_LICENSE
"}"
"[f:skip-fields]#[fields?\afields\a is the number of fields to skip over "
"before checking for uniqueness. A field is the minimal string matching "
- "the BRE \b[[:blank:]]]]*[^[:blank:]]]]*\b.]"
+ "the BRE \b[[:blank:]]]]*[^[:blank:]]]]*\b. -\anumber\a is equivalent to "
+ "\b--skip-fields\b=\anumber\a.]"
"[i:ignore-case?Ignore case in comparisons.]"
"[s:skip-chars]#[chars?\achars\a is the number of characters to skip over "
"before checking for uniqueness. If specified along with \b-f\b, "
"the first \achars\a after the first \afields\a are ignored. If "
"the \achars\a specifies more characters than are on the line, "
- "an empty string will be used for comparison.]"
+ "an empty string will be used for comparison. +\anumber\a is "
+ "equivalent to \b--skip-chars\b=\anumber\a.]"
"[u:unique?Output unique lines.]"
"[w:check-chars]#[chars?\achars\a is the number of characters to compare "
"after skipping any specified fields and characters.]"
@@ -145,11 +147,25 @@ static int uniq(Sfio_t *fdin, Sfio_t *fdout, int fields, int chars, int width, i
{
if(cwidth)
{
- outp[CWIDTH] = ' ';
- if(count<MAXCNT)
+ if(count<9)
{
- sfsprintf(outp,cwidth,"%*d",CWIDTH,count+1);
- outp[CWIDTH] = ' ';
+ f = 0;
+ while(f < CWIDTH-1)
+ outp[f++] = ' ';
+ outp[f++] = '0' + count + 1;
+ outp[f] = ' ';
+ }
+ else if(count<MAXCNT)
+ {
+ count++;
+ f = CWIDTH;
+ outp[f--] = ' ';
+ do
+ {
+ outp[f--] = '0' + (count % 10);
+ } while (count /= 10);
+ while (f >= 0)
+ outp[f--] = ' ';
}
else
{
diff --git a/usr/src/lib/libcmd/common/wc.c b/usr/src/lib/libcmd/common/wc.c
index 763090fc02..4203fffd3a 100644
--- a/usr/src/lib/libcmd/common/wc.c
+++ b/usr/src/lib/libcmd/common/wc.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
@@ -27,7 +27,7 @@
*/
static const char usage[] =
-"[-?\n@(#)$Id: wc (AT&T Research) 2006-08-25 $\n]"
+"[-?\n@(#)$Id: wc (AT&T Research) 2000-08-11 $\n]"
USAGE_LICENSE
"[+NAME?wc - print the number of bytes, words, and lines in files]"
"[+DESCRIPTION?\bwc\b reads one or more input files and, by default, "
@@ -50,7 +50,10 @@ USAGE_LICENSE
"[c:bytes|chars:chars?List the byte counts.]"
"[m|C:multibyte-chars?List the character counts.]"
"[q:quiet?Suppress invalid multibyte character warnings.]"
-"[L:longest-line|max-line-length?List the longest line length.]"
+"[L:longest-line|max-line-length?List the longest line length; the newline,"
+ "if any, is not counted in the length.]"
+"[N!:utf8?For \bUTF-8\b locales \b--noutf8\b disables \bUTF-8\b "
+ "optimzations and relies on the native \bmbtowc\b(3).]"
"\n"
"\n[file ...]\n"
"\n"
@@ -70,15 +73,15 @@ USAGE_LICENSE
static void printout(register Wc_t *wp, register char *name,register int mode)
{
- if(mode&WC_LINES)
+ if (mode&WC_LINES)
sfprintf(sfstdout," %7I*d",sizeof(wp->lines),wp->lines);
- if(mode&WC_WORDS)
+ if (mode&WC_WORDS)
sfprintf(sfstdout," %7I*d",sizeof(wp->words),wp->words);
- if(mode&WC_CHARS)
+ if (mode&WC_CHARS)
sfprintf(sfstdout," %7I*d",sizeof(wp->chars),wp->chars);
- if(mode&WC_LONGEST)
+ if (mode&WC_LONGEST)
sfprintf(sfstdout," %7I*d",sizeof(wp->chars),wp->longest);
- if(name)
+ if (name)
sfprintf(sfstdout," %s",name);
sfputc(sfstdout,'\n');
}
@@ -94,71 +97,72 @@ b_wc(int argc,register char **argv, void* context)
struct stat statb;
cmdinit(argc, argv, context, ERROR_CATALOG, 0);
- while (n = optget(argv,usage)) switch (n)
+ for (;;)
{
- case 'c':
- mode |= WC_CHARS;
- break;
- case 'l':
- mode |= WC_LINES;
- break;
- case 'L':
- mode |= WC_LONGEST;
- break;
- case 'm':
- case 'C':
- mode |= WC_MBYTE;
- break;
- case 'q':
- mode |= WC_QUIET;
- break;
- case 'w':
- mode |= WC_WORDS;
- break;
- case ':':
- error(2, "%s", opt_info.arg);
- break;
- case '?':
- error(ERROR_usage(2), "%s", opt_info.arg);
+ switch (optget(argv, usage))
+ {
+ case 'c':
+ mode |= WC_CHARS;
+ continue;
+ case 'l':
+ mode |= WC_LINES;
+ continue;
+ case 'L':
+ mode |= WC_LONGEST;
+ continue;
+ case 'N':
+ if (!opt_info.num)
+ mode |= WC_NOUTF8;
+ continue;
+ case 'm':
+ case 'C':
+ mode |= WC_MBYTE;
+ continue;
+ case 'q':
+ mode |= WC_QUIET;
+ continue;
+ case 'w':
+ mode |= WC_WORDS;
+ continue;
+ case ':':
+ error(2, "%s", opt_info.arg);
+ break;
+ case '?':
+ error(ERROR_usage(2), "%s", opt_info.arg);
+ break;
+ }
break;
}
argv += opt_info.index;
if (error_info.errors)
error(ERROR_usage(2), "%s", optusage(NiL));
- if(mode&WC_MBYTE)
+ if (mode&WC_MBYTE)
{
- if(mode&WC_CHARS)
+ if (mode&WC_CHARS)
error(2, "-c and -C are mutually exclusive");
- mode |= WC_CHARS;
- if(!mbwide())
- {
+ if (!mbwide())
mode &= ~WC_MBYTE;
- setlocale(LC_CTYPE, "C");
- }
+ mode |= WC_CHARS;
}
- if(!(mode&(WC_WORDS|WC_CHARS|WC_LINES|WC_MBYTE|WC_LONGEST)))
+ if (!(mode&(WC_WORDS|WC_CHARS|WC_LINES|WC_MBYTE|WC_LONGEST)))
mode |= (WC_WORDS|WC_CHARS|WC_LINES);
- if(!(wp = wc_init(mode)))
+ if (!(wp = wc_init(mode)))
error(3,"internal error");
- if(!(mode&WC_WORDS))
- {
- memzero(wp->space, (1<<CHAR_BIT));
- wp->space['\n'] = -1;
- }
- if(cp = *argv)
+ if (cp = *argv)
argv++;
+ n = 0;
do
{
- if(!cp || streq(cp,"-"))
+ if (!cp || streq(cp,"-"))
fp = sfstdin;
- else if(!(fp = sfopen(NiL,cp,"r")))
+ else if (!(fp = sfopen(NiL,cp,"r")))
{
error(ERROR_system(0),"%s: cannot open",cp);
continue;
}
- if(cp)
+ if (cp)
n++;
- if(!(mode&(WC_WORDS|WC_LINES|WC_MBYTE|WC_LONGEST)) && fstat(sffileno(fp),&statb)>=0
+ if (!(mode&(WC_WORDS|WC_LINES|WC_MBYTE|WC_LONGEST)) && fstat(sffileno(fp),&statb)>=0
&& S_ISREG(statb.st_mode))
{
wp->chars = statb.st_size - lseek(sffileno(fp),0L,1);
@@ -166,21 +170,19 @@ b_wc(int argc,register char **argv, void* context)
}
else
wc_count(wp, fp, cp);
- if(fp!=sfstdin)
+ if (fp!=sfstdin)
sfclose(fp);
tchars += wp->chars;
twords += wp->words;
tlines += wp->lines;
printout(wp,cp,mode);
- }
- while(cp= *argv++);
- if(n>1)
+ } while (cp= *argv++);
+ if (n > 1)
{
wp->lines = tlines;
wp->chars = tchars;
wp->words = twords;
printout(wp,"total",mode);
}
- return(error_info.errors<ERRORMAX?error_info.errors:ERRORMAX);
+ return error_info.errors<ERRORMAX?error_info.errors:ERRORMAX;
}
-
diff --git a/usr/src/lib/libcmd/common/wc.h b/usr/src/lib/libcmd/common/wc.h
index 2752af36a3..e23a1ec2c4 100644
--- a/usr/src/lib/libcmd/common/wc.h
+++ b/usr/src/lib/libcmd/common/wc.h
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
@@ -37,15 +37,17 @@
#define WC_MBYTE 0x08
#define WC_LONGEST 0x10
#define WC_QUIET 0x20
+#define WC_NOUTF8 0x40
typedef struct
{
- signed char space[1<<CHAR_BIT];
+ char type[1<<CHAR_BIT];
Sfoff_t words;
Sfoff_t lines;
Sfoff_t chars;
Sfoff_t longest;
int mode;
+ int mb;
} Wc_t;
#define wc_count _cmd_wccount
diff --git a/usr/src/lib/libcmd/common/wclib.c b/usr/src/lib/libcmd/common/wclib.c
index 67adb5fe15..c7ce5a338a 100644
--- a/usr/src/lib/libcmd/common/wclib.c
+++ b/usr/src/lib/libcmd/common/wclib.c
@@ -1,7 +1,7 @@
/***********************************************************************
* *
* This software is part of the ast package *
-* Copyright (c) 1992-2008 AT&T Intellectual Property *
+* Copyright (c) 1992-2009 AT&T Intellectual Property *
* and is licensed under the *
* Common Public License, Version 1.0 *
* by AT&T Intellectual Property *
@@ -34,6 +34,7 @@
#include <wchar.h>
#include <wctype.h>
+#include <lc.h>
#else
@@ -43,80 +44,197 @@
#endif
-#define endline(c) (((signed char)-1)<0?(c)<0:(c)==((char)-1))
-#define mbok(p,n) (((n)<1)?0:mbwide()?((*ast.mb_towc)(NiL,(char*)(p),n)>=0):1)
+#define WC_SP 0x08
+#define WC_NL 0x10
+#define WC_MB 0x20
+#define WC_ERR 0x40
-Wc_t *wc_init(int mode)
+#define eol(c) ((c)&WC_NL)
+#define mbc(c) ((c)&WC_MB)
+#define spc(c) ((c)&WC_SP)
+#define mbwc(w,p,n) (*ast.mb_towc)(&w,(char*)p,n)
+
+Wc_t* wc_init(int mode)
{
register int n;
register int w;
Wc_t* wp;
- if(!(wp = (Wc_t*)stakalloc(sizeof(Wc_t))))
- return(0);
- wp->mode = mode;
+ if (!(wp = (Wc_t*)stakalloc(sizeof(Wc_t))))
+ return 0;
+ if (!mbwide())
+ wp->mb = 0;
+#if _hdr_wchar && _hdr_wctype && _lib_iswctype
+ else if (!(mode & WC_NOUTF8) && (lcinfo(LC_CTYPE)->lc->flags & LC_utf8))
+ wp->mb = 1;
+#endif
+ else
+ wp->mb = -1;
w = mode & WC_WORDS;
- for(n=(1<<CHAR_BIT);--n >=0;)
- wp->space[n] = w ? !!isspace(n) : 0;
- wp->space['\n'] = -1;
- return(wp);
+ for (n = (1<<CHAR_BIT); --n >= 0;)
+ wp->type[n] = (w && isspace(n)) ? WC_SP : 0;
+ wp->type['\n'] = WC_SP|WC_NL;
+ if ((mode & (WC_MBYTE|WC_WORDS)) && wp->mb > 0)
+ {
+ for (n = 0; n < 64; n++)
+ {
+ wp->type[0x80+n] |= WC_MB;
+ if (n<32)
+ wp->type[0xc0+n] |= WC_MB+1;
+ else if (n<48)
+ wp->type[0xc0+n] |= WC_MB+2;
+ else if (n<56)
+ wp->type[0xc0+n] |= WC_MB+3;
+ else if (n<60)
+ wp->type[0xc0+n] |= WC_MB+4;
+ else if (n<62)
+ wp->type[0xc0+n] |= WC_MB+5;
+ }
+ wp->type[0xc0] = WC_MB|WC_ERR;
+ wp->type[0xc1] = WC_MB|WC_ERR;
+ wp->type[0xfe] = WC_MB|WC_ERR;
+ wp->type[0xff] = WC_MB|WC_ERR;
+ }
+ wp->mode = mode;
+ return wp;
+}
+
+static int invalid(const char *file, int nlines)
+{
+ error_info.file = (char*)file;
+ error_info.line = nlines;
+ error(ERROR_SYSTEM|1, "invalid multibyte character");
+ error_info.file = 0;
+ error_info.line = 0;
+ return nlines;
+}
+
+/*
+ * handle utf space characters
+ */
+
+static int chkstate(int state, register unsigned int c)
+{
+ switch(state)
+ {
+ case 1:
+ state = (c==0x9a?4:0);
+ break;
+ case 2:
+ state = ((c==0x80||c==0x81)?6+(c&1):0);
+ break;
+ case 3:
+ state = (c==0x80?5:0);
+ break;
+ case 4:
+ state = (c==0x80?10:0);
+ break;
+ case 5:
+ state = (c==0x80?10:0);
+ break;
+ case 6:
+ state = 0;
+ if(c==0xa0 || c==0xa1)
+ return(10);
+ else if((c&0xf0)== 0x80)
+ {
+ if((c&=0xf)==7)
+ return(iswspace(0x2007)?10:0);
+ if(c<=0xb)
+ return(10);
+ }
+ else if(c==0xaf && iswspace(0x202f))
+ return(10);
+ break;
+ case 7:
+ state = (c==0x9f?10:0);
+ break;
+ case 8:
+ return (iswspace(c)?10:0);
+ }
+ return state;
}
/*
* compute the line, word, and character count for file <fd>
*/
+
int wc_count(Wc_t *wp, Sfio_t *fd, const char* file)
{
- register signed char *space = wp->space;
- register unsigned char *cp;
+ register char* type = wp->type;
+ register unsigned char* cp;
register Sfoff_t nchars;
register Sfoff_t nwords;
register Sfoff_t nlines;
- register Sfoff_t eline;
- register Sfoff_t longest;
+ register Sfoff_t eline = -1;
+ register Sfoff_t longest = 0;
register ssize_t c;
- register unsigned char *endbuff;
- register int lasttype = 1;
+ register unsigned char* endbuff;
+ register int lasttype = WC_SP;
unsigned int lastchar;
- unsigned char *buff;
+ ssize_t n;
+ ssize_t o;
+ unsigned char* buff;
wchar_t x;
+ unsigned char side[32];
sfset(fd,SF_WRITE,1);
nlines = nwords = nchars = 0;
wp->longest = 0;
- if (wp->mode & (WC_LONGEST|WC_MBYTE))
+ if (wp->mb < 0 && (wp->mode & (WC_MBYTE|WC_WORDS)))
{
- longest = 0;
- eline = -1;
cp = buff = endbuff = 0;
for (;;)
{
- if (!mbok(cp, endbuff-cp))
- {
- if (buff)
- sfread(fd, buff, cp-buff);
- if (!(buff = (unsigned char*)sfreserve(fd, SF_UNBOUND, SF_LOCKR)))
- break;
- endbuff = (cp = buff) + sfvalue(fd);
- }
- nchars++;
- x = mbchar(cp);
- if (x == -1)
+ if (cp >= endbuff || (n = mbwc(x, cp, endbuff-cp)) < 0)
{
- if (eline != nlines && !(wp->mode & WC_QUIET))
+ if ((o = endbuff-cp) < sizeof(side))
+ {
+ if (buff)
+ {
+ if (o)
+ memcpy(side, cp, o);
+ mbinit();
+ }
+ else
+ o = 0;
+ cp = side + o;
+ if (!(buff = (unsigned char*)sfreserve(fd, SF_UNBOUND, 0)) || (n = sfvalue(fd)) <= 0)
+ {
+ if ((nchars - longest) > wp->longest)
+ wp->longest = nchars - longest;
+ break;
+ }
+ if ((c = sizeof(side) - o) > n)
+ c = n;
+ if (c)
+ memcpy(cp, buff, c);
+ endbuff = buff + n;
+ cp = side;
+ x = mbchar(cp);
+ if ((cp-side) < o)
+ {
+ cp = buff;
+ nchars += (cp-side) - 1;
+ }
+ else
+ cp = buff + (cp-side) - o;
+ }
+ else
{
- error_info.file = (char*)file;
- error_info.line = eline = nlines;
- error(ERROR_SYSTEM|1, "invalid multibyte character");
- error_info.file = 0;
- error_info.line = 0;
+ cp++;
+ x = -1;
}
+ if (x == -1 && eline != nlines && !(wp->mode & WC_QUIET))
+ eline = invalid(file, nlines);
}
- else if (x == '\n')
+ else
+ cp += n ? n : 1;
+ if (x == '\n')
{
if ((nchars - longest) > wp->longest)
wp->longest = nchars - longest;
- longest = nchars;
+ longest = nchars + 1;
nlines++;
lasttype = 1;
}
@@ -127,71 +245,253 @@ int wc_count(Wc_t *wp, Sfio_t *fd, const char* file)
lasttype = 0;
nwords++;
}
+ nchars++;
+ }
+ }
+ else if (!wp->mb && !(wp->mode & WC_LONGEST) || wp->mb > 0 && !(wp->mode & (WC_MBYTE|WC_WORDS|WC_LONGEST)))
+ {
+ if (!(wp->mode & (WC_MBYTE|WC_WORDS|WC_LONGEST)))
+ {
+ while ((cp = (unsigned char*)sfreserve(fd, SF_UNBOUND, 0)) && (c = sfvalue(fd)) > 0)
+ {
+ nchars += c;
+ endbuff = cp + c;
+ if (*--endbuff == '\n')
+ nlines++;
+ else
+ *endbuff = '\n';
+ for (;;)
+ if (*cp++ == '\n')
+ {
+ if (cp > endbuff)
+ break;
+ nlines++;
+ }
+ }
+ }
+ else
+ {
+ while ((cp = buff = (unsigned char*)sfreserve(fd, SF_UNBOUND, 0)) && (c = sfvalue(fd)) > 0)
+ {
+ nchars += c;
+ /* check to see whether first character terminates word */
+ if (c==1)
+ {
+ if (eol(lasttype))
+ nlines++;
+ if ((c = type[*cp]) && !lasttype)
+ nwords++;
+ lasttype = c;
+ continue;
+ }
+ if (!lasttype && type[*cp])
+ nwords++;
+ lastchar = cp[--c];
+ *(endbuff = cp+c) = '\n';
+ c = lasttype;
+ /* process each buffer */
+ for (;;)
+ {
+ /* process spaces and new-lines */
+ do
+ {
+ if (eol(c))
+ for (;;)
+ {
+ /* check for end of buffer */
+ if (cp > endbuff)
+ goto beob;
+ nlines++;
+ if (*cp != '\n')
+ break;
+ cp++;
+ }
+ } while (c = type[*cp++]);
+ /* skip over word characters */
+ while (!(c = type[*cp++]));
+ nwords++;
+ }
+ beob:
+ if ((cp -= 2) >= buff)
+ c = type[*cp];
+ else
+ c = lasttype;
+ lasttype = type[lastchar];
+ /* see if was in word */
+ if (!c && !lasttype)
+ nwords--;
+ }
+ if (eol(lasttype))
+ nlines++;
+ else if (!lasttype)
+ nwords++;
}
}
else
{
- for (;;)
+ int lineoff=0;
+ int skip=0;
+ int adjust=0;
+ int state=0;
+ int oldc;
+ int xspace;
+ int wasspace = 1;
+ unsigned char* start;
+
+ lastchar = 0;
+ start = (endbuff = side) + 1;
+ xspace = iswspace(0xa0) || iswspace(0x85);
+ while ((cp = buff = (unsigned char*)sfreserve(fd, SF_UNBOUND, 0)) && (c = sfvalue(fd)) > 0)
{
- /* fill next buffer and check for end-of-file */
- if (!(buff = (unsigned char*)sfreserve(fd, 0, 0)) || (c = sfvalue(fd)) <= 0)
- break;
- sfread(fd,(char*)(cp=buff),c);
nchars += c;
+ start = cp-lineoff;
/* check to see whether first character terminates word */
if(c==1)
{
- if(endline(lasttype))
+ if(eol(lasttype))
nlines++;
- if((c = space[*cp]) && !lasttype)
+ if((c = type[*cp]) && !lasttype)
nwords++;
lasttype = c;
+ endbuff = start;
continue;
}
- if(!lasttype && space[*cp])
- nwords++;
lastchar = cp[--c];
- cp[c] = '\n';
endbuff = cp+c;
+ cp[c] = '\n';
+ if(mbc(lasttype))
+ {
+ c = lasttype;
+ goto mbyte;
+ }
+ if(!lasttype && spc(type[*cp]))
+ nwords++;
c = lasttype;
/* process each buffer */
for (;;)
{
/* process spaces and new-lines */
- do if (endline(c))
+ spaces:
+ do
{
- for (;;)
+ if (eol(c))
{
/* check for end of buffer */
if (cp > endbuff)
goto eob;
+ if(wp->mode&WC_LONGEST)
+ {
+ if((cp-start)-adjust > longest)
+ longest = (cp-start)-adjust-1;
+ start = cp;
+ }
nlines++;
- if (*cp != '\n')
+ nchars -= adjust;
+ adjust = 0;
+ }
+ } while (spc(c = type[*cp++]));
+ wasspace=1;
+ if(mbc(c))
+ {
+ mbyte:
+ do
+ {
+ if(c&WC_ERR)
+ goto err;
+ if(skip && (c&7))
break;
- cp++;
+ if(!skip)
+ {
+ if(!(c&7))
+ {
+ skip=1;
+ break;
+ }
+ skip = (c&7);
+ adjust += skip;
+ state = 0;
+ if(skip==2 && (cp[-1]&0xc)==0 && (state=(cp[-1]&0x3)))
+ oldc = *cp;
+ else if(xspace && cp[-1]==0xc2)
+ {
+ state = 8;
+ oldc = *cp;
+ }
+ }
+ else
+ {
+ skip--;
+ if(state && (state=chkstate(state,oldc)))
+ {
+ if(state==10)
+ {
+ if(!wasspace)
+ nwords++;
+ wasspace = 1;
+ state=0;
+ goto spaces;
+ }
+ oldc = *cp;
+ }
+ }
+ } while (mbc(c = type[*cp++]));
+ wasspace = 0;
+ if(skip)
+ {
+ if(eol(c) && (cp > endbuff))
+ goto eob;
+ err:
+ skip = 0;
+ state = 0;
+ if(eline!=nlines && !(wp->mode & WC_QUIET))
+ eline = invalid(file, nlines);
+ while(mbc(c) && ((c|WC_ERR) || (c&7)==0))
+ c=type[*cp++];
+ if(eol(c) && (cp > endbuff))
+ {
+ c = WC_MB|WC_ERR;
+ goto eob;
+ }
+ if(mbc(c))
+ goto mbyte;
+ else if(c&WC_SP)
+ goto spaces;
+ }
+ if(spc(c))
+ {
+ nwords++;
+ continue;
}
- } while (c = space[*cp++]);
+ }
/* skip over word characters */
- while(!(c = space[*cp++]));
+ while(!(c = type[*cp++]));
+ if(mbc(c))
+ goto mbyte;
nwords++;
}
eob:
+ lineoff = cp-start;
if((cp -= 2) >= buff)
- c = space[*cp];
+ c = type[*cp];
else
- c = lasttype;
- lasttype = space[lastchar];
+ c = lasttype;
+ lasttype = type[lastchar];
/* see if was in word */
if(!c && !lasttype)
nwords--;
}
- if(endline(lasttype))
+ if ((wp->mode&WC_LONGEST) && ((endbuff + 1 - start) - adjust - (lastchar == '\n')) > longest)
+ longest = (endbuff + 1 - start) - adjust - (lastchar == '\n');
+ wp->longest = longest;
+ if (eol(lasttype))
nlines++;
- else if(!lasttype)
+ else if (!lasttype)
nwords++;
+ nchars -= adjust;
}
wp->chars = nchars;
wp->words = nwords;
wp->lines = nlines;
- return(0);
+ return 0;
}
+