[hackers] [sbase] untypedef expr, find, test, as is existing style in sbase || Evan Gates

2015-03-17 Thread git
commit cab14bf253767fa9f469eef5808f95045ce85ab0
Author: Evan Gates 
Date:   Tue Mar 17 10:59:16 2015 -0700

untypedef expr, find, test, as is existing style in sbase

diff --git a/expr.c b/expr.c
index aa2bea8..ef7c303 100644
--- a/expr.c
+++ b/expr.c
@@ -12,15 +12,15 @@ enum {
VAL = CHAR_MAX + 1, GE, LE, NE
 };
 
-typedef struct {
-   char *s; /* iff s is NULL, Val is an integer */
+struct val {
+   char *s; /* iff s is NULL, val is an integer */
intmax_t n;
-} Val;
+};
 
 static size_t intlen;
 
 static void
-enan(Val v)
+enan(struct val v)
 {
if (v.s)
enprintf(2, "syntax error: expected integer got `%s'\n", v.s);
@@ -34,7 +34,7 @@ ezero(intmax_t n)
 }
 
 static char *
-valstr(Val val, char *buf, size_t bufsiz)
+valstr(struct val val, char *buf, size_t bufsiz)
 {
if (val.s)
return val.s;
@@ -43,7 +43,7 @@ valstr(Val val, char *buf, size_t bufsiz)
 }
 
 static int
