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 31static __dead void usage(void); 32 33static __dead void 34usage(void) 35{ 36 (void)fprintf(stderr, "usage: %s [-x] [-e expression] [file]\n", 37 getprogname()); 38 exit(1); 39} 40 41int 42dc_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