summaryrefslogtreecommitdiff
path: root/testsuite/cwdrepl.c
diff options
context:
space:
mode:
Diffstat (limited to 'testsuite/cwdrepl.c')
-rw-r--r--testsuite/cwdrepl.c176
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
19NAME
20
21 cwdrepl - replace occurrences of CWD with .
22
23SYNOPSIS
24
25 COMMAND | cwdrepl [DIR REPL]...
26
27DESCRIPTION
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
54struct dirtrans
55{
56 char *dir;
57 size_t dirlen;
58 char const *trans;
59 ssize_t translen;
60};
61
62mu_list_t translist;
63
64static int
65transcmp (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
72static void
73newdir (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
107static inline int
108isbnd (int c)
109{
110 return mu_c_is_class (c, MU_CTYPE_CNTRL|MU_CTYPE_PUNCT|MU_CTYPE_SPACE);
111}
112
113int
114main (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}

Return to:

Send suggestions and report system problems to the System administrator.