1 /* do a rot13 of ASCII text */
2
3 #include "ex_utils.h"
4
5 #define CONF_USE_MMAP_DEF FALSE
6
7 /* configuration:
8 how to do it ... */
9 #define EX_ROT13_USE_ITER 1
10 #define EX_ROT13_USE_EXPORT_CHR 0
11 #define EX_ROT13_USE_SUB_CHR 0
12 #define EX_ROT13_USE_CSTR_MALLOC 0
13
14 #define ROT13_LETTER(x) ( \
15 (((x) >= 'A' && (x) <= 'M') || \
16 ((x) >= 'a' && (x) <= 'm')) ? ((x) + 13) : ((x) - 13) \
17 )
18
19 #if 0
20 #define ROT13_MAP(x) ( \
21 ((((x) >= 'A') && ((x) <= 'Z')) || \
22 (((x) >= 'a') && ((x) <= 'z'))) ? ROT13_LETTER(x) : (x) \
23 )
24 #else
25 static char rot13_map[] = {
26 1* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
27 1* 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31,
28 1* 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
29 1* 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
30 1* 64, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 65, 66,
31 1* 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 91, 92, 93, 94, 95,
32 1* 96,110,111,112,113,114,115,116,117,118,119,120,121,122, 97, 98,
33 1* 99,100,101,102,103,104,105,106,107,108,109,123,124,125,126,127,
34 1* 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
35 1* 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,
36 1* 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
37 1* 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,
38 1* 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,
39 1* 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,
40 1* 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,
41 1* 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255};
42 #define ROT13_MAP(x) rot13_map[(unsigned char)(x)]
43 #endif
44
ex_rot13_process(Vstr_base * s1,Vstr_base * s2)45 static int ex_rot13_process(Vstr_base *s1, Vstr_base *s2)
46 {
47 size_t count = 0;
48 static const char chrs[] = ("abcdefghijklmnopqrstuvwxyz"
49 "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
50
51 /* we don't want to create more data, if we are over our limit */
52 if (s1->len > EX_MAX_W_DATA_INCORE)
53 return (FALSE);
54
55 if (!s2->len)
56 return (FALSE);
57
58 if (EX_ROT13_USE_ITER)
59 {
60 Vstr_iter iter[1];
61
62 if (!vstr_iter_fwd_beg(s2, 1, s2->len, iter))
63 abort();
64
65 do
66 {
67 unsigned int scan = 0;
68 while (scan < iter->len)
69 {
70 char tmp = ROT13_MAP(iter->ptr[scan]);
71 vstr_add_rep_chr(s1, s1->len, tmp, 1);
72 ++scan;
73 }
74 } while (vstr_iter_fwd_nxt(iter));
75
76 vstr_del(s2, 1, s2->len);
77 }
78
79 if (EX_ROT13_USE_EXPORT_CHR)
80 {
81 unsigned int scan = 0;
82 while (scan++ < s2->len)
83 {
84 char tmp = vstr_export_chr(s2, scan);
85 tmp = ROT13_MAP(tmp);
86 vstr_add_rep_chr(s1, s1->len, tmp, 1);
87 }
88 vstr_del(s2, 1, s2->len);
89 }
90
91 if (EX_ROT13_USE_SUB_CHR)
92 {
93 unsigned int scan = 0;
94
95 while (scan++ < s2->len)
96 {
97 char tmp = vstr_export_chr(s2, scan);
98 tmp = ROT13_MAP(tmp);
99 vstr_sub_rep_chr(s2, scan, 1, tmp, 1);
100 }
101 vstr_add_vstr(s1, s1->len, s2, 1, s2->len,
102 VSTR_TYPE_ADD_BUF_REF);
103 vstr_del(s2, 1, s2->len);
104 }
105
106 if (EX_ROT13_USE_CSTR_MALLOC)
107 while (s2->len)
108 {
109 if ((count = VSTR_CSPN_CSTR_CHRS_FWD(s2, 1, s2->len, chrs)))
110 {
111 vstr_add_vstr(s1, s1->len, s2, 1, count,
112 VSTR_TYPE_ADD_BUF_REF);
113 vstr_del(s2, 1, count);
114
115 if (s1->len > EX_MAX_W_DATA_INCORE)
116 return (TRUE);
117 }
118
119 if ((count = VSTR_SPN_CSTR_CHRS_FWD(s2, 1, s2->len, chrs)))
120 {
121 char *ptr = vstr_export_cstr_malloc(s2, 1, count);
122 Vstr_ref *ref = vstr_ref_make_ptr(ptr, vstr_ref_cb_free_ptr_ref);
123
124 if (!ref || !ref->ptr)
125 errno = ENOMEM, err(EXIT_FAILURE, "vstr_make_conf");
126
127 while (*ptr)
128 {
129 *ptr = ROT13_LETTER(*ptr);
130 ++ptr;
131 }
132
133 vstr_add_ref(s1, s1->len, ref, 0, count);
134 vstr_del(s2, 1, count);
135 }
136 }
137
138 return (TRUE);
139 }
140
ex_rot13_read_fd_write_stdout(Vstr_base * s1,Vstr_base * s2,int fd)141 static void ex_rot13_read_fd_write_stdout(Vstr_base *s1, Vstr_base *s2, int fd)
142 {
143 while (TRUE)
144 {
145 int io_w_state = IO_OK;
146 int io_r_state = io_get(s2, fd);
147
148 if (io_r_state == IO_EOF)
149 break;
150
151 ex_rot13_process(s1, s2);
152
153 io_w_state = io_put(s1, 1);
154
155 io_limit(io_r_state, fd, io_w_state, 1, s1);
156 }
157 }
158
ex_rot13_process_limit(Vstr_base * s1,Vstr_base * s2,unsigned int lim)159 static void ex_rot13_process_limit(Vstr_base *s1, Vstr_base *s2,
160 unsigned int lim)
161 {
162 while (s2->len > lim)
163 {
164 int proc_data = ex_rot13_process(s1, s2);
165 if (!proc_data && (io_put(s1, STDOUT_FILENO) == IO_BLOCK))
166 io_block(-1, STDOUT_FILENO);
167 }
168 }
169
main(int argc,char * argv[])170 int main(int argc, char *argv[])
171 {
172 Vstr_base *s1 = NULL;
173 Vstr_base *s2 = ex_init(&s1);
174 int count = 1;
175 int use_mmap = CONF_USE_MMAP_DEF;
176
177 /* parse command line arguments... */
178 while (count < argc)
179 { /* quick hack getopt_long */
180 if (!strcmp("--", argv[count]))
181 {
182 ++count;
183 break;
184 }
185 else if (!strcmp("--mmap", argv[count])) /* toggle use of mmap */
186 use_mmap = !use_mmap;
187 else if (!strcmp("--version", argv[count]))
188 { /* print version and exit */
189 vstr_add_fmt(s1, 0, "%s", "\
190 jrot13 1.0.0\n\
191 Written by James Antill\n\
192 \n\
193 Uses Vstr string library.\n\
194 ");
195 goto out;
196 }
197 else if (!strcmp("--help", argv[count]))
198 { /* print version and exit */
199 vstr_add_fmt(s1, 0, "%s", "\
200 Usage: jrot13 [FILENAME]...\n\
201 or: jrot13 OPTION\n\
202 Output filenames.\n\
203 \n\
204 --help Display this help and exit\n\
205 --version Output version information and exit\n\
206 --mmap Toggle use of mmap() to load input files\n\
207 -- Treat rest of cmd line as input filenames\n\
208 \n\
209 Report bugs to James Antill <james@and.org>.\n\
210 ");
211 goto out;
212 }
213 else
214 break;
215 ++count;
216 }
217
218 if (count >= argc) /* use stdin */
219 {
220 io_fd_set_o_nonblock(STDIN_FILENO);
221 ex_rot13_read_fd_write_stdout(s1, s2, STDIN_FILENO);
222 }
223
224 /* loop through all arguments, open the file specified
225 * and do the read/write loop */
226 while (count < argc)
227 {
228 unsigned int ern = 0;
229
230 if (use_mmap)
231 vstr_sc_mmap_file(s2, s2->len, argv[count], 0, 0, &ern);
232
233 if (!use_mmap ||
234 (ern == VSTR_TYPE_SC_MMAP_FILE_ERR_FSTAT_ERRNO) ||
235 (ern == VSTR_TYPE_SC_MMAP_FILE_ERR_MMAP_ERRNO) ||
236 (ern == VSTR_TYPE_SC_MMAP_FILE_ERR_TOO_LARGE))
237 {
238 int fd = io_open(argv[count]);
239
240 ex_rot13_read_fd_write_stdout(s1, s2, fd);
241
242 if (close(fd) == -1)
243 warn("close(%s)", argv[count]);
244 }
245 else if (ern && (ern != VSTR_TYPE_SC_MMAP_FILE_ERR_CLOSE_ERRNO))
246 err(EXIT_FAILURE, "add");
247 else
248 ex_rot13_process_limit(s1, s2, EX_MAX_R_DATA_INCORE);
249
250 ++count;
251 }
252
253 ex_rot13_process_limit(s1, s2, 0);
254
255 out:
256 io_put_all(s1, STDOUT_FILENO);
257
258 exit (ex_exit(s1, s2));
259 }
260