Code reformating.
[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
15 /*
16 ** We allocate space for messages (msgs array)
17 ** this number of elements at a time.
18 */
19 #define MAXMSGS 256
20
21 /*
22 ** Safely call malloc
23 */
24 void *
25 mh_xmalloc(size_t size)
26 {
27         void *memory;
28
29         if (size == 0)
30                 adios(NULL, "Tried to malloc 0 bytes");
31
32         memory = malloc(size);
33         if (!memory)
34                 adios(NULL, "Malloc failed");
35
36         return memory;
37 }
38
39 /*
40 ** Safely call realloc
41 */
42 void *
43 mh_xrealloc(void *ptr, size_t size)
44 {
45         void *memory;
46
47         /* Some non-POSIX realloc()s don't cope with realloc(NULL,sz) */
48         if (!ptr)
49                 return mh_xmalloc(size);
50
51         if (size == 0)
52                 adios(NULL, "Tried to realloc 0bytes");
53
54         memory = realloc(ptr, size);
55         if (!memory)
56                 adios(NULL, "Realloc failed");
57
58         return memory;
59 }
60
61 /*
62 ** Return the present working directory, if the current directory does not
63 ** exist, or is too long, make / the pwd.
64 */
65 char *
66 pwd(void)
67 {
68         register char *cp;
69         static char curwd[PATH_MAX];
70
71         if (!getcwd(curwd, PATH_MAX)) {
72                 admonish(NULL, "unable to determine working directory");
73                 if (!mypath || !*mypath ||
74                                 (strcpy(curwd, mypath), chdir(curwd)) == -1) {
75                         strcpy(curwd, "/");
76                         chdir(curwd);
77                 }
78                 return curwd;
79         }
80
81         if ((cp = curwd + strlen(curwd) - 1) > curwd && *cp == '/')
82                 *cp = '\0';
83
84         return curwd;
85 }
86
87 /*
88 ** add   -- If "s1" is NULL, this routine just creates a
89 **       -- copy of "s2" into newly malloc'ed memory.
90 **       --
91 **       -- If "s1" is not NULL, then copy the concatenation
92 **       -- of "s1" and "s2" (note the order) into newly
93 **       -- malloc'ed memory.  Then free "s1".
94 */
95 char *
96 add(char *s2, char *s1)
97 {
98         char *cp;
99         size_t len1 = 0, len2 = 0;
100
101         if (s1)
102                 len1 = strlen(s1);
103         if (s2)
104                 len2 = strlen(s2);
105
106         cp = mh_xmalloc(len1 + len2 + 1);
107
108         /* Copy s1 and free it */
109         if (s1) {
110                 memcpy(cp, s1, len1);
111                 free(s1);
112         }
113
114         /* Copy s2 */
115         if (s2)
116                 memcpy(cp + len1, s2, len2);
117
118         /* Now NULL terminate the string */
119         cp[len1 + len2] = '\0';
120
121         return cp;
122 }
123
124 /*
125 ** folder_exists
126 **     Check to see if a folder exists.
127 */
128 int
129 folder_exists(char *folder)
130 {
131         struct stat st;
132         int exists = 0;
133
134         if (stat(folder, &st) == -1) {
135                 /*
136                 ** The folder either doesn't exist, or we hit an error.
137                 ** Either way return a failure.
138                 */
139                 exists = 0;
140         } else {
141                 /* We can see a folder with the right name */
142                 exists = 1;
143         }
144
145         return exists;
146 }
147
148
149 /*
150 ** create_folder
151 **     Check to see if a folder exists, if not, prompt the user to create it.
152 */
153 void
154 create_folder(char *folder, int autocreate, void (*done_callback)(int))
155 {
156         struct stat st;
157         extern int errno;
158         char *cp;
159
160         if (stat(folder, &st) == -1) {
161                 if (errno != ENOENT)
162                         adios(folder, "error on folder");
163                 if (autocreate == 0) {
164                         /* ask before creating folder */
165                         cp = concat("Create folder \"", folder, "\"? ", NULL);
166                         if (!getanswer(cp))
167                                 done_callback(1);
168                         free(cp);
169                 } else if (autocreate == -1) {
170                         /* do not create, so exit */
171                         done_callback(1);
172                 }
173                 if (!makedir(folder))
174                         adios(NULL, "unable to create folder %s", folder);
175         }
176 }
177
178 /*
179 ** num_digits
180 **     Return the number of digits in a nonnegative integer.
181 */
182 int
183 num_digits(int n)
184 {
185         int ndigits = 0;
186
187         /* Sanity check */
188         if (n < 0)
189                 adios(NULL, "oops, num_digits called with negative value");
190
191         if (n == 0)
192                 return 1;
193
194         while (n) {
195                 n /= 10;
196                 ndigits++;
197         }
198
199         return ndigits;
200 }
201
202 /*
203 ** Append a message arg to an array of them, resizing it if necessary.
204 ** The function is written to suit the arg parsing code it was extracted
205 ** from, and will probably be changed when the other code is cleaned up.
206 */
207 void
208 app_msgarg(struct msgs_array *msgs, char *cp)
209 {
210         if(msgs->size >= msgs->max)
211                 msgs->msgs = mh_xrealloc(msgs->msgs,
212                                 (msgs->max+=MAXMSGS)*sizeof(*msgs->msgs));
213         msgs->msgs[msgs->size++] = cp;
214 }
215
216 /* Open a form or components file */
217 int
218 open_form(char **form, char *def)
219 {
220         int in;
221         if (*form) {
222                 if ((in = open(etcpath(*form), O_RDONLY)) == NOTOK)
223                         adios(*form, "unable to open form file");
224         } else {
225                 if ((in = open(etcpath(def), O_RDONLY)) == NOTOK)
226                         adios(def, "unable to open default components file");
227                 *form = def;
228         }
229         return in;
230 }