-valcmp(Val a, Val b)
+valcmp(struct val a, struct val b)
 {
char buf1[intlen], buf2[intlen];
char *astr = valstr(a, buf1, sizeof(buf1));
@@ -59,8 +59,8 @@ valcmp(Val a, Val b)
  * then return the text matched by it \1 (empty string for no match)
  * else return number of characters matched (0 for no match)
  */
-static Val
-match(Val vstr, Val vregx)
+static struct val
+match(struct val vstr, struct val vregx)
 {
regex_t re;
regmatch_t matches[2];
@@ -76,7 +76,7 @@ match(Val vstr, Val vregx)
 
if (regexec(&re, str, 2, matches, 0)) {
regfree(&re);
-   return (Val){ (re.re_nsub ? "" : NULL), 0 };
+   return (struct val){ (re.re_nsub ? "" : NULL), 0 };
}
 
if (re.re_nsub) {
@@ -87,15 +87,15 @@ match(Val vstr, Val vregx)
*p = '\0';
d = strtoimax(s, &p, 10);
if (*s && !*p) /* string matched by subexpression is an integer 
*/
-   return (Val){ NULL, d };
+   return (struct val){ NULL, d };
 
/* FIXME? string is never free()d, worth fixing?
 * need to allocate as it could be in buf1 instead of vstr.s */
-   return (Val){ enstrdup(3, s), 0 };
+   return (struct val){ enstrdup(3, s), 0 };
}
regfree(&re);
 str += matches[0].rm_so;
-   return (Val){ NULL, utfnlen(str, matches[0].rm_eo - matches[0].rm_so) };
+   return (struct val){ NULL, utfnlen(str, matches[0].rm_eo - 
matches[0].rm_so) };
 }
 
 /* ops  points to a stack of operators, opp  points to one past the last op
@@ -105,9 +105,9 @@ match(Val vstr, Val vregx)
  * pop operator, pop two values, apply operator, push result
  */
 static void
-doop(int *ops, int **opp, Val *vals, Val **valp)
+doop(int *ops, int **opp, struct val *vals, struct val **valp)
 {
-   Val ret, a, b;
+   struct val ret, a, b;
int op;
 
/* For an operation, we need a valid operator
@@ -123,30 +123,30 @@ doop(int *ops, int **opp, Val *vals, Val **valp)
 
switch (op) {
case '|':
-   if  ( a.s && *a.s) ret = (Val){ a.s ,   0 };
-   else if (!a.s &&  a.n) ret = (Val){ NULL, a.n };
-   else if ( b.s && *b.s) ret = (Val){ b.s ,   0 };
-   else   ret = (Val){ NULL, b.n };
+   if  ( a.s && *a.s) ret = (struct val){ a.s ,   0 };
+   else if (!a.s &&  a.n) ret = (struct val){ NULL, a.n };
+   else if ( b.s && *b.s) ret = (struct val){ b.s ,   0 };
+   else   ret = (struct val){ NULL, b.n };
break;
case '&':
if (((a.s && *a.s) || a.n) && ((b.s && *b.s) || b.n))
ret = a;
else
-   ret = (Val){ NULL, 0 };
+   ret = (struct val){ NULL, 0 };
break;
 
-   case '=': ret = (Val){ NULL, valcmp(a, b) == 0 }; break;
-   case '>': ret = (Val){ NULL, valcmp(a, b) >  0 }; break;
-   case GE : ret = (Val){ NULL, valcmp(a, b) >= 0 }; break;
-   case '<': ret = (Val){ NULL, valcmp(a, b) <  0 }; break;
-   case LE : ret = (Val){ NULL, valcmp(a, b) <= 0 }; break;
-   case NE : ret = (Val){ NULL, valcmp(a, b) != 0 }; break;
+   case '=': ret = (struct val){ NULL, valcmp(a, b) == 0 }; break;
+   case '>': ret = (struct val){ NULL, valcmp(a, b) >  0 }; break;
+   case GE : ret = (struct val){ NULL, valcmp(a, b) >= 0 }; break;
+   case '<': ret = (struct val){ NULL, valcmp(a, b) <  0 }; break;
+   case LE : ret = (struct val){ NULL, valcmp(a, b) <= 0 }; break;
+   case NE : ret = (struct val){ NULL, valcmp(a, b) != 0 }; break;
 
-   case '+': enan(a); enan(b); ret = (Val){ NULL, a.n + b.n }; 
break;
-   case '-': enan(a); enan(b); ret = (Val){ NULL, a.n - b.n }; 
break;
-   case '*': enan(a); enan(b); ret = (Val){ NULL, a.n

Re: [hackers] [sbase] Rewrite foldline() in fold(1) || FRIGN

2015-03-17 Thread Roberto E. Vargas Caballero

> If fwrite() fails with a short element count, will ferror() always be
> on true?  I am not sure we can rely on this.
> 
> And also if fwrite() fails is it guaranteed that it will continue to
> fail on all future calls?

Yes, it is. If an error is produced in a stream, the value of error
associated with the strem is kept until is cleared with a clearerr
call.

Regards,




Re: [hackers] [sbase] Rewrite foldline() in fold(1) || FRIGN

2015-03-17 Thread Dimitris Papastamos
On Tue, Mar 17, 2015 at 11:35:33AM +0100, Roberto E. Vargas Caballero wrote:
> 
> Hi,
> 
> > +   for (p = str, col = 0; *p && *p != '\n'; p++) {
> > +   if (!UTF8_POINT(*p) && !bflag)
> > +   continue;
> > +   if (col >= width) {
> > +   off = (sflag && spacesect) ? spacesect - str : p - str;
> > +   if (fwrite(str, 1, off, stdout) != off)
> > +   eprintf("fwrite :");
> > +   putchar('\n');
> ...
> > +   fputs(str, stdout);
> 
> It's a bit strange this fwrite, why don't you use putchar there?, and
> why you check the return value of fwrite, but not the return value of
> putcharor fputs?.  I usually don't check the return value of write
> functions and at the end of the loop I do a call to ferror.

If fwrite() fails with a short element count, will ferror() always be
on true?  I am not sure we can rely on this.

And also if fwrite() fails is it guaranteed that it will continue to
fail on all future calls?



Re: [hackers] [sbase] Rewrite foldline() in fold(1) || FRIGN

2015-03-17 Thread FRIGN
On Tue, 17 Mar 2015 11:35:33 +0100
"Roberto E. Vargas Caballero"  wrote:

Hey Roberto,

> It's a bit strange this fwrite, why don't you use putchar there?

Look again, we write 'off' bytes, not 1.

> and why you check the return value of fwrite, but not the return value of
> putchar or fputs?.  I usually don't check the return value of write
> functions and at the end of the loop I do a call to ferror.

Calling ferror sounds like a nice idea. Let's take a look at it.

Cheers

FRIGN

-- 
FRIGN 



Re: [hackers] [sbase] Rewrite foldline() in fold(1) || FRIGN

2015-03-17 Thread Roberto E. Vargas Caballero

Hi,

> + for (p = str, col = 0; *p && *p != '\n'; p++) {
> + if (!UTF8_POINT(*p) && !bflag)
> + continue;
> + if (col >= width) {
> + off = (sflag && spacesect) ? spacesect - str : p - str;
> + if (fwrite(str, 1, off, stdout) != off)
> + eprintf("fwrite :");
> + putchar('\n');
...
> + fputs(str, stdout);

It's a bit strange this fwrite, why don't you use putchar there?, and
why you check the return value of fwrite, but not the return value of
putcharor fputs?.  I usually don't check the return value of write
functions and at the end of the loop I do a call to ferror.


Regards,




[hackers] [sbase] Add estrlcat() and estrlcpy() || FRIGN

2015-03-17 Thread git
commit 8729b6ba39a21229cf7de8ebc40960079c4bb1bf
Author: FRIGN 
Date:   Tue Mar 17 11:24:49 2015 +0100

Add estrlcat() and estrlcpy()

It has become a common idiom in sbase to check strlcat() and strlcpy()
using

if (strl{cat, cpy}(dst, src, siz) >= siz)
eprintf("path too long\n");

However, this was not carried out consistently and to this very day,
some tools employed unchecked calls to these functions, effectively
allowing silent truncations to happen, which in turn may lead to
security issues.
To finally put an end to this, the e*-functions detect truncation
automatically and the caller can lean back and enjoy coding without
trouble. :)

diff --git a/find.c b/find.c
index 9b876dc..9a427a2 100644
--- a/find.c
+++ b/find.c
@@ -977,10 +977,10 @@ find(char *path, Findhist *hist)
if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, ".."))
continue;
 
-   p = pathbuf + strlcpy(pathbuf, path, pathcap);
+   p = pathbuf + estrlcpy(pathbuf, path, pathcap);
if (*--p != '/')
-   strlcat(pathbuf, "/", pathcap);
-   strlcat(pathbuf, de->d_name, pathcap);
+   estrlcat(pathbuf, "/", pathcap);
+   estrlcat(pathbuf, de->d_name, pathcap);
find(pathbuf, &cur);
}
closedir(dir); /* check return value? */
diff --git a/libutil/recurse.c b/libutil/recurse.c
index 1637d0c..c4e8043 100644
--- a/libutil/recurse.c
+++ b/libutil/recurse.c
@@ -66,12 +66,10 @@ recurse(const char *path, void *data, struct recursor *r)
}
if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
continue;
-   if (strlcpy(subpath, path, PATH_MAX) >= PATH_MAX)
-   eprintf("strlcpy: path too long\n");
-   if (path[strlen(path) - 1] != '/' && strlcat(subpath, "/", 
PATH_MAX) >= PATH_MAX)
-   eprintf("strlcat: path too long\n");
-   if (strlcat(subpath, d->d_name, PATH_MAX) >= PATH_MAX)
-   eprintf("strlcat: path too long\n");
+   estrlcpy(subpath, path, sizeof(subpath));
+   if (path[strlen(path) - 1] != '/')
+   estrlcat(subpath, "/", sizeof(subpath));
+   estrlcat(subpath, d->d_name, sizeof(subpath));
if ((r->flags & SAMEDEV) && statf(subpath, &dst) < 0) {
if (errno != ENOENT) {
weprintf("%s %s:", statf_name, subpath);
diff --git a/libutil/strlcat.c b/libutil/strlcat.c
index 9e2d251..bf263b8 100644
--- a/libutil/strlcat.c
+++ b/libutil/strlcat.c
@@ -50,3 +50,14 @@ strlcat(char *dst, const char *src, size_t siz)
*d = '\0';
return(dlen + (s - src)); /* count does not include NUL */
 }
+
+size_t
+estrlcat(char *dst, const char *src, size_t siz)
+{
+   size_t ret;
+
+   if ((ret = strlcat(dst, src, siz)) >= siz)
+   eprintf("strlcat: input string too long\n");
+
+   return ret;
+}
diff --git a/libutil/strlcpy.c b/libutil/strlcpy.c
index 388b426..44b618a 100644
--- a/libutil/strlcpy.c
+++ b/libutil/strlcpy.c
@@ -46,3 +46,14 @@ strlcpy(char *dst, const char *src, size_t siz)
}
return(s - src - 1); /* count does not include NUL */
 }
