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