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