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