xref: /openbsd-src/usr.bin/dc/dc.c (revision e6c7c102cf5d9891f32552a42895134a59937045)
1*e6c7c102Sjsg /*	$OpenBSD: dc.c,v 1.21 2024/04/23 13:34:50 jsg Exp $	*/
2a6ce4a44Sotto 
3a6ce4a44Sotto /*
4a6ce4a44Sotto  * Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
5a6ce4a44Sotto  *
6a6ce4a44Sotto  * Permission to use, copy, modify, and distribute this software for any
7a6ce4a44Sotto  * purpose with or without fee is hereby granted, provided that the above
8a6ce4a44Sotto  * copyright notice and this permission notice appear in all copies.
9a6ce4a44Sotto  *
10a6ce4a44Sotto  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11a6ce4a44Sotto  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12a6ce4a44Sotto  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13a6ce4a44Sotto  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14a6ce4a44Sotto  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15a6ce4a44Sotto  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16a6ce4a44Sotto  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17a6ce4a44Sotto  */
18a6ce4a44Sotto 
19d6d2d216Sotto #include <sys/stat.h>
20a6ce4a44Sotto #include <err.h>
21d6d2d216Sotto #include <errno.h>
2262419bafSotto #include <stdlib.h>
235db19890Sotto #include <string.h>
2477f3d9ddSotto #include <unistd.h>
25a6ce4a44Sotto 
26a6ce4a44Sotto #include "extern.h"
27a6ce4a44Sotto 
28a6ce4a44Sotto static __dead void	usage(void);
29a6ce4a44Sotto 
30a6ce4a44Sotto extern char		*__progname;
31a6ce4a44Sotto 
32a6ce4a44Sotto static __dead void
usage(void)33a6ce4a44Sotto usage(void)
34a6ce4a44Sotto {
35e01e6ca4Ssobrado 	(void)fprintf(stderr, "usage: %s [-x] [-e expression] [file]\n",
36e01e6ca4Ssobrado 	    __progname);
37a6ce4a44Sotto 	exit(1);
38a6ce4a44Sotto }
39a6ce4a44Sotto 
40a6ce4a44Sotto int
dc_main(int argc,char * argv[])419490edf2Sderaadt dc_main(int argc, char *argv[])
42a6ce4a44Sotto {
4377f3d9ddSotto 	int		ch;
4477f3d9ddSotto 	bool		extended_regs = false;
45a6ce4a44Sotto 	FILE		*file;
46a6ce4a44Sotto 	struct source	src;
475db19890Sotto 	char		*buf, *p;
48d6d2d216Sotto 	struct stat	st;
49d6d2d216Sotto 
509ec9f480Sotto 	buf = bstrdup("");
5177f3d9ddSotto 	/* accept and ignore a single dash to be 4.4BSD dc(1) compatible */
52070edbb2Sotto 	optind = 1;
53070edbb2Sotto 	optreset = 1;
545db19890Sotto 	while ((ch = getopt(argc, argv, "e:x-")) != -1) {
5577f3d9ddSotto 		switch (ch) {
565db19890Sotto 		case 'e':
575db19890Sotto 			p = buf;
585db19890Sotto 			if (asprintf(&buf, "%s %s", buf, optarg) == -1)
595db19890Sotto 				err(1, NULL);
605db19890Sotto 			free(p);
615db19890Sotto 			break;
6277f3d9ddSotto 		case 'x':
6377f3d9ddSotto 			extended_regs = true;
6477f3d9ddSotto 			break;
6577f3d9ddSotto 		case '-':
6677f3d9ddSotto 			break;
6777f3d9ddSotto 		default:
68a6ce4a44Sotto 			usage();
6977f3d9ddSotto 		}
7077f3d9ddSotto 	}
7177f3d9ddSotto 	argc -= optind;
7277f3d9ddSotto 	argv += optind;
73a6ce4a44Sotto 
74e351538eSotto 	if (argc == 0) {
75e351538eSotto 		if (pledge("stdio", NULL) == -1)
76e351538eSotto 			err(1, "pledge");
77e351538eSotto 	}
78e351538eSotto 
7977f3d9ddSotto 	init_bmachine(extended_regs);
80b9a887b6Smillert 	(void)setvbuf(stdout, NULL, _IOLBF, 0);
81b9a887b6Smillert 	(void)setvbuf(stderr, NULL, _IOLBF, 0);
8277f3d9ddSotto 
8377f3d9ddSotto 	if (argc > 1)
8477f3d9ddSotto 		usage();
855db19890Sotto 	if (buf[0] != '\0') {
865db19890Sotto 		src_setstring(&src, buf);
875db19890Sotto 		reset_bmachine(&src);
885db19890Sotto 		eval();
895db19890Sotto 		free(buf);
905db19890Sotto 		if (argc == 0)
915db19890Sotto 			return (0);
925db19890Sotto 	}
935db19890Sotto 	if (argc == 1) {
94075700d3Sotto 		file = fopen(argv[0], "r");
95075700d3Sotto 		if (file == NULL)
96075700d3Sotto 			err(1, "cannot open file %s", argv[0]);
97e171f49eSmmcc 
980bd1216cSderaadt 		if (pledge("stdio", NULL) == -1)
990bd1216cSderaadt 			err(1, "pledge");
100e171f49eSmmcc 
101075700d3Sotto 		if (fstat(fileno(file), &st) == -1)
102d6d2d216Sotto 			err(1, "%s", argv[0]);
1035ad04d35Sguenther 		if (S_ISDIR(st.st_mode))
1045ad04d35Sguenther 			errc(1, EISDIR, "%s", argv[0]);
105a6ce4a44Sotto 		src_setstream(&src, file);
106a6ce4a44Sotto 		reset_bmachine(&src);
107a6ce4a44Sotto 		eval();
108a1a9dfc3Sotto 		(void)fclose(file);
109a6ce4a44Sotto 		/*
1105db19890Sotto 		 * BSD and Solaris dc(1) continue with stdin after processing
1115db19890Sotto 		 * the file given as the argument. We follow GNU dc(1).
112a6ce4a44Sotto 		 */
1135db19890Sotto 		return (0);
1145db19890Sotto 	}
115e171f49eSmmcc 
116a6ce4a44Sotto 	src_setstream(&src, stdin);
117a6ce4a44Sotto 	reset_bmachine(&src);
118a6ce4a44Sotto 	eval();
119a6ce4a44Sotto 
1205db19890Sotto 	return (0);
121a6ce4a44Sotto }
122