+
+size_t
+estrlcpy(char *dst, const char *src, size_t siz)
+{
+   size_t ret;
+
+   if ((ret = strlcpy(dst, src, siz)) >= siz)
+   eprintf("strlcpy: input string too long\n");
+
+   return ret;
+}
diff --git a/logger.c b/logger.c
index 0f8a763..80dcdc7 100644
--- a/logger.c
+++ b/logger.c
@@ -80,9 +80,9 @@ main(int argc, char *argv[])
sz += argc;
buf = ecalloc(1, sz);
for (i = 0; i < argc; i++) {
-   strlcat(buf, argv[i], sz);
+   estrlcat(buf, argv[i], sz);
if (i + 1 < argc)
-   strlcat(buf, " ", sz);
+   estrlcat(buf, " ", sz);
}
syslog(priority, "%s", buf);
}
diff --git a/mktemp.c b/mktemp.c
index 8dbb210..b4ecaf1 100644
--- a/mktemp.c
+++ b/mktemp.c
@@ -39,19 +39,14 @@ main(int argc, char *argv[])
if ((p = getenv("TMPDIR")))
tmpdir = p;
 
-   if (strlcpy(tmp, template, sizeof(tmp)) >= sizeof(tmp))
-   eprintf("path too long\n");
+   estrlcpy(tmp, template, sizeof(tmp));
p = dirname(tmp);
if (p[0] != '.') {
-   if (strlcpy(path, template, sizeof(path)) >= sizeof(path))
-   eprintf("path too long\n");
+   estrlcpy(path, template, sizeof(path));
} else {
-   if (strlcpy(path, tmpdir, sizeof(path)) >= sizeof(path))
-   eprintf("path too long\n");
-   if (strlcat(path, "/", sizeof(path)

[hackers] [sbase] Rewrite foldline() in fold(1) || FRIGN

2015-03-17 Thread git
commit 9d151741258d6e2f7eb415b8783a2c2a9efbda04
Author: FRIGN 
Date:   Mon Mar 16 19:26:42 2015 +0100

Rewrite foldline() in fold(1)

After the audit, I had this noted down as a TODO-item, but
considered the function to be tested enough to hold the line
until I came to rewrite it.
Admittedly, I didn't take a closer look at the previous loop
and there probably were some edge-cases which caused trouble, but
so far so good, the new version of this commit should be safe
and considered audited.

diff --git a/fold.c b/fold.c
index 020d429..c176497 100644
--- a/fold.c
+++ b/fold.c
@@ -3,6 +3,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "util.h"
 
@@ -11,46 +12,41 @@ static intsflag = 0;
 static size_t width = 80;
 
 static void
-foldline(const char *str)
-{
-   size_t i = 0, n = 0, col, j;
-   int space;
-   char c;
-
-   do {
-   space = 0;
-   for (j = i, col = 0; str[j] && col <= width; j++) {
-   c = str[j];
-   if (!UTF8_POINT(c) && !bflag)
-   continue;
-   if (sflag && isspace(c)) {
-   space = 1;
-   n = j + 1;
-   } else if (!space) {
-   n = j;
-   }
+foldline(const char *str) {
+   const char *p, *spacesect = NULL;
+   size_t col, off;
 
-   if (!bflag && iscntrl(c)) {
-   switch(c) {
-   case '\b':
-   col--;
-   break;
-   case '\r':
-   col = 0;
-   break;
-   case '\t':
-   col += (col + 1) % 8;
-   break;
-   }
-   } else {
-   col++;
+   for (p = str, col = 0; *p && *p != '\n'; p++) {
+   if (!UTF8_POINT(*p) && !bflag)
+   continue;
+   if (col >= width) {
+   off = (sflag && spacesect) ? spacesect - str : p - str;
+   if (fwrite(str, 1, off, stdout) != off)
+   eprintf("fwrite :");
+   putchar('\n');
+   spacesect = NULL;
+   col = 0;
+   p = str += off;
+   }
+   if (sflag && isspace(*p))
+   spacesect = p + 1;
+   if (!bflag && iscntrl(*p)) {
+   switch(*p) {
+   case '\b':
+   col -= (col > 0);
+   break;
+   case '\r':
+   col = 0;
+   break;
+   case '\t':
+   col += (col + 1) % 8;
+   break;
}
+   } else {
+   col++;
}
-   if (fwrite(str + i, 1, n - i, stdout) != n - i)
-   eprintf("fwrite :");
-   if (str[n])
-   putchar('\n');
-   } while (str[i = n] && str[i] != '\n');
+   }
+   fputs(str, stdout);
 }
 
 static void
@@ -69,7 +65,7 @@ fold(FILE *fp, const char *fname)
 static void
 usage(void)
 {
-   eprintf("usage: %s [-bs] [-w width | -width] [FILE...]\n", argv0);
+   eprintf("usage: %s [-bs] [-w num | -num] [FILE ...]\n", argv0);
 }
 
 int
@@ -102,10 +98,10 @@ main(int argc, char *argv[])
if (!(fp = fopen(*argv, "r"))) {
weprintf("fopen %s:", *argv);
ret = 1;
-   continue;
+   } else {
+   fold(fp, *argv);
+   fclose(fp);
}
-   fold(fp, *argv);
-   fclose(fp);
}
}
 



[hackers] [sbase] Audit logname(1) || FRIGN

2015-03-17 Thread git
commit 4d25d87ada83b40620579c2104386f246568cb10
Author: FRIGN 
Date:   Tue Mar 17 00:44:18 2015 +0100

Audit logname(1)

1) Add usage().
2) Idiomatic argv0-setter. We don't use arg.h, as we do not process
   flags or arguments.
3) Remove program-name from eprintf-call. This is done in the eprintf-
   function itself when the DEBUG-define is set.
   We'll activate it by default later.
4) Add empty line before return.

