/* * strings.c * Implementation of SUSv3 XCU strings utility * Copyright © 2007 Rich Felker * Licensed under the terms of the GNU General Public License, v2 or later */ #include #include #include #include #include #include #include #include #include static int my_mbrtowc(wchar_t *wc, int b, mbstate_t *st) { char c = b; int retry = 1; retry: switch ((int)mbrtowc(wc, &c, 1, st)) { case -2: return -2; case -1: memset(st, 0, sizeof(mbstate_t)); if (retry--) goto retry; return retry; /* yes this is lame */ } return 1; } int main(int argc, char *argv[]) { mbstate_t st; wchar_t *buf; size_t i, min = 4; int b; off_t start, ofs; int l; char fmtbuf[] = "%ll? ", *fmt=fmtbuf+5; int ret = 0; int in_str; FILE *f = stdin; char *name = "(stdin)"; if (!setlocale(LC_CTYPE, "")) { fprintf(stderr, "%s: warning: cannot set LC_CTYPE", argv[0]); perror(""); } while ((b = getopt(argc, argv, "an:t:")) != EOF) switch(b) { case 'a': /* no-op: we always search entire file */ break; case 'n': min = strtoul(optarg, NULL, 10); if (min < 1 || min >= SIZE_MAX) { fprintf(stderr, "%s: invalid argument to -%c: %s\n", argv[0], b, optarg); exit(1); } break; case 't': if (!strchr("dox", optarg[0]) || optarg[1]) { fprintf(stderr, "%s: invalid argument to -%c: %s\n", argv[0], b, optarg); exit(1); } fmt = fmtbuf; fmt[3] = optarg[0]; break; default: exit(1); } /* min+1 does not overflow because of above check */ if (!(buf = calloc(sizeof(wchar_t), min+1))) { fprintf(stderr, "%s: ", argv[0]); perror("calloc failed"); exit(1); } if (optind < argc) goto nextfile; begin: memset(&st, 0, sizeof(mbstate_t)); start = ofs = i = in_str = 0; while ((b=getc(f)) >= 0) { ofs++; l = my_mbrtowc(buf+i, b, &st); if (l == -2) continue; if (l == -1 || !iswprint(buf[i])) { if (in_str) putchar('\n'); in_str = 0; i = 0; start = ofs; continue; } if (i