xref: /netbsd-src/usr.bin/dc/dc.c (revision fc8ee2f577a06855648d534cfaeafda777e59180)
1*fc8ee2f5Schristos /*	$NetBSD: dc.c,v 1.2 2017/04/10 16:37:48 christos Exp $	*/
27d0b3229Schristos /*	$OpenBSD: dc.c,v 1.18 2016/07/17 17:30:47 otto Exp $	*/
37d0b3229Schristos 
47d0b3229Schristos /*
57d0b3229Schristos  * Copyright (c) 2003, Otto Moerbeek <otto@drijf.net>
67d0b3229Schristos  *
77d0b3229Schristos  * Permission to use, copy, modify, and distribute this software for any
87d0b3229Schristos  * purpose with or without fee is hereby granted, provided that the above
97d0b3229Schristos  * copyright notice and this permission notice appear in all copies.
107d0b3229Schristos  *
117d0b3229Schristos  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
127d0b3229Schristos  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
137d0b3229Schristos  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
147d0b3229Schristos  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
157d0b3229Schristos  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
167d0b3229Schristos  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
177d0b3229Schristos  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
187d0b3229Schristos  */
19*fc8ee2f5Schristos #include <sys/cdefs.h>
20*fc8ee2f5Schristos __RCSID("$NetBSD: dc.c,v 1.2 2017/04/10 16:37:48 christos Exp $");
217d0b3229Schristos 
227d0b3229Schristos #include <sys/stat.h>
237d0b3229Schristos #include <err.h>
247d0b3229Schristos #include <errno.h>
257d0b3229Schristos #include <stdlib.h>
267d0b3229Schristos #include <string.h>
277d0b3229Schristos #include <unistd.h>
287d0b3229Schristos 
297d0b3229Schristos #include "extern.h"
307d0b3229Schristos 
317d0b3229Schristos static __dead void	usage(void);
327d0b3229Schristos 
337d0b3229Schristos static __dead void
usage(void)347d0b3229Schristos usage(void)
357d0b3229Schristos {
367d0b3229Schristos 	(void)fprintf(stderr, "usage: %s [-x] [-e expression] [file]\n",
37*fc8ee2f5Schristos 	    getprogname());
387d0b3229Schristos 	exit(1);
397d0b3229Schristos }
407d0b3229Schristos 
417d0b3229Schristos int
dc_main(int argc,char * argv[])427d0b3229Schristos dc_main(int argc, char *argv[])
437d0b3229Schristos {
447d0b3229Schristos 	int		ch;
457d0b3229Schristos 	bool		extended_regs = false;
467d0b3229Schristos 	FILE		*file;
477d0b3229Schristos 	struct source	src;
487d0b3229Schristos 	char		*buf, *p;
497d0b3229Schristos 	struct stat	st;
507d0b3229Schristos 
517d0b3229Schristos 	if ((buf = strdup("")) == NULL)
527d0b3229Schristos 		err(1, NULL);
537d0b3229Schristos 	/* accept and ignore a single dash to be 4.4BSD dc(1) compatible */
547d0b3229Schristos 	optind = 1;
557d0b3229Schristos 	optreset = 1;
567d0b3229Schristos 	while ((ch = getopt(argc, argv, "e:x-")) != -1) {
577d0b3229Schristos 		switch (ch) {
587d0b3229Schristos 		case 'e':
597d0b3229Schristos 			p = buf;
607d0b3229Schristos 			if (asprintf(&buf, "%s %s", buf, optarg) == -1)
617d0b3229Schristos 				err(1, NULL);
627d0b3229Schristos 			free(p);
637d0b3229Schristos 			break;
647d0b3229Schristos 		case 'x':
657d0b3229Schristos 			extended_regs = true;
667d0b3229Schristos 			break;
677d0b3229Schristos 		case '-':
687d0b3229Schristos 			break;
697d0b3229Schristos 		default:
707d0b3229Schristos 			usage();
717d0b3229Schristos 		}
727d0b3229Schristos 	}
737d0b3229Schristos 	argc -= optind;
747d0b3229Schristos 	argv += optind;
757d0b3229Schristos 
767d0b3229Schristos 	init_bmachine(extended_regs);
777d0b3229Schristos 	(void)setvbuf(stdout, NULL, _IOLBF, 0);
787d0b3229Schristos 	(void)setvbuf(stderr, NULL, _IOLBF, 0);
797d0b3229Schristos 
807d0b3229Schristos 	if (argc > 1)
817d0b3229Schristos 		usage();
827d0b3229Schristos 	if (buf[0] != '\0') {
837d0b3229Schristos 		src_setstring(&src, buf);
847d0b3229Schristos 		reset_bmachine(&src);
857d0b3229Schristos 		eval();
867d0b3229Schristos 		free(buf);
877d0b3229Schristos 		if (argc == 0)
887d0b3229Schristos 			return (0);
897d0b3229Schristos 	}
907d0b3229Schristos 	if (argc == 1) {
917d0b3229Schristos 		file = fopen(argv[0], "r");
927d0b3229Schristos 		if (file == NULL)
937d0b3229Schristos 			err(1, "cannot open file %s", argv[0]);
947d0b3229Schristos 
95*fc8ee2f5Schristos #ifdef __OpenBSD__
967d0b3229Schristos 		if (pledge("stdio", NULL) == -1)
977d0b3229Schristos 			err(1, "pledge");
98*fc8ee2f5Schristos #endif
997d0b3229Schristos 
1007d0b3229Schristos 		if (fstat(fileno(file), &st) == -1)
1017d0b3229Schristos 			err(1, "%s", argv[0]);
1027d0b3229Schristos 		if (S_ISDIR(st.st_mode))
1037d0b3229Schristos 			errc(1, EISDIR, "%s", argv[0]);
1047d0b3229Schristos 		src_setstream(&src, file);
1057d0b3229Schristos 		reset_bmachine(&src);
1067d0b3229Schristos 		eval();
1077d0b3229Schristos 		(void)fclose(file);
1087d0b3229Schristos 		/*
1097d0b3229Schristos 		 * BSD and Solaris dc(1) continue with stdin after processing
1107d0b3229Schristos 		 * the file given as the argument. We follow GNU dc(1).
1117d0b3229Schristos 		 */
1127d0b3229Schristos 		 return (0);
1137d0b3229Schristos 	}
1147d0b3229Schristos 
115*fc8ee2f5Schristos #ifdef __OpenBSD__
1167d0b3229Schristos 	if (pledge("stdio", NULL) == -1)
1177d0b3229Schristos 		err(1, "pledge");
118*fc8ee2f5Schristos #endif
1197d0b3229Schristos 
1207d0b3229Schristos 	src_setstream(&src, stdin);
1217d0b3229Schristos 	reset_bmachine(&src);
1227d0b3229Schristos 	eval();
1237d0b3229Schristos 
1247d0b3229Schristos 	return (0);
1257d0b3229Schristos }
126