Home | History | Annotate | Line # | Download | only in dc
dc.c revision 1.1
      1 /*	$OpenBSD: dc.c,v 1.18 2016/07/17 17:30:47 otto Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 2003, Otto Moerbeek <otto (at) drijf.net>
      5  *
      6  * Permission to use, copy, modify, and distribute this software for any
      7  * purpose with or without fee is hereby granted, provided that the above
      8  * copyright notice and this permission notice appear in all copies.
      9  *
     10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     14  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
     15  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
     16  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     17  */
     18 
     19 #include <sys/stat.h>
     20 #include <err.h>
     21 #include <errno.h>
     22 #include <stdlib.h>
     23 #include <string.h>
     24 #include <unistd.h>
     25 
     26 #include "extern.h"
     27 
     28 static __dead void	usage(void);
     29 
     30 extern char		*__progname;
     31 
     32 static __dead void
     33 usage(void)
     34 {
     35 	(void)fprintf(stderr, "usage: %s [-x] [-e expression] [file]\n",
     36 	    __progname);
     37 	exit(1);
     38 }
     39 
     40 int
     41 dc_main(int argc, char *argv[])
     42 {
     43 	int		ch;
     44 	bool		extended_regs = false;
     45 	FILE		*file;
     46 	struct source	src;
     47 	char		*buf, *p;
     48 	struct stat	st;
     49 
     50 	if ((buf = strdup("")) == NULL)
     51 		err(1, NULL);
     52 	/* accept and ignore a single dash to be 4.4BSD dc(1) compatible */
     53 	optind = 1;
     54 	optreset = 1;
     55 	while ((ch = getopt(argc, argv, "e:x-")) != -1) {
     56 		switch (ch) {
     57 		case 'e':
     58 			p = buf;
     59 			if (asprintf(&buf, "%s %s", buf, optarg) == -1)
     60 				err(1, NULL);
     61 			free(p);
     62 			break;
     63 		case 'x':
     64 			extended_regs = true;
     65 			break;
     66 		case '-':
     67 			break;
     68 		default:
     69 			usage();
     70 		}
     71 	}
     72 	argc -= optind;
     73 	argv += optind;
     74 
     75 	init_bmachine(extended_regs);
     76 	(void)setvbuf(stdout, NULL, _IOLBF, 0);
     77 	(void)setvbuf(stderr, NULL, _IOLBF, 0);
     78 
     79 	if (argc > 1)
     80 		usage();
     81 	if (buf[0] != '\0') {
     82 		src_setstring(&src, buf);
     83 		reset_bmachine(&src);
     84 		eval();
     85 		free(buf);
     86 		if (argc == 0)
     87 			return (0);
     88 	}
     89 	if (argc == 1) {
     90 		file = fopen(argv[0], "r");
     91 		if (file == NULL)
     92 			err(1, "cannot open file %s", argv[0]);
     93 
     94 		if (pledge("stdio", NULL) == -1)
     95 			err(1, "pledge");
     96 
     97 		if (fstat(fileno(file), &st) == -1)
     98 			err(1, "%s", argv[0]);
     99 		if (S_ISDIR(st.st_mode))
    100 			errc(1, EISDIR, "%s", argv[0]);
    101 		src_setstream(&src, file);
    102 		reset_bmachine(&src);
    103 		eval();
    104 		(void)fclose(file);
    105 		/*
    106 		 * BSD and Solaris dc(1) continue with stdin after processing
    107 		 * the file given as the argument. We follow GNU dc(1).
    108 		 */
    109 		 return (0);
    110 	}
    111 
    112 	if (pledge("stdio", NULL) == -1)
    113 		err(1, "pledge");
    114 
    115 	src_setstream(&src, stdin);
    116 	reset_bmachine(&src);
    117 	eval();
    118 
    119 	return (0);
    120 }
    121