]> git.ipfire.org Git - thirdparty/util-linux.git/blame - include/carefulputc.h
su: use lib/pty-session.c code for --pty
[thirdparty/util-linux.git] / include / carefulputc.h
CommitLineData
a7da7922
NN
1#ifndef UTIL_LINUX_CAREFULPUTC_H
2#define UTIL_LINUX_CAREFULPUTC_H
48d7b13a 3
459e95f3
BS
4/*
5 * A putc() for use in write and wall (that sometimes are sgid tty).
6 * It avoids control characters in our locale, and also ASCII control
7 * characters. Note that the locale of the recipient is unknown.
8*/
66ee8158 9#include <stdio.h>
78a3b0af
KZ
10#include <string.h>
11#include <ctype.h>
66ee8158 12
76b680b1
RP
13#include "cctype.h"
14
c6d2d74e
SK
15static inline int fputc_careful(int c, FILE *fp, const char fail)
16{
66ee8158
KZ
17 int ret;
18
c6d2d74e 19 if (isprint(c) || c == '\a' || c == '\t' || c == '\r' || c == '\n')
66ee8158 20 ret = putc(c, fp);
76b680b1 21 else if (!c_isascii(c))
c6d2d74e 22 ret = fprintf(fp, "\\%3o", (unsigned char)c);
66ee8158 23 else {
ada6c48f 24 ret = putc(fail, fp);
66ee8158 25 if (ret != EOF)
c6d2d74e 26 ret = putc(c ^ 0x40, fp);
66ee8158
KZ
27 }
28 return (ret < 0) ? EOF : 0;
29}
48d7b13a 30
1ca2661b
KZ
31/*
32 * Requirements enumerated via testing (V8, Firefox, IE11):
33 *
34 * var charsToEscape = [];
35 * for (var i = 0; i < 65535; i += 1) {
36 * try {
37 * JSON.parse('{"sample": "' + String.fromCodePoint(i) + '"}');
38 * } catch (e) {
39 * charsToEscape.push(i);
40 * }
41 * }
42 */
43static inline void fputs_quoted_case_json(const char *data, FILE *out, int dir)
44{
45 const char *p;
46
47 fputc('"', out);
48 for (p = data; p && *p; p++) {
49
50 const unsigned char c = (unsigned char) *p;
51
52 /* From http://www.json.org
53 *
54 * The double-quote and backslashes would break out a string or
55 * init an escape sequence if not escaped.
56 *
57 * Note that single-quotes and forward slashes, while they're
58 * in the JSON spec, don't break double-quoted strings.
59 */
60 if (c == '"' || c == '\\') {
61 fputc('\\', out);
62 fputc(c, out);
63 continue;
64 }
65
66 /* All non-control characters OK; do the case swap as required. */
67 if (c >= 0x20) {
68 fputc(dir == 1 ? toupper(c) :
69 dir == -1 ? tolower(c) : *p, out);
70 continue;
71 }
72
73 /* In addition, all chars under ' ' break Node's/V8/Chrome's, and
74 * Firefox's JSON.parse function
75 */
76 switch (c) {
77 /* Handle short-hand cases to reduce output size. C
78 * has most of the same stuff here, so if there's an
79 * "Escape for C" function somewhere in the STL, we
80 * should probably be using it.
81 */
82 case '\b':
83 fputs("\\b", out);
84 break;
85 case '\t':
86 fputs("\\t", out);
87 break;
88 case '\n':
89 fputs("\\n", out);
90 break;
91 case '\f':
92 fputs("\\f", out);
93 break;
94 case '\r':
95 fputs("\\r", out);
96 break;
97 default:
98 /* Other assorted control characters */
99 fprintf(out, "\\u00%02x", c);
100 break;
101 }
102 }
103 fputc('"', out);
104}
105
106
6a768b55 107static inline void fputs_quoted_case(const char *data, FILE *out, int dir)
78a3b0af
KZ
108{
109 const char *p;
110
111 fputc('"', out);
112 for (p = data; p && *p; p++) {
113 if ((unsigned char) *p == 0x22 || /* " */
114 (unsigned char) *p == 0x5c || /* \ */
cca51b9e
KZ
115 (unsigned char) *p == 0x60 || /* ` */
116 (unsigned char) *p == 0x24 || /* $ */
78a3b0af
KZ
117 !isprint((unsigned char) *p) ||
118 iscntrl((unsigned char) *p)) {
119
120 fprintf(out, "\\x%02x", (unsigned char) *p);
121 } else
6a768b55
KZ
122 fputc(dir == 1 ? toupper(*p) :
123 dir == -1 ? tolower(*p) :
124 *p, out);
78a3b0af
KZ
125 }
126 fputc('"', out);
127}
128
6a768b55
KZ
129#define fputs_quoted(_d, _o) fputs_quoted_case(_d, _o, 0)
130#define fputs_quoted_upper(_d, _o) fputs_quoted_case(_d, _o, 1)
131#define fputs_quoted_lower(_d, _o) fputs_quoted_case(_d, _o, -1)
132
1ca2661b
KZ
133#define fputs_quoted_json(_d, _o) fputs_quoted_case_json(_d, _o, 0)
134#define fputs_quoted_json_upper(_d, _o) fputs_quoted_case_json(_d, _o, 1)
135#define fputs_quoted_json_lower(_d, _o) fputs_quoted_case_json(_d, _o, -1)
136
78a3b0af
KZ
137static inline void fputs_nonblank(const char *data, FILE *out)
138{
139 const char *p;
140
141 for (p = data; p && *p; p++) {
142 if (isblank((unsigned char) *p) ||
143 (unsigned char) *p == 0x5c || /* \ */
144 !isprint((unsigned char) *p) ||
145 iscntrl((unsigned char) *p)) {
146
147 fprintf(out, "\\x%02x", (unsigned char) *p);
148
149 } else
150 fputc(*p, out);
151 }
152}
153
154
a7da7922 155#endif /* _CAREFULPUTC_H */