xref: /openbsd/usr.bin/dc/dc.c (revision 7b36286a)
1 /*	$OpenBSD: dc.c,v 1.10 2007/07/29 17:12:18 sobrado Exp $	*/
2 
3 /*
4  * Copyright (c) 2003, Otto Moerbeek <otto@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 #ifndef lint
20 static const char rcsid[] = "$OpenBSD: dc.c,v 1.10 2007/07/29 17:12:18 sobrado Exp $";
21 #endif /* not lint */
22 
23 #include <sys/stat.h>
24 #include <err.h>
25 #include <errno.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <unistd.h>
29 
30 #include "extern.h"
31 
32 static __dead void	usage(void);
33 
34 extern char		*__progname;
35 
36 static __dead void
37 usage(void)
38 {
39 	(void)fprintf(stderr, "usage: %s [-x] [-e expression] [file]\n",
40 	    __progname);
41 	exit(1);
42 }
43 
44 int
45 main(int argc, char *argv[])
46 {
47 	int		ch;
48 	bool		extended_regs = false;
49 	FILE		*file;
50 	struct source	src;
51 	char		*buf, *p;
52 	struct stat	st;
53 
54 
55 	if ((buf = strdup("")) == NULL)
56 		err(1, NULL);
57 	/* accept and ignore a single dash to be 4.4BSD dc(1) compatible */
58 	while ((ch = getopt(argc, argv, "e:x-")) != -1) {
59 		switch (ch) {
60 		case 'e':
61 			p = buf;
62 			if (asprintf(&buf, "%s %s", buf, optarg) == -1)
63 				err(1, NULL);
64 			free(p);
65 			break;
66 		case 'x':
67 			extended_regs = true;
68 			break;
69 		case '-':
70 			break;
71 		default:
72 			usage();
73 		}
74 	}
75 	argc -= optind;
76 	argv += optind;
77 
78 	init_bmachine(extended_regs);
79 	(void)setlinebuf(stdout);
80 	(void)setlinebuf(stderr);
81 
82 	if (argc > 1)
83 		usage();
84 	if (buf[0] != '\0') {
85 		src_setstring(&src, buf);
86 		reset_bmachine(&src);
87 		eval();
88 		free(buf);
89 		if (argc == 0)
90 			return (0);
91 	}
92 	if (argc == 1) {
93 		file = fopen(argv[0], "r");
94 		if (file == NULL)
95 			err(1, "cannot open file %s", argv[0]);
96 		if (fstat(fileno(file), &st) == -1)
97 			err(1, "%s", argv[0]);
98 		if (S_ISDIR(st.st_mode)) {
99 			errno = EISDIR;
100 			err(1, "%s", argv[0]);
101 		}
102 		src_setstream(&src, file);
103 		reset_bmachine(&src);
104 		eval();
105 		(void)fclose(file);
106 		/*
107 		 * BSD and Solaris dc(1) continue with stdin after processing
108 		 * the file given as the argument. We follow GNU dc(1).
109 		 */
110 		 return (0);
111 	}
112 	src_setstream(&src, stdin);
113 	reset_bmachine(&src);
114 	eval();
115 
116 	return (0);
117 }
118