/src/util-linux/include/carefulputc.h
Line | Count | Source (jump to first uncovered line) |
1 | | #ifndef UTIL_LINUX_CAREFULPUTC_H |
2 | | #define UTIL_LINUX_CAREFULPUTC_H |
3 | | |
4 | | #include <stdio.h> |
5 | | #include <string.h> |
6 | | #include <ctype.h> |
7 | | #include <stdbool.h> |
8 | | |
9 | | #include "widechar.h" |
10 | | #include "cctype.h" |
11 | | |
12 | | /* |
13 | | * A puts() for use in write and wall (that sometimes are sgid tty). |
14 | | * It avoids control and invalid characters. |
15 | | * The locale of the recipient is nominally unknown, |
16 | | * but it's a solid bet that it's compatible with the author's. |
17 | | * Use soft_width=0 to disable wrapping. |
18 | | */ |
19 | | static inline int fputs_careful(const char * s, FILE *fp, const char ctrl, bool cr_lf, int soft_width) |
20 | 21.5k | { |
21 | 21.5k | int ret = 0, col = 0; |
22 | | |
23 | 194k | for (size_t slen = strlen(s); *s; ++s, --slen) { |
24 | 172k | if (*s == '\t') |
25 | 664 | col += (7 - (col % 8)) - 1; |
26 | 172k | else if (*s == '\r') |
27 | 3.66k | col = -1; |
28 | 168k | else if (*s == '\a') |
29 | 562 | --col; |
30 | | |
31 | 172k | if ((soft_width && col >= soft_width) || *s == '\n') { |
32 | 22.0k | if (soft_width) { |
33 | 0 | fprintf(fp, "%*s", soft_width - col, ""); |
34 | 0 | col = 0; |
35 | 0 | } |
36 | 22.0k | ret = fputs(cr_lf ? "\r\n" : "\n", fp); |
37 | 22.0k | if (*s == '\n' || ret < 0) |
38 | 22.0k | goto wrote; |
39 | 22.0k | } |
40 | | |
41 | 150k | if (isprint(*s) || *s == '\a' || *s == '\t' || *s == '\r') { |
42 | 62.1k | ret = putc(*s, fp); |
43 | 62.1k | ++col; |
44 | 88.5k | } else if (!c_isascii(*s)) { |
45 | 58.3k | #ifdef HAVE_WIDECHAR |
46 | 58.3k | wchar_t w; |
47 | 58.3k | size_t clen = mbtowc(&w, s, slen); |
48 | 58.3k | switch(clen) { |
49 | 0 | case (size_t)-2: // incomplete |
50 | 58.3k | case (size_t)-1: // EILSEQ |
51 | 58.3k | mbtowc(NULL, NULL, 0); |
52 | 58.3k | nonprint: |
53 | 58.3k | col += ret = fprintf(fp, "\\%3hho", *s); |
54 | 58.3k | break; |
55 | 0 | default: |
56 | 0 | if(!iswprint(w)) |
57 | 0 | goto nonprint; |
58 | 0 | ret = fwrite(s, 1, clen, fp); |
59 | 0 | if (soft_width) |
60 | 0 | col += wcwidth(w); |
61 | 0 | s += clen - 1; |
62 | 0 | slen -= clen - 1; |
63 | 0 | break; |
64 | 58.3k | } |
65 | | #else |
66 | | col += ret = fprintf(fp, "\\%3hho", *s); |
67 | | #endif |
68 | 58.3k | } else { |
69 | 30.2k | ret = fputs((char[]){ ctrl, *s ^ 0x40, '\0' }, fp); |
70 | 30.2k | col += 2; |
71 | 30.2k | } |
72 | | |
73 | 172k | wrote: |
74 | 172k | if (ret < 0) |
75 | 0 | return EOF; |
76 | 172k | } |
77 | 21.5k | return 0; |
78 | 21.5k | } |
79 | | |
80 | | static inline void fputs_quoted_case(const char *data, FILE *out, int dir) |
81 | 0 | { |
82 | 0 | const char *p; |
83 | 0 |
|
84 | 0 | fputc('"', out); |
85 | 0 | for (p = data; p && *p; p++) { |
86 | 0 | if ((unsigned char) *p == 0x22 || /* " */ |
87 | 0 | (unsigned char) *p == 0x5c || /* \ */ |
88 | 0 | (unsigned char) *p == 0x60 || /* ` */ |
89 | 0 | (unsigned char) *p == 0x24 || /* $ */ |
90 | 0 | !isprint((unsigned char) *p) || |
91 | 0 | iscntrl((unsigned char) *p)) { |
92 | 0 |
|
93 | 0 | fprintf(out, "\\x%02x", (unsigned char) *p); |
94 | 0 | } else |
95 | 0 | fputc(dir == 1 ? toupper(*p) : |
96 | 0 | dir == -1 ? tolower(*p) : |
97 | 0 | *p, out); |
98 | 0 | } |
99 | 0 | fputc('"', out); |
100 | 0 | } |
101 | | |
102 | | #define fputs_quoted(_d, _o) fputs_quoted_case(_d, _o, 0) |
103 | | #define fputs_quoted_upper(_d, _o) fputs_quoted_case(_d, _o, 1) |
104 | | #define fputs_quoted_lower(_d, _o) fputs_quoted_case(_d, _o, -1) |
105 | | |
106 | | static inline void fputs_nonblank(const char *data, FILE *out) |
107 | 0 | { |
108 | 0 | const char *p; |
109 | 0 |
|
110 | 0 | for (p = data; p && *p; p++) { |
111 | 0 | if (isblank((unsigned char) *p) || |
112 | 0 | (unsigned char) *p == 0x5c || /* \ */ |
113 | 0 | !isprint((unsigned char) *p) || |
114 | 0 | iscntrl((unsigned char) *p)) { |
115 | 0 |
|
116 | 0 | fprintf(out, "\\x%02x", (unsigned char) *p); |
117 | 0 |
|
118 | 0 | } else |
119 | 0 | fputc(*p, out); |
120 | 0 | } |
121 | 0 | } |
122 | | |
123 | | #endif /* _CAREFULPUTC_H */ |