diff --git a/README b/README
index ecace49..c936841 100644
--- a/README
+++ b/README
@@ -41,7 +41,7 @@ The following tools are implemented ('*' == finished, '#' == 
UTF-8 support,
 =*| linkyes  none
 =*| ln  yes  none
 =*| logger  yes  none
-=*  logname yes  none
+=*| logname yes  none
 =   ls  no   (-C), -S, -f, -m, -s, -x
 =*| md5sum  non-posixnone
 =*| mkdir   yes  none
diff --git a/logname.c b/logname.c
index f1981a5..11d287b 100644
--- a/logname.c
+++ b/logname.c
@@ -4,17 +4,26 @@
 
 #include "util.h"
 
+static void
+usage(void)
+{
+   eprintf("usage: %s\n", argv0);
+}
+
 int
 main(int argc, char *argv[])
 {
char *login;
 
-   argv0 = argv[0];
-   if (argc != 1)
-   eprintf("usage: %s\n", argv0);
+   argv0 = argv[0], argc--, argv++;
+
+   if (argc)
+   usage();
+
if ((login = getlogin()))
puts(login);
else
-   eprintf("%s: no login name\n", argv0);
+   eprintf("no login name\n");
+
return 0;
 }



[hackers] [sbase] Audit mktemp(1) || FRIGN

2015-03-17 Thread git
commit f724e87cc51c58404983439650f03851c897172f
Author: FRIGN 
Date:   Tue Mar 17 11:01:33 2015 +0100

Audit mktemp(1)

1) Unglobalize variables.
2) Sort local variables.
3) Use return instead of exit() in main().
4) Add empty line before return.

