diff options
Diffstat (limited to 'testsuite/cwdrepl.c')
-rw-r--r-- | testsuite/cwdrepl.c | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/testsuite/cwdrepl.c b/testsuite/cwdrepl.c new file mode 100644 index 000000000..9f6525f18 --- /dev/null +++ b/testsuite/cwdrepl.c | |||
@@ -0,0 +1,176 @@ | |||
1 | /* This file is part of GNU Mailutils testsuite. | ||
2 | Copyright (C) 2017 Free Software Foundation, Inc. | ||
3 | |||
4 | GNU Mailutils is free software; you can redistribute it and/or modify | ||
5 | it under the terms of the GNU General Public License as published by | ||
6 | the Free Software Foundation; either version 3, or (at your option) | ||
7 | any later version. | ||
8 | |||
9 | GNU Mailutils is distributed in the hope that it will be useful, | ||
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | GNU General Public License for more details. | ||
13 | |||
14 | You should have received a copy of the GNU General Public License | ||
15 | along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */ | ||
16 | |||
17 | /* | ||
18 | |||
19 | NAME | ||
20 | |||
21 | cwdrepl - replace occurrences of CWD with . | ||
22 | |||
23 | SYNOPSIS | ||
24 | |||
25 | COMMAND | cwdrepl [DIR REPL]... | ||
26 | |||
27 | DESCRIPTION | ||
28 | |||
29 | Some testcases operate programs that produce full file names as part | ||
30 | of their output. To make this output independent of the actual file | ||
31 | location, this tool replaces every occurrence of the current working | ||
32 | directory with dot. Both logical (as given by the PWD environment | ||
33 | variable) and physical (as returned by getcwd(3)) locations are replaced. | ||
34 | |||
35 | The same effect could have been achieved by using "pwd -P", "pwd -L" | ||
36 | and sed, but this would pose portability problems. | ||
37 | |||
38 | Additionally, any number of DIR REPL pairs can be supplied in the command | ||
39 | line. Each pair instructs the tool to replace every occurrence of DIR | ||
40 | with REPL on output. Note that these pairs take precedence over the | ||
41 | default ones, so running "cwdrepl $PWD 'PWD'" will replace occurrences | ||
42 | of the logical current working directory name with the string PWS, instead | ||
43 | of the default dot. | ||
44 | |||
45 | */ | ||
46 | |||
47 | #ifdef HAVE_CONFIG_H | ||
48 | # include <config.h> | ||
49 | #endif | ||
50 | #include <stdlib.h> | ||
51 | #include <string.h> | ||
52 | #include <mailutils/mailutils.h> | ||
53 | |||
54 | struct dirtrans | ||
55 | { | ||
56 | char *dir; | ||
57 | size_t dirlen; | ||
58 | char const *trans; | ||
59 | ssize_t translen; | ||
60 | }; | ||
61 | |||
62 | mu_list_t translist; | ||
63 | |||
64 | static int | ||
65 | transcmp (const void *a, const void *b) | ||
66 | { | ||
67 | struct dirtrans const *trans1 = a; | ||
68 | struct dirtrans const *trans2 = b; | ||
69 | return strcmp (trans1->dir, trans2->dir); | ||
70 | } | ||
71 | |||
72 | static void | ||
73 | newdir (char const *dir, char const *trans) | ||
74 | { | ||
75 | if (dir) | ||
76 | { | ||
77 | size_t dirlen = strlen (dir); | ||
78 | size_t translen = strlen (trans); | ||
79 | struct dirtrans *dt = mu_alloc (sizeof *dt); | ||
80 | |||
81 | while (dirlen > 0 && dir[dirlen-1] == '/') | ||
82 | dirlen--; | ||
83 | |||
84 | dt->dir = mu_alloc (dirlen + 1); | ||
85 | memcpy (dt->dir, dir, dirlen); | ||
86 | dt->dir[dirlen] = 0; | ||
87 | dt->dirlen = dirlen; | ||
88 | dt->trans = trans; | ||
89 | dt->translen = translen; | ||
90 | |||
91 | if (!translist) | ||
92 | { | ||
93 | MU_ASSERT (mu_list_create (&translist)); | ||
94 | mu_list_set_comparator (translist, transcmp); | ||
95 | } | ||
96 | else if (mu_list_locate (translist, dt, NULL) == 0) | ||
97 | { | ||
98 | free (dt->dir); | ||
99 | free (dt); | ||
100 | return; | ||
101 | } | ||
102 | |||
103 | MU_ASSERT (mu_list_append (translist, dt)); | ||
104 | } | ||
105 | } | ||
106 | |||
107 | static inline int | ||
108 | isbnd (int c) | ||
109 | { | ||
110 | return mu_c_is_class (c, MU_CTYPE_CNTRL|MU_CTYPE_PUNCT|MU_CTYPE_SPACE); | ||
111 | } | ||
112 | |||
113 | int | ||
114 | main (int argc, char **argv) | ||
115 | { | ||
116 | int i; | ||
117 | int rc; | ||
118 | char *buf = NULL; | ||
119 | size_t size, n; | ||
120 | mu_iterator_t itr; | ||
121 | |||
122 | mu_set_program_name (argv[0]); | ||
123 | mu_stdstream_setup (MU_STDSTREAM_RESET_NONE); | ||
124 | |||
125 | for (i = 1; i < argc; i += 2) | ||
126 | newdir (argv[i], (i + 1 < argc) ? argv[i + 1] : ""); | ||
127 | |||
128 | newdir (getenv ("PWD"), "."); | ||
129 | newdir (mu_getcwd (), "."); | ||
130 | |||
131 | MU_ASSERT (mu_list_get_iterator (translist, &itr)); | ||
132 | while ((rc = mu_stream_getline (mu_strin, &buf, &size, &n)) == 0 && n > 0) | ||
133 | { | ||
134 | n = mu_rtrim_class (buf, MU_CTYPE_SPACE); | ||
135 | for (mu_iterator_first (itr); !mu_iterator_is_done (itr); | ||
136 | mu_iterator_next (itr)) | ||
137 | { | ||
138 | struct dirtrans *dt; | ||
139 | size_t start = 0; | ||
140 | char *p; | ||
141 | |||
142 | mu_iterator_current (itr, (void**) &dt); | ||
143 | while ((p = strstr (buf + start, dt->dir))) | ||
144 | { | ||
145 | if (isbnd (p[dt->dirlen])) | ||
146 | { | ||
147 | size_t off = p - buf; | ||
148 | size_t rest = n - start; | ||
149 | ssize_t d = (ssize_t)dt->translen - dt->dirlen; | ||
150 | |||
151 | if (d > 0) | ||
152 | { | ||
153 | if (n + d + 1 > size) | ||
154 | { | ||
155 | size = n + d + 1; | ||
156 | buf = mu_realloc (buf, size); | ||
157 | p = buf + off; | ||
158 | } | ||
159 | } | ||
160 | |||
161 | memmove (p + dt->translen, p + dt->dirlen, | ||
162 | rest - dt->dirlen + 1); | ||
163 | memcpy (p, dt->trans, dt->translen); | ||
164 | |||
165 | n += d; | ||
166 | start = off + dt->translen; | ||
167 | } | ||
168 | else | ||
169 | start++; | ||
170 | } | ||
171 | } | ||
172 | mu_stream_write (mu_strout, buf, n, NULL); | ||
173 | mu_stream_write (mu_strout, "\n", 1, NULL); | ||
174 | } | ||
175 | return 0; | ||
176 | } | ||