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