aboutsummaryrefslogtreecommitdiff
path: root/usr.bin/units/units.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/units/units.c')
-rw-r--r--usr.bin/units/units.c188
1 files changed, 128 insertions, 60 deletions
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);
}