libmsngr  1.1
 All Data Structures Files Functions Variables Enumerations Enumerator Macros Groups
msngr_utils.c
Go to the documentation of this file.
1 /*******************************************************************************
2 *
3 * COPYRIGHT (C) 2010 Battelle Memorial Institute. All Rights Reserved.
4 *
5 ********************************************************************************
6 *
7 * Author:
8 * name: Brian Ermold
9 * phone: (509) 375-2277
10 * email: brian.ermold@pnl.gov
11 *
12 ********************************************************************************
13 *
14 * REPOSITORY INFORMATION:
15 * $Revision: 12906 $
16 * $Author: ermold $
17 * $Date: 2012-02-23 07:09:27 +0000 (Thu, 23 Feb 2012) $
18 *
19 ********************************************************************************
20 *
21 * NOTE: DOXYGEN is used to generate documentation for this file.
22 *
23 *******************************************************************************/
24 
25 /** @file msngr_utils.c
26  * Utility Functions.
27  */
28 
29 #include <stdlib.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <unistd.h>
33 #include <sys/stat.h>
34 
35 #include "messenger.h"
36 
37 /**
38  * @defgroup MSNGRUtils Utility Functions
39  */
40 /*@{*/
41 
42 /*******************************************************************************
43  * Private Functions
44  */
45 /** @privatesection */
46 
47 /*******************************************************************************
48  * Public Functions
49  */
50 /** @publicsection */
51 
52 /**
53  * Create a dynamically allocated copy of a string.
54  *
55  * The memory used by the returned string is dynamically allocated.
56  * It is the responsibility of the calling process to free this
57  * memory when it is no longer needed.
58  *
59  * @param string - pointer to the string to copy
60  *
61  * @return
62  * - pointer to the dynamically allocated copy of the string
63  * - NULL if a memory allocation error occurred
64  */
65 char *msngr_copy_string(const char *string)
66 {
67  size_t length = strlen(string) + 1;
68  char *copy = (char *)malloc(length * sizeof(char));
69 
70  if (copy) {
71  return((char *)memcpy(copy, string, length));
72  }
73 
74  return((char *)NULL);
75 }
76 
77 /**
78  * Create a new text string.
79  *
80  * This functions creates a new text string under the control of
81  * the format argument.
82  *
83  * The memory used by the returned string is dynamically allocated.
84  * It is the responsibility of the calling process to free this
85  * memory when it is no longer needed.
86  *
87  * @param format - format string (see printf)
88  * @param ... - arguments for the format string
89  *
90  * @return
91  * - pointer to the dynamically allocated text string
92  * - NULL if a memory allocation error occurred
93  */
94 char *msngr_create_string(const char *format, ...)
95 {
96  va_list args;
97  char *string;
98 
99  va_start(args, format);
100  string = msngr_format_va_list(format, args);
101  va_end(args);
102 
103  return(string);
104 }
105 
106 /**
107  * Convert seconds since 1970 to a formatted time string.
108  *
109  * This function will create a time string of the form:
110  *
111  * 'YYYY-MM-DD hh:mm:ss'.
112  *
113  * The string argument must be large enough to hold at
114  * least 20 characters (19 plus the null terminator).
115  *
116  * If an error occurs in this function, the message
117  * 'FORMATTING ERROR' will be copied into the text string.
118  *
119  * @param secs1970 - seconds since 1970
120  * @param string - time string to store the result in
121  *
122  * @return pointer to the string argument
123  */
124 char *msngr_format_time(time_t secs1970, char *string)
125 {
126  struct tm tm_time;
127 
128  memset(&tm_time, 0, sizeof(tm_time));
129 
130  if (!gmtime_r(&secs1970, &tm_time)) {
131  strcpy(string, "FORMATTING ERROR");
132  }
133  else {
134  sprintf(string,
135  "%04d-%02d-%02d %02d:%02d:%02d",
136  tm_time.tm_year + 1900,
137  tm_time.tm_mon + 1,
138  tm_time.tm_mday,
139  tm_time.tm_hour,
140  tm_time.tm_min,
141  tm_time.tm_sec);
142  }
143 
144  return(string);
145 }
146 
147 /**
148  * Create a text string from a format string and va_list.
149  *
150  * The memory used by the returned string is dynamically allocated.
151  * It is the responsibility of the calling process to free this
152  * memory when it is no longer needed.
153  *
154  * @param format - format string (see printf)
155  * @param args - arguments for the format string
156  *
157  * @return
158  * - pointer to the dynamically allocated text string
159  * - NULL if a memory allocation error occurred
160  */
162  const char *format,
163  va_list args)
164 {
165  int length;
166  char *string;
167 
168  length = msngr_vsnprintf((char *)NULL, 0, format, args) + 1;
169 
170  if (length <= 0) {
171  return((char *)NULL);
172  }
173 
174  string = (char *)malloc(length * sizeof(char));
175  if (!string) {
176  return((char *)NULL);
177  }
178 
179  msngr_vsprintf(string, format, args);
180 
181  return(string);
182 }
183 
184 /**
185  * Get the start time of a process.
186  *
187  * @param pid - process ID
188  *
189  * @return
190  * - process start time in seconds since 1970
191  * - 0 if the process does not exist
192  */
194 {
195  char pid_dir[32];
196  struct stat pid_dir_stats;
197 
198  snprintf(pid_dir, 32, "/proc/%d", (int)pid);
199 
200  if (stat(pid_dir, &pid_dir_stats) == 0) {
201  return(pid_dir_stats.st_mtime);
202  }
203 
204  return(0);
205 }
206 
207 /**
208  * Make the full path to a directory.
209  *
210  * This function will create the specified path if it does
211  * not already exist.
212  *
213  * The space pointed to by errstr should be large enough to
214  * hold MAX_LOG_ERROR bytes. Any less than that and the error
215  * message could be truncated.
216  *
217  * If errlen is 0 then no error message is written to errstr
218  * and errstr can be NULL.
219  *
220  * @param path - directory path to create
221  * @param mode - mode of the new directory
222  * @param errlen - length of the error message buffer
223  * @param errstr - output: error message
224  *
225  * @return
226  * - 1 if the path exists or was created
227  * - 0 if an error occurred
228  */
230  const char *path,
231  mode_t mode,
232  size_t errlen,
233  char *errstr)
234 {
235  char *buffer;
236  char *chrp;
237  char chr;
238 
239  if (access(path, F_OK) != 0) {
240 
241  buffer = malloc((strlen(path) + 1) * sizeof(char));
242  if (!buffer) {
243 
244  snprintf(errstr, errlen,
245  "Could not make path: %s\n"
246  " -> memory allocation error\n", path);
247 
248  return(0);
249  }
250 
251  strcpy(buffer, path);
252 
253  for (chrp = buffer+1; ; chrp++) {
254 
255  if (*chrp == '/' || *chrp == '\0') {
256 
257  chr = *chrp;
258  *chrp = '\0';
259 
260  if (access(buffer, F_OK) != 0) {
261 
262  if (mkdir(buffer, mode) < 0) {
263 
264  snprintf(errstr, errlen,
265  "Could not make path: %s\n"
266  " -> mkdir error: %s\n",
267  buffer, strerror(errno));
268 
269  free(buffer);
270  return(0);
271  }
272  }
273 
274  *chrp = chr;
275  if (chr == '\0') break;
276  }
277  }
278 
279  free(buffer);
280  }
281 
282  return(1);
283 }
284 
285 /**
286  * Wrapper to vprintf that preserves the argument list.
287  *
288  * @param format - format string
289  * @param args - arguments for the format string
290  *
291  * @return the number of bytes written to stdout
292  */
293 int msngr_vprintf(const char *format, va_list args)
294 {
295  va_list copy;
296  int retval;
297 
298  va_copy(copy, args);
299  retval = vprintf(format, copy);
300  va_end(copy);
301 
302  return(retval);
303 }
304 
305 /**
306  * Wrapper to vfprintf that preserves the argument list.
307  *
308  * @param stream - pointer to the output stream
309  * @param format - format string
310  * @param args - arguments for the format string
311  *
312  * @return the number of bytes written to the output stream
313  */
314 int msngr_vfprintf(FILE *stream, const char *format, va_list args)
315 {
316  va_list copy;
317  int retval;
318 
319  va_copy(copy, args);
320  retval = vfprintf(stream, format, copy);
321  va_end(copy);
322 
323  return(retval);
324 }
325 
326 /**
327  * Wrapper to vsprintf that preserves the argument list.
328  *
329  * @param string - output string
330  * @param format - format string
331  * @param args - arguments for the format string
332  *
333  * @return the number of bytes written to the output string
334  * (excluding the terminating null byte)
335  */
336 int msngr_vsprintf(char *string, const char *format, va_list args)
337 {
338  va_list copy;
339  int retval;
340 
341  va_copy(copy, args);
342  retval = vsprintf(string, format, copy);
343  va_end(copy);
344 
345  return(retval);
346 }
347 
348 /**
349  * Wrapper to vsnprintf that preserves the argument list.
350  *
351  * @param string - output string
352  * @param nbytes - the length of the output string
353  * @param format - format string
354  * @param args - arguments for the format string
355  *
356  * @return the number of bytes that would have been written to the
357  * output string if its length had been sufficiently large
358  * (excluding the terminating null byte.)
359  */
361  char *string,
362  size_t nbytes,
363  const char *format,
364  va_list args)
365 {
366  va_list copy;
367  int retval;
368 
369  va_copy(copy, args);
370  retval = vsnprintf(string, nbytes, format, copy);
371  va_end(copy);
372 
373  return(retval);
374 }
375 
376 /*@}*/