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@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
usage(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
dc_main(int argc,char * argv[])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