├── true.c ├── false.c ├── compat.h ├── whoami.1 ├── libutf ├── Makefile ├── isblankrune.c ├── isalnumrune.c ├── isgraphrune.c ├── ispunctrune.c ├── isxdigitrune.c ├── isprintrune.c ├── iscntrlrune.c ├── utftorunestr.c ├── fputrune.c ├── istitlerune.c ├── isspacerune.c ├── fgetrune.c ├── runetype.h ├── runetype.c └── isdigitrune.c ├── yes.1 ├── config.mk ├── setsid.1 ├── libutil ├── putword.c ├── linecmp.c ├── estrtod.c ├── writeall.c ├── concat.c ├── fnck.c ├── human.c ├── eregcomp.c ├── sha224.c ├── sha384.c ├── sha512-224.c ├── sha512-256.c ├── rm.c ├── mkdirp.c ├── fshut.c ├── getlines.c ├── enmasse.c ├── eprintf.c ├── unescape.c ├── parseoffset.c ├── strcasestr.c ├── strsep.c ├── ealloc.c ├── reallocarray.c ├── strlcpy.c ├── strnsubst.c └── strlcat.c ├── false.1 ├── scripts ├── install ├── uninstall ├── mkproto └── mkbox ├── true.1 ├── logname.1 ├── link.1 ├── sync.1 ├── hostname.1 ├── text.h ├── unlink.1 ├── sleep.1 ├── sync.c ├── rev.1 ├── yes.c ├── dirname.1 ├── cron.1 ├── link.c ├── sponge.1 ├── unlink.c ├── dirname.c ├── basename.1 ├── crypt.h ├── cat.1 ├── echo.c ├── sleep.c ├── tty.1 ├── cksum.1 ├── tee.1 ├── tty.c ├── logname.c ├── md5sum.1 ├── sha224.h ├── sha384.h ├── chroot.1 ├── rmdir.1 ├── sha1sum.1 ├── sha224sum.1 ├── sha256sum.1 ├── sha384sum.1 ├── sha512sum.1 ├── echo.1 ├── mkfifo.1 ├── sha512-224.h ├── sha512-256.h ├── sha512-224sum.1 ├── sha512-256sum.1 ├── wc.1 ├── printenv.1 ├── pwd.1 ├── md5.h ├── sha1.h ├── sha256.h ├── sha512.h ├── readlink.1 ├── mkdir.1 ├── mv.1 ├── basename.c ├── mkfifo.c ├── printenv.c ├── nice.1 ├── uuencode.1 ├── hostname.c ├── whoami.c ├── pathchk.1 ├── seq.1 ├── head.1 ├── which.1 ├── rm.1 ├── rm.c ├── comm.1 ├── tftp.1 ├── uname.1 ├── flock.1 ├── nohup.1 ├── mknod.1 ├── fold.1 ├── renice.1 ├── sponge.c ├── setsid.c ├── kill.1 ├── chgrp.1 ├── rmdir.c ├── printf.1 ├── mkdir.c ├── sha1sum.c ├── chroot.c ├── md5sum.c ├── sha224sum.c ├── sha256sum.c ├── sha384sum.c ├── sha512sum.c ├── paste.1 ├── time.1 ├── cmp.1 ├── sha512-224sum.c ├── sha512-256sum.c ├── unexpand.1 ├── env.c ├── uniq.1 ├── cat.c ├── pwd.c ├── fs.h ├── readlink.c ├── env.1 ├── strings.1 ├── chown.1 ├── nohup.c ├── getconf.1 ├── logger.1 ├── tail.1 ├── split.1 ├── nice.c ├── expand.1 ├── uudecode.1 ├── cp.c ├── uname.c ├── cols.1 ├── ln.1 ├── .gitignore ├── mktemp.1 ├── tee.c ├── mv.c ├── touch.1 ├── cp.1 ├── rev.c ├── mknod.c ├── chmod.1 ├── tsort.1 ├── cal.1 ├── arg.h ├── du.1 ├── time.c ├── tr.1 ├── flock.c ├── head.c ├── chgrp.c ├── tar.1 ├── cmp.c ├── cut.1 ├── chmod.c ├── renice.c ├── xinstall.1 ├── date.1 ├── od.1 ├── TODO ├── mktemp.c ├── logger.c ├── strings.c ├── which.c ├── comm.c ├── expr.1 ├── dd.1 ├── date.c ├── sort.1 ├── cols.c ├── wc.c └── chown.c /true.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | int 3 | main(void) 4 | { 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /false.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | int 3 | main(void) 4 | { 5 | return 1; 6 | } 7 | -------------------------------------------------------------------------------- /compat.h: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | 4 | #ifndef HOST_NAME_MAX 5 | #define HOST_NAME_MAX _POSIX_HOST_NAME_MAX 6 | #endif 7 | -------------------------------------------------------------------------------- /whoami.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-12-14 2 | .Dt WHOAMI 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm whoami 6 | .Nd show effective uid 7 | .Sh SYNOPSIS 8 | .Nm 9 | writes the name of the effective uid to stdout. 10 | -------------------------------------------------------------------------------- /libutf/Makefile: -------------------------------------------------------------------------------- 1 | AWK = awk 2 | UNICODE = http://unicode.org/Public/UCD/latest/ucd/UnicodeData.txt 3 | 4 | default: 5 | @echo Downloading and parsing $(UNICODE) 6 | @curl -\# $(UNICODE) | $(AWK) -f mkrunetype.awk 7 | -------------------------------------------------------------------------------- /libutf/isblankrune.c: -------------------------------------------------------------------------------- 1 | /* Automatically generated by mkrunetype.awk */ 2 | #include "../utf.h" 3 | #include "runetype.h" 4 | 5 | int 6 | isblankrune(Rune r) 7 | { 8 | return r == ' ' || r == '\t'; 9 | } 10 | -------------------------------------------------------------------------------- /libutf/isalnumrune.c: -------------------------------------------------------------------------------- 1 | /* Automatically generated by mkrunetype.awk */ 2 | #include "../utf.h" 3 | #include "runetype.h" 4 | 5 | int 6 | isalnumrune(Rune r) 7 | { 8 | return isalpharune(r) || isdigitrune(r); 9 | } 10 | -------------------------------------------------------------------------------- /libutf/isgraphrune.c: -------------------------------------------------------------------------------- 1 | /* Automatically generated by mkrunetype.awk */ 2 | #include "../utf.h" 3 | #include "runetype.h" 4 | 5 | int 6 | isgraphrune(Rune r) 7 | { 8 | return !isspacerune(r) && isprintrune(r); 9 | } 10 | -------------------------------------------------------------------------------- /libutf/ispunctrune.c: -------------------------------------------------------------------------------- 1 | /* Automatically generated by mkrunetype.awk */ 2 | #include "../utf.h" 3 | #include "runetype.h" 4 | 5 | int 6 | ispunctrune(Rune r) 7 | { 8 | return isgraphrune(r) && !isalnumrune(r); 9 | } 10 | -------------------------------------------------------------------------------- /libutf/isxdigitrune.c: -------------------------------------------------------------------------------- 1 | /* Automatically generated by mkrunetype.awk */ 2 | #include "../utf.h" 3 | #include "runetype.h" 4 | 5 | int 6 | isxdigitrune(Rune r) 7 | { 8 | return (r >= '0' && (r - '0') < 10) || (r >= 'a' && (r - 'a') < 6); 9 | } 10 | -------------------------------------------------------------------------------- /yes.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt YES 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm yes 6 | .Nd output string repeatedly 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Ar string 10 | .Sh DESCRIPTION 11 | .Nm 12 | will repeatedly write 'y' or 13 | .Ar string 14 | to stdout. 15 | -------------------------------------------------------------------------------- /config.mk: -------------------------------------------------------------------------------- 1 | # sbase version 2 | VERSION = 0.0 3 | 4 | # paths 5 | PREFIX = /usr/local 6 | MANPREFIX = $(PREFIX)/share/man 7 | 8 | # tools 9 | #CC = 10 | #AR = 11 | RANLIB = ranlib 12 | 13 | # -lrt might be needed on some systems 14 | # CFLAGS = 15 | # LDFLAGS = 16 | -------------------------------------------------------------------------------- /libutf/isprintrune.c: -------------------------------------------------------------------------------- 1 | /* Automatically generated by mkrunetype.awk */ 2 | #include "../utf.h" 3 | #include "runetype.h" 4 | 5 | int 6 | isprintrune(Rune r) 7 | { 8 | return !iscntrlrune(r) && (r != 0x2028) && (r != 0x2029) && 9 | ((r < 0xFFF9) || (r > 0xFFFB)); 10 | } 11 | -------------------------------------------------------------------------------- /setsid.1: -------------------------------------------------------------------------------- 1 | .Dd 2020-07-14 2 | .Dt SETSID 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm setsid 6 | .Nd run a command in a new session 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl f 10 | .Ar cmd 11 | .Op Ar arg ... 12 | .Sh DESCRIPTION 13 | .Nm 14 | runs 15 | .Ar cmd 16 | in a new session. 17 | .Sh SEE ALSO 18 | .Xr setsid 2 19 | -------------------------------------------------------------------------------- /libutil/putword.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | 4 | #include "../util.h" 5 | 6 | void 7 | putword(FILE *fp, const char *s) 8 | { 9 | static int first = 1; 10 | 11 | if (!first) 12 | fputc(' ', fp); 13 | 14 | fputs(s, fp); 15 | first = 0; 16 | } 17 | -------------------------------------------------------------------------------- /false.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt FALSE 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm false 6 | .Nd return failure 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Sh DESCRIPTION 10 | .Nm 11 | returns a status code indicating failure. 12 | .Sh STANDARDS 13 | The 14 | .Nm 15 | utility is compliant with the 16 | .St -p1003.1-2013 17 | specification. 18 | -------------------------------------------------------------------------------- /scripts/install: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | while read type src dst perm 6 | do 7 | case $type in 8 | d) 9 | mkdir -p $src 10 | ;; 11 | c) 12 | cp -f $src $dst 13 | ;; 14 | *) 15 | echo install: wrong entry type >&2 16 | exit 1 17 | ;; 18 | esac 19 | 20 | chmod $perm $dst 21 | done < $1 22 | -------------------------------------------------------------------------------- /true.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt TRUE 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm true 6 | .Nd return success 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Sh DESCRIPTION 10 | .Nm 11 | returns a status code indicating success. 12 | .Sh STANDARDS 13 | The 14 | .Nm 15 | utility is compliant with the 16 | .St -p1003.1-2013 17 | specification. 18 | -------------------------------------------------------------------------------- /logname.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt LOGNAME 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm logname 6 | .Nd show login name 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Sh DESCRIPTION 10 | .Nm 11 | writes the login name of the current user to stdout. 12 | .Sh STANDARDS 13 | The 14 | .Nm 15 | utility is compliant with the 16 | .St -p1003.1-2013 17 | specification. 18 | -------------------------------------------------------------------------------- /link.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt LINK 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm link 6 | .Nd call the link function 7 | .Ar target 8 | .Ar name 9 | .Sh DESCRIPTION 10 | .Nm 11 | creates a hard link 12 | .Ar name 13 | to 14 | .Ar target . 15 | .Sh STANDARDS 16 | The 17 | .Nm 18 | utility is compliant with the 19 | .St -p1003.1-2013 20 | specification. 21 | -------------------------------------------------------------------------------- /sync.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt SYNC 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm sync 6 | .Nd flush disk cache 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Sh DESCRIPTION 10 | .Nm 11 | invokes 12 | .Xr sync 2 13 | to flush all unwritten changes to disk. 14 | This is usually done before shutting down, rebooting or halting. 15 | .Sh SEE ALSO 16 | .Xr fsync 2 , 17 | .Xr sync 2 18 | -------------------------------------------------------------------------------- /hostname.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt HOSTNAME 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm hostname 6 | .Nd set or print host name 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Ar name 10 | .Sh DESCRIPTION 11 | .Nm 12 | sets the current host name to 13 | .Ar name . 14 | If no 15 | .Ar name 16 | is given, the current host name is written to stdout. 17 | .Sh SEE ALSO 18 | .Xr hostname 7 19 | -------------------------------------------------------------------------------- /text.h: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | 3 | struct line { 4 | char *data; 5 | size_t len; 6 | }; 7 | 8 | struct linebuf { 9 | struct line *lines; 10 | size_t nlines; 11 | size_t capacity; 12 | }; 13 | #define EMPTY_LINEBUF {NULL, 0, 0,} 14 | void getlines(FILE *, struct linebuf *); 15 | 16 | int linecmp(struct line *, struct line *); 17 | -------------------------------------------------------------------------------- /unlink.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt UNLINK 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm unlink 6 | .Nd unlink file 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Ar file 10 | .Sh DESCRIPTION 11 | .Nm 12 | calls 13 | .Xr unlink 2 14 | on 15 | .Ar file . 16 | .Sh SEE ALSO 17 | .Xr unlink 2 18 | .Sh STANDARDS 19 | The 20 | .Nm 21 | utility is compliant with the 22 | .St -p1003.1-2013 23 | specification. 24 | -------------------------------------------------------------------------------- /sleep.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt SLEEP 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm sleep 6 | .Nd wait for a number of seconds 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Ar num 10 | .Sh DESCRIPTION 11 | .Nm 12 | waits for 13 | .Ar num 14 | seconds to elapse. 15 | .Sh SEE ALSO 16 | .Xr sleep 3 17 | .Sh STANDARDS 18 | The 19 | .Nm 20 | utility is compliant with the 21 | .St -p1003.1-2013 22 | specification. 23 | -------------------------------------------------------------------------------- /libutil/linecmp.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | 5 | #include "../text.h" 6 | #include "../util.h" 7 | 8 | int 9 | linecmp(struct line *a, struct line *b) 10 | { 11 | int res = 0; 12 | 13 | if (!(res = memcmp(a->data, b->data, MIN(a->len, b->len)))) 14 | res = a->len - b->len; 15 | 16 | return res; 17 | } 18 | -------------------------------------------------------------------------------- /libutil/estrtod.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | 6 | #include "../util.h" 7 | 8 | double 9 | estrtod(const char *s) 10 | { 11 | char *end; 12 | double d; 13 | 14 | d = strtod(s, &end); 15 | if (end == s || *end != '\0') 16 | eprintf("%s: not a real number\n", s); 17 | return d; 18 | } 19 | -------------------------------------------------------------------------------- /sync.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | 4 | #include "util.h" 5 | 6 | static void 7 | usage(void) 8 | { 9 | eprintf("usage: %s\n", argv0); 10 | } 11 | 12 | int 13 | main(int argc, char *argv[]) 14 | { 15 | ARGBEGIN { 16 | default: 17 | usage(); 18 | } ARGEND 19 | 20 | if (argc) 21 | usage(); 22 | sync(); 23 | 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /libutf/iscntrlrune.c: -------------------------------------------------------------------------------- 1 | /* Automatically generated by mkrunetype.awk */ 2 | #include 3 | 4 | #include "../utf.h" 5 | #include "runetype.h" 6 | 7 | static const Rune cntrl2[][2] = { 8 | { 0x0000, 0x001F }, 9 | { 0x007F, 0x009F }, 10 | }; 11 | 12 | int 13 | iscntrlrune(Rune r) 14 | { 15 | if(bsearch(&r, cntrl2, nelem(cntrl2), sizeof *cntrl2, &rune2cmp)) 16 | return 1; 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /rev.1: -------------------------------------------------------------------------------- 1 | .Dd 2016-03-26 2 | .Dt REV 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm rev 6 | .Nd reverse each line 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Ar file ... 10 | .Sh DESCRIPTION 11 | .Nm 12 | reads each 13 | .Ar file 14 | in sequence and writes it to stdout, but with all characters in each 15 | line in reverse order. 16 | If no 17 | .Ar file 18 | is given 19 | .Nm 20 | reads from stdin. 21 | .Sh SEE ALSO 22 | .Xr tac 1 23 | -------------------------------------------------------------------------------- /libutil/writeall.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | 4 | #include "../util.h" 5 | 6 | ssize_t 7 | writeall(int fd, const void *buf, size_t len) 8 | { 9 | const char *p = buf; 10 | ssize_t n; 11 | 12 | while (len) { 13 | n = write(fd, p, len); 14 | if (n <= 0) 15 | return n; 16 | p += n; 17 | len -= n; 18 | } 19 | 20 | return p - (const char *)buf; 21 | } 22 | -------------------------------------------------------------------------------- /yes.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | 4 | #include "util.h" 5 | 6 | static void 7 | usage(void) 8 | { 9 | eprintf("usage: %s [string]\n", argv0); 10 | } 11 | 12 | int 13 | main(int argc, char *argv[]) 14 | { 15 | const char *s; 16 | 17 | ARGBEGIN { 18 | default: 19 | usage(); 20 | } ARGEND 21 | 22 | s = argc ? argv[0] : "y"; 23 | for (;;) 24 | puts(s); 25 | } 26 | -------------------------------------------------------------------------------- /dirname.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt DIRNAME 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm dirname 6 | .Nd strip final path component 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Ar path 10 | .Sh DESCRIPTION 11 | .Nm 12 | writes 13 | .Ar path 14 | with its final path component removed to stdout. 15 | .Sh SEE ALSO 16 | .Xr basename 1 , 17 | .Xr dirname 3 18 | .Sh STANDARDS 19 | The 20 | .Nm 21 | utility is compliant with the 22 | .St -p1003.1-2013 23 | specification. 24 | -------------------------------------------------------------------------------- /cron.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt CRON 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm cron 6 | .Nd clock daemon 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl f Ar file 10 | .Op Fl n 11 | .Sh DESCRIPTION 12 | .Nm 13 | schedules commands to be run at specified dates and times. 14 | .Sh OPTIONS 15 | .Bl -tag -width Ds 16 | .It Fl f Ar file 17 | Use the specified 18 | .Ar file 19 | instead of the default 20 | .Pa /etc/crontab . 21 | .It Fl n 22 | Do not daemonize. 23 | .El 24 | -------------------------------------------------------------------------------- /link.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | 4 | #include "util.h" 5 | 6 | static void 7 | usage(void) 8 | { 9 | eprintf("usage: %s target name\n", argv0); 10 | } 11 | 12 | int 13 | main(int argc, char *argv[]) 14 | { 15 | ARGBEGIN { 16 | default: 17 | usage(); 18 | } ARGEND 19 | 20 | if (argc != 2) 21 | usage(); 22 | 23 | if (link(argv[0], argv[1]) < 0) 24 | eprintf("link:"); 25 | 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /sponge.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt SPONGE 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm sponge 6 | .Nd soak up standard input and write to a file 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Ar file 10 | .Sh DESCRIPTION 11 | .Nm 12 | reads stdin completely, then writes the saved contents to 13 | .Ar file . 14 | This makes it possible to easily create pipes which read from and write to 15 | the same file. 16 | .Pp 17 | If 18 | .Ar file 19 | is a symbolic link, it writes to its destination instead. 20 | -------------------------------------------------------------------------------- /unlink.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | 4 | #include "util.h" 5 | 6 | static void 7 | usage(void) 8 | { 9 | eprintf("usage: %s file\n", argv0); 10 | } 11 | 12 | int 13 | main(int argc, char *argv[]) 14 | { 15 | ARGBEGIN { 16 | default: 17 | usage(); 18 | } ARGEND 19 | 20 | if (argc != 1) 21 | usage(); 22 | 23 | if (unlink(argv[0]) < 0) 24 | eprintf("unlink: '%s':", argv[0]); 25 | 26 | return 0; 27 | } 28 | -------------------------------------------------------------------------------- /dirname.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | 5 | #include "util.h" 6 | 7 | static void 8 | usage(void) 9 | { 10 | eprintf("usage: %s path\n", argv0); 11 | } 12 | 13 | int 14 | main(int argc, char *argv[]) 15 | { 16 | ARGBEGIN { 17 | default: 18 | usage(); 19 | } ARGEND 20 | 21 | if (argc != 1) 22 | usage(); 23 | 24 | puts(dirname(argv[0])); 25 | 26 | return fshut(stdout, ""); 27 | } 28 | -------------------------------------------------------------------------------- /basename.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt BASENAME 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm basename 6 | .Nd strip leading directory components of a path 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Ar path 10 | .Op Ar suffix 11 | .Sh DESCRIPTION 12 | .Nm 13 | writes 14 | .Ar path 15 | without leading directory components and 16 | .Ar suffix 17 | to stdout. 18 | .Sh SEE ALSO 19 | .Xr dirname 1 , 20 | .Xr basename 3 21 | .Sh STANDARDS 22 | The 23 | .Nm 24 | utility is compliant with the 25 | .St -p1003.1-2013 26 | specification. 27 | -------------------------------------------------------------------------------- /crypt.h: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | struct crypt_ops { 3 | void (*init)(void *); 4 | void (*update)(void *, const void *, unsigned long); 5 | void (*sum)(void *, uint8_t *); 6 | void *s; 7 | }; 8 | 9 | int cryptcheck(int, char **, struct crypt_ops *, uint8_t *, size_t); 10 | int cryptmain(int, char **, struct crypt_ops *, uint8_t *, size_t); 11 | int cryptsum(struct crypt_ops *, int, const char *, uint8_t *); 12 | void mdprint(const uint8_t *, const char *, size_t); 13 | -------------------------------------------------------------------------------- /scripts/uninstall: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | set -e 4 | 5 | while read type src dst perm 6 | do 7 | case $type in 8 | d) 9 | echo $type $src $dst $perm 10 | continue 11 | ;; 12 | c) 13 | rm -f $dst 14 | ;; 15 | *) 16 | echo uninstall: wrong entry type >&2 17 | exit 1 18 | ;; 19 | esac 20 | done < $1 | 21 | sort -r | 22 | while read type src dst perm 23 | do 24 | case $type in 25 | d) 26 | if test `ls $dst | wc -l` -eq 0 27 | then 28 | rmdir $dst 29 | fi 30 | ;; 31 | esac 32 | done 33 | -------------------------------------------------------------------------------- /libutil/concat.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | 4 | #include "../util.h" 5 | 6 | int 7 | concat(int f1, const char *s1, int f2, const char *s2) 8 | { 9 | char buf[BUFSIZ]; 10 | ssize_t n; 11 | 12 | while ((n = read(f1, buf, sizeof(buf))) > 0) { 13 | if (writeall(f2, buf, n) < 0) { 14 | weprintf("write %s:", s2); 15 | return -2; 16 | } 17 | } 18 | if (n < 0) { 19 | weprintf("read %s:", s1); 20 | return -1; 21 | } 22 | return 0; 23 | } 24 | -------------------------------------------------------------------------------- /cat.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt CAT 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm cat 6 | .Nd concatenate files 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl u 10 | .Op Ar file ... 11 | .Sh DESCRIPTION 12 | .Nm 13 | reads each 14 | .Ar file 15 | in sequence and writes it to stdout. 16 | If no 17 | .Ar file 18 | is given 19 | .Nm 20 | reads from stdin. 21 | .Sh OPTIONS 22 | .Bl -tag -width Ds 23 | .It Fl u 24 | Unbuffered output. 25 | .El 26 | .Sh STANDARDS 27 | The 28 | .Nm 29 | utility is compliant with the 30 | .St -p1003.1-2013 31 | specification. 32 | -------------------------------------------------------------------------------- /echo.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include "util.h" 5 | 6 | int 7 | main(int argc, char *argv[]) 8 | { 9 | int nflag = 0; 10 | 11 | argv0 = *argv, argv0 ? (argc--, argv++) : (void *)0; 12 | 13 | if (*argv && !strcmp(*argv, "-n")) { 14 | nflag = 1; 15 | argc--, argv++; 16 | } 17 | 18 | for (; *argv; argc--, argv++) 19 | putword(stdout, *argv); 20 | if (!nflag) 21 | putchar('\n'); 22 | 23 | return fshut(stdout, ""); 24 | } 25 | -------------------------------------------------------------------------------- /sleep.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | 4 | #include "util.h" 5 | 6 | static void 7 | usage(void) 8 | { 9 | eprintf("usage: %s num\n", argv0); 10 | } 11 | 12 | int 13 | main(int argc, char *argv[]) 14 | { 15 | unsigned seconds; 16 | 17 | ARGBEGIN { 18 | default: 19 | usage(); 20 | } ARGEND 21 | 22 | if (argc != 1) 23 | usage(); 24 | 25 | seconds = estrtonum(argv[0], 0, UINT_MAX); 26 | while ((seconds = sleep(seconds)) > 0) 27 | ; 28 | 29 | return 0; 30 | } 31 | -------------------------------------------------------------------------------- /tty.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt TTY 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm tty 6 | .Nd print terminal name 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Sh DESCRIPTION 10 | .Nm 11 | writes the name of the terminal open on stdin to stdout. 12 | .Sh EXIT STATUS 13 | .Bl -tag -width Ds 14 | .It 0 15 | stdin is a terminal. 16 | .It 1 17 | stdin is not a terminal. 18 | .It > 1 19 | An error occurred. 20 | .El 21 | .Sh SEE ALSO 22 | .Xr ttyname 3 23 | .Sh STANDARDS 24 | The 25 | .Nm 26 | utility is compliant with the 27 | .St -p1003.1-2013 28 | specification. 29 | -------------------------------------------------------------------------------- /cksum.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt CKSUM 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm cksum 6 | .Nd compute file checksum 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Ar file ... 10 | .Sh DESCRIPTION 11 | .Nm 12 | calculates a cyclic redundancy check (CRC) of 13 | .Ar file 14 | according to 15 | .St -iso8802-3 16 | and writes it, the file size in bytes and path to stdout. 17 | .Pp 18 | If no 19 | .Ar file 20 | is given, 21 | .Nm 22 | reads from stdin. 23 | .Sh STANDARDS 24 | The 25 | .Nm 26 | utility is compliant with the 27 | .St -p1003.1-2013 28 | specification. 29 | -------------------------------------------------------------------------------- /tee.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt TEE 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm tee 6 | .Nd multiply stdin 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl ai 10 | .Op Ar file ... 11 | .Sh DESCRIPTION 12 | .Nm 13 | reads from stdin and writes to stdout and each 14 | .Ar file . 15 | .Sh OPTIONS 16 | .Bl -tag -width Ds 17 | .It Fl a 18 | Append to each 19 | .Ar file 20 | instead of overwriting it. 21 | .It Fl i 22 | Ignore SIGINT, see 23 | .Xr signal 7 . 24 | .El 25 | .Sh STANDARDS 26 | The 27 | .Nm 28 | utility is compliant with the 29 | .St -p1003.1-2013 30 | specification. 31 | -------------------------------------------------------------------------------- /tty.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | 5 | #include "util.h" 6 | 7 | static void 8 | usage(void) 9 | { 10 | enprintf(2, "usage: %s\n", argv0); 11 | } 12 | 13 | int 14 | main(int argc, char *argv[]) 15 | { 16 | char *tty; 17 | 18 | ARGBEGIN { 19 | default: 20 | usage(); 21 | } ARGEND 22 | 23 | if (argc) 24 | usage(); 25 | 26 | tty = ttyname(STDIN_FILENO); 27 | puts(tty ? tty : "not a tty"); 28 | 29 | enfshut(2, stdout, ""); 30 | return !tty; 31 | } 32 | -------------------------------------------------------------------------------- /logname.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | 5 | #include "util.h" 6 | 7 | static void 8 | usage(void) 9 | { 10 | eprintf("usage: %s\n", argv0); 11 | } 12 | 13 | int 14 | main(int argc, char *argv[]) 15 | { 16 | char *login; 17 | 18 | argv0 = *argv, argv0 ? (argc--, argv++) : (void *)0; 19 | 20 | if (argc) 21 | usage(); 22 | 23 | if ((login = getlogin())) 24 | puts(login); 25 | else 26 | eprintf("no login name\n"); 27 | 28 | return fshut(stdout, ""); 29 | } 30 | -------------------------------------------------------------------------------- /libutil/fnck.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | 4 | #include "../util.h" 5 | 6 | void 7 | fnck(const char *a, const char *b, 8 | int (*fn)(const char *, const char *, int), int depth) 9 | { 10 | struct stat sta, stb; 11 | 12 | if (!stat(a, &sta) 13 | && !stat(b, &stb) 14 | && sta.st_dev == stb.st_dev 15 | && sta.st_ino == stb.st_ino) { 16 | weprintf("%s -> %s: same file\n", a, b); 17 | return; 18 | } 19 | 20 | if (fn(a, b, depth) < 0) 21 | eprintf("%s -> %s:", a, b); 22 | } 23 | -------------------------------------------------------------------------------- /libutf/utftorunestr.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include "../utf.h" 3 | 4 | size_t 5 | utftorunestr(const char *str, Rune *r) 6 | { 7 | size_t i; 8 | int n; 9 | 10 | for (i = 0; (n = chartorune(&r[i], str)) && r[i]; i++) 11 | str += n; 12 | 13 | return i; 14 | } 15 | 16 | size_t 17 | utfntorunestr(const char *str, size_t len, Rune *r) 18 | { 19 | size_t i; 20 | int n; 21 | const char *end = str + len; 22 | 23 | for (i = 0; (n = charntorune(&r[i], str, end - str)); i++) 24 | str += n; 25 | 26 | return i; 27 | } 28 | -------------------------------------------------------------------------------- /md5sum.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt MD5SUM 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm md5sum 6 | .Nd compute or check MD5 message digests 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl c 10 | .Op Ar file ... 11 | .Sh DESCRIPTION 12 | .Nm 13 | writes MD5 (128-bit) checksums of each 14 | .Ar file 15 | to stdout. 16 | If no 17 | .Ar file 18 | is given 19 | .Nm 20 | reads from stdin. 21 | .Sh OPTIONS 22 | .Bl -tag -width Ds 23 | .It Fl c 24 | Read list of MD5 checksums from each 25 | .Ar file 26 | and check them. 27 | If no 28 | .Ar file 29 | is given 30 | .Nm 31 | reads from stdin. 32 | .El 33 | -------------------------------------------------------------------------------- /sha224.h: -------------------------------------------------------------------------------- 1 | /* public domain sha224 implementation based on fips180-3 */ 2 | 3 | #include "sha256.h" 4 | 5 | #define sha224 sha256 /*struct*/ 6 | 7 | enum { SHA224_DIGEST_LENGTH = 28 }; 8 | 9 | /* reset state */ 10 | void sha224_init(void *ctx); 11 | /* process message */ 12 | #define sha224_update sha256_update 13 | /* get message digest */ 14 | /* state is ruined after sum, keep a copy if multiple sum is needed */ 15 | /* part of the message might be left in s, zero it if secrecy is needed */ 16 | void sha224_sum(void *ctx, uint8_t md[SHA224_DIGEST_LENGTH]); 17 | -------------------------------------------------------------------------------- /sha384.h: -------------------------------------------------------------------------------- 1 | /* public domain sha512 implementation based on fips180-3 */ 2 | 3 | #include "sha512.h" 4 | 5 | #define sha384 sha512 /*struct*/ 6 | 7 | enum { SHA384_DIGEST_LENGTH = 48 }; 8 | 9 | /* reset state */ 10 | void sha384_init(void *ctx); 11 | /* process message */ 12 | #define sha384_update sha512_update 13 | /* get message digest */ 14 | /* state is ruined after sum, keep a copy if multiple sum is needed */ 15 | /* part of the message might be left in s, zero it if secrecy is needed */ 16 | void sha384_sum(void *ctx, uint8_t md[SHA384_DIGEST_LENGTH]); 17 | -------------------------------------------------------------------------------- /chroot.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt CHROOT 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm chroot 6 | .Nd run a command or shell with a different root directory 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Ar dir 10 | .Op Ar cmd Op Ar arg ... 11 | .Sh DESCRIPTION 12 | .Nm 13 | runs 14 | .Ar cmd 15 | after changing the root directory to 16 | .Ar dir 17 | with the 18 | .Xr chroot 2 19 | system call and after changing the working directory to the new root. 20 | If 21 | .Ar cmd 22 | is not specified, an interactive shell is started in the new root. 23 | .Sh SEE ALSO 24 | .Xr chdir 2 , 25 | .Xr chroot 2 26 | -------------------------------------------------------------------------------- /rmdir.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt RMDIR 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm rmdir 6 | .Nd remove empty directories 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl p 10 | .Ar dir ... 11 | .Sh DESCRIPTION 12 | .Nm 13 | removes each empty 14 | .Ar dir . 15 | .Sh OPTIONS 16 | .Bl -tag -width Ds 17 | .It Fl p 18 | Remove 19 | .Ar dir 20 | and its parents in the pathname 21 | .Ar dir . 22 | .El 23 | .Sh SEE ALSO 24 | .Xr rm 1 , 25 | .Xr unlink 1 , 26 | .Xr rmdir 2 , 27 | .Xr unlink 2 28 | .Sh STANDARDS 29 | The 30 | .Nm 31 | utility is compliant with the 32 | .St -p1003.1-2013 33 | specification. 34 | -------------------------------------------------------------------------------- /sha1sum.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt SHA1SUM 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm sha1sum 6 | .Nd compute or check SHA-1 message digests 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl c 10 | .Op Ar file ... 11 | .Sh DESCRIPTION 12 | .Nm 13 | writes SHA-1 (160-bit) checksums of each 14 | .Ar file 15 | to stdout. 16 | If no 17 | .Ar file 18 | is given 19 | .Nm 20 | reads from stdin. 21 | .Sh OPTIONS 22 | .Bl -tag -width Ds 23 | .It Fl c 24 | Read list of SHA-1 checksums from each 25 | .Ar file 26 | and check them. 27 | If no 28 | .Ar file 29 | is given 30 | .Nm 31 | reads from stdin. 32 | .El 33 | -------------------------------------------------------------------------------- /sha224sum.1: -------------------------------------------------------------------------------- 1 | .Dd 2016-02-24 2 | .Dt SHA224SUM 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm sha224sum 6 | .Nd compute or check SHA-224 message digests 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl c 10 | .Op Ar file ... 11 | .Sh DESCRIPTION 12 | .Nm 13 | writes SHA-224 (224-bit) checksums of each 14 | .Ar file 15 | to stdout. 16 | If no 17 | .Ar file 18 | is given 19 | .Nm 20 | reads from stdin. 21 | .Sh OPTIONS 22 | .Bl -tag -width Ds 23 | .It Fl c 24 | Read list of SHA-224 checksums from each 25 | .Ar file 26 | and check them. 27 | If no 28 | .Ar file 29 | is given 30 | .Nm 31 | reads from stdin. 32 | .El 33 | -------------------------------------------------------------------------------- /sha256sum.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt SHA256SUM 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm sha256sum 6 | .Nd compute or check SHA-256 message digests 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl c 10 | .Op Ar file ... 11 | .Sh DESCRIPTION 12 | .Nm 13 | writes SHA-256 (256-bit) checksums of each 14 | .Ar file 15 | to stdout. 16 | If no 17 | .Ar file 18 | is given 19 | .Nm 20 | reads from stdin. 21 | .Sh OPTIONS 22 | .Bl -tag -width Ds 23 | .It Fl c 24 | Read list of SHA-256 checksums from each 25 | .Ar file 26 | and check them. 27 | If no 28 | .Ar file 29 | is given 30 | .Nm 31 | reads from stdin. 32 | .El 33 | -------------------------------------------------------------------------------- /sha384sum.1: -------------------------------------------------------------------------------- 1 | .Dd 2016-02-24 2 | .Dt SHA384SUM 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm sha384sum 6 | .Nd compute or check SHA-384 message digests 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl c 10 | .Op Ar file ... 11 | .Sh DESCRIPTION 12 | .Nm 13 | writes SHA-384 (384-bit) checksums of each 14 | .Ar file 15 | to stdout. 16 | If no 17 | .Ar file 18 | is given 19 | .Nm 20 | reads from stdin. 21 | .Sh OPTIONS 22 | .Bl -tag -width Ds 23 | .It Fl c 24 | Read list of SHA-384 checksums from each 25 | .Ar file 26 | and check them. 27 | If no 28 | .Ar file 29 | is given 30 | .Nm 31 | reads from stdin. 32 | .El 33 | -------------------------------------------------------------------------------- /sha512sum.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt SHA512SUM 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm sha512sum 6 | .Nd compute or check SHA-512 message digests 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl c 10 | .Op Ar file ... 11 | .Sh DESCRIPTION 12 | .Nm 13 | writes SHA-512 (512-bit) checksums of each 14 | .Ar file 15 | to stdout. 16 | If no 17 | .Ar file 18 | is given 19 | .Nm 20 | reads from stdin. 21 | .Sh OPTIONS 22 | .Bl -tag -width Ds 23 | .It Fl c 24 | Read list of SHA-512 checksums from each 25 | .Ar file 26 | and check them. 27 | If no 28 | .Ar file 29 | is given 30 | .Nm 31 | reads from stdin. 32 | .El 33 | -------------------------------------------------------------------------------- /echo.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt ECHO 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm echo 6 | .Nd print arguments 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl n 10 | .Op Ar string ... 11 | .Sh DESCRIPTION 12 | .Nm 13 | writes each 14 | .Ar string 15 | to stdout, separated by spaces and terminated by 16 | a newline. 17 | .Sh OPTIONS 18 | .Bl -tag -width Ds 19 | .It Fl n 20 | Do not print the terminating newline. 21 | .El 22 | .Sh STANDARDS 23 | The 24 | .Nm 25 | utility is compliant with the 26 | .St -p1003.1-2013 27 | specification. 28 | .Pp 29 | The 30 | .Op Fl n 31 | flag is an extension to that specification. 32 | -------------------------------------------------------------------------------- /mkfifo.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt MKFIFO 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm mkfifo 6 | .Nd create named pipes 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl m Ar mode 10 | .Ar name ... 11 | .Sh DESCRIPTION 12 | .Nm 13 | creates a named pipe for each 14 | .Ar name 15 | if it does not already exist. 16 | .Sh OPTIONS 17 | .Bl -tag -width Ds 18 | .It Fl m 19 | Set the file 20 | .Ar mode 21 | of newly created named pipes. 22 | See 23 | .Xr chmod 1 . 24 | .El 25 | .Sh SEE ALSO 26 | .Xr mkfifo 3 27 | .Sh STANDARDS 28 | The 29 | .Nm 30 | utility is compliant with the 31 | .St -p1003.1-2013 32 | specification. 33 | -------------------------------------------------------------------------------- /libutil/human.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | 6 | #include "../util.h" 7 | 8 | char * 9 | humansize(off_t n) 10 | { 11 | static char buf[16]; 12 | const char postfixes[] = "BKMGTPE"; 13 | double size; 14 | int i; 15 | 16 | for (size = n, i = 0; size >= 1024 && i < strlen(postfixes); i++) 17 | size /= 1024; 18 | 19 | if (!i) 20 | snprintf(buf, sizeof(buf), "%ju", (uintmax_t)n); 21 | else 22 | snprintf(buf, sizeof(buf), "%.1f%c", size, postfixes[i]); 23 | 24 | return buf; 25 | } 26 | -------------------------------------------------------------------------------- /sha512-224.h: -------------------------------------------------------------------------------- 1 | /* public domain sha512/224 implementation based on fips180-3 */ 2 | 3 | #include "sha512.h" 4 | 5 | #define sha512_224 sha512 /*struct*/ 6 | 7 | enum { SHA512_224_DIGEST_LENGTH = 28 }; 8 | 9 | /* reset state */ 10 | void sha512_224_init(void *ctx); 11 | /* process message */ 12 | #define sha512_224_update sha512_update 13 | /* get message digest */ 14 | /* state is ruined after sum, keep a copy if multiple sum is needed */ 15 | /* part of the message might be left in s, zero it if secrecy is needed */ 16 | void sha512_224_sum(void *ctx, uint8_t md[SHA512_224_DIGEST_LENGTH]); 17 | -------------------------------------------------------------------------------- /sha512-256.h: -------------------------------------------------------------------------------- 1 | /* public domain sha512/256 implementation based on fips180-3 */ 2 | 3 | #include "sha512.h" 4 | 5 | #define sha512_256 sha512 /*struct*/ 6 | 7 | enum { SHA512_256_DIGEST_LENGTH = 32 }; 8 | 9 | /* reset state */ 10 | void sha512_256_init(void *ctx); 11 | /* process message */ 12 | #define sha512_256_update sha512_update 13 | /* get message digest */ 14 | /* state is ruined after sum, keep a copy if multiple sum is needed */ 15 | /* part of the message might be left in s, zero it if secrecy is needed */ 16 | void sha512_256_sum(void *ctx, uint8_t md[SHA512_256_DIGEST_LENGTH]); 17 | -------------------------------------------------------------------------------- /libutf/fputrune.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "../utf.h" 8 | 9 | int 10 | fputrune(const Rune *r, FILE *fp) 11 | { 12 | char buf[UTFmax]; 13 | 14 | return fwrite(buf, runetochar(buf, r), 1, fp); 15 | } 16 | 17 | int 18 | efputrune(const Rune *r, FILE *fp, const char *file) 19 | { 20 | int ret; 21 | 22 | if ((ret = fputrune(r, fp)) < 0) { 23 | fprintf(stderr, "fputrune %s: %s\n", file, strerror(errno)); 24 | exit(1); 25 | } 26 | return ret; 27 | } 28 | -------------------------------------------------------------------------------- /libutil/eregcomp.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | 6 | #include "../util.h" 7 | 8 | int 9 | enregcomp(int status, regex_t *preg, const char *regex, int cflags) 10 | { 11 | char errbuf[BUFSIZ] = ""; 12 | int r; 13 | 14 | if ((r = regcomp(preg, regex, cflags)) == 0) 15 | return r; 16 | 17 | regerror(r, preg, errbuf, sizeof(errbuf)); 18 | enprintf(status, "invalid regex: %s\n", errbuf); 19 | 20 | return r; 21 | } 22 | 23 | int 24 | eregcomp(regex_t *preg, const char *regex, int cflags) 25 | { 26 | return enregcomp(1, preg, regex, cflags); 27 | } 28 | -------------------------------------------------------------------------------- /sha512-224sum.1: -------------------------------------------------------------------------------- 1 | .Dd 2016-02-24 2 | .Dt SHA512-224SUM 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm sha512-224sum 6 | .Nd compute or check SHA-512/224 message digests 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl c 10 | .Op Ar file ... 11 | .Sh DESCRIPTION 12 | .Nm 13 | writes SHA-512/224 (224-bit) checksums of each 14 | .Ar file 15 | to stdout. 16 | If no 17 | .Ar file 18 | is given 19 | .Nm 20 | reads from stdin. 21 | .Sh OPTIONS 22 | .Bl -tag -width Ds 23 | .It Fl c 24 | Read list of SHA-512/224 checksums from each 25 | .Ar file 26 | and check them. 27 | If no 28 | .Ar file 29 | is given 30 | .Nm 31 | reads from stdin. 32 | .El 33 | -------------------------------------------------------------------------------- /sha512-256sum.1: -------------------------------------------------------------------------------- 1 | .Dd 2016-02-24 2 | .Dt SHA512-256SUM 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm sha512-256sum 6 | .Nd compute or check SHA-512/256 message digests 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl c 10 | .Op Ar file ... 11 | .Sh DESCRIPTION 12 | .Nm 13 | writes SHA-512/256 (256-bit) checksums of each 14 | .Ar file 15 | to stdout. 16 | If no 17 | .Ar file 18 | is given 19 | .Nm 20 | reads from stdin. 21 | .Sh OPTIONS 22 | .Bl -tag -width Ds 23 | .It Fl c 24 | Read list of SHA-512/256 checksums from each 25 | .Ar file 26 | and check them. 27 | If no 28 | .Ar file 29 | is given 30 | .Nm 31 | reads from stdin. 32 | .El 33 | -------------------------------------------------------------------------------- /wc.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt WC 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm wc 6 | .Nd word count 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl c | Fl m 10 | .Op Fl lw 11 | .Op Ar file ... 12 | .Sh DESCRIPTION 13 | .Nm 14 | writes the number of lines, words and bytes in each 15 | .Ar file 16 | to stdout. 17 | If no 18 | .Ar file 19 | is given 20 | .Nm 21 | reads from stdin. 22 | .Sh OPTIONS 23 | .Bl -tag -width Ds 24 | .It Fl c | Fl l | Fl m | Fl w 25 | Print the number of bytes | lines | characters | words. 26 | .El 27 | .Sh STANDARDS 28 | The 29 | .Nm 30 | utility is compliant with the 31 | .St -p1003.1-2013 32 | specification. 33 | -------------------------------------------------------------------------------- /scripts/mkproto: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | usage() 4 | { 5 | echo mkproto: prefix manprefix proto>&2 6 | exit 1 7 | } 8 | 9 | prefix=${1?$(usage)} 10 | manprefix=${2?$(usage)} 11 | proto=${3?$(usage)} 12 | 13 | trap "rm -f scripts/proto" EXIT INT QUIT TERM 14 | 15 | (set -e 16 | echo d $prefix/bin $prefix/bin 755 17 | find . ! -name . -prune -type f \( -perm -u+x -o -perm -g+x -o -perm o+x \) | 18 | sed "s@.*@c & $prefix/bin/& 755@" 19 | 20 | echo d $manprefix/man1 $manprefix/man1 755 21 | find . ! -name . -prune -name '*.1' | 22 | sed "s@.*@c & $manprefix/man1/& 644@") > $proto 23 | 24 | trap "" EXIT INT QUIT TERM 25 | -------------------------------------------------------------------------------- /libutil/sha224.c: -------------------------------------------------------------------------------- 1 | /* public domain sha224 implementation based on fips180-3 */ 2 | #include 3 | #include "../sha224.h" 4 | 5 | extern void sha256_sum_n(void *, uint8_t *, int n); 6 | 7 | void 8 | sha224_init(void *ctx) 9 | { 10 | struct sha224 *s = ctx; 11 | s->len = 0; 12 | s->h[0] = 0xc1059ed8; 13 | s->h[1] = 0x367cd507; 14 | s->h[2] = 0x3070dd17; 15 | s->h[3] = 0xf70e5939; 16 | s->h[4] = 0xffc00b31; 17 | s->h[5] = 0x68581511; 18 | s->h[6] = 0x64f98fa7; 19 | s->h[7] = 0xbefa4fa4; 20 | } 21 | 22 | void 23 | sha224_sum(void *ctx, uint8_t md[SHA224_DIGEST_LENGTH]) 24 | { 25 | sha256_sum_n(ctx, md, 8); 26 | } 27 | -------------------------------------------------------------------------------- /printenv.1: -------------------------------------------------------------------------------- 1 | .Dd 2016-03-30 2 | .Dt PRINTENV 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm printenv 6 | .Nd print the environment or values of variables 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Ar var ... 10 | .Sh DESCRIPTION 11 | .Nm 12 | prints the entire environment as key=value pairs if no 13 | .Ar var 14 | is given. 15 | Otherwise, 16 | .Nm 17 | prints only the value of each 18 | .Ar var 19 | one per line in the order specified. 20 | .Sh EXIT STATUS 21 | .Bl -tag -width Ds 22 | .It 0 23 | Successful completion. 24 | .It 1 25 | One or more queried variables were not found. 26 | .It > 1 27 | An error occurred. 28 | .El 29 | .Sh SEE ALSO 30 | .Xr env 1 31 | -------------------------------------------------------------------------------- /libutf/istitlerune.c: -------------------------------------------------------------------------------- 1 | /* Automatically generated by mkrunetype.awk */ 2 | #include 3 | 4 | #include "../utf.h" 5 | #include "runetype.h" 6 | 7 | static const Rune title2[][2] = { 8 | { 0x1F88, 0x1F8F }, 9 | { 0x1F98, 0x1F9F }, 10 | { 0x1FA8, 0x1FAF }, 11 | }; 12 | 13 | static const Rune title1[] = { 14 | 0x01C5, 15 | 0x01C8, 16 | 0x01CB, 17 | 0x01F2, 18 | 0x1FBC, 19 | 0x1FCC, 20 | 0x1FFC, 21 | }; 22 | 23 | int 24 | istitlerune(Rune r) 25 | { 26 | if(bsearch(&r, title2, nelem(title2), sizeof *title2, &rune2cmp)) 27 | return 1; 28 | if(bsearch(&r, title1, nelem(title1), sizeof *title1, &rune1cmp)) 29 | return 1; 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /libutf/isspacerune.c: -------------------------------------------------------------------------------- 1 | /* Automatically generated by mkrunetype.awk */ 2 | #include 3 | 4 | #include "../utf.h" 5 | #include "runetype.h" 6 | 7 | static const Rune space2[][2] = { 8 | { 0x0009, 0x000D }, 9 | { 0x001C, 0x0020 }, 10 | { 0x2000, 0x200A }, 11 | { 0x2028, 0x2029 }, 12 | }; 13 | 14 | static const Rune space1[] = { 15 | 0x0085, 16 | 0x00A0, 17 | 0x1680, 18 | 0x202F, 19 | 0x205F, 20 | 0x3000, 21 | }; 22 | 23 | int 24 | isspacerune(Rune r) 25 | { 26 | if(bsearch(&r, space2, nelem(space2), sizeof *space2, &rune2cmp)) 27 | return 1; 28 | if(bsearch(&r, space1, nelem(space1), sizeof *space1, &rune1cmp)) 29 | return 1; 30 | return 0; 31 | } 32 | -------------------------------------------------------------------------------- /pwd.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt PWD 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm pwd 6 | .Nd print working directory 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl L | Fl P 10 | .Sh DESCRIPTION 11 | .Nm 12 | prints the path of the current working directory. 13 | .Sh OPTIONS 14 | .Bl -tag -width Ds 15 | .It Fl L 16 | Logical path, uses $PWD. 17 | This is the default. 18 | .It Fl P 19 | Physical path, avoids all symlinks. 20 | .El 21 | .Sh ENVIRONMENT 22 | .Bl -tag -width PWD 23 | .It Ev PWD 24 | The logical path to the current working directory. 25 | .El 26 | .Sh SEE ALSO 27 | .Xr getcwd 3 28 | .Sh STANDARDS 29 | The 30 | .Nm 31 | utility is compliant with the 32 | .St -p1003.1-2013 33 | specification. 34 | -------------------------------------------------------------------------------- /md5.h: -------------------------------------------------------------------------------- 1 | /* public domain md5 implementation based on rfc1321 and libtomcrypt */ 2 | 3 | struct md5 { 4 | uint64_t len; /* processed message length */ 5 | uint32_t h[4]; /* hash state */ 6 | uint8_t buf[64]; /* message block buffer */ 7 | }; 8 | 9 | enum { MD5_DIGEST_LENGTH = 16 }; 10 | 11 | /* reset state */ 12 | void md5_init(void *ctx); 13 | /* process message */ 14 | void md5_update(void *ctx, const void *m, unsigned long len); 15 | /* get message digest */ 16 | /* state is ruined after sum, keep a copy if multiple sum is needed */ 17 | /* part of the message might be left in s, zero it if secrecy is needed */ 18 | void md5_sum(void *ctx, uint8_t md[MD5_DIGEST_LENGTH]); 19 | -------------------------------------------------------------------------------- /sha1.h: -------------------------------------------------------------------------------- 1 | /* public domain sha1 implementation based on rfc3174 and libtomcrypt */ 2 | 3 | struct sha1 { 4 | uint64_t len; /* processed message length */ 5 | uint32_t h[5]; /* hash state */ 6 | uint8_t buf[64]; /* message block buffer */ 7 | }; 8 | 9 | enum { SHA1_DIGEST_LENGTH = 20 }; 10 | 11 | /* reset state */ 12 | void sha1_init(void *ctx); 13 | /* process message */ 14 | void sha1_update(void *ctx, const void *m, unsigned long len); 15 | /* get message digest */ 16 | /* state is ruined after sum, keep a copy if multiple sum is needed */ 17 | /* part of the message might be left in s, zero it if secrecy is needed */ 18 | void sha1_sum(void *ctx, uint8_t md[SHA1_DIGEST_LENGTH]); 19 | -------------------------------------------------------------------------------- /sha256.h: -------------------------------------------------------------------------------- 1 | /* public domain sha256 implementation based on fips180-3 */ 2 | 3 | struct sha256 { 4 | uint64_t len; /* processed message length */ 5 | uint32_t h[8]; /* hash state */ 6 | uint8_t buf[64]; /* message block buffer */ 7 | }; 8 | 9 | enum { SHA256_DIGEST_LENGTH = 32 }; 10 | 11 | /* reset state */ 12 | void sha256_init(void *ctx); 13 | /* process message */ 14 | void sha256_update(void *ctx, const void *m, unsigned long len); 15 | /* get message digest */ 16 | /* state is ruined after sum, keep a copy if multiple sum is needed */ 17 | /* part of the message might be left in s, zero it if secrecy is needed */ 18 | void sha256_sum(void *ctx, uint8_t md[SHA256_DIGEST_LENGTH]); 19 | -------------------------------------------------------------------------------- /sha512.h: -------------------------------------------------------------------------------- 1 | /* public domain sha512 implementation based on fips180-3 */ 2 | 3 | struct sha512 { 4 | uint64_t len; /* processed message length */ 5 | uint64_t h[8]; /* hash state */ 6 | uint8_t buf[128]; /* message block buffer */ 7 | }; 8 | 9 | enum { SHA512_DIGEST_LENGTH = 64 }; 10 | 11 | /* reset state */ 12 | void sha512_init(void *ctx); 13 | /* process message */ 14 | void sha512_update(void *ctx, const void *m, unsigned long len); 15 | /* get message digest */ 16 | /* state is ruined after sum, keep a copy if multiple sum is needed */ 17 | /* part of the message might be left in s, zero it if secrecy is needed */ 18 | void sha512_sum(void *ctx, uint8_t md[SHA512_DIGEST_LENGTH]); 19 | -------------------------------------------------------------------------------- /readlink.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-11-16 2 | .Dt READLINK 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm readlink 6 | .Nd print symbolic link target or canonical file name 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl f 10 | .Op Fl n 11 | .Ar path 12 | .Sh DESCRIPTION 13 | .Nm 14 | writes the target of 15 | .Ar path , 16 | if it is a symbolic link, to stdout. 17 | If not, 18 | .Nm 19 | exits with a non-zero return value. 20 | .Sh OPTIONS 21 | .Bl -tag -width Ds 22 | .It Fl f 23 | Canonicalize 24 | .Ar path , 25 | which needn't be a symlink, 26 | by recursively following every symlink in its path components. 27 | .It Fl n 28 | Do not print the terminating newline. 29 | .El 30 | .Sh SEE ALSO 31 | .Xr readlink 2 , 32 | .Xr realpath 3 33 | -------------------------------------------------------------------------------- /libutil/sha384.c: -------------------------------------------------------------------------------- 1 | /* public domain sha384 implementation based on fips180-3 */ 2 | #include 3 | #include "../sha384.h" 4 | 5 | extern void sha512_sum_n(void *, uint8_t *, int n); 6 | 7 | void 8 | sha384_init(void *ctx) 9 | { 10 | struct sha384 *s = ctx; 11 | s->len = 0; 12 | s->h[0] = 0xcbbb9d5dc1059ed8ULL; 13 | s->h[1] = 0x629a292a367cd507ULL; 14 | s->h[2] = 0x9159015a3070dd17ULL; 15 | s->h[3] = 0x152fecd8f70e5939ULL; 16 | s->h[4] = 0x67332667ffc00b31ULL; 17 | s->h[5] = 0x8eb44a8768581511ULL; 18 | s->h[6] = 0xdb0c2e0d64f98fa7ULL; 19 | s->h[7] = 0x47b5481dbefa4fa4ULL; 20 | } 21 | 22 | void 23 | sha384_sum(void *ctx, uint8_t md[SHA384_DIGEST_LENGTH]) 24 | { 25 | sha512_sum_n(ctx, md, 6); 26 | } 27 | -------------------------------------------------------------------------------- /mkdir.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt MKDIR 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm mkdir 6 | .Nd create directories 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl p 10 | .Op Fl m Ar mode 11 | .Ar name ... 12 | .Sh DESCRIPTION 13 | .Nm 14 | creates a directory for each 15 | .Ar name 16 | if it does not already exist. 17 | .Sh OPTIONS 18 | .Bl -tag -width Ds 19 | .It Fl m 20 | Set the file 21 | .Ar mode 22 | of newly created directories. 23 | See 24 | .Xr chmod 1 . 25 | .It Fl p 26 | Also create necessary parent directories and 27 | do not fail if 28 | .Ar name 29 | already exists. 30 | .El 31 | .Sh SEE ALSO 32 | .Xr mkdir 2 33 | .Sh STANDARDS 34 | The 35 | .Nm 36 | utility is compliant with the 37 | .St -p1003.1-2013 38 | specification. 39 | -------------------------------------------------------------------------------- /mv.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt MV 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm mv 6 | .Nd move files and directories 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl f 10 | .Ar source ... 11 | .Ar dest 12 | .Sh DESCRIPTION 13 | .Nm 14 | moves each 15 | .Ar source 16 | to 17 | .Ar dest . 18 | If only one 19 | .Ar source 20 | is given and 21 | .Ar dest 22 | is not a directory, 23 | .Nm 24 | overwrites the latter with the former. 25 | .Sh OPTIONS 26 | .Bl -tag -width Ds 27 | .It Fl f 28 | Do not prompt before overwriting. 29 | .Ar dest . 30 | Prompting has not been implemented yet. 31 | .El 32 | .Sh STANDARDS 33 | The 34 | .Nm 35 | utility is compliant with the 36 | .St -p1003.1-2013 37 | specification except from the 38 | .Op Fl i 39 | flag. 40 | -------------------------------------------------------------------------------- /basename.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | 6 | #include "util.h" 7 | 8 | static void 9 | usage(void) 10 | { 11 | eprintf("usage: %s path [suffix]\n", argv0); 12 | } 13 | 14 | int 15 | main(int argc, char *argv[]) 16 | { 17 | ssize_t off; 18 | char *p; 19 | 20 | ARGBEGIN { 21 | default: 22 | usage(); 23 | } ARGEND 24 | 25 | if (argc != 1 && argc != 2) 26 | usage(); 27 | 28 | p = basename(argv[0]); 29 | if (argc == 2) { 30 | off = strlen(p) - strlen(argv[1]); 31 | if (off > 0 && !strcmp(p + off, argv[1])) 32 | p[off] = '\0'; 33 | } 34 | puts(p); 35 | 36 | return fshut(stdout, ""); 37 | } 38 | -------------------------------------------------------------------------------- /mkfifo.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | 4 | #include 5 | 6 | #include "util.h" 7 | 8 | static void 9 | usage(void) 10 | { 11 | eprintf("usage: %s [-m mode] name ...\n", argv0); 12 | } 13 | 14 | int 15 | main(int argc, char *argv[]) 16 | { 17 | mode_t mode = 0666; 18 | int ret = 0; 19 | 20 | ARGBEGIN { 21 | case 'm': 22 | mode = parsemode(EARGF(usage()), mode, umask(0)); 23 | break; 24 | default: 25 | usage(); 26 | } ARGEND 27 | 28 | if (!argc) 29 | usage(); 30 | 31 | for (; *argv; argc--, argv++) { 32 | if (mkfifo(*argv, mode) < 0) { 33 | weprintf("mkfifo %s:", *argv); 34 | ret = 1; 35 | } 36 | } 37 | 38 | return ret; 39 | } 40 | -------------------------------------------------------------------------------- /printenv.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | 5 | #include "util.h" 6 | 7 | extern char **environ; 8 | 9 | static void 10 | usage(void) 11 | { 12 | eprintf("usage: %s [var ...]\n", argv0); 13 | } 14 | 15 | int 16 | main(int argc, char *argv[]) 17 | { 18 | char *var; 19 | int ret = 0; 20 | 21 | ARGBEGIN { 22 | default: 23 | usage(); 24 | } ARGEND 25 | 26 | if (!argc) { 27 | for (; *environ; environ++) 28 | puts(*environ); 29 | } else { 30 | for (; *argv; argc--, argv++) { 31 | if ((var = getenv(*argv))) 32 | puts(var); 33 | else 34 | ret = 1; 35 | } 36 | } 37 | 38 | return fshut(stdout, "") ? 2 : ret; 39 | } 40 | -------------------------------------------------------------------------------- /libutil/sha512-224.c: -------------------------------------------------------------------------------- 1 | /* public domain sha512/224 implementation based on fips180-3 */ 2 | #include 3 | #include "../sha512-224.h" 4 | 5 | extern void sha512_sum_n(void *, uint8_t *, int n); 6 | 7 | void 8 | sha512_224_init(void *ctx) 9 | { 10 | struct sha512_224 *s = ctx; 11 | s->len = 0; 12 | s->h[0] = 0x8c3d37c819544da2ULL; 13 | s->h[1] = 0x73e1996689dcd4d6ULL; 14 | s->h[2] = 0x1dfab7ae32ff9c82ULL; 15 | s->h[3] = 0x679dd514582f9fcfULL; 16 | s->h[4] = 0x0f6d2b697bd44da8ULL; 17 | s->h[5] = 0x77e36f7304c48942ULL; 18 | s->h[6] = 0x3f9d85a86a1d36c8ULL; 19 | s->h[7] = 0x1112e6ad91d692a1ULL; 20 | } 21 | 22 | void 23 | sha512_224_sum(void *ctx, uint8_t md[SHA512_224_DIGEST_LENGTH]) 24 | { 25 | sha512_sum_n(ctx, md, 4); 26 | } 27 | -------------------------------------------------------------------------------- /libutil/sha512-256.c: -------------------------------------------------------------------------------- 1 | /* public domain sha512/256 implementation based on fips180-3 */ 2 | #include 3 | #include "../sha512-256.h" 4 | 5 | extern void sha512_sum_n(void *, uint8_t *, int n); 6 | 7 | void 8 | sha512_256_init(void *ctx) 9 | { 10 | struct sha512_256 *s = ctx; 11 | s->len = 0; 12 | s->h[0] = 0x22312194fc2bf72cULL; 13 | s->h[1] = 0x9f555fa3c84c64c2ULL; 14 | s->h[2] = 0x2393b86b6f53b151ULL; 15 | s->h[3] = 0x963877195940eabdULL; 16 | s->h[4] = 0x96283ee2a88effe3ULL; 17 | s->h[5] = 0xbe5e1e2553863992ULL; 18 | s->h[6] = 0x2b0199fc2c85b8aaULL; 19 | s->h[7] = 0x0eb72ddc81c52ca2ULL; 20 | } 21 | 22 | void 23 | sha512_256_sum(void *ctx, uint8_t md[SHA512_256_DIGEST_LENGTH]) 24 | { 25 | sha512_sum_n(ctx, md, 4); 26 | } 27 | -------------------------------------------------------------------------------- /nice.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt NICE 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm nice 6 | .Nd run command with altered niceness 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl n Ar inc 10 | .Ar cmd 11 | .Op Ar arg ... 12 | .Sh DESCRIPTION 13 | .Nm 14 | runs 15 | .Ar cmd 16 | with the current niceness plus 17 | .Ar inc . 18 | A negative niceness is reserved to the superuser. 19 | .Sh OPTIONS 20 | .Bl -tag -width Ds 21 | .It Fl n Ar inc 22 | Change niceness by 23 | .Ar inc , 24 | ranging from 25 | .Sy -20 26 | (highest priority) 27 | to 28 | .Sy +20 29 | (lowest priority). 30 | Default is 10. 31 | .El 32 | .Sh SEE ALSO 33 | .Xr nice 2 , 34 | .Xr renice 2 35 | .Sh STANDARDS 36 | The 37 | .Nm 38 | utility is compliant with the 39 | .St -p1003.1-2013 40 | specification. 41 | -------------------------------------------------------------------------------- /uuencode.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt UUENCODE 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm uuencode 6 | .Nd encode a binary file 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl m 10 | .Op Ar file 11 | .Ar name 12 | .Sh DESCRIPTION 13 | .Nm 14 | reads 15 | .Ar file 16 | and writes an encoded version to stdout. 17 | The encoding uses only printing ASCII characters and 18 | includes the mode of the file and the operand 19 | .Ar name 20 | for use by uudecode. 21 | If no 22 | .Ar name 23 | is given 24 | .Nm 25 | reads from stdin. 26 | .Sh OPTIONS 27 | .Bl -tag -width Ds 28 | .It Fl m 29 | Use Base64 for encoding. 30 | .El 31 | .Sh SEE ALSO 32 | .Xr uudecode 1 33 | .Sh STANDARDS 34 | The 35 | .Nm 36 | utility is compliant with the 37 | .St -p1003.1-2013 38 | specification. 39 | -------------------------------------------------------------------------------- /hostname.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | 6 | #include "util.h" 7 | 8 | static void 9 | usage(void) 10 | { 11 | eprintf("usage: %s [name]\n", argv0); 12 | } 13 | 14 | int 15 | main(int argc, char *argv[]) 16 | { 17 | char host[HOST_NAME_MAX + 1]; 18 | 19 | ARGBEGIN { 20 | default: 21 | usage(); 22 | } ARGEND 23 | 24 | if (!argc) { 25 | if (gethostname(host, sizeof(host)) < 0) 26 | eprintf("gethostname:"); 27 | puts(host); 28 | } else if (argc == 1) { 29 | if (sethostname(argv[0], strlen(argv[0])) < 0) 30 | eprintf("sethostname:"); 31 | } else { 32 | usage(); 33 | } 34 | 35 | return fshut(stdout, ""); 36 | } 37 | -------------------------------------------------------------------------------- /libutf/fgetrune.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "../utf.h" 8 | 9 | int 10 | fgetrune(Rune *r, FILE *fp) 11 | { 12 | char buf[UTFmax]; 13 | int i = 0, c; 14 | 15 | while (i < UTFmax && (c = fgetc(fp)) != EOF) { 16 | buf[i++] = c; 17 | if (charntorune(r, buf, i) > 0) 18 | break; 19 | } 20 | if (ferror(fp)) 21 | return -1; 22 | 23 | return i; 24 | } 25 | 26 | int 27 | efgetrune(Rune *r, FILE *fp, const char *file) 28 | { 29 | int ret; 30 | 31 | if ((ret = fgetrune(r, fp)) < 0) { 32 | fprintf(stderr, "fgetrune %s: %s\n", file, strerror(errno)); 33 | exit(1); 34 | } 35 | return ret; 36 | } 37 | -------------------------------------------------------------------------------- /whoami.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "util.h" 8 | 9 | static void 10 | usage(void) 11 | { 12 | eprintf("usage: %s\n", argv0); 13 | } 14 | 15 | int 16 | main(int argc, char *argv[]) 17 | { 18 | uid_t uid; 19 | struct passwd *pw; 20 | 21 | argv0 = *argv, argv0 ? (argc--, argv++) : (void *)0; 22 | 23 | if (argc) 24 | usage(); 25 | 26 | uid = geteuid(); 27 | errno = 0; 28 | if (!(pw = getpwuid(uid))) { 29 | if (errno) 30 | eprintf("getpwuid %d:", uid); 31 | else 32 | eprintf("getpwuid %d: no such user\n", uid); 33 | } 34 | puts(pw->pw_name); 35 | 36 | return fshut(stdout, ""); 37 | } 38 | -------------------------------------------------------------------------------- /pathchk.1: -------------------------------------------------------------------------------- 1 | .Dd 2016-02-03 2 | .Dt PATHCHK 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm pathchk 6 | .Nd validate filename validity or portability 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl p 10 | .Op Fl P 11 | .Ar file Ar ... 12 | .Sh DESCRIPTION 13 | .Nm 14 | checks that filenames are valid for the system, 15 | and optional on other POSIX systems. 16 | .Sh OPTIONS 17 | .Bl -tag -width Ds 18 | .It Fl p 19 | Check for most POSIX systems. 20 | .It Fl P 21 | Check for empty pathnames and leading hythens. 22 | .El 23 | .Sh EXIT STATUS 24 | .Bl -tag -width Ds 25 | .It 0 26 | All pathname operands passed all of the checks. 27 | .It > 0 28 | An error occurred. 29 | .El 30 | .Sh STANDARDS 31 | The 32 | .Nm 33 | utility is compliant with the 34 | .St -p1003.1-2013 35 | specification. 36 | -------------------------------------------------------------------------------- /seq.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt SEQ 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm seq 6 | .Nd print a sequence of numbers 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl w 10 | .Op Fl f Ar fmt 11 | .Op Fl s Ar sep 12 | .Op Ar startnum Op Ar step 13 | .Ar endnum 14 | .Sh DESCRIPTION 15 | .Nm 16 | writes a sequence of numbers from 17 | .Ar startnum 18 | (default: 1) to 19 | .Ar endnum 20 | in 21 | .Ar step 22 | intervals (default: 1) 23 | to stdout. 24 | .Sh OPTIONS 25 | .Bl -tag -width Ds 26 | .It Fl f Ar fmt 27 | Use 28 | .Ar fmt 29 | as the output line format according to 30 | .Xr printf 3 . 31 | .It Fl s Ar sep 32 | Print 33 | .Ar sep 34 | between output lines. 35 | The default is "\en". 36 | .It Fl w 37 | Print out lines in equal width. 38 | .El 39 | .Sh SEE ALSO 40 | .Xr printf 3 41 | -------------------------------------------------------------------------------- /head.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt HEAD 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm head 6 | .Nd display initial lines of files 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl n Ar num | Fl Ns Ar num 10 | .Op Ar file ... 11 | .Sh DESCRIPTION 12 | .Nm 13 | writes 14 | .Ar num 15 | lines of each 16 | .Ar file 17 | to stdout. 18 | If no 19 | .Ar file 20 | is given 21 | .Nm 22 | reads from stdin. 23 | .Sh OPTIONS 24 | .Bl -tag -width Ds 25 | .It Fl n Ar num | Fl Ns Ar num 26 | Display initial 27 | .Ar num 28 | | 29 | .Sy N 30 | lines. 31 | Default is 10. 32 | .El 33 | .Sh SEE ALSO 34 | .Xr tail 1 35 | .Sh STANDARDS 36 | The 37 | .Nm 38 | utility is compliant with the 39 | .St -p1003.1-2013 40 | specification. 41 | .Pp 42 | The 43 | .Op Fl Ns num 44 | syntax is an extension to that specification. 45 | -------------------------------------------------------------------------------- /which.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt WHICH 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm which 6 | .Nd locate programs in the path 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl a 10 | .Ar name ... 11 | .Sh DESCRIPTION 12 | .Nm 13 | looks for each 14 | .Ar name 15 | in the 16 | .Ev PATH 17 | directories, stopping at the first match and printing 18 | the full path to stdout. 19 | .Sh OPTIONS 20 | .Bl -tag -width Ds 21 | .It Fl a 22 | Don't stop at the first match and search all 23 | .Ev PATH 24 | directories. 25 | .El 26 | .Sh EXIT STATUS 27 | .Bl -tag -width Ds 28 | .It 0 29 | Each 30 | .Ar name 31 | was found. 32 | .It 1 33 | At least one 34 | .Ar name 35 | was not found. 36 | .It 2 37 | No 38 | .Ar name 39 | was found. 40 | .It 3 41 | An error occurred. 42 | .El 43 | .Sh SEE ALSO 44 | .Xr environ 7 45 | -------------------------------------------------------------------------------- /rm.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt RM 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm rm 6 | .Nd remove directory entries 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl f 10 | .Op Fl Rr 11 | .Ar file ... 12 | .Sh DESCRIPTION 13 | .Nm 14 | removes each 15 | .Ar file . 16 | If 17 | .Ar file 18 | is a directory, it has to be empty unless 19 | .Fl R 20 | or 21 | .Fl r 22 | is specified. 23 | .Sh OPTIONS 24 | .Bl -tag -width Ds 25 | .It Fl f 26 | Do not prompt before removing 27 | .Ar file . 28 | Do not report when 29 | .Ar file 30 | doesn't exist or couldn't be removed. 31 | .It Fl Rr 32 | Remove directories recursively. 33 | .El 34 | .Sh SEE ALSO 35 | .Xr remove 3 36 | .Sh STANDARDS 37 | The 38 | .Nm 39 | utility is compliant with the 40 | .St -p1003.1-2013 41 | specification except from the 42 | .Op Fl i 43 | flag. 44 | -------------------------------------------------------------------------------- /rm.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | 4 | #include "fs.h" 5 | #include "util.h" 6 | 7 | static void 8 | usage(void) 9 | { 10 | eprintf("usage: %s [-f] [-Rr] file ...\n", argv0); 11 | } 12 | 13 | int 14 | main(int argc, char *argv[]) 15 | { 16 | struct recursor r = { .fn = rm, .maxdepth = 1, .follow = 'P' }; 17 | 18 | ARGBEGIN { 19 | case 'f': 20 | r.flags |= SILENT; 21 | break; 22 | case 'R': 23 | case 'r': 24 | r.maxdepth = 0; 25 | break; 26 | default: 27 | usage(); 28 | } ARGEND 29 | 30 | if (!argc) { 31 | if (!(r.flags & SILENT)) 32 | usage(); 33 | else 34 | return 0; 35 | } 36 | 37 | for (; *argv; argc--, argv++) 38 | recurse(AT_FDCWD, *argv, NULL, &r); 39 | 40 | return rm_status || recurse_status; 41 | } 42 | -------------------------------------------------------------------------------- /comm.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt COMM 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm comm 6 | .Nd select or reject lines common to two files 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl 123 10 | .Ar file1 11 | .Ar file2 12 | .Sh DESCRIPTION 13 | .Nm 14 | reads 15 | .Ar file1 16 | and 17 | .Ar file2, 18 | which should both be sorted lexically, and writes three text columns 19 | to stdout: 20 | .Bl -tag -width Ds 21 | .It 1 22 | Lines only in 23 | .Ar file1 . 24 | .It 2 25 | Lines only in 26 | .Ar file2 . 27 | .It 3 28 | Common lines. 29 | .El 30 | .Sh OPTIONS 31 | .Bl -tag -width Ds 32 | .It Fl 1 | Fl 2 | Fl 3 33 | Suppress column 1 | 2 | 3 34 | .El 35 | .Sh SEE ALSO 36 | .Xr cmp 1 , 37 | .Xr sort 1 , 38 | .Xr uniq 1 39 | .Sh STANDARDS 40 | The 41 | .Nm 42 | utility is compliant with the 43 | .St -p1003.1-2013 44 | specification. 45 | -------------------------------------------------------------------------------- /tftp.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt TFTP 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm tftp 6 | .Nd trivial file transfer protocol client 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Fl h Ar host 10 | .Op Fl p Ar port 11 | .Op Fl x | c 12 | .Ar file 13 | .Sh DESCRIPTION 14 | .Nm 15 | is a client that implements the trivial file transfer protocol over 16 | either IPv4 or IPv6 as specified in RFC 1350. 17 | It can be used to transfer files to and from remote machines. 18 | .Sh OPTIONS 19 | .Bl -tag -width Ds 20 | .It Fl h Ar host 21 | Set the remote hostname. 22 | .It Fl p Ar port 23 | Set the remote port. 24 | It defaults to port 69. 25 | .It Fl x 26 | Extract a file from the server. 27 | This is the default if no flags are specified. 28 | Output goes to stdout. 29 | .It Fl c 30 | Create a file on the server. 31 | Input comes from stdin. 32 | .El 33 | -------------------------------------------------------------------------------- /uname.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt UNAME 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm uname 6 | .Nd print system information 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl amnrsv 10 | .Sh DESCRIPTION 11 | .Nm 12 | writes system information to stdout. 13 | If no flags are given, 14 | .Nm 15 | implies 16 | .Fl s . 17 | .Sh OPTIONS 18 | .Bl -tag -width Ds 19 | .It Fl a 20 | Print all the information below. 21 | .It Fl m 22 | Print the machine's architecture. 23 | .It Fl n 24 | Print the system's network node hostname. 25 | .It Fl r 26 | Print the operating system's release name. 27 | .It Fl s 28 | Print the name of the operating system. 29 | .It Fl v 30 | Print the operating system's version name. 31 | .El 32 | .Sh SEE ALSO 33 | .Xr uname 2 34 | .Sh STANDARDS 35 | The 36 | .Nm 37 | utility is compliant with the 38 | .St -p1003.1-2013 39 | specification. 40 | -------------------------------------------------------------------------------- /flock.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt FLOCK 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm flock 6 | .Nd tool to manage locks on files 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl nosux 10 | .Ar file 11 | .Ar cmd Op arg ... 12 | .Sh DESCRIPTION 13 | .Nm 14 | is used to manage advisory locks on open files. 15 | It is commonly used to prevent long running cron jobs from running in 16 | parallel. 17 | If 18 | .Ar file 19 | does not exist, it will be created. 20 | .Sh OPTIONS 21 | .Bl -tag -width Ds 22 | .It Fl n 23 | Set non-blocking mode on the lock. 24 | Fail immediately if the lock cannot be acquired. 25 | .It Fl o 26 | Close the file descriptor before exec to avoid having the exec'ed 27 | program holding on to the lock. 28 | .It Fl s 29 | Acquire a shared lock. 30 | .It Fl u 31 | Release the lock. 32 | .It Fl x 33 | Acquire an exclusive lock. 34 | This is the default. 35 | .El 36 | -------------------------------------------------------------------------------- /nohup.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt NOHUP 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm nohup 6 | .Nd run command immune to hangups 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Ar cmd 10 | .Op Ar arg ... 11 | .Sh DESCRIPTION 12 | .Nm 13 | runs 14 | .Ar cmd 15 | with the 16 | .Em HUP 17 | signal set to be ignored. 18 | .Pp 19 | If stdout is a terminal, it is appended to 20 | .Em nohup.out 21 | in the current working directory. 22 | If stderr is a terminal, it is redirected to stdout. 23 | .Sh EXIT STATUS 24 | .Bl -tag -width Ds 25 | .It 0 26 | .Ar cmd 27 | executed successfully. 28 | .It 1 29 | Internal error. 30 | .It 126 31 | .Ar cmd 32 | was found but could not be executed. 33 | .It 127 34 | .Ar cmd 35 | could not be found. 36 | .El 37 | .Sh SEE ALSO 38 | .Xr signal 7 39 | .Sh STANDARDS 40 | The 41 | .Nm 42 | utility is compliant with the 43 | .St -p1003.1-2013 44 | specification. 45 | -------------------------------------------------------------------------------- /mknod.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-02-02 2 | .Dt MKNOD 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm mknod 6 | .Nd create a special device file 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl m Ar mode 10 | .Ar name 11 | .Cm b Ns | Ns Cm c Ns | Ns Cm u 12 | .Ar major 13 | .Ar minor 14 | .Nm 15 | .Op Fl m Ar mode 16 | .Ar name 17 | .Cm p 18 | .Sh DESCRIPTION 19 | .Nm 20 | creates a special file named 21 | .Ar name . 22 | .Pp 23 | The following special file types are supported: 24 | .Bl -tag -width Ds 25 | .It Cm b 26 | A block device. 27 | .It Cm c | u 28 | A character device. 29 | .It Cm p 30 | A named pipe. 31 | .El 32 | .Pp 33 | Block and character devices are created with major number 34 | .Ar major , 35 | and minor number 36 | .Ar minor . 37 | .Sh OPTIONS 38 | .Bl -tag -width Ds 39 | .It Fl m 40 | Set the mode of the new file based on the octal value of 41 | .Ar mode . 42 | .El 43 | .Sh SEE ALSO 44 | .Xr mknod 2 45 | -------------------------------------------------------------------------------- /fold.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt FOLD 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm fold 6 | .Nd wrap lines to width 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl bs 10 | .Op Fl w Ar num | Fl Ns Ar num 11 | .Op Ar file ... 12 | .Sh DESCRIPTION 13 | .Nm 14 | reads each 15 | .Ar file 16 | and prints its lines wrapped such that no line 17 | exceeds a certain width. 18 | If no file is given, 19 | .Nm 20 | reads from stdin. 21 | .Sh OPTIONS 22 | .Bl -tag -width Ds 23 | .It Fl b 24 | Count bytes rather than characters. 25 | .It Fl s 26 | If a line contains spaces, break 27 | at the last space within width. 28 | .It Fl w Ar num | Fl Ns Ar num 29 | Break at 30 | .Ar num 31 | characters. 32 | The default is 80. 33 | .El 34 | .Sh STANDARDS 35 | The 36 | .Nm 37 | utility is compliant with the 38 | .St -p1003.1-2013 39 | specification. 40 | .Pp 41 | The 42 | .Op Fl Ns Ar num 43 | syntax is an extension to that specification. 44 | -------------------------------------------------------------------------------- /renice.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt RENICE 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm renice 6 | .Nd change niceness of processes 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Fl n Ar num 10 | .Op Fl g | Fl p | Fl u 11 | .Ar id ... 12 | .Sh DESCRIPTION 13 | .Nm 14 | changes the niceness of each process with the given 15 | .Ar id . 16 | Only the superuser can lower the niceness. 17 | .Sh OPTIONS 18 | .Bl -tag -width Ds 19 | .It Fl g | Fl p | Fl u 20 | Interpret each 21 | .Ar id 22 | as a process group ID | process ID | user name or ID. 23 | The middle option is default. 24 | .It Fl n Ar num 25 | Change niceness by 26 | .Ar num , 27 | with niceness ranging from 28 | .Sy -20 29 | (highest priority) 30 | to 31 | .Sy +20 32 | (lowest priority). 33 | .El 34 | .Sh SEE ALSO 35 | .Xr nice 2 , 36 | .Xr renice 2 37 | .Sh STANDARDS 38 | The 39 | .Nm 40 | utility is compliant with the 41 | .St -p1003.1-2013 42 | specification. 43 | -------------------------------------------------------------------------------- /sponge.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | 6 | #include "util.h" 7 | 8 | static void 9 | usage(void) 10 | { 11 | eprintf("usage: %s file\n", argv0); 12 | } 13 | 14 | int 15 | main(int argc, char *argv[]) 16 | { 17 | char tmp[] = "/tmp/sponge-XXXXXX"; 18 | int fd, tmpfd; 19 | 20 | ARGBEGIN { 21 | default: 22 | usage(); 23 | } ARGEND 24 | 25 | if (argc != 1) 26 | usage(); 27 | 28 | if ((tmpfd = mkstemp(tmp)) < 0) 29 | eprintf("mkstemp:"); 30 | unlink(tmp); 31 | if (concat(0, "", tmpfd, "") < 0) 32 | return 1; 33 | if (lseek(tmpfd, 0, SEEK_SET) < 0) 34 | eprintf("lseek:"); 35 | 36 | if ((fd = creat(argv[0], 0666)) < 0) 37 | eprintf("creat %s:", argv[0]); 38 | if (concat(tmpfd, "", fd, argv[0]) < 0) 39 | return 1; 40 | 41 | return 0; 42 | } 43 | -------------------------------------------------------------------------------- /libutil/rm.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "../fs.h" 10 | #include "../util.h" 11 | 12 | int rm_status = 0; 13 | 14 | void 15 | rm(int dirfd, const char *name, struct stat *st, void *data, struct recursor *r) 16 | { 17 | if (!r->maxdepth && S_ISDIR(st->st_mode)) { 18 | recurse(dirfd, name, NULL, r); 19 | 20 | if (unlinkat(dirfd, name, AT_REMOVEDIR) < 0) { 21 | if (!(r->flags & SILENT)) 22 | weprintf("rmdir %s:", r->path); 23 | if (!((r->flags & SILENT) && errno == ENOENT)) 24 | rm_status = 1; 25 | } 26 | } else if (unlinkat(dirfd, name, 0) < 0) { 27 | if (!(r->flags & SILENT)) 28 | weprintf("unlink %s:", r->path); 29 | if (!((r->flags & SILENT) && errno == ENOENT)) 30 | rm_status = 1; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /setsid.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | 5 | #include "util.h" 6 | 7 | static int fflag = 0; 8 | 9 | static void 10 | usage(void) 11 | { 12 | eprintf("usage: %s [-f] cmd [arg ...]\n", argv0); 13 | } 14 | 15 | int 16 | main(int argc, char *argv[]) 17 | { 18 | int savederrno; 19 | 20 | ARGBEGIN { 21 | case 'f': 22 | fflag = 1; 23 | break; 24 | default: 25 | usage(); 26 | } ARGEND 27 | 28 | if (!argc) 29 | usage(); 30 | 31 | if (fflag || getpgrp() == getpid()) { 32 | switch (fork()) { 33 | case -1: 34 | eprintf("fork:"); 35 | case 0: 36 | break; 37 | default: 38 | return 0; 39 | } 40 | } 41 | if (setsid() < 0) 42 | eprintf("setsid:"); 43 | execvp(argv[0], argv); 44 | savederrno = errno; 45 | weprintf("execvp %s:", argv[0]); 46 | 47 | _exit(126 + (savederrno == ENOENT)); 48 | } 49 | -------------------------------------------------------------------------------- /libutil/mkdirp.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #include "../util.h" 8 | 9 | int 10 | mkdirp(const char *path, mode_t mode, mode_t pmode) 11 | { 12 | char tmp[PATH_MAX], *p; 13 | struct stat st; 14 | 15 | if (stat(path, &st) == 0) { 16 | if (S_ISDIR(st.st_mode)) 17 | return 0; 18 | errno = ENOTDIR; 19 | weprintf("%s:", path); 20 | return -1; 21 | } 22 | 23 | estrlcpy(tmp, path, sizeof(tmp)); 24 | for (p = tmp + (tmp[0] == '/'); *p; p++) { 25 | if (*p != '/') 26 | continue; 27 | *p = '\0'; 28 | if (mkdir(tmp, pmode) < 0 && errno != EEXIST) { 29 | weprintf("mkdir %s:", tmp); 30 | return -1; 31 | } 32 | *p = '/'; 33 | } 34 | if (mkdir(tmp, mode) < 0 && errno != EEXIST) { 35 | weprintf("mkdir %s:", tmp); 36 | return -1; 37 | } 38 | return 0; 39 | } 40 | -------------------------------------------------------------------------------- /libutil/fshut.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | 5 | #include "../util.h" 6 | 7 | int 8 | fshut(FILE *fp, const char *fname) 9 | { 10 | int ret = 0; 11 | 12 | /* fflush() is undefined for input streams by ISO C, 13 | * but not POSIX 2008 if you ignore ISO C overrides. 14 | * Leave it unchecked and rely on the following 15 | * functions to detect errors. 16 | */ 17 | fflush(fp); 18 | 19 | if (ferror(fp) && !ret) { 20 | weprintf("ferror %s:", fname); 21 | ret = 1; 22 | } 23 | 24 | if (fclose(fp) && !ret) { 25 | weprintf("fclose %s:", fname); 26 | ret = 1; 27 | } 28 | 29 | return ret; 30 | } 31 | 32 | void 33 | enfshut(int status, FILE *fp, const char *fname) 34 | { 35 | if (fshut(fp, fname)) 36 | exit(status); 37 | } 38 | 39 | void 40 | efshut(FILE *fp, const char *fname) 41 | { 42 | enfshut(1, fp, fname); 43 | } 44 | -------------------------------------------------------------------------------- /kill.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt KILL 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm kill 6 | .Nd signal processes 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl s Ar signame | Fl num | Fl signame 10 | .Ar pid ... 11 | .Nm 12 | .Fl l Op Ar num 13 | .Sh DESCRIPTION 14 | .Nm 15 | signals TERM to each process or process group specified by 16 | .Ar pid . 17 | .Sh OPTIONS 18 | .Bl -tag -width Ds 19 | .It Fl l Op Ar num 20 | List all available signals or the signal name of 21 | .Ar num . 22 | .It Fl s Ar signame | Fl num | Fl signame 23 | Send signal corresponding to 24 | .Ar signame 25 | | 26 | .Ar num . 27 | The default is TERM. 28 | .El 29 | .Sh SEE ALSO 30 | .Xr kill 2 , 31 | .Xr signal 7 32 | .Sh STANDARDS 33 | The 34 | .Nm 35 | utility is compliant with the 36 | .St -p1003.1-2013 37 | specification. 38 | .Pp 39 | The 40 | .Fl Ar signame 41 | and 42 | .Fl Ar num 43 | syntax is marked by 44 | .St -p1003.1-2013 45 | as an 46 | X/OPEN System Interfaces 47 | option. 48 | -------------------------------------------------------------------------------- /chgrp.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt CHGRP 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm chgrp 6 | .Nd change file group ownership 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl h 10 | .Oo 11 | .Fl R 12 | .Op Fl H | L | P 13 | .Oc 14 | .Ar group 15 | .Ar file ... 16 | .Sh DESCRIPTION 17 | .Nm 18 | sets the group id of each 19 | .Ar file 20 | to the gid of 21 | .Ar group . 22 | .Sh OPTIONS 23 | .Bl -tag -width Ds 24 | .It Fl h 25 | Preserve 26 | .Ar file 27 | if it is a symbolic link. 28 | .It Fl R 29 | Change file group ownerships recursively. 30 | .It Fl H 31 | Dereference 32 | .Ar file 33 | if it is a symbolic link. 34 | .It Fl L 35 | Dereference all symbolic links. 36 | .It Fl P 37 | Preserve symbolic links. 38 | This is the default. 39 | .El 40 | .Sh SEE ALSO 41 | .Xr chmod 1 , 42 | .Xr chown 1 , 43 | .Xr chmod 2 , 44 | .Xr chown 2 , 45 | .Xr getgrnam 3 46 | .Sh STANDARDS 47 | The 48 | .Nm 49 | utility is compliant with the 50 | .St -p1003.1-2013 51 | specification. 52 | -------------------------------------------------------------------------------- /rmdir.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | 6 | #include "util.h" 7 | 8 | static void 9 | usage(void) 10 | { 11 | eprintf("usage: %s [-p] dir ...\n", argv0); 12 | } 13 | 14 | int 15 | main(int argc, char *argv[]) 16 | { 17 | int pflag = 0, ret = 0; 18 | char *d; 19 | 20 | ARGBEGIN { 21 | case 'p': 22 | pflag = 1; 23 | break; 24 | default: 25 | usage(); 26 | } ARGEND 27 | 28 | if (!argc) 29 | usage(); 30 | 31 | for (; *argv; argc--, argv++) { 32 | if (rmdir(*argv) < 0) { 33 | weprintf("rmdir %s:", *argv); 34 | ret = 1; 35 | } else if (pflag) { 36 | d = dirname(*argv); 37 | for (; strcmp(d, "/") && strcmp(d, ".") ;) { 38 | if (rmdir(d) < 0) { 39 | weprintf("rmdir %s:", d); 40 | ret = 1; 41 | break; 42 | } 43 | d = dirname(d); 44 | } 45 | } 46 | } 47 | 48 | return ret; 49 | } 50 | -------------------------------------------------------------------------------- /printf.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt PRINTF 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm printf 6 | .Nd print formatted data 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Ar format 10 | .Op Ar arg ... 11 | .Sh DESCRIPTION 12 | .Nm 13 | writes formatted data according to 14 | .Ar format 15 | using each 16 | .Ar arg 17 | until drained. 18 | .Pp 19 | .Nm 20 | interprets the standard escape sequences \e\e, \e', \e", \ea, \eb, \ee, 21 | \ef, \en, \er, \et, \ev, \exH[H], \eO[OOO], the sequence \ec, which 22 | terminates further output if it's found inside 23 | .Ar format 24 | or a %b format string, the format specification %b for an unescaped string and all C 25 | .Xr printf 3 26 | format specifications ending with csdiouxXaAeEfFgG, including variable width and precision. 27 | .Sh STANDARDS 28 | The 29 | .Nm 30 | utility is compliant with the 31 | .St -p1003.1-2013 32 | specification. 33 | .Pp 34 | The possibility of specifying 4-digit octals is an extension to that specification. 35 | -------------------------------------------------------------------------------- /mkdir.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | 4 | #include 5 | #include 6 | 7 | #include "util.h" 8 | 9 | static void 10 | usage(void) 11 | { 12 | eprintf("usage: %s [-p] [-m mode] name ...\n", argv0); 13 | } 14 | 15 | int 16 | main(int argc, char *argv[]) 17 | { 18 | mode_t mode, mask; 19 | int pflag = 0, ret = 0; 20 | 21 | mask = umask(0); 22 | mode = 0777 & ~mask; 23 | 24 | ARGBEGIN { 25 | case 'p': 26 | pflag = 1; 27 | break; 28 | case 'm': 29 | mode = parsemode(EARGF(usage()), 0777, mask); 30 | break; 31 | default: 32 | usage(); 33 | } ARGEND 34 | 35 | if (!argc) 36 | usage(); 37 | 38 | for (; *argv; argc--, argv++) { 39 | if (pflag) { 40 | if (mkdirp(*argv, mode, 0777 & (~mask | 0300)) < 0) 41 | ret = 1; 42 | } else if (mkdir(*argv, mode) < 0) { 43 | weprintf("mkdir %s:", *argv); 44 | ret = 1; 45 | } 46 | } 47 | 48 | return ret; 49 | } 50 | -------------------------------------------------------------------------------- /sha1sum.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | 5 | #include "crypt.h" 6 | #include "sha1.h" 7 | #include "util.h" 8 | 9 | static struct sha1 s; 10 | struct crypt_ops sha1_ops = { 11 | sha1_init, 12 | sha1_update, 13 | sha1_sum, 14 | &s, 15 | }; 16 | 17 | static void 18 | usage(void) 19 | { 20 | eprintf("usage: %s [-c] [file ...]\n", argv0); 21 | } 22 | 23 | int 24 | main(int argc, char *argv[]) 25 | { 26 | int ret = 0, (*cryptfunc)(int, char **, struct crypt_ops *, uint8_t *, size_t) = cryptmain; 27 | uint8_t md[SHA1_DIGEST_LENGTH]; 28 | 29 | ARGBEGIN { 30 | case 'b': 31 | case 't': 32 | /* ignore */ 33 | break; 34 | case 'c': 35 | cryptfunc = cryptcheck; 36 | break; 37 | default: 38 | usage(); 39 | } ARGEND 40 | 41 | ret |= cryptfunc(argc, argv, &sha1_ops, md, sizeof(md)); 42 | ret |= fshut(stdin, "") | fshut(stdout, ""); 43 | 44 | return ret; 45 | } 46 | -------------------------------------------------------------------------------- /chroot.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | 6 | #include "util.h" 7 | 8 | static void 9 | usage(void) 10 | { 11 | eprintf("usage: %s dir [cmd [arg ...]]\n", argv0); 12 | } 13 | 14 | int 15 | main(int argc, char *argv[]) 16 | { 17 | char *shell[] = { "/bin/sh", "-i", NULL }, *aux, *cmd; 18 | int savederrno; 19 | 20 | ARGBEGIN { 21 | default: 22 | usage(); 23 | } ARGEND 24 | 25 | if (!argc) 26 | usage(); 27 | 28 | if ((aux = getenv("SHELL"))) 29 | shell[0] = aux; 30 | 31 | if (chroot(argv[0]) < 0) 32 | eprintf("chroot %s:", argv[0]); 33 | 34 | if (chdir("/") < 0) 35 | eprintf("chdir:"); 36 | 37 | if (argc == 1) { 38 | cmd = *shell; 39 | execvp(cmd, shell); 40 | } else { 41 | cmd = argv[1]; 42 | execvp(cmd, argv + 1); 43 | } 44 | 45 | savederrno = errno; 46 | weprintf("execvp %s:", cmd); 47 | 48 | _exit(126 + (savederrno == ENOENT)); 49 | } 50 | -------------------------------------------------------------------------------- /md5sum.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | 6 | #include "crypt.h" 7 | #include "md5.h" 8 | #include "util.h" 9 | 10 | static struct md5 s; 11 | struct crypt_ops md5_ops = { 12 | md5_init, 13 | md5_update, 14 | md5_sum, 15 | &s, 16 | }; 17 | 18 | static void 19 | usage(void) 20 | { 21 | eprintf("usage: %s [-c] [file ...]\n", argv0); 22 | } 23 | 24 | int 25 | main(int argc, char *argv[]) 26 | { 27 | int ret = 0, (*cryptfunc)(int, char **, struct crypt_ops *, uint8_t *, size_t) = cryptmain; 28 | uint8_t md[MD5_DIGEST_LENGTH]; 29 | 30 | ARGBEGIN { 31 | case 'b': 32 | case 't': 33 | /* ignore */ 34 | break; 35 | case 'c': 36 | cryptfunc = cryptcheck; 37 | break; 38 | default: 39 | usage(); 40 | } ARGEND 41 | 42 | ret |= cryptfunc(argc, argv, &md5_ops, md, sizeof(md)); 43 | ret |= fshut(stdin, "") | fshut(stdout, ""); 44 | 45 | return ret; 46 | } 47 | -------------------------------------------------------------------------------- /sha224sum.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | 5 | #include "crypt.h" 6 | #include "sha224.h" 7 | #include "util.h" 8 | 9 | static struct sha224 s; 10 | struct crypt_ops sha224_ops = { 11 | sha224_init, 12 | sha224_update, 13 | sha224_sum, 14 | &s, 15 | }; 16 | 17 | static void 18 | usage(void) 19 | { 20 | eprintf("usage: %s [-c] [file ...]\n", argv0); 21 | } 22 | 23 | int 24 | main(int argc, char *argv[]) 25 | { 26 | int ret = 0, (*cryptfunc)(int, char **, struct crypt_ops *, uint8_t *, size_t) = cryptmain; 27 | uint8_t md[SHA224_DIGEST_LENGTH]; 28 | 29 | ARGBEGIN { 30 | case 'b': 31 | case 't': 32 | /* ignore */ 33 | break; 34 | case 'c': 35 | cryptfunc = cryptcheck; 36 | break; 37 | default: 38 | usage(); 39 | } ARGEND 40 | 41 | ret |= cryptfunc(argc, argv, &sha224_ops, md, sizeof(md)); 42 | ret |= fshut(stdin, "") | fshut(stdout, ""); 43 | 44 | return ret; 45 | } 46 | -------------------------------------------------------------------------------- /sha256sum.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | 5 | #include "crypt.h" 6 | #include "sha256.h" 7 | #include "util.h" 8 | 9 | static struct sha256 s; 10 | struct crypt_ops sha256_ops = { 11 | sha256_init, 12 | sha256_update, 13 | sha256_sum, 14 | &s, 15 | }; 16 | 17 | static void 18 | usage(void) 19 | { 20 | eprintf("usage: %s [-c] [file ...]\n", argv0); 21 | } 22 | 23 | int 24 | main(int argc, char *argv[]) 25 | { 26 | int ret = 0, (*cryptfunc)(int, char **, struct crypt_ops *, uint8_t *, size_t) = cryptmain; 27 | uint8_t md[SHA256_DIGEST_LENGTH]; 28 | 29 | ARGBEGIN { 30 | case 'b': 31 | case 't': 32 | /* ignore */ 33 | break; 34 | case 'c': 35 | cryptfunc = cryptcheck; 36 | break; 37 | default: 38 | usage(); 39 | } ARGEND 40 | 41 | ret |= cryptfunc(argc, argv, &sha256_ops, md, sizeof(md)); 42 | ret |= fshut(stdin, "") | fshut(stdout, ""); 43 | 44 | return ret; 45 | } 46 | -------------------------------------------------------------------------------- /sha384sum.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | 5 | #include "crypt.h" 6 | #include "sha384.h" 7 | #include "util.h" 8 | 9 | static struct sha384 s; 10 | struct crypt_ops sha384_ops = { 11 | sha384_init, 12 | sha384_update, 13 | sha384_sum, 14 | &s, 15 | }; 16 | 17 | static void 18 | usage(void) 19 | { 20 | eprintf("usage: %s [-c] [file ...]\n", argv0); 21 | } 22 | 23 | int 24 | main(int argc, char *argv[]) 25 | { 26 | int ret = 0, (*cryptfunc)(int, char **, struct crypt_ops *, uint8_t *, size_t) = cryptmain; 27 | uint8_t md[SHA384_DIGEST_LENGTH]; 28 | 29 | ARGBEGIN { 30 | case 'b': 31 | case 't': 32 | /* ignore */ 33 | break; 34 | case 'c': 35 | cryptfunc = cryptcheck; 36 | break; 37 | default: 38 | usage(); 39 | } ARGEND 40 | 41 | ret |= cryptfunc(argc, argv, &sha384_ops, md, sizeof(md)); 42 | ret |= fshut(stdin, "") | fshut(stdout, ""); 43 | 44 | return ret; 45 | } 46 | -------------------------------------------------------------------------------- /sha512sum.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | 5 | #include "crypt.h" 6 | #include "sha512.h" 7 | #include "util.h" 8 | 9 | static struct sha512 s; 10 | struct crypt_ops sha512_ops = { 11 | sha512_init, 12 | sha512_update, 13 | sha512_sum, 14 | &s, 15 | }; 16 | 17 | static void 18 | usage(void) 19 | { 20 | eprintf("usage: %s [-c] [file ...]\n", argv0); 21 | } 22 | 23 | int 24 | main(int argc, char *argv[]) 25 | { 26 | int ret = 0, (*cryptfunc)(int, char **, struct crypt_ops *, uint8_t *, size_t) = cryptmain; 27 | uint8_t md[SHA512_DIGEST_LENGTH]; 28 | 29 | ARGBEGIN { 30 | case 'b': 31 | case 't': 32 | /* ignore */ 33 | break; 34 | case 'c': 35 | cryptfunc = cryptcheck; 36 | break; 37 | default: 38 | usage(); 39 | } ARGEND 40 | 41 | ret |= cryptfunc(argc, argv, &sha512_ops, md, sizeof(md)); 42 | ret |= fshut(stdin, "") | fshut(stdout, ""); 43 | 44 | return ret; 45 | } 46 | -------------------------------------------------------------------------------- /paste.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt PASTE 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm paste 6 | .Nd merge lines of files in parallel or sequentially 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl s 10 | .Op Fl d Ar list 11 | .Ar file ... 12 | .Sh DESCRIPTION 13 | .Nm 14 | reads single lines from each 15 | .Ar file 16 | and writes them into one line, replacing 17 | .Sy \en 18 | with 19 | .Sy \et 20 | except from the last 21 | .Ar file . 22 | This process is repeated until each 23 | .Ar file 24 | is starved, treating zero-reads as empty lines along the way. 25 | .Pp 26 | If 27 | .Ar file 28 | is '-', 29 | .Nm 30 | interprets it as stdin. 31 | .Sh OPTIONS 32 | .Bl -tag -width Ds 33 | .It Fl d Ar list 34 | Replace 35 | .Sy \en 36 | with escaped characters from 37 | .Ar list 38 | by cycling through it. 39 | .It Fl s 40 | Read each 41 | .Ar file 42 | sequentially instead of in parallel. 43 | .El 44 | .Sh SEE ALSO 45 | .Xr cut 1 46 | .Sh STANDARDS 47 | The 48 | .Nm 49 | utility is compliant with the 50 | .St -p1003.1-2013 51 | specification. 52 | -------------------------------------------------------------------------------- /time.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt TIME 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm time 6 | .Nd time a command 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl p 10 | .Ar cmd 11 | .Op Ar arg ... 12 | .Sh DESCRIPTION 13 | .Nm 14 | executes 15 | .Ar cmd 16 | and writes timing statistics to stderr after it finishes. 17 | The statistics include the elapsed real time 18 | between invocation and termination and the user 19 | and system CPU time (see 20 | .Xr times 2 ) . 21 | .Sh OPTIONS 22 | .Bl -tag -width Ds 23 | .It Fl p 24 | Use the format "real %f\enuser %f\ensys %f\en" for printing. 25 | This is the default. 26 | .El 27 | .Sh EXIT STATUS 28 | .Bl -tag -width Ds 29 | .It 0 30 | .Ar cmd 31 | executed successfully. 32 | .It 1 33 | Internal error. 34 | .It 126 35 | .Ar cmd 36 | was found but could not be executed. 37 | .It 127 38 | .Ar cmd 39 | could not be found. 40 | .El 41 | .Sh SEE ALSO 42 | .Xr times 2 , 43 | .Xr waitpid 2 44 | .Sh STANDARDS 45 | The 46 | .Nm 47 | utility is compliant with the 48 | .St -p1003.1-2013 49 | specification. 50 | -------------------------------------------------------------------------------- /cmp.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt CMP 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm cmp 6 | .Nd compare two files 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl l | Fl s 10 | .Ar file1 file2 11 | .Sh DESCRIPTION 12 | .Nm 13 | compares 14 | .Ar file1 15 | and 16 | .Ar file2 17 | byte by byte. 18 | If they differ, 19 | .Nm 20 | writes the first differing byte- and line-number to stdout. 21 | .Sh OPTIONS 22 | .Bl -tag -width Ds 23 | .It Fl l 24 | Print byte-number and bytes (in octal) for each difference. 25 | .It Fl s 26 | Print nothing and only return status. 27 | .El 28 | .Sh EXIT STATUS 29 | .Bl -tag -width Ds 30 | .It 0 31 | .Ar file1 32 | and 33 | .Ar file2 34 | are identical. 35 | .It 1 36 | .Ar file1 37 | and 38 | .Ar file2 39 | are different. 40 | .It > 1 41 | An error occurred. 42 | .El 43 | .Sh SEE ALSO 44 | .Xr comm 1 , 45 | .Xr diff 1 46 | .Sh STANDARDS 47 | The 48 | .Nm 49 | utility is compliant with the 50 | .St -p1003.1-2013 51 | specification. 52 | .Pp 53 | The "char" in the default result format has been replaced with "byte". 54 | -------------------------------------------------------------------------------- /sha512-224sum.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | 5 | #include "crypt.h" 6 | #include "sha512-224.h" 7 | #include "util.h" 8 | 9 | static struct sha512_224 s; 10 | struct crypt_ops sha512_224_ops = { 11 | sha512_224_init, 12 | sha512_224_update, 13 | sha512_224_sum, 14 | &s, 15 | }; 16 | 17 | static void 18 | usage(void) 19 | { 20 | eprintf("usage: %s [-c] [file ...]\n", argv0); 21 | } 22 | 23 | int 24 | main(int argc, char *argv[]) 25 | { 26 | int ret = 0, (*cryptfunc)(int, char **, struct crypt_ops *, uint8_t *, size_t) = cryptmain; 27 | uint8_t md[SHA512_224_DIGEST_LENGTH]; 28 | 29 | ARGBEGIN { 30 | case 'b': 31 | case 't': 32 | /* ignore */ 33 | break; 34 | case 'c': 35 | cryptfunc = cryptcheck; 36 | break; 37 | default: 38 | usage(); 39 | } ARGEND 40 | 41 | ret |= cryptfunc(argc, argv, &sha512_224_ops, md, sizeof(md)); 42 | ret |= fshut(stdin, "") | fshut(stdout, ""); 43 | 44 | return ret; 45 | } 46 | -------------------------------------------------------------------------------- /sha512-256sum.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | 5 | #include "crypt.h" 6 | #include "sha512-256.h" 7 | #include "util.h" 8 | 9 | static struct sha512_256 s; 10 | struct crypt_ops sha512_256_ops = { 11 | sha512_256_init, 12 | sha512_256_update, 13 | sha512_256_sum, 14 | &s, 15 | }; 16 | 17 | static void 18 | usage(void) 19 | { 20 | eprintf("usage: %s [-c] [file ...]\n", argv0); 21 | } 22 | 23 | int 24 | main(int argc, char *argv[]) 25 | { 26 | int ret = 0, (*cryptfunc)(int, char **, struct crypt_ops *, uint8_t *, size_t) = cryptmain; 27 | uint8_t md[SHA512_256_DIGEST_LENGTH]; 28 | 29 | ARGBEGIN { 30 | case 'b': 31 | case 't': 32 | /* ignore */ 33 | break; 34 | case 'c': 35 | cryptfunc = cryptcheck; 36 | break; 37 | default: 38 | usage(); 39 | } ARGEND 40 | 41 | ret |= cryptfunc(argc, argv, &sha512_256_ops, md, sizeof(md)); 42 | ret |= fshut(stdin, "") | fshut(stdout, ""); 43 | 44 | return ret; 45 | } 46 | -------------------------------------------------------------------------------- /unexpand.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt UNEXPAND 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm unexpand 6 | .Nd unexpand spaces to tabs 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl a 10 | .Op Fl t Ar tablist 11 | .Op Ar file ... 12 | .Sh DESCRIPTION 13 | .Nm 14 | converts spaces to tabs in each 15 | .Ar file 16 | as specified in 17 | .Ar tablist . 18 | If no file is given, 19 | .Nm 20 | reads from stdin. 21 | .Pp 22 | Backspace characters are preserved and decrement the column count 23 | for tab calculations. 24 | .Sh OPTIONS 25 | .Bl -tag -width Ds 26 | .It Fl a 27 | Convert spaces to tabs everywhere, not just at the start of lines. 28 | .It Fl t Ar tablist 29 | Specify tab size or tabstops. 30 | .Ar tablist 31 | is a list of one (in the former case) or multiple (in the latter case) 32 | strictly positive integers separated by ' ' or ','. 33 | .Pp 34 | The default 35 | .Ar tablist 36 | is "8". 37 | .El 38 | .Sh SEE ALSO 39 | .Xr expand 1 40 | .Sh STANDARDS 41 | The 42 | .Nm 43 | utility is compliant with the 44 | .St -p1003.1-2013 45 | specification. 46 | -------------------------------------------------------------------------------- /env.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "util.h" 9 | 10 | extern char **environ; 11 | 12 | static void 13 | usage(void) 14 | { 15 | eprintf("usage: %s [-i] [-u var] ... [var=value] ... [cmd [arg ...]]\n", argv0); 16 | } 17 | 18 | int 19 | main(int argc, char *argv[]) 20 | { 21 | int savederrno; 22 | 23 | ARGBEGIN { 24 | case 'i': 25 | *environ = NULL; 26 | break; 27 | case 'u': 28 | if (unsetenv(EARGF(usage())) < 0) 29 | eprintf("unsetenv:"); 30 | break; 31 | default: 32 | usage(); 33 | } ARGEND 34 | 35 | for (; *argv && strchr(*argv, '='); argc--, argv++) 36 | putenv(*argv); 37 | 38 | if (*argv) { 39 | execvp(*argv, argv); 40 | savederrno = errno; 41 | weprintf("execvp %s:", *argv); 42 | _exit(126 + (savederrno == ENOENT)); 43 | } 44 | 45 | for (; *environ; environ++) 46 | puts(*environ); 47 | 48 | return fshut(stdout, ""); 49 | } 50 | -------------------------------------------------------------------------------- /uniq.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt UNIQ 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm uniq 6 | .Nd report or filter out repeated lines in a file 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl c 10 | .Op Fl d | u 11 | .Op Fl f Ar num 12 | .Op Fl s Ar num 13 | .Op Ar input Op Ar output 14 | .Sh DESCRIPTION 15 | .Nm 16 | reads the 17 | .Ar input 18 | file and writes one copy of a line from each group of consecutive 19 | duplicate lines to the 20 | .Ar output 21 | file. 22 | If no 23 | .Ar input 24 | file is given 25 | .Nm 26 | reads from stdin. 27 | If no 28 | .Ar output 29 | file is given 30 | .Nm 31 | writes to stdout. 32 | .Sh OPTIONS 33 | .Bl -tag -width Ds 34 | .It Fl c 35 | Prefix each line with the number of consecutive occurrences in 36 | .Ar input . 37 | .It Fl d | Fl u 38 | Print duplicate | unique lines only. 39 | .It Fl f Ar num | Fl s Ar num 40 | Ignore the first 41 | .Ar num 42 | fields | characters in each input line when doing comparisons. 43 | .El 44 | .Sh STANDARDS 45 | The 46 | .Nm 47 | utility is compliant with the 48 | .St -p1003.1-2013 49 | specification. 50 | -------------------------------------------------------------------------------- /cat.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | 6 | #include "util.h" 7 | 8 | static void 9 | usage(void) 10 | { 11 | eprintf("usage: %s [-u] [file ...]\n", argv0); 12 | } 13 | 14 | int 15 | main(int argc, char *argv[]) 16 | { 17 | int fd, ret = 0; 18 | 19 | ARGBEGIN { 20 | case 'u': 21 | break; 22 | default: 23 | usage(); 24 | } ARGEND 25 | 26 | if (!argc) { 27 | if (concat(0, "", 1, "") < 0) 28 | ret = 1; 29 | } else { 30 | for (; *argv; argc--, argv++) { 31 | if (!strcmp(*argv, "-")) { 32 | *argv = ""; 33 | fd = 0; 34 | } else if ((fd = open(*argv, O_RDONLY)) < 0) { 35 | weprintf("open %s:", *argv); 36 | ret = 1; 37 | continue; 38 | } 39 | switch (concat(fd, *argv, 1, "")) { 40 | case -1: 41 | ret = 1; 42 | break; 43 | case -2: 44 | return 1; /* exit on write error */ 45 | } 46 | if (fd != 0) 47 | close(fd); 48 | } 49 | } 50 | 51 | return ret; 52 | } 53 | -------------------------------------------------------------------------------- /pwd.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "util.h" 9 | 10 | static const char * 11 | getpwd(const char *cwd) 12 | { 13 | const char *pwd; 14 | struct stat cst, pst; 15 | 16 | if (!(pwd = getenv("PWD")) || pwd[0] != '/' || stat(pwd, &pst) < 0) 17 | return cwd; 18 | if (stat(cwd, &cst) < 0) 19 | eprintf("stat %s:", cwd); 20 | 21 | return (pst.st_dev == cst.st_dev && pst.st_ino == cst.st_ino) ? pwd : cwd; 22 | } 23 | 24 | static void 25 | usage(void) 26 | { 27 | eprintf("usage: %s [-LP]\n", argv0); 28 | } 29 | 30 | int 31 | main(int argc, char *argv[]) 32 | { 33 | char cwd[PATH_MAX]; 34 | char mode = 'L'; 35 | 36 | ARGBEGIN { 37 | case 'L': 38 | case 'P': 39 | mode = ARGC(); 40 | break; 41 | default: 42 | usage(); 43 | } ARGEND 44 | 45 | if (!getcwd(cwd, sizeof(cwd))) 46 | eprintf("getcwd:"); 47 | puts((mode == 'L') ? getpwd(cwd) : cwd); 48 | 49 | return fshut(stdout, ""); 50 | } 51 | -------------------------------------------------------------------------------- /libutil/getlines.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | 6 | #include "../text.h" 7 | #include "../util.h" 8 | 9 | void 10 | getlines(FILE *fp, struct linebuf *b) 11 | { 12 | char *line = NULL; 13 | size_t size = 0, linelen = 0; 14 | ssize_t len; 15 | 16 | while ((len = getline(&line, &size, fp)) > 0) { 17 | if (++b->nlines > b->capacity) { 18 | b->capacity += 512; 19 | b->lines = ereallocarray(b->lines, b->capacity, sizeof(*b->lines)); 20 | } 21 | linelen = len; 22 | b->lines[b->nlines - 1].data = memcpy(emalloc(linelen + 1), line, linelen + 1); 23 | b->lines[b->nlines - 1].len = linelen; 24 | } 25 | free(line); 26 | if (b->lines && b->nlines && linelen && b->lines[b->nlines - 1].data[linelen - 1] != '\n') { 27 | b->lines[b->nlines - 1].data = erealloc(b->lines[b->nlines - 1].data, linelen + 2); 28 | b->lines[b->nlines - 1].data[linelen] = '\n'; 29 | b->lines[b->nlines - 1].data[linelen + 1] = '\0'; 30 | b->lines[b->nlines - 1].len++; 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /fs.h: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | 6 | struct history { 7 | struct history *prev; 8 | dev_t dev; 9 | ino_t ino; 10 | }; 11 | 12 | struct recursor { 13 | void (*fn)(int, const char *, struct stat *, void *, struct recursor *); 14 | char path[PATH_MAX]; 15 | size_t pathlen; 16 | struct history *hist; 17 | int depth; 18 | int maxdepth; 19 | int follow; 20 | int flags; 21 | }; 22 | 23 | enum { 24 | SAMEDEV = 1 << 0, 25 | DIRFIRST = 1 << 1, 26 | SILENT = 1 << 2, 27 | }; 28 | 29 | extern int cp_aflag; 30 | extern int cp_fflag; 31 | extern int cp_pflag; 32 | extern int cp_rflag; 33 | extern int cp_vflag; 34 | extern int cp_follow; 35 | extern int cp_status; 36 | 37 | extern int rm_fflag; 38 | extern int rm_rflag; 39 | extern int rm_status; 40 | 41 | extern int recurse_status; 42 | 43 | void recurse(int, const char *, void *, struct recursor *); 44 | 45 | int cp(const char *, const char *, int); 46 | void rm(int, const char *, struct stat *st, void *, struct recursor *); 47 | -------------------------------------------------------------------------------- /libutil/enmasse.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "../util.h" 10 | 11 | void 12 | enmasse(int argc, char *argv[], int (*fn)(const char *, const char *, int)) 13 | { 14 | struct stat st; 15 | char buf[PATH_MAX], *dir; 16 | int i, len; 17 | size_t dlen; 18 | 19 | if (argc == 2 && !(stat(argv[1], &st) == 0 && S_ISDIR(st.st_mode))) { 20 | fnck(argv[0], argv[1], fn, 0); 21 | return; 22 | } else { 23 | dir = (argc == 1) ? "." : argv[--argc]; 24 | } 25 | 26 | for (i = 0; i < argc; i++) { 27 | dlen = strlen(dir); 28 | if (dlen > 0 && dir[dlen - 1] == '/') 29 | len = snprintf(buf, sizeof(buf), "%s%s", dir, basename(argv[i])); 30 | else 31 | len = snprintf(buf, sizeof(buf), "%s/%s", dir, basename(argv[i])); 32 | if (len < 0 || len >= sizeof(buf)) { 33 | eprintf("%s/%s: filename too long\n", dir, 34 | basename(argv[i])); 35 | } 36 | fnck(argv[i], buf, fn, 0); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /readlink.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "util.h" 9 | 10 | static void 11 | usage(void) 12 | { 13 | eprintf("usage: %s [-fn] path\n", argv0); 14 | } 15 | 16 | int 17 | main(int argc, char *argv[]) 18 | { 19 | char buf[PATH_MAX]; 20 | ssize_t n; 21 | int nflag = 0, fflag = 0; 22 | 23 | ARGBEGIN { 24 | case 'f': 25 | fflag = ARGC(); 26 | break; 27 | case 'n': 28 | nflag = 1; 29 | break; 30 | default: 31 | usage(); 32 | } ARGEND 33 | 34 | if (argc != 1) 35 | usage(); 36 | 37 | if (strlen(argv[0]) >= PATH_MAX) 38 | eprintf("path too long\n"); 39 | 40 | if (fflag) { 41 | if (!realpath(argv[0], buf)) 42 | eprintf("realpath %s:", argv[0]); 43 | } else { 44 | if ((n = readlink(argv[0], buf, PATH_MAX - 1)) < 0) 45 | eprintf("readlink %s:", argv[0]); 46 | buf[n] = '\0'; 47 | } 48 | 49 | fputs(buf, stdout); 50 | if (!nflag) 51 | putchar('\n'); 52 | 53 | return fshut(stdout, ""); 54 | } 55 | -------------------------------------------------------------------------------- /env.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt ENV 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm env 6 | .Nd modify the environment, then print it or run a command 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl i 10 | .Oo Fl u Ar var Oc ... 11 | .Oo Ar var Ns = Ns Ar value Oc ... 12 | .Oo Ar cmd Oo arg ... Oc Oc 13 | .Sh DESCRIPTION 14 | .Nm 15 | unsets each 16 | .Ar var , 17 | then adds or sets each 18 | .Ar ( var , value ) 19 | tuple in the environment. 20 | .Pp 21 | If 22 | .Ar cmd 23 | is given, it is executed in this new environment; 24 | otherwise, the modified environment is printed to stdout. 25 | .Sh OPTIONS 26 | .Bl -tag -width Ds 27 | .It Fl i 28 | Completely ignore the existing environment and execute 29 | .Ar cmd 30 | only with each 31 | .Ar ( var , value ) 32 | tuple specified. 33 | .It Fl u Ar var 34 | Unset 35 | .Ar var 36 | in the environment. 37 | .El 38 | .Sh SEE ALSO 39 | .Xr printenv 1 , 40 | .Xr putenv 3 , 41 | .Xr environ 7 42 | .Sh STANDARDS 43 | The 44 | .Nm 45 | utility is compliant with the 46 | .St -p1003.1-2013 47 | specification. 48 | .Pp 49 | The 50 | .Op Fl u 51 | flag is an extension to that specification. 52 | -------------------------------------------------------------------------------- /strings.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt STRINGS 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm strings 6 | .Nd print strings of printable characters in files 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl a 10 | .Op Fl n Ar num 11 | .Op Fl t Ar format 12 | .Op Ar file ... 13 | .Sh DESCRIPTION 14 | .Nm 15 | writes sequences of at least 4 printable characters in each 16 | .Ar file 17 | to stdout. 18 | If no 19 | .Ar file 20 | is given, 21 | .Nm 22 | reads from stdin. 23 | .Sh OPTIONS 24 | .Bl -tag -width Ds 25 | .It Fl a 26 | Scan each 27 | .Ar file 28 | entirely. 29 | This is the default. 30 | .It Fl n Ar num 31 | Print sequences of at least 32 | .Ar num 33 | characters. 34 | The default is 4. 35 | .It Fl t Ar format 36 | Prepend each string with its byte offset, with 37 | .Ar format 38 | being one of 39 | .Sy d , o , x 40 | for decimal, octal or hexadecimal numbers. 41 | .El 42 | .Sh STANDARDS 43 | The 44 | .Nm 45 | utility is compliant with the 46 | .St -p1003.1-2013 47 | specification. 48 | .Pp 49 | The 50 | .Op Fl t 51 | output format has been changed from "%F %s" to "%8lF: %s", with 52 | .Sy F 53 | being one of 54 | .Sy d , o , x . 55 | -------------------------------------------------------------------------------- /libutil/eprintf.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "../util.h" 8 | 9 | char *argv0; 10 | 11 | static void xvprintf(const char *, va_list); 12 | 13 | void 14 | eprintf(const char *fmt, ...) 15 | { 16 | va_list ap; 17 | 18 | va_start(ap, fmt); 19 | xvprintf(fmt, ap); 20 | va_end(ap); 21 | 22 | exit(1); 23 | } 24 | 25 | void 26 | enprintf(int status, const char *fmt, ...) 27 | { 28 | va_list ap; 29 | 30 | va_start(ap, fmt); 31 | xvprintf(fmt, ap); 32 | va_end(ap); 33 | 34 | exit(status); 35 | } 36 | 37 | void 38 | weprintf(const char *fmt, ...) 39 | { 40 | va_list ap; 41 | 42 | va_start(ap, fmt); 43 | xvprintf(fmt, ap); 44 | va_end(ap); 45 | } 46 | 47 | void 48 | xvprintf(const char *fmt, va_list ap) 49 | { 50 | if (argv0 && strncmp(fmt, "usage", strlen("usage"))) 51 | fprintf(stderr, "%s: ", argv0); 52 | 53 | vfprintf(stderr, fmt, ap); 54 | 55 | if (fmt[0] && fmt[strlen(fmt)-1] == ':') { 56 | fputc(' ', stderr); 57 | perror(NULL); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /chown.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt CHOWN 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm chown 6 | .Nd change file ownership 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl h 10 | .Oo 11 | .Fl R 12 | .Op Fl H | L | P 13 | .Oc 14 | .Ar owner Ns Op Pf : Op Ar group 15 | .Op Ar file ... 16 | .Nm 17 | .Op Fl h 18 | .Oo 19 | .Fl R 20 | .Op Fl H | L | P 21 | .Oc 22 | .Pf : Ar group 23 | .Op Ar file ... 24 | .Sh DESCRIPTION 25 | .Nm 26 | sets the user and/or group id of each 27 | .Ar file 28 | to the uid of 29 | .Ar owner 30 | and/or the gid of 31 | .Ar group 32 | respectively. 33 | .Sh OPTIONS 34 | .Bl -tag -width Ds 35 | .It Fl h 36 | Preserve 37 | .Ar file 38 | if it is a symbolic link. 39 | .It Fl R 40 | Change file ownerships recursively. 41 | .It Fl H 42 | Dereference 43 | .Ar file 44 | if it is a symbolic link. 45 | .It Fl L 46 | Dereference all symbolic links. 47 | .It Fl P 48 | Preserve symbolic links. 49 | This is the default. 50 | .El 51 | .Sh SEE ALSO 52 | .Xr chmod 1 , 53 | .Xr chown 2 , 54 | .Xr getgrnam 3 , 55 | .Xr getpwnam 3 56 | .Sh STANDARDS 57 | The 58 | .Nm 59 | utility is compliant with the 60 | .St -p1003.1-2013 61 | specification. 62 | -------------------------------------------------------------------------------- /nohup.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "util.h" 10 | 11 | static void 12 | usage(void) 13 | { 14 | eprintf("usage: %s cmd [arg ...]\n", argv0); 15 | } 16 | 17 | int 18 | main(int argc, char *argv[]) 19 | { 20 | int fd, savederrno; 21 | 22 | ARGBEGIN { 23 | default: 24 | usage(); 25 | } ARGEND 26 | 27 | if (!argc) 28 | usage(); 29 | 30 | if (signal(SIGHUP, SIG_IGN) == SIG_ERR) 31 | enprintf(127, "signal HUP:"); 32 | 33 | if (isatty(STDOUT_FILENO)) { 34 | if ((fd = open("nohup.out", O_WRONLY | O_APPEND | O_CREAT, S_IRUSR | S_IWUSR)) < 0) 35 | enprintf(127, "open nohup.out:"); 36 | if (dup2(fd, STDOUT_FILENO) < 0) 37 | enprintf(127, "dup2:"); 38 | close(fd); 39 | } 40 | if (isatty(STDERR_FILENO) && dup2(STDOUT_FILENO, STDERR_FILENO) < 0) 41 | enprintf(127, "dup2:"); 42 | 43 | execvp(argv[0], argv); 44 | savederrno = errno; 45 | weprintf("execvp %s:", argv[0]); 46 | 47 | _exit(126 + (savederrno == ENOENT)); 48 | } 49 | -------------------------------------------------------------------------------- /getconf.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt GETCONF 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm getconf 6 | .Nd get configuration values 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl v Ar spec 10 | .Ar var 11 | .Ar [path] 12 | .Sh DESCRIPTION 13 | .Nm 14 | writes the value of the variable 15 | .Ar var 16 | to stdout. 17 | .sp 18 | If 19 | .Ar path 20 | is given, 21 | .Ar var 22 | is matched against configuration values from 23 | .Xr pathconf 3 . 24 | If 25 | .Ar path 26 | is not given, 27 | .Ar var 28 | is matched against configuration values from 29 | .Xr sysconf 3 , 30 | .Xr confstr 3 31 | and limits.h (Minimum and Maximum). 32 | .sp 33 | If 34 | .Ar var 35 | is not defined, 36 | .Nm 37 | writes "undefined" to stdout. 38 | .Sh OPTIONS 39 | .Bl -tag -width Ds 40 | .It Fl v Ar spec 41 | Ignored. 42 | .El 43 | .Sh EXIT STATUS 44 | .Bl -tag -width Ds 45 | .It 0 46 | .Ar var 47 | was matched and its value written successfully. 48 | .It 1 49 | An error occured or 50 | .Ar var 51 | was invalid. 52 | .El 53 | .Sh STANDARDS 54 | The 55 | .Nm 56 | utility is compliant with the 57 | .St -p1003.1-2013 58 | specification except from the 59 | .Op Fl v 60 | flag. 61 | -------------------------------------------------------------------------------- /logger.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt LOGGER 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm logger 6 | .Nd make entries in the system log 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl is 10 | .Op Fl p Ar priority 11 | .Op Fl t Ar tag 12 | .Op Ar message ... 13 | .Sh DESCRIPTION 14 | .Nm 15 | provides a shell command interface to the 16 | .Xr syslog 3 17 | system log module and writes each 18 | .Ar message 19 | to the log. 20 | If no 21 | .Ar message 22 | is given, 23 | .Nm 24 | logs stdin. 25 | .Sh OPTIONS 26 | .Bl -tag -width xxxxxxxxxxxx 27 | .It Fl i 28 | Add the logger process ID to each line in the log. 29 | .It Fl p Ar priority 30 | Set the message 31 | .Ar priority 32 | given symbolically as a 33 | .Dq facility.level 34 | pair. 35 | The default is 36 | .Dq user.notice . 37 | .It Fl s 38 | Also log to stderr. 39 | .It Fl t Ar tag 40 | Add 41 | .Ar tag 42 | to each line in the log. 43 | .El 44 | .Sh SEE ALSO 45 | .Xr syslogd 1 , 46 | .Xr syslog 3 47 | .Sh STANDARDS 48 | The 49 | .Nm 50 | utility is compliant with the 51 | .St -p1003.1-2013 52 | specification. 53 | .Pp 54 | The 55 | .Op Fl ipst 56 | flags are an extensions to that specification. 57 | -------------------------------------------------------------------------------- /tail.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt TAIL 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm tail 6 | .Nd display final lines of files 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl f 10 | .Op Fl c Ar num | Fl m Ar num | Fl n Ar num | Fl Ns Ar num 11 | .Op Ar file ... 12 | .Sh DESCRIPTION 13 | .Nm 14 | writes the last 10 lines of each 15 | .Ar file 16 | to stdout. 17 | If no 18 | .Ar file 19 | is given, 20 | .Nm 21 | reads from stdin. 22 | .Sh OPTIONS 23 | .Bl -tag -width Ds 24 | .It Fl c Ar num | Fl m Ar num | Fl n Ar num | Fl Ns Ar num 25 | Display final 26 | .Ar num 27 | bytes | characters | lines | lines. 28 | If 29 | .Ar num 30 | begins with '+' 31 | it is an offset from the beginning of each 32 | .Ar file . 33 | If 34 | .Ar num 35 | begins with '-' it is as if no sign was given. 36 | The default is 10 lines. 37 | .It Fl f 38 | If one 39 | .Ar file 40 | is specified, append lines to output as 41 | .Ar file 42 | grows. 43 | .El 44 | .Sh SEE ALSO 45 | .Xr head 1 46 | .Sh STANDARDS 47 | The 48 | .Nm 49 | utility is compliant with the 50 | .St -p1003.1-2013 51 | specification. 52 | .Pp 53 | The 54 | .Op Fl Ns Ar num 55 | syntax is an extension to that specification. 56 | -------------------------------------------------------------------------------- /split.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt SPLIT 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm split 6 | .Nd split up a file 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl a Ar num 10 | .Op Fl b Ar num[k|m|g] | Fl l Ar num 11 | .Op Fl d 12 | .Op Ar file Op Ar prefix 13 | .Sh DESCRIPTION 14 | .Nm 15 | splits 16 | .Ar file 17 | into files with 1000 lines each, named with 18 | .Ar prefix 19 | "x" followed by 2-digit alphabetical count suffixes. 20 | If 21 | .Nm 22 | runs out of suffixes, it stops after the last valid filename. 23 | .Sh OPTIONS 24 | .Bl -tag -width Ds 25 | .It Fl a Ar num 26 | Set suffix length to 27 | .Ar num 28 | characters. 29 | The default is 2. 30 | .It Fl b Ar num[k|m|g] | Fl l Ar num 31 | Start a new file every 32 | .Ar num 33 | bytes | lines. 34 | The units k, m, and g are case insensitive and powers of 2, not 10. 35 | The default is 1000 lines. 36 | .It Fl d 37 | Use decimal rather than alphabetical suffixes. 38 | .El 39 | .Sh SEE ALSO 40 | .Xr cat 1 41 | .Sh STANDARDS 42 | The 43 | .Nm 44 | utility is compliant with the 45 | .St -p1003.1-2013 46 | specification. 47 | .Pp 48 | The 49 | .Op Fl d 50 | flag and g unit are an extension to that specification. 51 | -------------------------------------------------------------------------------- /nice.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "util.h" 9 | 10 | #ifndef PRIO_MIN 11 | #define PRIO_MIN -NZERO 12 | #endif 13 | 14 | #ifndef PRIO_MAX 15 | #define PRIO_MAX (NZERO-1) 16 | #endif 17 | 18 | static void 19 | usage(void) 20 | { 21 | eprintf("usage: %s [-n inc] cmd [arg ...]\n", argv0); 22 | } 23 | 24 | int 25 | main(int argc, char *argv[]) 26 | { 27 | int val = 10, r, savederrno; 28 | 29 | ARGBEGIN { 30 | case 'n': 31 | val = estrtonum(EARGF(usage()), PRIO_MIN, PRIO_MAX); 32 | break; 33 | default: 34 | usage(); 35 | break; 36 | } ARGEND 37 | 38 | if (!argc) 39 | usage(); 40 | 41 | errno = 0; 42 | r = getpriority(PRIO_PROCESS, 0); 43 | if (errno) 44 | weprintf("getpriority:"); 45 | else 46 | val += r; 47 | LIMIT(val, PRIO_MIN, PRIO_MAX); 48 | if (setpriority(PRIO_PROCESS, 0, val) < 0) 49 | weprintf("setpriority:"); 50 | 51 | execvp(argv[0], argv); 52 | savederrno = errno; 53 | weprintf("execvp %s:", argv[0]); 54 | 55 | _exit(126 + (savederrno == ENOENT)); 56 | } 57 | -------------------------------------------------------------------------------- /expand.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt EXPAND 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm expand 6 | .Nd expand tabs to spaces 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl i 10 | .Op Fl t Ar tablist 11 | .Op Ar file ... 12 | .Sh DESCRIPTION 13 | .Nm 14 | converts tabs to spaces in each 15 | .Ar file 16 | as specified in 17 | .Ar tablist . 18 | If no file is given, 19 | .Nm 20 | reads from stdin. 21 | .Pp 22 | Backspace characters are preserved and decrement the column count 23 | for tab calculations. 24 | .Sh OPTIONS 25 | .Bl -tag -width Ds 26 | .It Fl i 27 | Only expand tabs at the beginning of lines, i.e. expand each 28 | line until a character different from '\et' and ' ' is reached. 29 | .It Fl t Ar tablist 30 | Specify tab size or tabstops. 31 | .Ar tablist 32 | is a list of one (in the former case) or multiple (in the latter case) 33 | strictly positive integers separated by ' ' or ','. 34 | .Pp 35 | The default 36 | .Ar tablist 37 | is "8". 38 | .El 39 | .Sh SEE ALSO 40 | .Xr fold 1 , 41 | .Xr unexpand 1 42 | .Sh STANDARDS 43 | The 44 | .Nm 45 | utility is compliant with the 46 | .St -p1003.1-2013 47 | specification. 48 | .Pp 49 | The 50 | .Op Fl i 51 | flag is an extension to that specification. 52 | -------------------------------------------------------------------------------- /uudecode.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt UUDECODE 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm uudecode 6 | .Nd decode a uuencoded file 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl m 10 | .Op Fl o Ar output 11 | .Op Ar file 12 | .Sh DESCRIPTION 13 | .Nm 14 | reads 15 | .Ar file 16 | and writes a decoded version to the file specified in the uuencoded header. 17 | In case the file already exists, it is truncated. 18 | Otherwise a new file is created. 19 | The permissions of the created/accessed file are changed to reflect the 20 | mode in the header. 21 | If no 22 | .Ar file 23 | is given 24 | .Nm 25 | reads from stdin. 26 | .Sh OPTIONS 27 | .Bl -tag -width Ds 28 | .It Fl m 29 | Use Base64 for decoding. 30 | .It Fl o Ar output 31 | Write to 32 | .Ar output 33 | rather than the file specified in the header. 34 | .El 35 | .Sh IMPLEMENTATION NOTES 36 | For safety uudecode operates on regular files and stdout only. 37 | Trying to uudecode to a link, directory, or special file 38 | yields an error. 39 | .Sh SEE ALSO 40 | .Xr uuencode 1 41 | .Sh STANDARDS 42 | The 43 | .Nm 44 | utility is compliant with the 45 | .St -p1003.1-2013 46 | specification. 47 | .Pp 48 | The 49 | .Op Fl m 50 | flag is an extension to that specification. 51 | -------------------------------------------------------------------------------- /cp.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | 4 | #include "fs.h" 5 | #include "util.h" 6 | 7 | static void 8 | usage(void) 9 | { 10 | eprintf("usage: %s [-afpv] [-R [-H | -L | -P]] source ... dest\n", argv0); 11 | } 12 | 13 | int 14 | main(int argc, char *argv[]) 15 | { 16 | struct stat st; 17 | 18 | ARGBEGIN { 19 | case 'a': 20 | cp_follow = 'P'; 21 | cp_aflag = cp_pflag = cp_rflag = 1; 22 | break; 23 | case 'f': 24 | cp_fflag = 1; 25 | break; 26 | case 'p': 27 | cp_pflag = 1; 28 | break; 29 | case 'r': 30 | case 'R': 31 | cp_rflag = 1; 32 | break; 33 | case 'v': 34 | cp_vflag = 1; 35 | break; 36 | case 'H': 37 | case 'L': 38 | case 'P': 39 | cp_follow = ARGC(); 40 | break; 41 | default: 42 | usage(); 43 | } ARGEND 44 | 45 | if (argc < 2) 46 | usage(); 47 | 48 | if (!cp_follow) 49 | cp_follow = cp_rflag ? 'P' : 'L'; 50 | 51 | if (argc > 2) { 52 | if (stat(argv[argc - 1], &st) < 0) 53 | eprintf("stat %s:", argv[argc - 1]); 54 | if (!S_ISDIR(st.st_mode)) 55 | eprintf("%s: not a directory\n", argv[argc - 1]); 56 | } 57 | enmasse(argc, argv, cp); 58 | 59 | return fshut(stdout, "") || cp_status; 60 | } 61 | -------------------------------------------------------------------------------- /uname.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | 4 | #include 5 | 6 | #include "util.h" 7 | 8 | static void 9 | usage(void) 10 | { 11 | eprintf("usage: %s [-amnrsv]\n", argv0); 12 | } 13 | 14 | int 15 | main(int argc, char *argv[]) 16 | { 17 | struct utsname u; 18 | int mflag = 0, nflag = 0, rflag = 0, sflag = 0, vflag = 0; 19 | 20 | ARGBEGIN { 21 | case 'a': 22 | mflag = nflag = rflag = sflag = vflag = 1; 23 | break; 24 | case 'm': 25 | mflag = 1; 26 | break; 27 | case 'n': 28 | nflag = 1; 29 | break; 30 | case 'r': 31 | rflag = 1; 32 | break; 33 | case 's': 34 | sflag = 1; 35 | break; 36 | case 'v': 37 | vflag = 1; 38 | break; 39 | default: 40 | usage(); 41 | } ARGEND 42 | 43 | if (argc) 44 | usage(); 45 | 46 | if (uname(&u) < 0) 47 | eprintf("uname:"); 48 | 49 | if (sflag || !(nflag || rflag || vflag || mflag)) 50 | putword(stdout, u.sysname); 51 | if (nflag) 52 | putword(stdout, u.nodename); 53 | if (rflag) 54 | putword(stdout, u.release); 55 | if (vflag) 56 | putword(stdout, u.version); 57 | if (mflag) 58 | putword(stdout, u.machine); 59 | putchar('\n'); 60 | 61 | return fshut(stdout, ""); 62 | } 63 | -------------------------------------------------------------------------------- /cols.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt COLS 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm cols 6 | .Nd columnize output 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl c Ar num 10 | .Op Ar file ... 11 | .Sh DESCRIPTION 12 | .Nm 13 | reads each 14 | .Ar file 15 | in sequence and writes them to stdout, in as many vertical 16 | columns as will fit in 17 | .Ar num 18 | character columns. 19 | If no 20 | .Ar file 21 | is given, 22 | .Nm 23 | reads from stdin. 24 | .Pp 25 | By default 26 | .Nm cols 27 | tries to figure out the width of the output device. 28 | If that fails, it defaults to 65 chars. 29 | .Sh OPTIONS 30 | .Bl -tag -width Ds 31 | .It Fl c Ar num 32 | Set maximum number of character columns to 33 | .Ar num , 34 | unless input lines exceed this limit. 35 | .El 36 | .Sh ENVIRONMENT 37 | .Bl -tag -width Ds 38 | .It COLUMNS 39 | The width of the output device. 40 | .El 41 | .Sh HISTORY 42 | .Nm 43 | is similar to 44 | .Xr mc 1 45 | in Plan 9. It was renamed to 46 | .Nm 47 | to avoid the name collision with the popular file manager 48 | Midnight Commander. 49 | .Sh CAVEATS 50 | This implementation of 51 | .Nm 52 | assumes that each UTF-8 code point occupies one character cell, 53 | and thus mishandles TAB characters (among others). 54 | .Pp 55 | .Nm 56 | currently mangles files which contain embedded NULs. 57 | -------------------------------------------------------------------------------- /ln.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt LN 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm ln 6 | .Nd link files 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl f 10 | .Op Fl L | Fl P | Fl s 11 | .Ar target 12 | .Op Ar name 13 | .Nm 14 | .Op Fl f 15 | .Op Fl L | Fl P | Fl s 16 | .Ar target ... 17 | .Ar directory 18 | .Sh DESCRIPTION 19 | .Nm 20 | creates a hard link 21 | .Ar name 22 | to 23 | .Ar target . 24 | If no 25 | .Ar name 26 | is given, a hard link to 27 | .Ar target 28 | is created in the current directory. 29 | If more than one 30 | .Ar target 31 | is given, 32 | .Nm 33 | hardlinks them in the existing 34 | .Ar directory . 35 | .Sh OPTIONS 36 | .Bl -tag -width Ds 37 | .It Fl f 38 | If 39 | .Ar name 40 | exists and is not a 41 | .Ar target , 42 | remove it to allow the link. 43 | .It Fl L | Fl P 44 | If 45 | .Ar target 46 | is a symbolic link, create a hard link to the (referenced file) | 47 | (symbolic link itself). The former is the default. 48 | .It Fl s 49 | Create symbolic links instead of hard links. 50 | Disables 51 | .Fl L 52 | and 53 | .Fl P , 54 | because their purpose does not apply to symbolic links. 55 | .El 56 | .Sh SEE ALSO 57 | .Xr cp 1 , 58 | .Xr link 2 , 59 | .Xr symlink 2 60 | .Sh STANDARDS 61 | The 62 | .Nm 63 | utility is compliant with the 64 | .St -p1003.1-2013 65 | specification. 66 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | /build 3 | /getconf.h 4 | /libutf.a 5 | /libutil.a 6 | /basename 7 | /cal 8 | /cat 9 | /chgrp 10 | /chmod 11 | /chown 12 | /chroot 13 | /cksum 14 | /cmp 15 | /cols 16 | /comm 17 | /cp 18 | /cron 19 | /cut 20 | /date 21 | /dd 22 | /dirname 23 | /du 24 | /echo 25 | /ed 26 | /env 27 | /expand 28 | /expr 29 | /false 30 | /find 31 | /flock 32 | /fold 33 | /getconf 34 | /grep 35 | /head 36 | /hostname 37 | /join 38 | /kill 39 | /link 40 | /ln 41 | /logger 42 | /logname 43 | /ls 44 | /md5sum 45 | /mkdir 46 | /mkfifo 47 | /mknod 48 | /mktemp 49 | /mv 50 | /nice 51 | /nl 52 | /nohup 53 | /od 54 | /paste 55 | /pathchk 56 | /printenv 57 | /printf 58 | /pwd 59 | /readlink 60 | /renice 61 | /rev 62 | /rm 63 | /rmdir 64 | /sed 65 | /seq 66 | /setsid 67 | /sha1sum 68 | /sha224sum 69 | /sha256sum 70 | /sha384sum 71 | /sha512sum 72 | /sha512-224sum 73 | /sha512-256sum 74 | /sleep 75 | /sort 76 | /split 77 | /sponge 78 | /strings 79 | /sync 80 | /tail 81 | /tar 82 | /tee 83 | /test 84 | /tftp 85 | /time 86 | /touch 87 | /tr 88 | /true 89 | /tsort 90 | /tty 91 | /uname 92 | /unexpand 93 | /uniq 94 | /unlink 95 | /uudecode 96 | /uuencode 97 | /wc 98 | /which 99 | /whoami 100 | /xargs 101 | /xinstall 102 | /yes 103 | -------------------------------------------------------------------------------- /mktemp.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt MKTEMP 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm mktemp 6 | .Nd create temporary file or directory 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl dqtu 10 | .Op Fl p Ar directory 11 | .Op Ar template 12 | .Sh DESCRIPTION 13 | .Nm 14 | creates a temporary file by generating a unique filename with 15 | .Ar template , 16 | which has to have at least six 'X's appended to it. 17 | If no 18 | .Ar template 19 | is specified, a default of 'tmp.XXXXXXXXXX' is used and the 20 | tmpdir set to '/tmp' or, if set, the TMPDIR environment variable. 21 | .Sh OPTIONS 22 | .Bl -tag -width Ds 23 | .It Fl d 24 | Create a temporary directory instead of a file. 25 | .It Fl p Ar directory 26 | Use the specified 27 | .Ar directory 28 | as a prefix when generating the temporary filename. 29 | The directory will be overridden by the user's 30 | .Ev TMPDIR 31 | environment variable if it is set. 32 | This option implies the 33 | .Fl t 34 | flag (see below). 35 | .It Fl q 36 | Fail silently if an error occurs. 37 | .It Fl t 38 | Generate a path rooted in a temporary directory. 39 | .It Fl u 40 | Unlink file before 41 | .Nm 42 | exits. 43 | This is slightly better than 44 | .Xr mktemp 3 45 | but still introduces a race condition. 46 | Use of this option is not encouraged. 47 | .El 48 | .Sh SEE ALSO 49 | .Xr mkdtemp 3 , 50 | .Xr mkstemp 3 51 | -------------------------------------------------------------------------------- /tee.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | 6 | #include "util.h" 7 | 8 | static void 9 | usage(void) 10 | { 11 | eprintf("usage: %s [-ai] [file ...]\n", argv0); 12 | } 13 | 14 | int 15 | main(int argc, char *argv[]) 16 | { 17 | int *fds = NULL; 18 | size_t i, nfds; 19 | ssize_t n; 20 | int ret = 0, aflag = O_TRUNC, iflag = 0; 21 | char buf[BUFSIZ]; 22 | 23 | ARGBEGIN { 24 | case 'a': 25 | aflag = O_APPEND; 26 | break; 27 | case 'i': 28 | iflag = 1; 29 | break; 30 | default: 31 | usage(); 32 | } ARGEND 33 | 34 | if (iflag && signal(SIGINT, SIG_IGN) == SIG_ERR) 35 | eprintf("signal:"); 36 | nfds = argc + 1; 37 | fds = ecalloc(nfds, sizeof(*fds)); 38 | 39 | for (i = 0; i < argc; i++) { 40 | if ((fds[i] = open(argv[i], O_WRONLY|O_CREAT|aflag, 0666)) < 0) { 41 | weprintf("open %s:", argv[i]); 42 | ret = 1; 43 | } 44 | } 45 | fds[i] = 1; 46 | 47 | while ((n = read(0, buf, sizeof(buf))) > 0) { 48 | for (i = 0; i < nfds; i++) { 49 | if (fds[i] >= 0 && writeall(fds[i], buf, n) < 0) { 50 | weprintf("write %s:", (i != argc) ? argv[i] : ""); 51 | fds[i] = -1; 52 | ret = 1; 53 | } 54 | } 55 | } 56 | if (n < 0) 57 | eprintf("read :"); 58 | 59 | return ret; 60 | } 61 | -------------------------------------------------------------------------------- /libutil/unescape.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | 5 | #include "../util.h" 6 | 7 | #define is_odigit(c) ('0' <= c && c <= '7') 8 | 9 | size_t 10 | unescape(char *s) 11 | { 12 | static const char escapes[256] = { 13 | ['"'] = '"', 14 | ['\''] = '\'', 15 | ['\\'] = '\\', 16 | ['a'] = '\a', 17 | ['b'] = '\b', 18 | ['E'] = 033, 19 | ['e'] = 033, 20 | ['f'] = '\f', 21 | ['n'] = '\n', 22 | ['r'] = '\r', 23 | ['t'] = '\t', 24 | ['v'] = '\v' 25 | }; 26 | size_t m, q; 27 | char *r, *w; 28 | 29 | for (r = w = s; *r;) { 30 | if (*r != '\\') { 31 | *w++ = *r++; 32 | continue; 33 | } 34 | r++; 35 | if (!*r) { 36 | eprintf("null escape sequence\n"); 37 | } else if (escapes[(unsigned char)*r]) { 38 | *w++ = escapes[(unsigned char)*r++]; 39 | } else if (is_odigit(*r)) { 40 | for (q = 0, m = 4; m && is_odigit(*r); m--, r++) 41 | q = q * 8 + (*r - '0'); 42 | *w++ = MIN(q, 255); 43 | } else if (*r == 'x' && isxdigit(r[1])) { 44 | r++; 45 | for (q = 0, m = 2; m && isxdigit(*r); m--, r++) 46 | if (isdigit(*r)) 47 | q = q * 16 + (*r - '0'); 48 | else 49 | q = q * 16 + (tolower(*r) - 'a' + 10); 50 | *w++ = q; 51 | } else { 52 | eprintf("invalid escape sequence '\\%c'\n", *r); 53 | } 54 | } 55 | *w = '\0'; 56 | 57 | return w - s; 58 | } 59 | -------------------------------------------------------------------------------- /mv.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "fs.h" 9 | #include "util.h" 10 | 11 | static int mv_status = 0; 12 | 13 | static int 14 | mv(const char *s1, const char *s2, int depth) 15 | { 16 | struct recursor r = { .fn = rm, .follow = 'P' }; 17 | 18 | if (!rename(s1, s2)) 19 | return 0; 20 | if (errno == EXDEV) { 21 | cp_aflag = cp_rflag = cp_pflag = 1; 22 | cp_follow = 'P'; 23 | cp_status = 0; 24 | rm_status = 0; 25 | cp(s1, s2, depth); 26 | if (cp_status == 0) 27 | recurse(AT_FDCWD, s1, NULL, &r); 28 | if (cp_status || rm_status) 29 | mv_status = 1; 30 | } else { 31 | weprintf("%s -> %s:", s1, s2); 32 | mv_status = 1; 33 | } 34 | 35 | return 0; 36 | } 37 | 38 | static void 39 | usage(void) 40 | { 41 | eprintf("usage: %s [-f] source ... dest\n", argv0); 42 | } 43 | 44 | int 45 | main(int argc, char *argv[]) 46 | { 47 | struct stat st; 48 | 49 | ARGBEGIN { 50 | case 'f': 51 | break; 52 | default: 53 | usage(); 54 | } ARGEND 55 | 56 | if (argc < 2) 57 | usage(); 58 | 59 | if (argc > 2) { 60 | if (stat(argv[argc - 1], &st) < 0) 61 | eprintf("stat %s:", argv[argc - 1]); 62 | if (!S_ISDIR(st.st_mode)) 63 | eprintf("%s: not a directory\n", argv[argc - 1]); 64 | } 65 | enmasse(argc, argv, mv); 66 | 67 | return mv_status; 68 | } 69 | -------------------------------------------------------------------------------- /libutil/parseoffset.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "../util.h" 9 | 10 | off_t 11 | parseoffset(const char *str) 12 | { 13 | off_t res, scale = 1; 14 | char *end; 15 | 16 | /* strictly check what strtol() usually would let pass */ 17 | if (!str || !*str || isspace(*str) || *str == '+' || *str == '-') { 18 | weprintf("parseoffset %s: invalid value\n", str); 19 | return -1; 20 | } 21 | 22 | errno = 0; 23 | res = strtol(str, &end, 0); 24 | if (errno) { 25 | weprintf("parseoffset %s: invalid value\n", str); 26 | return -1; 27 | } 28 | if (res < 0) { 29 | weprintf("parseoffset %s: negative value\n", str); 30 | return -1; 31 | } 32 | 33 | /* suffix */ 34 | if (*end) { 35 | switch (toupper((int)*end)) { 36 | case 'B': 37 | scale = 512L; 38 | break; 39 | case 'K': 40 | scale = 1024L; 41 | break; 42 | case 'M': 43 | scale = 1024L * 1024L; 44 | break; 45 | case 'G': 46 | scale = 1024L * 1024L * 1024L; 47 | break; 48 | default: 49 | weprintf("parseoffset %s: invalid suffix '%s'\n", str, end); 50 | return -1; 51 | } 52 | } 53 | 54 | /* prevent overflow */ 55 | if (res > (SSIZE_MAX / scale)) { 56 | weprintf("parseoffset %s: out of range\n", str); 57 | return -1; 58 | } 59 | 60 | return res * scale; 61 | } 62 | -------------------------------------------------------------------------------- /libutf/runetype.h: -------------------------------------------------------------------------------- 1 | /* MIT/X Consortium Copyright (c) 2012 Connor Lane Smith 2 | * (c) 2015 Laslo Hunhold 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | 23 | #define nelem(x) (sizeof (x) / sizeof *(x)) 24 | 25 | int rune1cmp(const void *, const void *); 26 | int rune2cmp(const void *, const void *); 27 | -------------------------------------------------------------------------------- /touch.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt TOUCH 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm touch 6 | .Nd set file timestamps 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl acm 10 | .Op Fl d Ar time | Fl r Ar ref_file | Fl T Ar time | Fl t Ar time 11 | .Ar file ... 12 | .Sh DESCRIPTION 13 | .Nm 14 | sets the access and modification time of each 15 | .Ar file 16 | to the current time of day. 17 | If 18 | .Ar file 19 | doesn't exist, it is created with default permissions. 20 | .Sh OPTIONS 21 | .Bl -tag -width Ds 22 | .It Fl a | Fl m 23 | Set the access | modification time of 24 | .Ar file. 25 | .It Fl c 26 | Don't create 27 | .Ar file 28 | if it doesn't exist, not affecting exit status. 29 | .It Fl d Ar time 30 | Set the 31 | .Ar time 32 | of the format YYYY-MM-DDThh:mm:SS[Z] used for 33 | .Op Fl am . 34 | .It Fl r Ar ref_file 35 | Set the 36 | .Ar time 37 | used for 38 | .Op Fl am 39 | to the modification time of 40 | .Ar ref_file . 41 | .It Fl T Ar time 42 | Set the 43 | .Ar time 44 | used for 45 | .Op Fl am 46 | given as the number of seconds since the 47 | Unix epoch 1970-01-01T00:00:00Z. 48 | .It Fl t Ar time 49 | Set the 50 | .Ar time 51 | of the format [[CC]YY]MMDDhhmm[.SS] used for 52 | .Op Fl am . 53 | .El 54 | .Sh SEE ALSO 55 | .Xr date 1 56 | .Sh STANDARDS 57 | The 58 | .Nm 59 | utility is compliant with the 60 | .St -p1003.1-2013 61 | specification except from fractional seconds with 62 | .Op Fl d . 63 | .Pp 64 | The 65 | .Op Fl T 66 | flag is an extension to that specification. 67 | -------------------------------------------------------------------------------- /cp.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt CP 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm cp 6 | .Nd copy files and directories 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl afpv 10 | .Oo 11 | .Fl R 12 | .Op Fl H | L | P 13 | .Oc 14 | .Ar source ... 15 | .Ar dest 16 | .Sh DESCRIPTION 17 | .Nm 18 | copies 19 | .Ar source 20 | to 21 | .Ar dest . 22 | If more than one 23 | .Ar source 24 | is given 25 | .Ar dest 26 | has to be a directory. 27 | .Sh OPTIONS 28 | .Bl -tag -width Ds 29 | .It Fl a 30 | Preserve block devices, character devices, sockets and FIFOs. 31 | Implies 32 | .Fl p , 33 | .Fl P 34 | and 35 | .Fl R . 36 | .It Fl f 37 | If an existing 38 | .Ar dest 39 | cannot be opened, remove it and try again. 40 | .It Fl p 41 | Preserve mode, timestamp and permissions. 42 | .It Fl v 43 | Write "'source' -> 'dest'" for each 44 | .Ar source 45 | to stdout. 46 | .It Fl H 47 | Dereference 48 | .Ar source 49 | if it is a symbolic link. 50 | .It Fl L 51 | Dereference all symbolic links. 52 | This is the default without 53 | .Fl R . 54 | .It Fl P 55 | Preserve symbolic links. 56 | This is the default with 57 | .Fl R . 58 | .It Fl R 59 | Traverse directories recursively. 60 | If this flag is not specified, directories are not copied. 61 | .El 62 | .Sh SEE ALSO 63 | .Xr mv 1 64 | .Sh STANDARDS 65 | The 66 | .Nm 67 | utility is compliant with the 68 | .St -p1003.1-2013 69 | specification except from the 70 | .Op Fl i 71 | flag. 72 | .Pp 73 | The 74 | .Op Fl av 75 | flags are an extension to that specification. 76 | -------------------------------------------------------------------------------- /rev.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | 6 | #include "text.h" 7 | #include "util.h" 8 | 9 | static void 10 | usage(void) 11 | { 12 | eprintf("usage: %s [file ...]\n", argv0); 13 | } 14 | 15 | static void 16 | rev(FILE *fp) 17 | { 18 | static char *line = NULL; 19 | static size_t size = 0; 20 | size_t i; 21 | ssize_t n; 22 | int lf; 23 | 24 | while ((n = getline(&line, &size, fp)) > 0) { 25 | lf = n && line[n - 1] == '\n'; 26 | i = n -= lf; 27 | for (n = 0; i--;) { 28 | if ((line[i] & 0xC0) == 0x80) { 29 | n++; 30 | } else { 31 | fwrite(line + i, 1, n + 1, stdout); 32 | n = 0; 33 | } 34 | } 35 | if (n) 36 | fwrite(line, 1, n, stdout); 37 | if (lf) 38 | fputc('\n', stdout); 39 | } 40 | } 41 | 42 | int 43 | main(int argc, char *argv[]) 44 | { 45 | FILE *fp; 46 | int ret = 0; 47 | 48 | ARGBEGIN { 49 | default: 50 | usage(); 51 | } ARGEND 52 | 53 | if (!argc) { 54 | rev(stdin); 55 | } else { 56 | for (; *argv; argc--, argv++) { 57 | if (!strcmp(*argv, "-")) { 58 | *argv = ""; 59 | fp = stdin; 60 | } else if (!(fp = fopen(*argv, "r"))) { 61 | weprintf("fopen %s:", *argv); 62 | ret = 1; 63 | continue; 64 | } 65 | rev(fp); 66 | if (fp != stdin && fshut(fp, *argv)) 67 | ret = 1; 68 | } 69 | } 70 | 71 | ret |= fshut(stdin, "") | fshut(stdout, ""); 72 | 73 | return ret; 74 | } 75 | -------------------------------------------------------------------------------- /mknod.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #ifndef makedev 5 | #include 6 | #endif 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "util.h" 15 | 16 | static void 17 | usage(void) 18 | { 19 | eprintf("usage: %s [-m mode] name b|c|u major minor\n" 20 | " %s [-m mode] name p\n", 21 | argv0, argv0); 22 | } 23 | 24 | int 25 | main(int argc, char *argv[]) 26 | { 27 | mode_t mode = 0666; 28 | dev_t dev; 29 | 30 | ARGBEGIN { 31 | case 'm': 32 | mode = parsemode(EARGF(usage()), mode, umask(0)); 33 | break; 34 | default: 35 | usage(); 36 | } ARGEND; 37 | 38 | if (argc < 2) 39 | usage(); 40 | 41 | if (strlen(argv[1]) != 1) 42 | goto invalid; 43 | switch (argv[1][0]) { 44 | case 'b': 45 | mode |= S_IFBLK; 46 | break; 47 | case 'u': 48 | case 'c': 49 | mode |= S_IFCHR; 50 | break; 51 | case 'p': 52 | mode |= S_IFIFO; 53 | break; 54 | default: 55 | invalid: 56 | eprintf("invalid type '%s'\n", argv[1]); 57 | } 58 | 59 | if (S_ISFIFO(mode)) { 60 | if (argc != 2) 61 | usage(); 62 | dev = 0; 63 | } else { 64 | if (argc != 4) 65 | usage(); 66 | dev = makedev(estrtonum(argv[2], 0, LLONG_MAX), estrtonum(argv[3], 0, LLONG_MAX)); 67 | } 68 | 69 | if (mknod(argv[0], mode, dev) == -1) 70 | eprintf("mknod %s:", argv[0]); 71 | return 0; 72 | } 73 | -------------------------------------------------------------------------------- /libutil/strcasestr.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2005-2014 Rich Felker, et al. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files (the 6 | * "Software"), to deal in the Software without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be 13 | * included in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | #include 24 | #include 25 | 26 | #include "../util.h" 27 | 28 | char * 29 | strcasestr(const char *h, const char *n) 30 | { 31 | size_t l = strlen(n); 32 | 33 | for (; *h; h++) 34 | if (!strncasecmp(h, n, l)) 35 | return (char *)h; 36 | 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /libutil/strsep.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2005-2014 Rich Felker, et al. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining 5 | * a copy of this software and associated documentation files (the 6 | * "Software"), to deal in the Software without restriction, including 7 | * without limitation the rights to use, copy, modify, merge, publish, 8 | * distribute, sublicense, and/or sell copies of the Software, and to 9 | * permit persons to whom the Software is furnished to do so, subject to 10 | * the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be 13 | * included in all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 17 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 18 | * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY 19 | * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 20 | * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 21 | * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 22 | */ 23 | #include 24 | 25 | #include "../util.h" 26 | 27 | char * 28 | strsep(char **str, const char *sep) 29 | { 30 | char *s = *str, *end; 31 | if (!s) return NULL; 32 | end = s + strcspn(s, sep); 33 | if (*end) *end++ = 0; 34 | else end = 0; 35 | *str = end; 36 | return s; 37 | } 38 | -------------------------------------------------------------------------------- /chmod.1: -------------------------------------------------------------------------------- 1 | .Dd 2019-12-21 2 | .Dt CHMOD 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm chmod 6 | .Nd change file modes 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl R 10 | .Ar mode 11 | .Ar file ... 12 | .Sh DESCRIPTION 13 | .Nm 14 | changes the file mode of each 15 | .Ar file 16 | to 17 | .Ar mode . 18 | .Pp 19 | If 20 | .Ar mode 21 | is 22 | .Em octal 23 | "[sog]e" 24 | .Bl -tag -width Ds 25 | .It s 26 | .Xr sticky 1 => s += 1 27 | .Pp 28 | .Xr setgid 2 => s += 2 29 | .Pp 30 | .Xr setuid 4 => s += 4 31 | .It o|g|e 32 | owner | group | everyone 33 | .Pp 34 | .Xr execute 1 => o|g|e += 1 35 | .Pp 36 | .Xr write 2 => o|g|e += 2 37 | .Pp 38 | .Xr read 4 => o|g|e += 4 39 | .El 40 | .Pp 41 | Leading zeroes may be omitted. 42 | .Pp 43 | If 44 | .Ar mode 45 | is 46 | .Em symbolic 47 | "[ugoa]*[+-=][rwxXst]*" 48 | .Bl -tag -width Ds 49 | .It u|g|o|a 50 | owner | group | other (non-group) | everyone 51 | .It +|-|= 52 | add | remove | set 53 | .It r|w|x|s|t 54 | read | write | execute | setuid and setgid | sticky 55 | .It X 56 | execute, if directory or at least one execute bit is already set 57 | .El 58 | .Pp 59 | Symbolic links are followed if they are passed as operands, and ignored 60 | if they are encountered during directory traversal. 61 | .Sh OPTIONS 62 | .Bl -tag -width Ds 63 | .It Fl R 64 | Change modes recursively. 65 | .El 66 | .Sh SEE ALSO 67 | .Xr chgrp 1 , 68 | .Xr umask 1 69 | .Sh STANDARDS 70 | The 71 | .Nm 72 | utility is compliant with the 73 | .St -p1003.1-2013 74 | specification. 75 | .Pp 76 | The 77 | .Op Fl HLP 78 | flags are an extension to that specification. 79 | -------------------------------------------------------------------------------- /tsort.1: -------------------------------------------------------------------------------- 1 | .Dd 2016-02-16 2 | .Dt TSORT 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm tsort 6 | .Nd topological sort 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Ar file 10 | .Sh DESCRIPTION 11 | .Nm 12 | topologically sorts a graph. 13 | The graph is read either from 14 | .Ar file 15 | or from standard input. 16 | The result is not optimized for any particular usage. 17 | Loops are detected and reported to standard error, but does not stop the 18 | sort. 19 | .Pp 20 | The input is a list of edges (vertex pairs), where 21 | the edge is directed from the first vertex to the 22 | second vertex. 23 | .Sh OPTIONS 24 | None. 25 | .Sh EXIT STATUS 26 | .Bl -tag -width Ds 27 | .It 0 28 | The graph as successfully sorted. 29 | .It 1 30 | The graph as successfully sorted, but contained loops. 31 | .It > 1 32 | An error occurred. 33 | .El 34 | .Sh EXAMPLES 35 | .Bd -literal -offset left 36 | The input 37 | 38 | a a 39 | a b 40 | a c 41 | a c 42 | a d 43 | b c 44 | c b 45 | e f 46 | 47 | or equivalently 48 | 49 | a a a b a c a c a d 50 | b c c b e f 51 | 52 | represents the graph 53 | 54 | ┌─┐ 55 | ↓ │ 56 | ┏━━━┓ 57 | ┌──────┃ a ┃──────┐ 58 | │ ┗━━━┛ │ 59 | │ │ │ │ 60 | ↓ ↓ ↓ ↓ 61 | ┏━━━┓───→┏━━━┓ ┏━━━┓ 62 | ┃ b ┃ ┃ c ┃ ┃ d ┃ 63 | ┗━━━┛←───┗━━━┛ ┗━━━┛ 64 | 65 | ┏━━━┓ ┏━━━┓ 66 | ┃ e ┃───→┃ f ┃ 67 | ┗━━━┛ ┗━━━┛ 68 | .Ed 69 | .Sh STANDARDS 70 | The 71 | .Nm 72 | utility is compliant with the 73 | .St -p1003.1-2013 74 | specification. 75 | -------------------------------------------------------------------------------- /cal.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt CAL 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm cal 6 | .Nd show calendar 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl 1 | Fl 3 | Fl y | Fl n Ar num 10 | .Op Fl s | Fl m | Fl f Ar num 11 | .Op Fl c Ar num 12 | .Oo Oo Ar month Oc Ar year Oc 13 | .Sh DESCRIPTION 14 | .Nm 15 | writes a calendar of 16 | .Ar month 17 | and 18 | .Ar year 19 | or the current month to stdout. 20 | If 21 | .Ar year 22 | is given without 23 | .Ar month , 24 | .Nm 25 | writes a 3-column calendar of the whole 26 | year to stdout. 27 | The date formatting is according to 28 | .Xr localtime 3 . 29 | .Pp 30 | The Julian calendar is used until Sep 2, 1752. 31 | The Gregorian calendar is used starting the next day on Sep 14, 1752. 32 | .Sh OPTIONS 33 | .Bl -tag -width Ds 34 | .It Fl 1 35 | Print current month. 36 | This is the default. 37 | .It Fl 3 38 | Print previous, current and next month. 39 | .It Fl c Ar num 40 | Print 41 | .Ar num 42 | calendars in a row. 43 | The default is 3. 44 | .It Fl f Ar num 45 | Set 46 | .Ar num 47 | (0 is Sunday, 6 is Saturday) as first day of week. 48 | .It Fl m 49 | Set Monday as first day of week. 50 | .It Fl n Ar num 51 | Output 52 | .Ar num 53 | months starting from and including the current month. 54 | .It Fl s 55 | Set Sunday as first day of week. 56 | .It Fl y 57 | Print the entire 58 | .Ar year 59 | or current year. 60 | .El 61 | .Sh SEE ALSO 62 | .Xr localtime 3 63 | .Sh STANDARDS 64 | The 65 | .Nm 66 | utility is compliant with the 67 | .St -p1003.1-2013 68 | specification. 69 | .Pp 70 | The flags 71 | .Op Fl 13cfmnsy 72 | are an extension to that specification. 73 | -------------------------------------------------------------------------------- /arg.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copy me if you can. 3 | * by 20h 4 | */ 5 | 6 | #ifndef ARG_H__ 7 | #define ARG_H__ 8 | 9 | extern char *argv0; 10 | 11 | /* use main(int argc, char *argv[]) */ 12 | #define ARGBEGIN for (argv0 = *argv, argv++, argc--;\ 13 | argv[0] && argv[0][0] == '-'\ 14 | && argv[0][1];\ 15 | argc--, argv++) {\ 16 | char argc_;\ 17 | char **argv_;\ 18 | int brk_;\ 19 | if (argv[0][1] == '-' && argv[0][2] == '\0') {\ 20 | argv++;\ 21 | argc--;\ 22 | break;\ 23 | }\ 24 | for (brk_ = 0, argv[0]++, argv_ = argv;\ 25 | argv[0][0] && !brk_;\ 26 | argv[0]++) {\ 27 | if (argv_ != argv)\ 28 | break;\ 29 | argc_ = argv[0][0];\ 30 | switch (argc_) 31 | 32 | /* Handles obsolete -NUM syntax */ 33 | #define ARGNUM case '0':\ 34 | case '1':\ 35 | case '2':\ 36 | case '3':\ 37 | case '4':\ 38 | case '5':\ 39 | case '6':\ 40 | case '7':\ 41 | case '8':\ 42 | case '9' 43 | 44 | #define ARGEND }\ 45 | } 46 | 47 | #define ARGC() argc_ 48 | 49 | #define ARGNUMF() (brk_ = 1, estrtonum(argv[0], 0, INT_MAX)) 50 | 51 | #define EARGF(x) ((argv[0][1] == '\0' && argv[1] == NULL)?\ 52 | ((x), abort(), (char *)0) :\ 53 | (brk_ = 1, (argv[0][1] != '\0')?\ 54 | (&argv[0][1]) :\ 55 | (argc--, argv++, argv[0]))) 56 | 57 | #define ARGF() ((argv[0][1] == '\0' && argv[1] == NULL)?\ 58 | (char *)0 :\ 59 | (brk_ = 1, (argv[0][1] != '\0')?\ 60 | (&argv[0][1]) :\ 61 | (argc--, argv++, argv[0]))) 62 | 63 | #define LNGARG() &argv[0][0] 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /du.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt DU 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm du 6 | .Nd display disk usage statistics 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl a | s 10 | .Op Fl d Ar depth 11 | .Op Fl h 12 | .Op Fl k 13 | .Op Fl H | L | P 14 | .Op Fl x 15 | .Op Ar file ... 16 | .Sh DESCRIPTION 17 | .Nm 18 | displays the file system block usage for each 19 | .Ar file 20 | argument and for each directory in the file hierarchy rooted in directory 21 | argument. 22 | If no 23 | .Ar file 24 | is specified, the block usage of the hierarchy rooted in the current directory 25 | is displayed. 26 | .Sh OPTIONS 27 | .Bl -tag -width Ds 28 | .It Fl a 29 | Display an entry for each file in the file hierarchy. 30 | .It Fl s 31 | Display only the grand total for the specified files. 32 | .It Fl d Ar depth 33 | Maximum directory depth to print files and directories. 34 | .It Fl h 35 | Enable human-readable output. 36 | .It Fl k 37 | By default all sizes are reported in 512-byte block counts. 38 | The 39 | .Fl k 40 | option causes the numbers to be reported in kilobyte counts. 41 | .It Fl H 42 | Only dereference symbolic links that are passed as command line arguments when 43 | recursively traversing directories. 44 | .It Fl L 45 | Always dereference symbolic links while recursively traversing directories. 46 | .It Fl P 47 | Don't dereference symbolic links. 48 | This is the default. 49 | .It Fl x 50 | Do not traverse file systems mount points. 51 | .El 52 | .Sh STANDARDS 53 | The 54 | .Nm 55 | utility is compliant with the 56 | .St -p1003.1-2013 57 | specification. 58 | .Pp 59 | The 60 | .Op Fl dhP 61 | flags are an extension to that specification. 62 | -------------------------------------------------------------------------------- /libutil/ealloc.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | 5 | #include "../util.h" 6 | 7 | void * 8 | ecalloc(size_t nmemb, size_t size) 9 | { 10 | return encalloc(1, nmemb, size); 11 | } 12 | 13 | void * 14 | emalloc(size_t size) 15 | { 16 | return enmalloc(1, size); 17 | } 18 | 19 | void * 20 | erealloc(void *p, size_t size) 21 | { 22 | return enrealloc(1, p, size); 23 | } 24 | 25 | char * 26 | estrdup(const char *s) 27 | { 28 | return enstrdup(1, s); 29 | } 30 | 31 | char * 32 | estrndup(const char *s, size_t n) 33 | { 34 | return enstrndup(1, s, n); 35 | } 36 | 37 | void * 38 | encalloc(int status, size_t nmemb, size_t size) 39 | { 40 | void *p; 41 | 42 | p = calloc(nmemb, size); 43 | if (!p) 44 | enprintf(status, "calloc: out of memory\n"); 45 | return p; 46 | } 47 | 48 | void * 49 | enmalloc(int status, size_t size) 50 | { 51 | void *p; 52 | 53 | p = malloc(size); 54 | if (!p) 55 | enprintf(status, "malloc: out of memory\n"); 56 | return p; 57 | } 58 | 59 | void * 60 | enrealloc(int status, void *p, size_t size) 61 | { 62 | p = realloc(p, size); 63 | if (!p) 64 | enprintf(status, "realloc: out of memory\n"); 65 | return p; 66 | } 67 | 68 | char * 69 | enstrdup(int status, const char *s) 70 | { 71 | char *p; 72 | 73 | p = strdup(s); 74 | if (!p) 75 | enprintf(status, "strdup: out of memory\n"); 76 | return p; 77 | } 78 | 79 | char * 80 | enstrndup(int status, const char *s, size_t n) 81 | { 82 | char *p; 83 | 84 | p = strndup(s, n); 85 | if (!p) 86 | enprintf(status, "strndup: out of memory\n"); 87 | return p; 88 | } 89 | -------------------------------------------------------------------------------- /libutf/runetype.c: -------------------------------------------------------------------------------- 1 | /* MIT/X Consortium Copyright (c) 2012 Connor Lane Smith 2 | * (c) 2015 Laslo Hunhold 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 20 | * DEALINGS IN THE SOFTWARE. 21 | */ 22 | #include "../utf.h" 23 | 24 | int 25 | rune1cmp(const void *v1, const void *v2) 26 | { 27 | Rune r1 = *(Rune *)v1, r2 = *(Rune *)v2; 28 | 29 | return r1 - r2; 30 | } 31 | 32 | int 33 | rune2cmp(const void *v1, const void *v2) 34 | { 35 | Rune r = *(Rune *)v1, *p = (Rune *)v2; 36 | 37 | if(r >= p[0] && r <= p[1]) 38 | return 0; 39 | else 40 | return r - p[0]; 41 | } 42 | -------------------------------------------------------------------------------- /time.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | 9 | #include "util.h" 10 | 11 | static void 12 | usage(void) 13 | { 14 | eprintf("usage: %s [-p] cmd [arg ...]\n", argv0); 15 | } 16 | 17 | int 18 | main(int argc, char *argv[]) 19 | { 20 | pid_t pid; 21 | struct tms tms; /* user and sys times */ 22 | clock_t r0, r1; /* real time */ 23 | long ticks; /* per second */ 24 | int status, savederrno, ret = 0; 25 | 26 | ARGBEGIN { 27 | case 'p': 28 | break; 29 | default: 30 | usage(); 31 | } ARGEND 32 | 33 | if (!argc) 34 | usage(); 35 | 36 | if ((ticks = sysconf(_SC_CLK_TCK)) <= 0) 37 | eprintf("sysconf _SC_CLK_TCK:"); 38 | 39 | if ((r0 = times(&tms)) == (clock_t)-1) 40 | eprintf("times:"); 41 | 42 | switch ((pid = fork())) { 43 | case -1: 44 | eprintf("fork:"); 45 | case 0: 46 | execvp(argv[0], argv); 47 | savederrno = errno; 48 | weprintf("execvp %s:", argv[0]); 49 | _exit(126 + (savederrno == ENOENT)); 50 | default: 51 | break; 52 | } 53 | waitpid(pid, &status, 0); 54 | 55 | if ((r1 = times(&tms)) == (clock_t)-1) 56 | eprintf("times:"); 57 | 58 | if (WIFSIGNALED(status)) { 59 | fprintf(stderr, "Command terminated by signal %d\n", 60 | WTERMSIG(status)); 61 | ret = 128 + WTERMSIG(status); 62 | } 63 | 64 | fprintf(stderr, "real %f\nuser %f\nsys %f\n", 65 | (r1 - r0) / (double)ticks, 66 | tms.tms_cutime / (double)ticks, 67 | tms.tms_cstime / (double)ticks); 68 | 69 | if (WIFEXITED(status)) 70 | ret = WEXITSTATUS(status); 71 | 72 | return ret; 73 | } 74 | -------------------------------------------------------------------------------- /tr.1: -------------------------------------------------------------------------------- 1 | .Dd 2016-10-05 2 | .Dt TR 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm tr 6 | .Nd translate characters 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl c | Fl C 10 | .Op Fl sd 11 | .Ar set1 set2 12 | .Sh DESCRIPTION 13 | .Nm 14 | matches characters from stdin and performs translations to stdout. 15 | .Sh OPTIONS 16 | .Bl -tag -width Ds 17 | .It Fl c | Fl C 18 | Match to 19 | .Ar set1 20 | complement. 21 | .It Fl d 22 | Delete characters matching 23 | .Ar set1 . 24 | .It Fl s 25 | Squeeze repeated characters matching 26 | .Ar set1 27 | or 28 | .Ar set2 29 | if 30 | .Fl d 31 | is set. 32 | .El 33 | .Sh SET 34 | .Bl -tag -width Ds 35 | .It Literal Sy c 36 | .It Escape sequence Sy \ec 37 | \e\e, \e', \e", \ea, \eb, \ee, \ef, \en, \er, \et, \ev, \exH[H], \eO[OO] 38 | .It Range Sy c-d 39 | .It Repeat Sy [c*n] 40 | Only in 41 | .Ar set2 . 42 | If n = 0 or left out, set n to length of 43 | .Ar set1 . 44 | .It Character class Sy [:class:] 45 | See 46 | .Xr wctype 3 . 47 | .It Equivalence class Sy [=c=] 48 | Resolve to 49 | .Sy c . 50 | .El 51 | .Sh TRANSLATION 52 | If 53 | .Fl d 54 | is not set, 55 | .Nm 56 | translates from 57 | .Ar set1 58 | to 59 | .Ar set2 60 | by index or character class. 61 | .Pp 62 | If 63 | .Ar set2 64 | is shorter than 65 | .Ar set1 66 | or 67 | .Ar set1 68 | is a character class, 69 | overflowing characters translate to the last character in 70 | .Ar set2 . 71 | .Sh EXIT STATUS 72 | .Bl -tag -width Ds 73 | .It 0 74 | Input processed successfully. 75 | .It 1 76 | An error occurred. 77 | .El 78 | .Sh SEE ALSO 79 | .Xr awk 1 , 80 | .Xr sed 1 , 81 | .Xr utf8 7 82 | .Sh STANDARDS 83 | The 84 | .Nm 85 | utility is compliant with the 86 | .St -p1003.1-2013 87 | specification except from equivalence classes. 88 | -------------------------------------------------------------------------------- /flock.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "util.h" 11 | 12 | static void 13 | usage(void) 14 | { 15 | eprintf("usage: %s [-nosux] file cmd [arg ...]\n", argv0); 16 | } 17 | 18 | int 19 | main(int argc, char *argv[]) 20 | { 21 | int fd, status, savederrno, flags = LOCK_EX, nonblk = 0, oflag = 0; 22 | pid_t pid; 23 | 24 | ARGBEGIN { 25 | case 'n': 26 | nonblk = LOCK_NB; 27 | break; 28 | case 'o': 29 | oflag = 1; 30 | break; 31 | case 's': 32 | flags = LOCK_SH; 33 | break; 34 | case 'u': 35 | flags = LOCK_UN; 36 | break; 37 | case 'x': 38 | flags = LOCK_EX; 39 | break; 40 | default: 41 | usage(); 42 | } ARGEND 43 | 44 | if (argc < 2) 45 | usage(); 46 | 47 | if ((fd = open(*argv, O_RDONLY | O_CREAT, 0644)) < 0) 48 | eprintf("open %s:", *argv); 49 | 50 | if (flock(fd, flags | nonblk)) { 51 | if (nonblk && errno == EWOULDBLOCK) 52 | return 1; 53 | eprintf("flock:"); 54 | } 55 | 56 | switch ((pid = fork())) { 57 | case -1: 58 | eprintf("fork:"); 59 | case 0: 60 | if (oflag && close(fd) < 0) 61 | eprintf("close:"); 62 | argv++; 63 | execvp(*argv, argv); 64 | savederrno = errno; 65 | weprintf("execvp %s:", *argv); 66 | _exit(126 + (savederrno == ENOENT)); 67 | default: 68 | break; 69 | } 70 | if (waitpid(pid, &status, 0) < 0) 71 | eprintf("waitpid:"); 72 | 73 | if (close(fd) < 0) 74 | eprintf("close:"); 75 | 76 | if (WIFSIGNALED(status)) 77 | return 128 + WTERMSIG(status); 78 | if (WIFEXITED(status)) 79 | return WEXITSTATUS(status); 80 | 81 | return 0; 82 | } 83 | -------------------------------------------------------------------------------- /head.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "util.h" 8 | 9 | static void 10 | head(FILE *fp, const char *fname, size_t n) 11 | { 12 | char *buf = NULL; 13 | size_t i = 0, size = 0; 14 | ssize_t len; 15 | 16 | while (i < n && (len = getline(&buf, &size, fp)) > 0) { 17 | fwrite(buf, 1, len, stdout); 18 | i += (len && (buf[len - 1] == '\n')); 19 | } 20 | free(buf); 21 | if (ferror(fp)) 22 | eprintf("getline %s:", fname); 23 | } 24 | 25 | static void 26 | usage(void) 27 | { 28 | eprintf("usage: %s [-num | -n num] [file ...]\n", argv0); 29 | } 30 | 31 | int 32 | main(int argc, char *argv[]) 33 | { 34 | size_t n = 10; 35 | FILE *fp; 36 | int ret = 0, newline = 0, many = 0; 37 | 38 | ARGBEGIN { 39 | case 'n': 40 | n = estrtonum(EARGF(usage()), 0, MIN(LLONG_MAX, SIZE_MAX)); 41 | break; 42 | ARGNUM: 43 | n = ARGNUMF(); 44 | break; 45 | default: 46 | usage(); 47 | } ARGEND 48 | 49 | if (!argc) { 50 | head(stdin, "", n); 51 | } else { 52 | many = argc > 1; 53 | for (newline = 0; *argv; argc--, argv++) { 54 | if (!strcmp(*argv, "-")) { 55 | *argv = ""; 56 | fp = stdin; 57 | } else if (!(fp = fopen(*argv, "r"))) { 58 | weprintf("fopen %s:", *argv); 59 | ret = 1; 60 | continue; 61 | } 62 | if (many) { 63 | if (newline) 64 | putchar('\n'); 65 | printf("==> %s <==\n", *argv); 66 | } 67 | newline = 1; 68 | head(fp, *argv, n); 69 | if (fp != stdin && fshut(fp, *argv)) 70 | ret = 1; 71 | } 72 | } 73 | 74 | ret |= fshut(stdin, "") | fshut(stdout, ""); 75 | 76 | return ret; 77 | } 78 | -------------------------------------------------------------------------------- /chgrp.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | #include "fs.h" 10 | #include "util.h" 11 | 12 | static int hflag = 0; 13 | static gid_t gid = -1; 14 | static int ret = 0; 15 | 16 | static void 17 | chgrp(int dirfd, const char *name, struct stat *st, void *data, struct recursor *r) 18 | { 19 | int flags = 0; 20 | 21 | if ((r->maxdepth == 0 && r->follow == 'P') || (r->follow == 'H' && r->depth) || (hflag && !(r->depth))) 22 | flags |= AT_SYMLINK_NOFOLLOW; 23 | if (fchownat(dirfd, name, -1, gid, flags) < 0) { 24 | weprintf("chown %s:", r->path); 25 | ret = 1; 26 | } else if (S_ISDIR(st->st_mode)) { 27 | recurse(dirfd, name, NULL, r); 28 | } 29 | } 30 | 31 | static void 32 | usage(void) 33 | { 34 | eprintf("usage: %s [-h] [-R [-H | -L | -P]] group file ...\n", argv0); 35 | } 36 | 37 | int 38 | main(int argc, char *argv[]) 39 | { 40 | struct group *gr; 41 | struct recursor r = { .fn = chgrp, .maxdepth = 1, .follow = 'P' }; 42 | 43 | ARGBEGIN { 44 | case 'h': 45 | hflag = 1; 46 | break; 47 | case 'R': 48 | r.maxdepth = 0; 49 | break; 50 | case 'H': 51 | case 'L': 52 | case 'P': 53 | r.follow = ARGC(); 54 | break; 55 | default: 56 | usage(); 57 | } ARGEND 58 | 59 | if (argc < 2) 60 | usage(); 61 | 62 | errno = 0; 63 | if ((gr = getgrnam(argv[0]))) { 64 | gid = gr->gr_gid; 65 | } else { 66 | if (errno) 67 | eprintf("getgrnam %s:", argv[0]); 68 | gid = estrtonum(argv[0], 0, UINT_MAX); 69 | } 70 | 71 | for (argc--, argv++; *argv; argc--, argv++) 72 | recurse(AT_FDCWD, *argv, NULL, &r); 73 | 74 | return ret || recurse_status; 75 | } 76 | -------------------------------------------------------------------------------- /tar.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt TAR 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm tar 6 | .Nd create, list or extract a tape archive 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl C Ar dir 10 | .Op Fl J | Fl Z | Fl a | Fl j | Fl z 11 | .Fl x Op Fl m | Fl t 12 | .Op Fl f Ar file 13 | .Op Ar file ... 14 | .Nm 15 | .Op Fl C Ar dir 16 | .Op Fl J | Fl Z | Fl a | Fl j | Fl z 17 | .Op Fl h 18 | .Fl c Ar path ... 19 | .Op Fl f Ar file 20 | .Sh DESCRIPTION 21 | .Nm 22 | is the standard file archiver. 23 | .Sh OPTIONS 24 | .Bl -tag -width Ds 25 | .It Fl c Ar path ... 26 | Create archive from 27 | .Ar path . 28 | .It Fl C Ar dir 29 | Change directory to 30 | .Ar dir 31 | before beginning. 32 | .It Fl f Ar file 33 | Set 34 | .Ar file 35 | as input | output archive instead of stdin | stdout. 36 | If '-', stdin | stdout is used. 37 | .It Fl m 38 | Do not preserve modification time. 39 | .It Fl t 40 | List all files in the archive. 41 | .It Fl x 42 | Extract archive. 43 | .It Fl h 44 | Always dereference symbolic links while recursively traversing directories. 45 | .It Fl J | Fl Z | Fl a | Fl j | Fl z 46 | Use xz | compress | lzma | bzip2 | gzip compression or decompression. 47 | These utilities must be installed separately. 48 | Using these flags is discouraged in favour of the flexibility 49 | and clarity of pipes: 50 | .Bd -literal -offset indent 51 | $ bzip2 -cd archive.tar.bz2 | tar -x 52 | $ gzip -cd archive.tar.gz | tar -x 53 | .Ed 54 | .Bd -literal -offset indent 55 | $ tar -c file ... | bzip2 > archive.tar.bz2 56 | $ tar -c file ... | gzip2 > archive.tar.gz 57 | .Ed 58 | .El 59 | .Sh SEE ALSO 60 | .Xr ar 1 , 61 | .Xr bzip2 1 , 62 | .Xr gzip 1 63 | .Sh STANDARDS 64 | The 65 | .Nm 66 | utility is compliant with the UStar (Uniform Standard Tape ARchive) 67 | format defined in the 68 | .St -p1003.1-88 69 | specification. 70 | -------------------------------------------------------------------------------- /cmp.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | 6 | #include "util.h" 7 | 8 | static void 9 | usage(void) 10 | { 11 | enprintf(2, "usage: %s [-l | -s] file1 file2\n", argv0); 12 | } 13 | 14 | int 15 | main(int argc, char *argv[]) 16 | { 17 | FILE *fp[2]; 18 | size_t line = 1, n; 19 | int ret = 0, lflag = 0, sflag = 0, same = 1, b[2]; 20 | 21 | ARGBEGIN { 22 | case 'l': 23 | lflag = 1; 24 | break; 25 | case 's': 26 | sflag = 1; 27 | break; 28 | default: 29 | usage(); 30 | } ARGEND 31 | 32 | if (argc != 2 || (lflag && sflag)) 33 | usage(); 34 | 35 | for (n = 0; n < 2; n++) { 36 | if (!strcmp(argv[n], "-")) { 37 | argv[n] = ""; 38 | fp[n] = stdin; 39 | } else { 40 | if (!(fp[n] = fopen(argv[n], "r"))) { 41 | if (!sflag) 42 | weprintf("fopen %s:", argv[n]); 43 | return 2; 44 | } 45 | } 46 | } 47 | 48 | for (n = 1; ; n++) { 49 | b[0] = getc(fp[0]); 50 | b[1] = getc(fp[1]); 51 | 52 | if (b[0] == b[1]) { 53 | if (b[0] == EOF) 54 | break; 55 | else if (b[0] == '\n') 56 | line++; 57 | continue; 58 | } else if (b[0] == EOF || b[1] == EOF) { 59 | if (!sflag) 60 | weprintf("EOF on %s\n", argv[(b[0] != EOF)]); 61 | same = 0; 62 | break; 63 | } else if (!lflag) { 64 | if (!sflag) 65 | printf("%s %s differ: byte %zu, line %zu\n", 66 | argv[0], argv[1], n, line); 67 | same = 0; 68 | break; 69 | } else { 70 | printf("%zu %o %o\n", n, b[0], b[1]); 71 | same = 0; 72 | } 73 | } 74 | 75 | if (!ret) 76 | ret = !same; 77 | if (fshut(fp[0], argv[0]) | (fp[0] != fp[1] && fshut(fp[1], argv[1])) | 78 | fshut(stdout, "")) 79 | ret = 2; 80 | 81 | return ret; 82 | } 83 | -------------------------------------------------------------------------------- /cut.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt CUT 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm cut 6 | .Nd extract columns of data 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Fl b Ar list 10 | .Op Fl n 11 | .Op Ar file ... 12 | .Nm 13 | .Fl c Ar list 14 | .Op Ar file ... 15 | .Nm 16 | .Fl f Ar list 17 | .Op Fl d Ar delim 18 | .Op Fl s 19 | .Op Ar file ... 20 | .Sh DESCRIPTION 21 | .Nm 22 | out bytes, characters or delimited fields from each line of 23 | .Ar file 24 | and write to stdout. 25 | .Pp 26 | If no 27 | .Ar file 28 | is given or 29 | .Ar file 30 | is '-', 31 | .Nm 32 | reads from stdin. 33 | .Pp 34 | .Ar list 35 | is a comma or space separated list of numbers and ranges starting 36 | from 1. 37 | Ranges have the form 'N-M'. If N or M is missing, beginning or end 38 | of line is assumed. 39 | Numbers and ranges may be repeated, overlapping and in any order. 40 | .Pp 41 | Selected input is written in the same order it is read 42 | and is written exactly once. 43 | .Sh OPTIONS 44 | .Bl -tag -width Ds 45 | .It Fl b Ar list | Fl c Ar list 46 | .Ar list 47 | specifies byte | character positions. 48 | .It Fl d Ar delim 49 | Use 50 | .Ar delim 51 | as field delimiter, which can be an arbitrary string. 52 | Default is '\et'. 53 | .It Fl f Ar list 54 | .Ar list 55 | specifies field numbers. 56 | Lines not containing field delimiters are passed through, unless 57 | .Fl s 58 | is specified. 59 | .It Fl n 60 | Do not split multibyte characters. 61 | A character is written when its last byte is selected. 62 | .It Fl s 63 | Suppress lines not containing field delimiters. 64 | .El 65 | .Sh STANDARDS 66 | The 67 | .Nm 68 | utility is compliant with the 69 | .St -p1003.1-2013 70 | specification. 71 | .Pp 72 | The possibility of separating numbers and ranges with a space and specifying 73 | multibyte delimiters of arbitrary length is an extension to that specification. 74 | -------------------------------------------------------------------------------- /libutil/reallocarray.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2008 Otto Moerbeek 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | #include "../util.h" 23 | 24 | /* 25 | * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX 26 | * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW 27 | */ 28 | #define MUL_NO_OVERFLOW (1UL << (sizeof(size_t) * 4)) 29 | 30 | void * 31 | reallocarray(void *optr, size_t nmemb, size_t size) 32 | { 33 | if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) && 34 | nmemb > 0 && SIZE_MAX / nmemb < size) { 35 | errno = ENOMEM; 36 | return NULL; 37 | } 38 | return realloc(optr, size * nmemb); 39 | } 40 | 41 | void * 42 | ereallocarray(void *optr, size_t nmemb, size_t size) 43 | { 44 | return enreallocarray(1, optr, nmemb, size); 45 | } 46 | 47 | void * 48 | enreallocarray(int status, void *optr, size_t nmemb, size_t size) 49 | { 50 | void *p; 51 | 52 | if (!(p = reallocarray(optr, nmemb, size))) 53 | enprintf(status, "reallocarray: out of memory\n"); 54 | 55 | return p; 56 | } 57 | -------------------------------------------------------------------------------- /chmod.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | 5 | #include "fs.h" 6 | #include "util.h" 7 | 8 | static char *modestr = ""; 9 | static mode_t mask = 0; 10 | static int ret = 0; 11 | 12 | static void 13 | chmodr(int dirfd, const char *name, struct stat *st, void *data, struct recursor *r) 14 | { 15 | mode_t m; 16 | 17 | m = parsemode(modestr, st->st_mode, mask); 18 | if (!S_ISLNK(st->st_mode) && fchmodat(dirfd, name, m, 0) < 0) { 19 | weprintf("chmod %s:", r->path); 20 | ret = 1; 21 | } else if (S_ISDIR(st->st_mode)) { 22 | recurse(dirfd, name, NULL, r); 23 | } 24 | } 25 | 26 | static void 27 | usage(void) 28 | { 29 | eprintf("usage: %s [-R] mode file ...\n", argv0); 30 | } 31 | 32 | int 33 | main(int argc, char *argv[]) 34 | { 35 | struct recursor r = { .fn = chmodr, .maxdepth = 1, .follow = 'H', .flags = DIRFIRST }; 36 | size_t i; 37 | 38 | argv0 = *argv, argv0 ? (argc--, argv++) : (void *)0; 39 | 40 | for (; *argv && (*argv)[0] == '-'; argc--, argv++) { 41 | if (!(*argv)[1]) 42 | usage(); 43 | for (i = 1; (*argv)[i]; i++) { 44 | switch ((*argv)[i]) { 45 | case 'R': 46 | r.maxdepth = 0; 47 | break; 48 | case 'r': case 'w': case 'x': case 'X': case 's': case 't': 49 | /* -[rwxXst] are valid modes, so we're done */ 50 | if (i == 1) 51 | goto done; 52 | /* fallthrough */ 53 | case '-': 54 | /* -- terminator */ 55 | if (i == 1 && !(*argv)[i + 1]) { 56 | argv++; 57 | argc--; 58 | goto done; 59 | } 60 | /* fallthrough */ 61 | default: 62 | usage(); 63 | } 64 | } 65 | } 66 | done: 67 | mask = getumask(); 68 | modestr = *argv; 69 | 70 | if (argc < 2) 71 | usage(); 72 | 73 | for (--argc, ++argv; *argv; argc--, argv++) 74 | recurse(AT_FDCWD, *argv, NULL, &r); 75 | 76 | return ret || recurse_status; 77 | } 78 | -------------------------------------------------------------------------------- /renice.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "util.h" 9 | 10 | #ifndef PRIO_MIN 11 | #define PRIO_MIN -NZERO 12 | #endif 13 | 14 | #ifndef PRIO_MAX 15 | #define PRIO_MAX (NZERO-1) 16 | #endif 17 | 18 | static int 19 | renice(int which, int who, long adj) 20 | { 21 | errno = 0; 22 | adj += getpriority(which, who); 23 | if (errno) { 24 | weprintf("getpriority %d:", who); 25 | return 0; 26 | } 27 | 28 | adj = MAX(PRIO_MIN, MIN(adj, PRIO_MAX)); 29 | if (setpriority(which, who, (int)adj) < 0) { 30 | weprintf("setpriority %d:", who); 31 | return 0; 32 | } 33 | 34 | return 1; 35 | } 36 | 37 | static void 38 | usage(void) 39 | { 40 | eprintf("usage: %s -n num [-g | -p | -u] id ...\n", argv0); 41 | } 42 | 43 | int 44 | main(int argc, char *argv[]) 45 | { 46 | const char *adj = NULL; 47 | long val; 48 | int which = PRIO_PROCESS, ret = 0; 49 | struct passwd *pw; 50 | int who; 51 | 52 | ARGBEGIN { 53 | case 'n': 54 | adj = EARGF(usage()); 55 | break; 56 | case 'g': 57 | which = PRIO_PGRP; 58 | break; 59 | case 'p': 60 | which = PRIO_PROCESS; 61 | break; 62 | case 'u': 63 | which = PRIO_USER; 64 | break; 65 | default: 66 | usage(); 67 | } ARGEND 68 | 69 | if (!argc || !adj) 70 | usage(); 71 | 72 | val = estrtonum(adj, PRIO_MIN, PRIO_MAX); 73 | for (; *argv; argc--, argv++) { 74 | if (which == PRIO_USER) { 75 | errno = 0; 76 | if (!(pw = getpwnam(*argv))) { 77 | if (errno) 78 | weprintf("getpwnam %s:", *argv); 79 | else 80 | weprintf("getpwnam %s: no user found\n", *argv); 81 | ret = 1; 82 | continue; 83 | } 84 | who = pw->pw_uid; 85 | } else { 86 | who = estrtonum(*argv, 1, INT_MAX); 87 | } 88 | if (!renice(which, who, val)) 89 | ret = 1; 90 | } 91 | 92 | return ret; 93 | } 94 | -------------------------------------------------------------------------------- /xinstall.1: -------------------------------------------------------------------------------- 1 | .Dd 2016-12-03 2 | .Dt INSTALL 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm install 6 | .Nd copy files and set attributes 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl g Ar group 10 | .Op Fl o Ar owner 11 | .Op Fl m Ar mode 12 | .Po 13 | .Fl d Ar dir ... 14 | | 15 | .Op Fl D 16 | .Po 17 | .Fl t Ar dest 18 | .Ar source ... 19 | | 20 | .Ar source ... 21 | .Ar dest 22 | .Pc 23 | .Pc 24 | .Sh DESCRIPTION 25 | .Nm 26 | copies 27 | .Ar source 28 | to 29 | .Ar dest . 30 | If more than one 31 | .Ar source 32 | is given 33 | .Ar dest 34 | is treated as a directory. 35 | Otherwise 36 | .Ar dest 37 | is treated as a filename. 38 | .Nm 39 | can also change the attributes of the copies. 40 | .Sh OPTIONS 41 | .Bl -tag -width Ds 42 | .It Fl d 43 | Create the directories 44 | .Ar dir . 45 | .It Fl D 46 | Create missing parent directories to 47 | .Ar dest . 48 | If 49 | .Ar dest 50 | is to be treated as a directory, it is created too if missing. 51 | .It Fl g Ar group 52 | Change the installed files' group to 53 | .Ar group . 54 | This may be a group name or a group identifier. 55 | .It Fl m Ar mode 56 | Change the file modes. 57 | Both numerical and symbolic values are supported. 58 | See 59 | .Xr chmod 1 60 | for the syntex. 61 | Default mode 0755. 62 | If a file has the mode 0644 and is copied with 63 | .It Fl o Ar owner 64 | Change the installed files' owner to 65 | .Ar owner . 66 | This may be a user name or a user identifier. 67 | .It Fl t Ar dest 68 | Copy files into the directory 69 | .Ar dest . 70 | .Nm install , 71 | the copy's mode will be 0755 unless 72 | .Fl m 73 | is used to select another mode. 74 | When the symbolic notation is used, the base mode is 0000. 75 | .El 76 | .Sh SEE ALSO 77 | .Xr chmod 1 , 78 | .Xr chown 1 , 79 | .Xr cp 1 , 80 | .Xr mkdir 1 81 | .Sh STANDARDS 82 | The 83 | .Nm 84 | utility is not standardized. 85 | This implementation is a subset of the GNU implementation and a subset 86 | with extensions to the FreeBSD implementation. 87 | -------------------------------------------------------------------------------- /date.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt DATE 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm date 6 | .Nd print or set date and time 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl d Ar time 10 | .Op Fl u 11 | .Oo 12 | .Cm + Ns Ar format | 13 | .Sm off 14 | .Ar mmddHHMM Oo Oo Ar CC Oc Ar yy Oc 15 | .Sm on 16 | .Oc 17 | .Sh DESCRIPTION 18 | .Nm 19 | prints the date and time according to 20 | .Xr locale 7 21 | or 22 | .Ar format 23 | using 24 | .Xr strftime 3 25 | or sets the date. 26 | .Sh OPTIONS 27 | .Bl -tag -width Ds 28 | .It Fl d Ar time 29 | Print 30 | .Ar time 31 | given as the number of seconds since the 32 | Unix epoch 1970-01-01T00:00:00Z. 33 | .It Fl u 34 | Print or set UTC time instead of local time. 35 | .El 36 | .Pp 37 | An operand with a leading plus 38 | .Pq Cm + 39 | sign signals a user-defined format string using 40 | .Xr strftime 3 41 | conversion specifications. 42 | .Pp 43 | An operand without a leading plus sign is interpreted as a value 44 | for setting the system's current date and time. 45 | The canonical representation for setting the date and time is: 46 | .Pp 47 | .Bl -tag -width Ds -compact -offset indent 48 | .It Ar mm 49 | The month of the year, from 01 to 12. 50 | .It Ar dd 51 | The day of the month, from 01 to 31. 52 | .It Ar HH 53 | The hour of the day, from 00 to 23. 54 | .It Ar MM 55 | The minute of the hour, from 00 to 59. 56 | .It Ar CC 57 | The first two digits of the year (the century). 58 | .It Ar yy 59 | The second two digits of the year. 60 | If 61 | .Ar yy 62 | is specified, but 63 | .Ar CC 64 | is not, a value for 65 | .Ar yy 66 | between 69 and 99 results in a 67 | .Ar CC 68 | value of 19. 69 | Otherwise, a 70 | .Ar CC 71 | value of 20 is used. 72 | .El 73 | .Pp 74 | The century and year are optional. 75 | The default is the current year. 76 | .Sh STANDARDS 77 | The 78 | .Nm 79 | utility is compliant with the 80 | .St -p1003.1-2013 81 | specification. 82 | .Pp 83 | The 84 | .Op Fl d 85 | flag is an extension to that specification. 86 | -------------------------------------------------------------------------------- /libutil/strlcpy.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1998 Todd C. Miller 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | #include "../util.h" 21 | 22 | /* 23 | * Copy src to string dst of size siz. At most siz-1 characters 24 | * will be copied. Always NUL terminates (unless siz == 0). 25 | * Returns strlen(src); if retval >= siz, truncation occurred. 26 | */ 27 | size_t 28 | strlcpy(char *dst, const char *src, size_t siz) 29 | { 30 | char *d = dst; 31 | const char *s = src; 32 | size_t n = siz; 33 | /* Copy as many bytes as will fit */ 34 | if (n != 0) { 35 | while (--n != 0) { 36 | if ((*d++ = *s++) == '\0') 37 | break; 38 | } 39 | } 40 | /* Not enough room in dst, add NUL and traverse rest of src */ 41 | if (n == 0) { 42 | if (siz != 0) 43 | *d = '\0'; /* NUL-terminate dst */ 44 | while (*s++) 45 | ; 46 | } 47 | return(s - src - 1); /* count does not include NUL */ 48 | } 49 | 50 | size_t 51 | estrlcpy(char *dst, const char *src, size_t siz) 52 | { 53 | size_t ret; 54 | 55 | if ((ret = strlcpy(dst, src, siz)) >= siz) 56 | eprintf("strlcpy: input string too long\n"); 57 | 58 | return ret; 59 | } 60 | -------------------------------------------------------------------------------- /libutil/strnsubst.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2002 J. Mallett. All rights reserved. 3 | * You may do whatever you want with this file as long as 4 | * the above copyright and this notice remain intact, along 5 | * with the following statement: 6 | * For the man who taught me vi, and who got too old, too young. 7 | */ 8 | 9 | #include 10 | #include 11 | #include 12 | 13 | #include "../util.h" 14 | 15 | /* 16 | * Replaces str with a string consisting of str with match replaced with 17 | * replstr as many times as can be done before the constructed string is 18 | * maxsize bytes large. It does not free the string pointed to by str, it 19 | * is up to the calling program to be sure that the original contents of 20 | * str as well as the new contents are handled in an appropriate manner. 21 | * If replstr is NULL, then that internally is changed to a nil-string, so 22 | * that we can still pretend to do somewhat meaningful substitution. 23 | * No value is returned. 24 | */ 25 | void 26 | strnsubst(char **str, const char *match, const char *replstr, size_t maxsize) 27 | { 28 | char *s1, *s2, *this; 29 | size_t matchlen, s2len; 30 | int n; 31 | 32 | if ((s1 = *str) == NULL) 33 | return; 34 | s2 = emalloc(maxsize); 35 | 36 | if (replstr == NULL) 37 | replstr = ""; 38 | 39 | if (match == NULL || *match == '\0' || strlen(s1) >= maxsize) { 40 | strlcpy(s2, s1, maxsize); 41 | goto done; 42 | } 43 | 44 | *s2 = '\0'; 45 | s2len = 0; 46 | matchlen = strlen(match); 47 | for (;;) { 48 | if ((this = strstr(s1, match)) == NULL) 49 | break; 50 | n = snprintf(s2 + s2len, maxsize - s2len, "%.*s%s", 51 | (int)(this - s1), s1, replstr); 52 | if (n == -1 || n + s2len + strlen(this + matchlen) >= maxsize) 53 | break; /* out of room */ 54 | s2len += n; 55 | s1 = this + matchlen; 56 | } 57 | strlcpy(s2 + s2len, s1, maxsize - s2len); 58 | done: 59 | *str = s2; 60 | return; 61 | } 62 | -------------------------------------------------------------------------------- /od.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-25 2 | .Dt OD 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm od 6 | .Nd octal dump 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl bdosvx 10 | .Op Fl A Ar addrformat 11 | .Op Fl E | e 12 | .Op Fl j Ar skip 13 | .Op Fl t Ar outputformat... 14 | .Op Ar file ... 15 | .Sh DESCRIPTION 16 | .Nm 17 | writes an octal dump of each 18 | .Ar file 19 | to stdout. 20 | If no 21 | .Ar file 22 | is given 23 | .Nm 24 | reads from stdin. 25 | .Sh OPTIONS 26 | .Bl -tag -width Ds 27 | .It Fl A Ar addressformat 28 | .Ar addressformat 29 | is one of d|o|x|n and sets the address to be 30 | either in \fId\fRecimal, \fIo\fRctal, he\fIx\fRadecimal or \fIn\fRot 31 | printed at all. 32 | The default is octal. 33 | .It Fl E | e 34 | Force Little Endian 35 | .Fl ( e ) 36 | or Big Endian 37 | .Fl ( E ) 38 | system-independently. 39 | .It Fl b 40 | Equivalent to 41 | .Fl t o1 . 42 | .It Fl d 43 | Equivalent to 44 | .Fl t u2 . 45 | .It Fl j Ar skip 46 | Ignore the first 47 | .Ar skip 48 | bytes of input. 49 | .It Fl o 50 | Equivalent to 51 | .Fl t o2 . 52 | .It Fl s 53 | Equivalent to 54 | .Fl t d2 . 55 | .It Fl t Ar outputformat 56 | .Ar outputformat 57 | is a list of a|c|d|o|u|x followed by a digit or C|S|I|L and sets 58 | the content to be in n\fIa\fRmed character, \fIc\fRharacter, signed 59 | \fId\fRecimal, \fIo\fRctal, \fIu\fRnsigned decimal, or 60 | he\fIx\fRadecimal format, processing the given amount of bytes or the length 61 | of \fIC\fRhar, \fIS\fRhort, \fII\fRnteger or \fIL\fRong. 62 | The default is octal with 4 bytes. 63 | .It Fl v 64 | Always set. 65 | Write all input data, including duplicate lines. 66 | .It Fl x 67 | Equivalent to 68 | .Fl t x2 . 69 | .El 70 | .Sh STANDARDS 71 | The 72 | .Nm 73 | utility is compliant with the 74 | .St -p1003.1-2013 75 | specification except that the 76 | .Op Fl v 77 | flag is always enabled and the 'd' parameter for the 78 | .Op Fl t 79 | flag is interpreted as 'u'. 80 | .Pp 81 | The 82 | .Op Ee 83 | flags are an extension to that specification. 84 | -------------------------------------------------------------------------------- /TODO: -------------------------------------------------------------------------------- 1 | The following list of commands is taken from the toybox roadmap[0] and 2 | has been stripped down accordingly. Commands that belong to ubase[1] 3 | are not listed here as well as commands that fall outside the scope of 4 | sbase such as vi and sh are also not listed here. 5 | 6 | at 7 | awk 8 | bc 9 | diff 10 | patch 11 | stty 12 | 13 | If you are looking for some work to do on sbase, another option is to 14 | pick a utility from the list in the README which has missing flags or 15 | features noted. 16 | 17 | What also needs to be implemented is the capability of the tools to 18 | handle data with NUL-bytes in it. 19 | 20 | The return values of mdcheckline() in crypt.c need to be fixed (0 -> success, 21 | 1 -> error). 22 | 23 | [0] http://landley.net/toybox/roadmap.html 24 | [1] http://git.suckless.org/ubase/ 25 | 26 | Bugs 27 | ==== 28 | 29 | ed 30 | -- 31 | * cat < 3 | 4 | #include "../utf.h" 5 | #include "runetype.h" 6 | 7 | static const Rune digit2[][2] = { 8 | { 0x0030, 0x0039 }, 9 | { 0x0660, 0x0669 }, 10 | { 0x06F0, 0x06F9 }, 11 | { 0x07C0, 0x07C9 }, 12 | { 0x0966, 0x096F }, 13 | { 0x09E6, 0x09EF }, 14 | { 0x0A66, 0x0A6F }, 15 | { 0x0AE6, 0x0AEF }, 16 | { 0x0B66, 0x0B6F }, 17 | { 0x0BE6, 0x0BEF }, 18 | { 0x0C66, 0x0C6F }, 19 | { 0x0CE6, 0x0CEF }, 20 | { 0x0D66, 0x0D6F }, 21 | { 0x0DE6, 0x0DEF }, 22 | { 0x0E50, 0x0E59 }, 23 | { 0x0ED0, 0x0ED9 }, 24 | { 0x0F20, 0x0F29 }, 25 | { 0x1040, 0x1049 }, 26 | { 0x1090, 0x1099 }, 27 | { 0x17E0, 0x17E9 }, 28 | { 0x1810, 0x1819 }, 29 | { 0x1946, 0x194F }, 30 | { 0x19D0, 0x19D9 }, 31 | { 0x1A80, 0x1A89 }, 32 | { 0x1A90, 0x1A99 }, 33 | { 0x1B50, 0x1B59 }, 34 | { 0x1BB0, 0x1BB9 }, 35 | { 0x1C40, 0x1C49 }, 36 | { 0x1C50, 0x1C59 }, 37 | { 0xA620, 0xA629 }, 38 | { 0xA8D0, 0xA8D9 }, 39 | { 0xA900, 0xA909 }, 40 | { 0xA9D0, 0xA9D9 }, 41 | { 0xA9F0, 0xA9F9 }, 42 | { 0xAA50, 0xAA59 }, 43 | { 0xABF0, 0xABF9 }, 44 | { 0xFF10, 0xFF19 }, 45 | { 0x104A0, 0x104A9 }, 46 | { 0x10D30, 0x10D39 }, 47 | { 0x11066, 0x1106F }, 48 | { 0x110F0, 0x110F9 }, 49 | { 0x11136, 0x1113F }, 50 | { 0x111D0, 0x111D9 }, 51 | { 0x112F0, 0x112F9 }, 52 | { 0x11450, 0x11459 }, 53 | { 0x114D0, 0x114D9 }, 54 | { 0x11650, 0x11659 }, 55 | { 0x116C0, 0x116C9 }, 56 | { 0x11730, 0x11739 }, 57 | { 0x118E0, 0x118E9 }, 58 | { 0x11950, 0x11959 }, 59 | { 0x11C50, 0x11C59 }, 60 | { 0x11D50, 0x11D59 }, 61 | { 0x11DA0, 0x11DA9 }, 62 | { 0x11F50, 0x11F59 }, 63 | { 0x16A60, 0x16A69 }, 64 | { 0x16AC0, 0x16AC9 }, 65 | { 0x16B50, 0x16B59 }, 66 | { 0x1D7CE, 0x1D7FF }, 67 | { 0x1E140, 0x1E149 }, 68 | { 0x1E2F0, 0x1E2F9 }, 69 | { 0x1E4F0, 0x1E4F9 }, 70 | { 0x1E950, 0x1E959 }, 71 | { 0x1FBF0, 0x1FBF9 }, 72 | }; 73 | 74 | int 75 | isdigitrune(Rune r) 76 | { 77 | if(bsearch(&r, digit2, nelem(digit2), sizeof *digit2, &rune2cmp)) 78 | return 1; 79 | return 0; 80 | } 81 | -------------------------------------------------------------------------------- /mktemp.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "util.h" 9 | 10 | static void 11 | usage(void) 12 | { 13 | eprintf("usage: %s [-dqtu] [-p directory] [template]\n", argv0); 14 | } 15 | 16 | int 17 | main(int argc, char *argv[]) 18 | { 19 | int dflag = 0, pflag = 0, qflag = 0, tflag = 0, uflag = 0, fd; 20 | char *template = "tmp.XXXXXXXXXX", *tmpdir = "", *pdir, 21 | *p, path[PATH_MAX], tmp[PATH_MAX]; 22 | size_t len; 23 | 24 | ARGBEGIN { 25 | case 'd': 26 | dflag = 1; 27 | break; 28 | case 'p': 29 | pflag = 1; 30 | pdir = EARGF(usage()); 31 | break; 32 | case 'q': 33 | qflag = 1; 34 | break; 35 | case 't': 36 | tflag = 1; 37 | break; 38 | case 'u': 39 | uflag = 1; 40 | break; 41 | default: 42 | usage(); 43 | } ARGEND 44 | 45 | if (argc > 1) 46 | usage(); 47 | else if (argc == 1) 48 | template = argv[0]; 49 | 50 | if (!argc || pflag || tflag) { 51 | if ((p = getenv("TMPDIR"))) 52 | tmpdir = p; 53 | else if (pflag) 54 | tmpdir = pdir; 55 | else 56 | tmpdir = "/tmp"; 57 | } 58 | 59 | len = estrlcpy(path, tmpdir, sizeof(path)); 60 | if (path[0] && path[len - 1] != '/') 61 | estrlcat(path, "/", sizeof(path)); 62 | 63 | estrlcpy(tmp, template, sizeof(tmp)); 64 | p = dirname(tmp); 65 | if (!(p[0] == '.' && p[1] == '\0')) { 66 | if (tflag && !pflag) 67 | eprintf("template must not contain directory separators in -t mode\n"); 68 | } 69 | estrlcat(path, template, sizeof(path)); 70 | 71 | if (dflag) { 72 | if (!mkdtemp(path)) { 73 | if (!qflag) 74 | eprintf("mkdtemp %s:", path); 75 | return 1; 76 | } 77 | } else { 78 | if ((fd = mkstemp(path)) < 0) { 79 | if (!qflag) 80 | eprintf("mkstemp %s:", path); 81 | return 1; 82 | } 83 | if (close(fd)) 84 | eprintf("close %s:", path); 85 | } 86 | if (uflag) 87 | unlink(path); 88 | puts(path); 89 | 90 | efshut(stdout, ""); 91 | return 0; 92 | } 93 | -------------------------------------------------------------------------------- /libutil/strlcat.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 1998 Todd C. Miller 3 | * 4 | * Permission to use, copy, modify, and distribute this software for any 5 | * purpose with or without fee is hereby granted, provided that the above 6 | * copyright notice and this permission notice appear in all copies. 7 | * 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | */ 16 | 17 | #include 18 | #include 19 | 20 | #include "../util.h" 21 | 22 | /* 23 | * Appends src to string dst of size siz (unlike strncat, siz is the 24 | * full size of dst, not space left). At most siz-1 characters 25 | * will be copied. Always NUL terminates (unless siz <= strlen(dst)). 26 | * Returns strlen(src) + MIN(siz, strlen(initial dst)). 27 | * If retval >= siz, truncation occurred. 28 | */ 29 | size_t 30 | strlcat(char *dst, const char *src, size_t siz) 31 | { 32 | char *d = dst; 33 | const char *s = src; 34 | size_t n = siz; 35 | size_t dlen; 36 | /* Find the end of dst and adjust bytes left but don't go past end */ 37 | while (n-- != 0 && *d != '\0') 38 | d++; 39 | dlen = d - dst; 40 | n = siz - dlen; 41 | if (n == 0) 42 | return(dlen + strlen(s)); 43 | while (*s != '\0') { 44 | if (n != 1) { 45 | *d++ = *s; 46 | n--; 47 | } 48 | s++; 49 | } 50 | *d = '\0'; 51 | return(dlen + (s - src)); /* count does not include NUL */ 52 | } 53 | 54 | size_t 55 | estrlcat(char *dst, const char *src, size_t siz) 56 | { 57 | size_t ret; 58 | 59 | if ((ret = strlcat(dst, src, siz)) >= siz) 60 | eprintf("strlcat: input string too long\n"); 61 | 62 | return ret; 63 | } 64 | -------------------------------------------------------------------------------- /logger.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | #define SYSLOG_NAMES 7 | #include 8 | #include 9 | 10 | #include "util.h" 11 | 12 | static int 13 | decodetable(CODE *table, char *name) 14 | { 15 | CODE *c; 16 | 17 | for (c = table; c->c_name; c++) 18 | if (!strcasecmp(name, c->c_name)) 19 | return c->c_val; 20 | eprintf("invalid priority name: %s\n", name); 21 | 22 | return -1; /* not reached */ 23 | } 24 | 25 | static int 26 | decodepri(char *pri) 27 | { 28 | char *lev, *fac = pri; 29 | 30 | if (!(lev = strchr(pri, '.'))) 31 | eprintf("invalid priority name: %s\n", pri); 32 | *lev++ = '\0'; 33 | if (!*lev) 34 | eprintf("invalid priority name: %s\n", pri); 35 | 36 | return (decodetable(facilitynames, fac) & LOG_FACMASK) | 37 | (decodetable(prioritynames, lev) & LOG_PRIMASK); 38 | } 39 | 40 | static void 41 | usage(void) 42 | { 43 | eprintf("usage: %s [-is] [-p priority] [-t tag] [message ...]\n", argv0); 44 | } 45 | 46 | int 47 | main(int argc, char *argv[]) 48 | { 49 | size_t sz; 50 | int logflags = 0, priority = LOG_NOTICE, i; 51 | char *buf = NULL, *tag = NULL; 52 | 53 | ARGBEGIN { 54 | case 'i': 55 | logflags |= LOG_PID; 56 | break; 57 | case 'p': 58 | priority = decodepri(EARGF(usage())); 59 | break; 60 | case 's': 61 | logflags |= LOG_PERROR; 62 | break; 63 | case 't': 64 | tag = EARGF(usage()); 65 | break; 66 | default: 67 | usage(); 68 | } ARGEND 69 | 70 | openlog(tag ? tag : getlogin(), logflags, 0); 71 | 72 | if (!argc) { 73 | while (getline(&buf, &sz, stdin) > 0) 74 | syslog(priority, "%s", buf); 75 | } else { 76 | for (i = 0, sz = 0; i < argc; i++) 77 | sz += strlen(argv[i]); 78 | sz += argc; 79 | buf = ecalloc(1, sz); 80 | for (i = 0; i < argc; i++) { 81 | estrlcat(buf, argv[i], sz); 82 | if (i + 1 < argc) 83 | estrlcat(buf, " ", sz); 84 | } 85 | syslog(priority, "%s", buf); 86 | } 87 | 88 | closelog(); 89 | 90 | return fshut(stdin, ""); 91 | } 92 | -------------------------------------------------------------------------------- /strings.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include "utf.h" 8 | #include "util.h" 9 | 10 | static char *format = ""; 11 | 12 | static void 13 | strings(FILE *fp, const char *fname, size_t min) 14 | { 15 | Rune r, *rbuf; 16 | size_t i, bread; 17 | off_t off; 18 | 19 | rbuf = ereallocarray(NULL, min, sizeof(*rbuf)); 20 | 21 | for (off = 0, i = 0; (bread = efgetrune(&r, fp, fname)); ) { 22 | off += bread; 23 | if (r == Runeerror) 24 | continue; 25 | if (!isprintrune(r)) { 26 | if (i == min) 27 | putchar('\n'); 28 | i = 0; 29 | continue; 30 | } 31 | if (i == min) { 32 | efputrune(&r, stdout, ""); 33 | continue; 34 | } 35 | rbuf[i++] = r; 36 | if (i < min) 37 | continue; 38 | printf(format, (long)off - i); 39 | for (i = 0; i < min; i++) 40 | efputrune(rbuf + i, stdout, ""); 41 | } 42 | free(rbuf); 43 | } 44 | 45 | static void 46 | usage(void) 47 | { 48 | eprintf("usage: %s [-a] [-n num] [-t format] [file ...]\n", argv0); 49 | } 50 | 51 | int 52 | main(int argc, char *argv[]) 53 | { 54 | FILE *fp; 55 | size_t min = 4; 56 | int ret = 0; 57 | char f; 58 | 59 | ARGBEGIN { 60 | case 'a': 61 | break; 62 | case 'n': 63 | min = estrtonum(EARGF(usage()), 1, LLONG_MAX); 64 | break; 65 | case 't': 66 | format = estrdup("%8l#: "); 67 | f = *EARGF(usage()); 68 | if (f == 'd' || f == 'o' || f == 'x') 69 | format[3] = f; 70 | else 71 | usage(); 72 | break; 73 | default: 74 | usage(); 75 | } ARGEND 76 | 77 | if (!argc) { 78 | strings(stdin, "", min); 79 | } else { 80 | for (; *argv; argc--, argv++) { 81 | if (!strcmp(*argv, "-")) { 82 | *argv = ""; 83 | fp = stdin; 84 | } else if (!(fp = fopen(*argv, "r"))) { 85 | weprintf("fopen %s:", *argv); 86 | ret = 1; 87 | continue; 88 | } 89 | strings(fp, *argv, min); 90 | if (fp != stdin && fshut(fp, *argv)) 91 | ret = 1; 92 | } 93 | } 94 | 95 | ret |= fshut(stdin, "") | fshut(stdout, ""); 96 | 97 | return ret; 98 | } 99 | -------------------------------------------------------------------------------- /which.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "util.h" 13 | 14 | static int aflag; 15 | 16 | static int 17 | canexec(int fd, const char *name) 18 | { 19 | struct stat st; 20 | 21 | if (fstatat(fd, name, &st, 0) < 0 || !S_ISREG(st.st_mode)) 22 | return 0; 23 | return faccessat(fd, name, X_OK, AT_EACCESS) == 0; 24 | } 25 | 26 | static int 27 | which(const char *path, const char *name) 28 | { 29 | char *ptr, *p; 30 | size_t i, len; 31 | int dirfd, found = 0; 32 | 33 | if (strchr(name, '/')) { 34 | found = canexec(AT_FDCWD, name); 35 | if (found) 36 | puts(name); 37 | return found; 38 | } 39 | 40 | ptr = p = enstrdup(3, path); 41 | len = strlen(p); 42 | for (i = 0; i < len + 1; i++) { 43 | if (ptr[i] != ':' && ptr[i] != '\0') 44 | continue; 45 | ptr[i] = '\0'; 46 | if ((dirfd = open(p, O_RDONLY)) >= 0) { 47 | if (canexec(dirfd, name)) { 48 | found = 1; 49 | fputs(p, stdout); 50 | if (i && ptr[i - 1] != '/') 51 | fputc('/', stdout); 52 | puts(name); 53 | } 54 | close(dirfd); 55 | if (!aflag && found) 56 | break; 57 | } 58 | p = ptr + i + 1; 59 | } 60 | free(ptr); 61 | 62 | return found; 63 | } 64 | 65 | static void 66 | usage(void) 67 | { 68 | eprintf("usage: %s [-a] name ...\n", argv0); 69 | } 70 | 71 | int 72 | main(int argc, char *argv[]) 73 | { 74 | char *path; 75 | int found = 0, foundall = 1; 76 | 77 | ARGBEGIN { 78 | case 'a': 79 | aflag = 1; 80 | break; 81 | default: 82 | usage(); 83 | } ARGEND 84 | 85 | if (!argc) 86 | usage(); 87 | 88 | if (!(path = getenv("PATH"))) 89 | enprintf(3, "$PATH is not set\n"); 90 | 91 | for (; *argv; argc--, argv++) { 92 | if (which(path, *argv)) { 93 | found = 1; 94 | } else { 95 | weprintf("%s: not an external command\n", *argv); 96 | foundall = 0; 97 | } 98 | } 99 | 100 | return found ? foundall ? 0 : 1 : 2; 101 | } 102 | -------------------------------------------------------------------------------- /comm.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | 6 | #include "text.h" 7 | #include "util.h" 8 | 9 | static int show = 0x07; 10 | 11 | static void 12 | printline(int pos, struct line *line) 13 | { 14 | int i; 15 | 16 | if (!(show & (0x1 << pos))) 17 | return; 18 | 19 | for (i = 0; i < pos; i++) { 20 | if (show & (0x1 << i)) 21 | putchar('\t'); 22 | } 23 | fwrite(line->data, 1, line->len, stdout); 24 | } 25 | 26 | static void 27 | usage(void) 28 | { 29 | eprintf("usage: %s [-123] file1 file2\n", argv0); 30 | } 31 | 32 | int 33 | main(int argc, char *argv[]) 34 | { 35 | FILE *fp[2]; 36 | static struct line line[2]; 37 | size_t linecap[2] = { 0, 0 }; 38 | ssize_t len; 39 | int ret = 0, i, diff = 0, seenline = 0; 40 | 41 | ARGBEGIN { 42 | case '1': 43 | case '2': 44 | case '3': 45 | show &= 0x07 ^ (1 << (ARGC() - '1')); 46 | break; 47 | default: 48 | usage(); 49 | } ARGEND 50 | 51 | if (argc != 2) 52 | usage(); 53 | 54 | for (i = 0; i < 2; i++) { 55 | if (!strcmp(argv[i], "-")) { 56 | argv[i] = ""; 57 | fp[i] = stdin; 58 | } else if (!(fp[i] = fopen(argv[i], "r"))) { 59 | eprintf("fopen %s:", argv[i]); 60 | } 61 | } 62 | 63 | for (;;) { 64 | for (i = 0; i < 2; i++) { 65 | if (diff && i == (diff < 0)) 66 | continue; 67 | if ((len = getline(&(line[i].data), &linecap[i], 68 | fp[i])) > 0) { 69 | line[i].len = len; 70 | seenline = 1; 71 | continue; 72 | } 73 | if (ferror(fp[i])) 74 | eprintf("getline %s:", argv[i]); 75 | if ((diff || seenline) && line[!i].data[0]) 76 | printline(!i, &line[!i]); 77 | while ((len = getline(&(line[!i].data), &linecap[!i], 78 | fp[!i])) > 0) { 79 | line[!i].len = len; 80 | printline(!i, &line[!i]); 81 | } 82 | if (ferror(fp[!i])) 83 | eprintf("getline %s:", argv[!i]); 84 | goto end; 85 | } 86 | diff = linecmp(&line[0], &line[1]); 87 | LIMIT(diff, -1, 1); 88 | seenline = 0; 89 | printline((2 - diff) % 3, &line[MAX(0, diff)]); 90 | } 91 | end: 92 | ret |= fshut(fp[0], argv[0]); 93 | ret |= (fp[0] != fp[1]) && fshut(fp[1], argv[1]); 94 | ret |= fshut(stdout, ""); 95 | 96 | return ret; 97 | } 98 | -------------------------------------------------------------------------------- /scripts/mkbox: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | trap "rm -rf build" INT QUIT TERM 4 | 5 | rm -rf build 6 | mkdir -p build 7 | 8 | cp *.h build 9 | 10 | cat > build/sbase-box.c < 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "util.h" 20 | #include "sbase-box.h" 21 | 22 | struct cmd { 23 | char *name; 24 | int (*fn)(int, char **); 25 | } cmds[] = { 26 | {"install", xinstall_main}, 27 | {"[", test_main}, 28 | $(grep -l ^main *.c | 29 | while read f 30 | do 31 | sed -n ' 32 | /^main/ { 33 | s/main/'${f%.c}'_main/ 34 | s/-/_/g 35 | w build/'$f' 36 | s/\(^.*\)(.*)/ {"'${f%.c}'", \1},/p 37 | d 38 | } 39 | w 'build/$f $f 40 | done) 41 | {NULL}, 42 | }; 43 | 44 | static void 45 | install(char *path) 46 | { 47 | int r; 48 | struct cmd *bp; 49 | char fname[FILENAME_MAX]; 50 | 51 | if (path == NULL) { 52 | fputs("sbase-box [-i path] [command]\n", stderr); 53 | exit(1); 54 | } 55 | 56 | for (bp = cmds; bp->name; ++bp) { 57 | r = snprintf(fname, sizeof(fname), "%s/%s", path, bp->name); 58 | if (r < 0 || r >= sizeof(fname)) { 59 | fprintf(stderr, 60 | "sbase-box: destination path truncated for '%s'\n", 61 | bp->name); 62 | exit(1); 63 | } 64 | remove(fname); 65 | if (symlink("sbase-box", fname) < 0) { 66 | fprintf(stderr, 67 | "sbase-box: %s: %s\n", 68 | bp->name, strerror(errno)); 69 | exit(1); 70 | } 71 | } 72 | } 73 | 74 | int 75 | main(int argc, char *argv[]) 76 | { 77 | char *s = basename(argv[0]); 78 | struct cmd *bp; 79 | 80 | if (!strcmp(s, "sbase-box") && argc > 1) { 81 | argc--; argv++; 82 | if (strcmp(argv[0], "-i") == 0) { 83 | install(argv[1]); 84 | exit(0); 85 | } 86 | s = basename(argv[0]); 87 | } 88 | 89 | for (bp = cmds; bp->name; ++bp) { 90 | if (strcmp(bp->name, s) == 0) 91 | return (*bp->fn)(argc, argv); 92 | } 93 | 94 | for (bp = cmds; bp->name; ++bp) 95 | printf("%s ", bp->name); 96 | putchar('\n'); 97 | 98 | return 0; 99 | } 100 | EOF 101 | 102 | sed -n 's/.* \(.*_main\).*/int \1(int, char **);/p'\ 103 | build/sbase-box.c > build/sbase-box.h 104 | -------------------------------------------------------------------------------- /expr.1: -------------------------------------------------------------------------------- 1 | .Dd 2015-10-08 2 | .Dt EXPR 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm expr 6 | .Nd evaluate expression 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Ar expression 10 | .Sh DESCRIPTION 11 | .Nm 12 | evaluates 13 | .Ar expression 14 | and writes the result to stdout. 15 | .Pp 16 | There are two elemental expressions, 17 | .Sy integer 18 | and 19 | .Sy string. 20 | Let 21 | .Sy expr 22 | be a non-elemental expression and 23 | .Sy expr1 , 24 | .Sy expr2 25 | arbitrary expressions. 26 | Then 27 | .Sy expr 28 | has the recursive form 29 | .Sy expr = [(] expr1 operand expr2 [)]. 30 | .Pp 31 | With 32 | .Sy operand 33 | being in order of increasing precedence: 34 | .Bl -tag -width Ds 35 | .It | 36 | Evaluate to 37 | .Sy expr1 38 | if it is neither an empty string nor 0; otherwise evaluate to 39 | .Sy expr2 . 40 | .It & 41 | Evaluate to 42 | .Sy expr1 43 | if 44 | .Sy expr1 45 | and 46 | .Sy expr2 47 | are neither empty strings nor 0; otherwise evaluate to 0. 48 | .It = > >= < <= != 49 | If 50 | .Sy expr1 51 | and 52 | .Sy expr2 53 | are integers, evaluate to 1 if the relation is true and 0 if it is false. 54 | If 55 | .Sy expr1 56 | and 57 | .Sy expr2 58 | are strings, apply the relation to the return value of 59 | .Xr strcmp 3 . 60 | .It + - 61 | If 62 | .Sy expr1 63 | and 64 | .Sy expr2 65 | are integers, evaluate to their sum or subtraction. 66 | .It * / % 67 | If 68 | .Sy expr1 69 | and 70 | .Sy expr2 71 | are integers, evaluate to their multiplication, division or remainder. 72 | .It : 73 | Evaluate to the number of characters matched in 74 | .Sy expr1 75 | against 76 | .Sy expr2 . expr2 77 | is anchored with an implicit '^'. 78 | .Pp 79 | You can't directly match the empty string, since zero matched characters 80 | resolve equally to a failed match. 81 | To work around this limitation, use "expr X'' : 'X$' instead of "expr '' 82 | : '$'" 83 | .El 84 | .Sh EXIT STATUS 85 | .Bl -tag -width Ds 86 | .It 0 87 | .Ar expression 88 | is neither an empty string nor 0. 89 | .It 1 90 | .Ar expression 91 | is an empty string or 0. 92 | .It 2 93 | .Ar expression 94 | is invalid. 95 | .It > 2 96 | An error occurred. 97 | .El 98 | .Sh SEE ALSO 99 | .Xr test 1 100 | .Sh STANDARDS 101 | The 102 | .Nm 103 | utility is compliant with the 104 | .St -p1003.1-2013 105 | specification. 106 | -------------------------------------------------------------------------------- /dd.1: -------------------------------------------------------------------------------- 1 | .Dd 2020-04-28 2 | .Dt DD 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm dd 6 | .Nd convert and copy a file 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Ar operand Ns ... 10 | .Sh DESCRIPTION 11 | .Nm 12 | copies its input to its output, possibly after conversion, using 13 | the specified block sizes, 14 | .Pp 15 | The following operands are available: 16 | .Bl -tag -width ibs=expr 17 | .It Cm if= Ns Ar file 18 | Read from the file named by 19 | .Ar file 20 | instead of standard input. 21 | .It Cm of= Ns Ar file 22 | Write to the file named by 23 | .Ar file 24 | instead of standard output. 25 | .It Cm ibs= Ns Ar expr 26 | Set the input block size to 27 | .Ar expr 28 | (defaults to 512). 29 | .It Cm obs= Ns Ar expr 30 | Set the output block size to 31 | .Ar expr 32 | (defaults to 512). 33 | .It Cm bs= Ns Ar expr 34 | Set the input and output block sizes to 35 | .Ar expr . 36 | Additionally, if no conversion other than 37 | .Cm noerror , 38 | .Cm notrunc , 39 | or 40 | .Cm sync 41 | is specified, input blocks are copied as single output blocks, even 42 | when the input block is short. 43 | .It Cm skip= Ns Ar n 44 | Skip 45 | .Ar n 46 | input blocks before starting to copy. 47 | .It Cm seek= Ns Ar n 48 | Skip 49 | .Ar n 50 | output blocks before starting to copy. 51 | .It Cm count= Ns Ar n 52 | Copy at most 53 | .Ar n 54 | input blocks. 55 | .It Cm conv= Ns Ar value Ns Op , Ns Ar value Ns ... 56 | Apply the conversions specified by 57 | .Ar value . 58 | .Bl -tag -width Ds 59 | .It Cm lcase 60 | Map uppercase characters to the corresponding lowercase character 61 | using 62 | .Fn tolower . 63 | .It Cm ucase 64 | Map lowercase characters to the corresponding uppercase character 65 | using 66 | .Fn toupper . 67 | .It Cm swab 68 | Swap each pair of bytes in the input block. 69 | If there is an odd number of bytes in a block, the last one is 70 | unmodified. 71 | .It Cm noerror 72 | In case of an error reading from the input, do not fail. 73 | Instead, print a diagnostic message and a summary of the current 74 | status. 75 | .It Cm notrunc 76 | Do not truncate the output file. 77 | .It Cm sync 78 | In case of a partial input block, pad with null bytes to form a 79 | complete block. 80 | .El 81 | .El 82 | .Sh STANDARDS 83 | The 84 | .Nm 85 | utility is compliant with the 86 | .St -p1003.1-2008 87 | specification, except that it does not implement the 88 | .Cm block 89 | and 90 | .Cm unblock 91 | conversions. 92 | -------------------------------------------------------------------------------- /date.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "util.h" 9 | 10 | static void 11 | usage(void) 12 | { 13 | eprintf("usage: %s [-u] [-d time] [+format | mmddHHMM[[CC]yy]]\n", argv0); 14 | } 15 | 16 | static int 17 | datefield(const char *s, size_t i) 18 | { 19 | if (!isdigit(s[i]) || !isdigit(s[i+1])) 20 | eprintf("invalid date format: %s\n", s); 21 | 22 | return (s[i] - '0') * 10 + (s[i+1] - '0'); 23 | } 24 | 25 | static void 26 | setdate(const char *s, struct tm *now) 27 | { 28 | struct tm date; 29 | struct timespec ts; 30 | 31 | switch (strlen(s)) { 32 | case 8: 33 | date.tm_year = now->tm_year; 34 | break; 35 | case 10: 36 | date.tm_year = datefield(s, 8); 37 | if (date.tm_year < 69) 38 | date.tm_year += 100; 39 | break; 40 | case 12: 41 | date.tm_year = ((datefield(s, 8) - 19) * 100) + datefield(s, 10); 42 | break; 43 | default: 44 | eprintf("invalid date format: %s\n", s); 45 | break; 46 | } 47 | 48 | date.tm_mon = datefield(s, 0) - 1; 49 | date.tm_mday = datefield(s, 2); 50 | date.tm_hour = datefield(s, 4); 51 | date.tm_min = datefield(s, 6); 52 | date.tm_sec = 0; 53 | date.tm_isdst = -1; 54 | 55 | ts.tv_sec = mktime(&date); 56 | if (ts.tv_sec == -1) 57 | eprintf("mktime:"); 58 | ts.tv_nsec = 0; 59 | 60 | if (clock_settime(CLOCK_REALTIME, &ts) == -1) 61 | eprintf("clock_settime:"); 62 | } 63 | 64 | int 65 | main(int argc, char *argv[]) 66 | { 67 | struct tm *now; 68 | time_t t; 69 | char buf[BUFSIZ], *fmt = "%a %b %e %H:%M:%S %Z %Y"; 70 | 71 | t = time(NULL); 72 | if (t == -1) 73 | eprintf("time:"); 74 | 75 | ARGBEGIN { 76 | case 'd': 77 | t = estrtonum(EARGF(usage()), 0, LLONG_MAX); 78 | break; 79 | case 'u': 80 | if (setenv("TZ", "UTC0", 1) < 0) 81 | eprintf("setenv:"); 82 | break; 83 | default: 84 | usage(); 85 | } ARGEND 86 | 87 | if (!(now = localtime(&t))) 88 | eprintf("localtime:"); 89 | if (argc) { 90 | if (argc != 1) 91 | usage(); 92 | if (argv[0][0] != '+') { 93 | setdate(argv[0], now); 94 | return 0; 95 | } 96 | fmt = &argv[0][1]; 97 | } 98 | 99 | strftime(buf, sizeof(buf), fmt, now); 100 | puts(buf); 101 | 102 | return fshut(stdout, ""); 103 | } 104 | -------------------------------------------------------------------------------- /sort.1: -------------------------------------------------------------------------------- 1 | .Dd 2016-02-17 2 | .Dt SORT 1 3 | .Os sbase 4 | .Sh NAME 5 | .Nm sort 6 | .Nd sort lines 7 | .Sh SYNOPSIS 8 | .Nm 9 | .Op Fl Cbcdfimnru 10 | .Op Fl o Ar outfile 11 | .Op Fl t Ar delim 12 | .Op Fl k Ar key ... 13 | .Op Ar file ... 14 | .Sh DESCRIPTION 15 | .Nm 16 | writes the sorted concatenation of each 17 | .Ar file 18 | to stdout. 19 | If no 20 | .Ar file 21 | is given 22 | .Nm 23 | reads from stdin. 24 | .Sh OPTIONS 25 | .Bl -tag -width Ds 26 | .It Fl C 27 | Check that the concatenation of the given 28 | .Ar files 29 | is sorted rather than sorting them. 30 | In this mode, no output is printed to stdout, and the exit status 31 | indicates the result of the check. 32 | .It Fl b 33 | Skip leading whitespace of columns when sorting. 34 | .It Fl c 35 | The same as 36 | .Fl C 37 | except that when disorder is detected, a message is written to stderr 38 | indicating the location of the disorder. 39 | .It Fl d 40 | Skip non-whitespace and non-alphanumeric characters. 41 | .It Fl f 42 | Ignore letter case when sorting. 43 | .It Fl i 44 | Skip non-printable characters. 45 | .It Fl k Ar key 46 | Specify a key definition of the form 47 | .Sm off 48 | .Sy S 49 | .No [. 50 | .Sy s 51 | .No ][ 52 | .Sy f 53 | .No ][, 54 | .Sy E 55 | .No [. 56 | .Sy e 57 | .No ][ 58 | .Sy f 59 | .No ]] 60 | .Sm on 61 | where 62 | .Sy S , s , E 63 | and 64 | .Sy e 65 | are the starting column, starting character in that column, ending column and 66 | the ending character of that column respectively. 67 | If they are not specified, 68 | .Sy s 69 | refers to the first character of the specified starting column, 70 | .Sy E 71 | refers to the last column of every line, and 72 | .Sy e 73 | refers to the last character of the ending column. 74 | .Sy f 75 | can be used to specify options 76 | .Sy ( n , b ) 77 | that only apply to this key definition. 78 | .Sy b 79 | is special in that it only applies to the column that it was specified after. 80 | .It Fl m 81 | Assume sorted input, merge only. 82 | .It Fl n 83 | Perform a numeric sort. 84 | .It Fl o Ar outfile 85 | Write output to 86 | .Ar outfile 87 | rather than stdout. 88 | .It Fl r 89 | Reverses the sort. 90 | .It Fl t Ar delim 91 | Set 92 | .Ar delim 93 | as the field delimiter. 94 | .It Fl u 95 | Print equal lines only once. 96 | .El 97 | .Sh STANDARDS 98 | The 99 | .Nm 100 | utility is compliant with the 101 | .St -p1003.1-2013 102 | specification. 103 | -------------------------------------------------------------------------------- /cols.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "text.h" 12 | #include "util.h" 13 | 14 | static void 15 | usage(void) 16 | { 17 | eprintf("usage: %s [-c num] [file ...]\n", argv0); 18 | } 19 | 20 | int 21 | main(int argc, char *argv[]) 22 | { 23 | FILE *fp; 24 | struct winsize w; 25 | struct linebuf b = EMPTY_LINEBUF; 26 | size_t chars = 65, maxlen = 0, i, j, k, len, cols, rows; 27 | int cflag = 0, ret = 0; 28 | char *p; 29 | 30 | ARGBEGIN { 31 | case 'c': 32 | cflag = 1; 33 | chars = estrtonum(EARGF(usage()), 1, MIN(LLONG_MAX, SIZE_MAX)); 34 | break; 35 | default: 36 | usage(); 37 | } ARGEND 38 | 39 | if (!cflag) { 40 | if ((p = getenv("COLUMNS"))) 41 | chars = estrtonum(p, 1, MIN(LLONG_MAX, SIZE_MAX)); 42 | else if (!ioctl(STDOUT_FILENO, TIOCGWINSZ, &w) && w.ws_col > 0) 43 | chars = w.ws_col; 44 | } 45 | 46 | if (!argc) { 47 | getlines(stdin, &b); 48 | } else { 49 | for (; *argv; argc--, argv++) { 50 | if (!strcmp(*argv, "-")) { 51 | *argv = ""; 52 | fp = stdin; 53 | } else if (!(fp = fopen(*argv, "r"))) { 54 | weprintf("fopen %s:", *argv); 55 | ret = 1; 56 | continue; 57 | } 58 | getlines(fp, &b); 59 | if (fp != stdin && fshut(fp, *argv)) 60 | ret = 1; 61 | } 62 | } 63 | 64 | for (i = 0; i < b.nlines; i++) { 65 | for (j = 0, len = 0; j < b.lines[i].len; j++) { 66 | if (UTF8_POINT(b.lines[i].data[j])) 67 | len++; 68 | } 69 | if (len && b.lines[i].data[b.lines[i].len - 1] == '\n') { 70 | b.lines[i].data[--(b.lines[i].len)] = '\0'; 71 | len--; 72 | } 73 | if (len > maxlen) 74 | maxlen = len; 75 | } 76 | 77 | for (cols = 1; (cols + 1) * maxlen + cols <= chars; cols++); 78 | rows = b.nlines / cols + (b.nlines % cols > 0); 79 | 80 | for (i = 0; i < rows; i++) { 81 | for (j = 0; j < cols && i + j * rows < b.nlines; j++) { 82 | for (k = 0, len = 0; k < b.lines[i + j * rows].len; k++) { 83 | if (UTF8_POINT(b.lines[i + j * rows].data[k])) 84 | len++; 85 | } 86 | fwrite(b.lines[i + j * rows].data, 1, 87 | b.lines[i + j * rows].len, stdout); 88 | if (j < cols - 1) 89 | for (k = len; k < maxlen + 1; k++) 90 | putchar(' '); 91 | } 92 | putchar('\n'); 93 | } 94 | 95 | ret |= fshut(stdin, "") | fshut(stdout, ""); 96 | 97 | return ret; 98 | } 99 | -------------------------------------------------------------------------------- /wc.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | 4 | #include "utf.h" 5 | #include "util.h" 6 | 7 | static int lflag = 0; 8 | static int wflag = 0; 9 | static char cmode = 0; 10 | static size_t tc = 0, tl = 0, tw = 0; 11 | 12 | static void 13 | output(const char *str, size_t nc, size_t nl, size_t nw) 14 | { 15 | int first = 1; 16 | 17 | if (lflag) { 18 | first = 0; 19 | printf("%zu", nl); 20 | } 21 | if (wflag) { 22 | if (!first) 23 | putchar(' '); 24 | first = 0; 25 | printf("%zu", nw); 26 | } 27 | if (cmode) { 28 | if (!first) 29 | putchar(' '); 30 | printf("%zu", nc); 31 | } 32 | if (str) 33 | printf(" %s", str); 34 | putchar('\n'); 35 | } 36 | 37 | static void 38 | wc(FILE *fp, const char *str) 39 | { 40 | int word = 0, rlen; 41 | Rune c; 42 | size_t nc = 0, nl = 0, nw = 0; 43 | 44 | while ((rlen = efgetrune(&c, fp, str))) { 45 | nc += (cmode == 'c') ? rlen : (c != Runeerror); 46 | if (c == '\n') 47 | nl++; 48 | if (!isspacerune(c)) 49 | word = 1; 50 | else if (word) { 51 | word = 0; 52 | nw++; 53 | } 54 | } 55 | if (word) 56 | nw++; 57 | tc += nc; 58 | tl += nl; 59 | tw += nw; 60 | output(str, nc, nl, nw); 61 | } 62 | 63 | static void 64 | usage(void) 65 | { 66 | eprintf("usage: %s [-c | -m] [-lw] [file ...]\n", argv0); 67 | } 68 | 69 | int 70 | main(int argc, char *argv[]) 71 | { 72 | FILE *fp; 73 | int many; 74 | int ret = 0; 75 | 76 | ARGBEGIN { 77 | case 'c': 78 | cmode = 'c'; 79 | break; 80 | case 'm': 81 | cmode = 'm'; 82 | break; 83 | case 'l': 84 | lflag = 1; 85 | break; 86 | case 'w': 87 | wflag = 1; 88 | break; 89 | default: 90 | usage(); 91 | } ARGEND 92 | 93 | if (!lflag && !wflag && !cmode) { 94 | cmode = 'c'; 95 | lflag = 1; 96 | wflag = 1; 97 | } 98 | 99 | if (!argc) { 100 | wc(stdin, NULL); 101 | } else { 102 | for (many = (argc > 1); *argv; argc--, argv++) { 103 | if (!strcmp(*argv, "-")) { 104 | *argv = ""; 105 | fp = stdin; 106 | } else if (!(fp = fopen(*argv, "r"))) { 107 | weprintf("fopen %s:", *argv); 108 | ret = 1; 109 | continue; 110 | } 111 | wc(fp, *argv); 112 | if (fp != stdin && fshut(fp, *argv)) 113 | ret = 1; 114 | } 115 | if (many) 116 | output("total", tc, tl, tw); 117 | } 118 | 119 | ret |= fshut(stdin, "") | fshut(stdout, ""); 120 | 121 | return ret; 122 | } 123 | -------------------------------------------------------------------------------- /chown.c: -------------------------------------------------------------------------------- 1 | /* See LICENSE file for copyright and license details. */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "fs.h" 12 | #include "util.h" 13 | 14 | static int hflag = 0; 15 | static uid_t uid = -1; 16 | static gid_t gid = -1; 17 | static int ret = 0; 18 | 19 | static void 20 | chownpwgr(int dirfd, const char *name, struct stat *st, void *data, struct recursor *r) 21 | { 22 | int flags = 0; 23 | 24 | if ((r->maxdepth == 0 && r->follow == 'P') || (r->follow == 'H' && r->depth) || (hflag && !(r->depth))) 25 | flags |= AT_SYMLINK_NOFOLLOW; 26 | 27 | if (fchownat(dirfd, name, uid, gid, flags) < 0) { 28 | weprintf("chown %s:", r->path); 29 | ret = 1; 30 | } else if (S_ISDIR(st->st_mode)) { 31 | recurse(dirfd, name, NULL, r); 32 | } 33 | } 34 | 35 | static void 36 | usage(void) 37 | { 38 | eprintf("usage: %s [-h] [-R [-H | -L | -P]] owner[:[group]] file ...\n" 39 | " %s [-h] [-R [-H | -L | -P]] :group file ...\n", 40 | argv0, argv0); 41 | } 42 | 43 | int 44 | main(int argc, char *argv[]) 45 | { 46 | struct group *gr; 47 | struct passwd *pw; 48 | struct recursor r = { .fn = chownpwgr, .maxdepth = 1, .follow = 'P' }; 49 | char *owner, *group; 50 | 51 | ARGBEGIN { 52 | case 'h': 53 | hflag = 1; 54 | break; 55 | case 'r': 56 | case 'R': 57 | r.maxdepth = 0; 58 | break; 59 | case 'H': 60 | case 'L': 61 | case 'P': 62 | r.follow = ARGC(); 63 | break; 64 | default: 65 | usage(); 66 | } ARGEND 67 | 68 | if (argc < 2) 69 | usage(); 70 | 71 | owner = argv[0]; 72 | if ((group = strchr(owner, ':'))) 73 | *group++ = '\0'; 74 | 75 | if (owner && *owner) { 76 | errno = 0; 77 | pw = getpwnam(owner); 78 | if (pw) { 79 | uid = pw->pw_uid; 80 | } else { 81 | if (errno) 82 | eprintf("getpwnam %s:", owner); 83 | uid = estrtonum(owner, 0, UINT_MAX); 84 | } 85 | } 86 | if (group && *group) { 87 | errno = 0; 88 | gr = getgrnam(group); 89 | if (gr) { 90 | gid = gr->gr_gid; 91 | } else { 92 | if (errno) 93 | eprintf("getgrnam %s:", group); 94 | gid = estrtonum(group, 0, UINT_MAX); 95 | } 96 | } 97 | if (uid == (uid_t)-1 && gid == (gid_t)-1) 98 | usage(); 99 | 100 | for (argc--, argv++; *argv; argc--, argv++) 101 | recurse(AT_FDCWD, *argv, NULL, &r); 102 | 103 | return ret || recurse_status; 104 | } 105 | --------------------------------------------------------------------------------