Move #include from h/mh.h to source files
[mmh] / sbr / utils.c
1 /*
2 ** utils.c -- various utility routines
3 **
4 ** This code is Copyright (c) 2006, by the authors of nmh.  See the
5 ** COPYRIGHT file in the root directory of the nmh distribution for
6 ** complete copyright information.
7 */
8
9 #include <h/mh.h>
10 #include <h/utils.h>
11 #include <stdlib.h>
12 #include <fcntl.h>
13 #include <errno.h>
14 #include <unistd.h>
15 #include <sys/stat.h>
16
17 /*
18 ** We allocate space for messages (msgs array)
19 ** this number of elements at a time.
20 */
21 #define MAXMSGS 256
22
23 /*
24 ** Safely call malloc
25 */
26 void *
27 mh_xmalloc(size_t size)
28 {
29         void *memory;
30
31         if (size == 0)
32                 adios(NULL, "Tried to malloc 0 bytes");
33
34         memory = malloc(size);
35         if (!memory)
36                 adios(NULL, "Malloc failed");
37
38         return memory;
39 }
40
41 /*
42 ** Safely call realloc
43 */
44 void *
45 mh_xrealloc(void *ptr, size_t size)
46 {
47         void *memory;
48
49         /* Some non-POSIX realloc()s don't cope with realloc(NULL,sz) */
50         if (!ptr) {
51                 return mh_xmalloc(size);
52         }
53
54         if (size == 0)
55                 adios(NULL, "Tried to realloc 0 bytes");
56
57         memory = realloc(ptr, size);
58         if (!memory)
59                 adios(NULL, "Realloc failed");
60
61         return memory;
62 }
63
64 /*
65 ** Return the present working directory, if the current directory does not
66 ** exist, or is too long, make / the pwd.
67 */
68 char *
69 pwd(void)
70 {
71         register char *cp;
72         static char curwd[PATH_MAX];
73
74         if (!getcwd(curwd, PATH_MAX)) {
75                 admonish(NULL, "unable to determine working directory");
76                 if (!mypath || !*mypath ||
77                                 (strcpy(curwd, mypath), chdir(curwd)) == -1) {
78                         strcpy(curwd, "/");
79                         chdir(curwd);
80                 }
81                 return curwd;
82         }
83
84         if ((cp = curwd + strlen(curwd) - 1) > curwd && *cp == '/') {
85                 /* strip trailing slash */
86                 *cp = '\0';
87         }
88
89         return curwd;
90 }
91
92 /*
93 ** add   -- If "s1" is NULL, this routine just creates a
94 **       -- copy of "s2" into newly malloc'ed memory.
95 **       -- (use getcpy() instead in this case)
96 **       --
97 **       -- If "s1" is not NULL, then copy the concatenation
98 **       -- of "s1" and "s2" (note the order) into newly
99 **       -- malloc'ed memory.  Then free "s1".
100 */
101 char *
102 add(char *s2, char *s1)
103 {
104         char *cp;
105         size_t len1 = 0, len2 = 0;
106
107         if (s1)
108                 len1 = strlen(s1);
109         if (s2)
110                 len2 = strlen(s2);
111
112         cp = mh_xmalloc(len1 + len2 + 1);
113
114         /* Copy s1 and free it */
115         if (s1) {
116                 memcpy(cp, s1, len1);
117                 free(s1);
118         }
119
120         /* Copy s2 */
121         if (s2)
122                 memcpy(cp + len1, s2, len2);
123
124         /* Now NULL terminate the string */
125         cp[len1 + len2] = '\0';
126
127         return cp;
128 }
129
130
131 /*
132 ** create_folder
133 **     Check to see if a folder exists, if not, prompt the user to create it.
134 */
135 void
136 create_folder(char *folder, int autocreate, void (*done_callback)(int))
137 {
138         struct stat st;
139         extern int errno;
140         char *cp;
141
142         if (stat(folder, &st) == -1) {
143                 if (errno != ENOENT)
144                         adios(folder, "error on folder");
145                 if (autocreate == 0) {
146                         /* ask before creating folder */
147                         cp = concat("Create folder \"", folder, "\"? ", NULL);
148                         if (!getanswer(cp))
149                                 done_callback(1);
150                         free(cp);
151                 } else if (autocreate == -1) {
152                         /* do not create, so exit */
153                         done_callback(1);
154                 }
155                 if (!makedir(folder))
156                         adios(NULL, "unable to create folder %s", folder);
157         }
158 }
159
160 /*
161 ** num_digits
162 **     Return the number of digits in a nonnegative integer.
163 */
164 int
165 num_digits(int n)
166 {
167         int ndigits = 0;
168
169         /* Sanity check */
170         if (n < 0)
171                 adios(NULL, "oops, num_digits called with negative value");
172
173         if (n == 0)
174                 return 1;
175
176         while (n) {
177                 n /= 10;
178                 ndigits++;
179         }
180
181         return ndigits;
182 }
183
184 /*
185 ** Append a message arg to an array of them, resizing it if necessary.
186 ** The function is written to suit the arg parsing code it was extracted
187 ** from, and will probably be changed when the other code is cleaned up.
188 */
189 void
190 app_msgarg(struct msgs_array *msgs, char *cp)
191 {
192         if(msgs->size >= msgs->max)
193                 msgs->msgs = mh_xrealloc(msgs->msgs,
194                                 (msgs->max+=MAXMSGS)*sizeof(*msgs->msgs));
195         msgs->msgs[msgs->size++] = cp;
196 }