1 /* Copyright (C) 2002 by  Red Hat, Incorporated. All rights reserved.
2  *
3  * Permission to use, copy, modify, and distribute this software
4  * is freely granted, provided that this notice is preserved.
5  */
6 
7 #include <errno.h>
8 #include <sys/types.h>
9 #include <string.h>
10 #include <stdlib.h>
11 #include <argz.h>
12 
13 #include "buf_findstr.h"
14 
15 error_t
argz_replace(char ** argz,size_t * argz_len,const char * str,const char * with,unsigned * replace_count)16 argz_replace (char **argz,
17        size_t *argz_len,
18        const char *str,
19        const char *with,
20        unsigned *replace_count)
21 {
22   const size_t str_len = strlen(str);
23   const size_t with_len = strlen(with);
24   const ssize_t len_diff = with_len - str_len;
25 
26   char *buf_iter = *argz;
27   size_t buf_len = *argz_len;
28   char *last_iter = NULL;
29   char *new_argz = NULL;
30   size_t new_argz_len = 0;
31   char *new_argz_iter = NULL;
32   char *argz_realloc = NULL;
33 
34   *replace_count = 0;
35   new_argz_len = *argz_len;
36 
37   while(buf_len)
38     {
39       if(_buf_findstr(str, &buf_iter, &buf_len))
40         {
41           *replace_count += 1;
42           new_argz_len += len_diff;
43         }
44     }
45 
46   if (*replace_count)
47     {
48       if (!(new_argz = (char *)malloc(new_argz_len)))
49 	return ENOMEM;
50 
51       buf_iter = *argz;
52       buf_len = *argz_len;
53       last_iter = buf_iter;
54       new_argz_iter = new_argz;
55 
56       while(buf_len)
57         {
58           if (_buf_findstr(str, &buf_iter, &buf_len))
59             {
60               /* copy everything up to, but not including str, from old argz to
61                  new argz. */
62               memcpy(new_argz_iter, last_iter, buf_iter - last_iter - str_len);
63               new_argz_iter += (buf_iter - last_iter - str_len);
64               /* copy replacement string. */
65               memcpy(new_argz_iter, with, with_len);
66               new_argz_iter += with_len;
67               last_iter = buf_iter;
68             }
69         }
70       /* copy everything after last occurrence of str. */
71       memcpy(new_argz_iter, last_iter, *argz + *argz_len - last_iter);
72 
73       /* reallocate argz, and copy over the new value. */
74       if(!(argz_realloc = (char *)realloc(*argz, new_argz_len)))
75         {
76           free(new_argz);
77           return ENOMEM;
78         }
79       *argz = argz_realloc;
80 
81       memcpy(*argz, new_argz, new_argz_len);
82       *argz_len = new_argz_len;
83 
84       if (*argz_len == 0)
85         {
86           free(*argz);
87           *argz = NULL;
88         }
89       free(new_argz);
90     }
91 
92   return 0;
93 }
94