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