diff --git a/README b/README
index c936841..7c29823 100644
--- a/README
+++ b/README
@@ -46,7 +46,7 @@ The following tools are implemented ('*' == finished, '#' == 
UTF-8 support,
 =*| md5sum  non-posixnone
 =*| mkdir   yes  none
 =*| mkfifo  yes  none
-=*  mktemp  non-posixnone
+=*| mktemp  non-posixnone
 =*| mv  yes  none (-i)
 =*| niceyes  none
 =   nl  no   -d, -f, -h, -p
diff --git a/mktemp.c b/mktemp.c
index 08796cd..8dbb210 100644
--- a/mktemp.c
+++ b/mktemp.c
@@ -12,16 +12,13 @@ usage(void)
eprintf("usage: %s [-dq] [template]\n", argv0);
 }
 
-static int dflag = 0;
-static int qflag = 0;
-
 int
 main(int argc, char *argv[])
 {
-   char *template = "tmp.XX";
-   char *tmpdir = "/tmp", *p;
-   char path[PATH_MAX], tmp[PATH_MAX];
-   int fd;
+   int dflag = 0, qflag = 0, fd;
+   char *template = "tmp.XX",
+*tmpdir = "/tmp", *p,
+ path[PATH_MAX], tmp[PATH_MAX];
 
ARGBEGIN {
case 'd':
@@ -61,16 +58,17 @@ main(int argc, char *argv[])
if (!mkdtemp(path)) {
if (!qflag)
eprintf("mkdtemp %s:", path);
-   exit(1);
+   return 1;
}
} else {
if ((fd = mkstemp(path)) < 0) {
if (!qflag)
eprintf("mkstemp %s:", path);
-   exit(1);
+   return 1;
}
close(fd);
}
puts(path);
+
return 0;
 }