aboutsummaryrefslogtreecommitdiff
path: root/usr.bin/units
diff options
context:
space:
mode:
authorSimon J. Gerraty <sjg@FreeBSD.org>2014-04-28 07:50:45 +0000
committerSimon J. Gerraty <sjg@FreeBSD.org>2014-04-28 07:50:45 +0000
commit3b8f08459569bf0faa21473e5cec2491e95c9349 (patch)
tree80f45dd81ca716bcd7ca9674581e1fc40b93cd34 /usr.bin/units
parent9d2ab4a62d6733c45958627ac113bdbd818d1e2a (diff)
parentb2ba55951383498f252746f618d513139da06e8e (diff)
downloadsrc-3b8f08459569bf0faa21473e5cec2491e95c9349.tar.gz
src-3b8f08459569bf0faa21473e5cec2491e95c9349.zip
Notes
Diffstat (limited to 'usr.bin/units')
-rw-r--r--usr.bin/units/Makefile3
-rw-r--r--usr.bin/units/units.115
-rw-r--r--usr.bin/units/units.c188
-rw-r--r--usr.bin/units/units.lib12
4 files changed, 154 insertions, 64 deletions
diff --git a/usr.bin/units/Makefile b/usr.bin/units/Makefile
index cb783ab95bb2..ebd1e0724f3a 100644
--- a/usr.bin/units/Makefile
+++ b/usr.bin/units/Makefile
@@ -4,4 +4,7 @@ PROG= units
FILES= units.lib
FILESDIR= ${SHAREDIR}/misc
+LDADD+=-ledit -ltermcap
+DPADD+=${LIBEDIT} ${LIBTERMCAP}
+
.include <bsd.prog.mk>
diff --git a/usr.bin/units/units.1 b/usr.bin/units/units.1
index a7371c1889ea..83f2d9ed094f 100644
--- a/usr.bin/units/units.1
+++ b/usr.bin/units/units.1
@@ -1,5 +1,5 @@
.\" $FreeBSD$
-.Dd July 14, 1993
+.Dd April 14, 2014
.Dt UNITS 1
.Os
.Sh NAME
@@ -8,7 +8,7 @@
.Sh SYNOPSIS
.Nm
.Op Fl f Ar filename
-.Op Fl qv
+.Op Fl qvUV
.Op Ar from-unit to-unit
.Sh OPTIONS
The following options are available:
@@ -18,14 +18,21 @@ Specify the name of the units data file to load.
.It Fl q
Suppress prompting of the user for units and the display of statistics
about the number of units loaded.
-.It Fl v
-Print the version number.
+.It Fl U
+If the default unit file exists prints its location. If not, print
+.Qo
+Units data file not found
+.Qc
+.It Fl V
+Print the version number, usage, and then exit.
.It Ar from-unit to-unit
Allow a single unit conversion to be done directly from the command
line.
The program will not print prompts.
It will print out the
result of the single specified conversion.
+.It Fl v
+Print the units in the conversion output. Be more verbose in general.
.El
.Sh DESCRIPTION
The
diff --git a/usr.bin/units/units.c b/usr.bin/units/units.c
index 3f4dfd1cea69..70bd9ec5b63a 100644
--- a/usr.bin/units/units.c
+++ b/usr.bin/units/units.c
@@ -22,14 +22,17 @@ static const char rcsid[] =
#include <ctype.h>
#include <err.h>
+#include <errno.h>
+#include <histedit.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include "pathnames.h"
+#include <sys/capsicum.h>
-#define VERSION "1.0"
+#include "pathnames.h"
#ifndef UNITSFILE
#define UNITSFILE _PATH_UNITSLIB
@@ -73,25 +76,35 @@ static char NULLUNIT[] = "";
static int unitcount;
static int prefixcount;
-
-char *dupstr(const char *str);
-void readunits(const char *userfile);
-void initializeunit(struct unittype * theunit);
-int addsubunit(char *product[], char *toadd);
-void showunit(struct unittype * theunit);
-void zeroerror(void);
-int addunit(struct unittype *theunit, char *toadd, int flip, int quantity);
-int compare(const void *item1, const void *item2);
-void sortunit(struct unittype * theunit);
-void cancelunit(struct unittype * theunit);
-char *lookupunit(const char *unit);
-int reduceproduct(struct unittype * theunit, int flip);
-int reduceunit(struct unittype * theunit);
-int compareproducts(char **one, char **two);
-int compareunits(struct unittype * first, struct unittype * second);
-int completereduce(struct unittype * unit);
-void showanswer(struct unittype * have, struct unittype * want);
-void usage(void);
+static bool verbose = false;
+static const char * havestr;
+static const char * wantstr;
+
+
+static int addsubunit(char *product[], char *toadd);
+static int addunit(struct unittype *theunit, const char *toadd, int flip, int quantity);
+static void cancelunit(struct unittype * theunit);
+static int compare(const void *item1, const void *item2);
+static int compareproducts(char **one, char **two);
+static int compareunits(struct unittype * first, struct unittype * second);
+static int completereduce(struct unittype * unit);
+static char *dupstr(const char *str);
+static void initializeunit(struct unittype * theunit);
+static char *lookupunit(const char *unit);
+static void readunits(const char *userfile);
+static int reduceproduct(struct unittype * theunit, int flip);
+static int reduceunit(struct unittype * theunit);
+static void showanswer(struct unittype * have, struct unittype * want);
+static void showunit(struct unittype * theunit);
+static void sortunit(struct unittype * theunit);
+static void usage(void);
+static void zeroerror(void);
+
+static const char* promptstr = "";
+
+static const char * prompt(EditLine *e __unused) {
+ return promptstr;
+}
char *
dupstr(const char *str)
@@ -112,6 +125,7 @@ readunits(const char *userfile)
FILE *unitfile;
char line[512], *lineptr;
int len, linenum, i;
+ cap_rights_t unitfilerights;
unitcount = 0;
linenum = 0;
@@ -143,6 +157,10 @@ readunits(const char *userfile)
errx(1, "can't find units file '%s'", UNITSFILE);
}
}
+ cap_rights_init(&unitfilerights, CAP_READ, CAP_FSTAT);
+ if (cap_rights_limit(fileno(unitfile), &unitfilerights) < 0
+ && errno != ENOSYS)
+ err(1, "cap_rights_limit() failed");
while (!feof(unitfile)) {
if (!fgets(line, sizeof(line), unitfile))
break;
@@ -227,7 +245,7 @@ addsubunit(char *product[], char *toadd)
return 1;
}
if (!*ptr)
- *(ptr + 1) = 0;
+ *(ptr + 1) = NULL;
*ptr = dupstr(toadd);
return 0;
}
@@ -240,7 +258,7 @@ showunit(struct unittype * theunit)
int printedslash;
int counter = 1;
- printf("\t%.8g", theunit->factor);
+ printf("%.8g", theunit->factor);
if (theunit->offset)
printf("&%.8g", theunit->offset);
for (ptr = theunit->numerator; *ptr; ptr++) {
@@ -275,7 +293,7 @@ showunit(struct unittype * theunit)
counter = 1;
}
}
- if (counter > 1)
+ if ( counter > 1)
printf("%s%d", powerstring, counter);
printf("\n");
}
@@ -296,7 +314,7 @@ zeroerror(void)
*/
int
-addunit(struct unittype * theunit, char *toadd, int flip, int quantity)
+addunit(struct unittype * theunit, const char *toadd, int flip, int quantity)
{
char *scratch, *savescr;
char *item;
@@ -631,32 +649,50 @@ completereduce(struct unittype * unit)
return 0;
}
-
void
showanswer(struct unittype * have, struct unittype * want)
{
+ double ans;
+
if (compareunits(have, want)) {
printf("conformability error\n");
+ if (verbose)
+ printf("\t%s = ", havestr);
+ else
+ printf("\t");
showunit(have);
+ if (verbose)
+ printf("\t%s = ", wantstr);
+ else
+ printf("\t");
showunit(want);
}
else if (have->offset != want->offset) {
if (want->quantity)
printf("WARNING: conversion of non-proportional quantities.\n");
- printf("\t");
if (have->quantity)
- printf("%.8g\n",
+ printf("\t%.8g\n",
(have->factor + have->offset-want->offset)/want->factor);
- else
- printf(" (-> x*%.8g %+.8g)\n\t (<- y*%.8g %+.8g)\n",
+ else {
+ printf("\t (-> x*%.8g %+.8g)\n\t (<- y*%.8g %+.8g)\n",
have->factor / want->factor,
(have->offset-want->offset)/want->factor,
want->factor / have->factor,
(want->offset - have->offset)/have->factor);
+ }
+ }
+ else {
+ ans = have->factor / want->factor;
+ if (verbose)
+ printf("\t%s = %.8g * %s\n", havestr, ans, wantstr);
+ else
+ printf("\t* %.8g\n", ans);
+
+ if (verbose)
+ printf("\t%s = (1 / %.8g) * %s\n", havestr, 1/ans, wantstr);
+ else
+ printf("\t/ %.8g\n", 1/ans);
}
- else
- printf("\t* %.8g\n\t/ %.8g\n", have->factor / want->factor,
- want->factor / have->factor);
}
@@ -664,7 +700,7 @@ void
usage(void)
{
fprintf(stderr,
- "usage: units [-f unitsfile] [-q] [-v] [from-unit to-unit]\n");
+ "usage: units [-f unitsfile] [-UVq] [from-unit to-unit]\n");
exit(3);
}
@@ -674,38 +710,67 @@ main(int argc, char **argv)
{
struct unittype have, want;
- char havestr[81], wantstr[81];
int optchar;
- char *userfile = 0;
- int quiet = 0;
-
- while ((optchar = getopt(argc, argv, "vqf:")) != -1) {
+ bool quiet;
+ bool readfile;
+ History *inhistory;
+ EditLine *el;
+ HistEvent ev;
+ int inputsz;
+
+ quiet = false;
+ readfile = false;
+ while ((optchar = getopt(argc, argv, "fqvUV:")) != -1) {
switch (optchar) {
case 'f':
- userfile = optarg;
+ readfile = true;
+ if (strlen(optarg) == 0)
+ readunits(NULL);
+ else
+ readunits(optarg);
break;
case 'q':
- quiet = 1;
+ quiet = true;
break;
case 'v':
- fprintf(stderr, "\n units version %s Copyright (c) 1993 by Adrian Mariano\n",
- VERSION);
- fprintf(stderr, " This program may be freely distributed\n");
+ verbose = true;
+ break;
+ case 'U':
+ if (access(UNITSFILE, F_OK) == 0)
+ printf("%s\n", UNITSFILE);
+ else
+ printf("Units data file not found");
+ exit(0);
+ break;
+ case 'V':
+ fprintf(stderr, "FreeBSD units\n");
usage();
+ break;
default:
usage();
- break;
}
}
- if (optind != argc - 2 && optind != argc)
- usage();
+ if (!readfile)
+ readunits(NULL);
- readunits(userfile);
+ inhistory = history_init();
+ el = el_init(argv[0], stdin, stdout, stderr);
+ el_set(el, EL_PROMPT, &prompt);
+ el_set(el, EL_EDITOR, "emacs");
+ el_set(el, EL_SIGNAL, 1);
+ el_set(el, EL_HIST, history, inhistory);
+ el_source(el, NULL);
+ history(inhistory, &ev, H_SETSIZE, 800);
+ if (inhistory == 0)
+ err(1, "Could not initalize history");
+
+ if (cap_enter() < 0 && errno != ENOSYS)
+ err(1, "unable to enter capability mode");
if (optind == argc - 2) {
- strlcpy(havestr, argv[optind], sizeof(havestr));
- strlcpy(wantstr, argv[optind + 1], sizeof(wantstr));
+ havestr = argv[optind];
+ wantstr = argv[optind + 1];
initializeunit(&have);
addunit(&have, havestr, 0, 1);
completereduce(&have);
@@ -722,28 +787,31 @@ main(int argc, char **argv)
do {
initializeunit(&have);
if (!quiet)
- printf("You have: ");
- if (!fgets(havestr, sizeof(havestr), stdin)) {
- if (!quiet)
- putchar('\n');
+ promptstr = "You have: ";
+ havestr = el_gets(el, &inputsz);
+ if (havestr == NULL)
exit(0);
- }
+ if (inputsz > 0)
+ history(inhistory, &ev, H_ENTER,
+ havestr);
} while (addunit(&have, havestr, 0, 1) ||
completereduce(&have));
do {
initializeunit(&want);
if (!quiet)
- printf("You want: ");
- if (!fgets(wantstr, sizeof(wantstr), stdin)) {
- if (!quiet)
- putchar('\n');
+ promptstr = "You want: ";
+ wantstr = el_gets(el, &inputsz);
+ if (wantstr == NULL)
exit(0);
- }
+ if (inputsz > 0)
+ history(inhistory, &ev, H_ENTER,
+ wantstr);
} while (addunit(&want, wantstr, 0, 1) ||
completereduce(&want));
showanswer(&have, &want);
}
}
+ history_end(inhistory);
return(0);
}
diff --git a/usr.bin/units/units.lib b/usr.bin/units/units.lib
index 67127bcb9e3b..4c48322454b2 100644
--- a/usr.bin/units/units.lib
+++ b/usr.bin/units/units.lib
@@ -39,8 +39,13 @@ zopto- 1e-21
zepto- zopto
yocto- 1e-24
+quarter- 1|4
semi- .5
demi- .5
+hemi- .5
+half- .5
+double- 2
+triple- 3
Y- yotta
Z- zetta
@@ -55,6 +60,7 @@ da- deka
d- deci
c- centi
m- milli
+u- micro
n- nano
p- pico
f- femto
@@ -298,6 +304,7 @@ N newton
joule nt-m
J joule
cal 4.1868 joule
+ergon erg
/ Electrical
@@ -438,6 +445,7 @@ bakersdozen 13
bar 1e+5 nt/m2
barie 1e-1 nt/m2
barleycorn 1|3 in
+beardsecond 5 nm
barn 1e-28 m2
oilbarrel 42 gal
barrel oilbarrel
@@ -526,6 +534,7 @@ hogshead 63 gallon
hd hogshead
homestead 1|4 mi2
horsepower 735.50 watt
+donkeypower 250 watt
hp horsepower
hubble 1e9 ly
hyl gm force sec2/m
@@ -594,6 +603,7 @@ poise gm/cm-sec
P poise
pole rd
pond 9.80665e-3 nt
+potrzebie 2.263348517438173216473 mm
poundal ft-lb/sec2
pdl poundal
proof 1|200
@@ -679,6 +689,8 @@ degreesrankine 5|9 K
degrankine degreesrankine
degreerankine degreesrankine
degreaumur 10|8&+273.15 K
+gasmark 25|1&250 degF
+Stufe 25|1&125 degC
drachm 60 grain
poncelet 100 kg m g / sec
denier .05|450 gram / m