/src/common/err.c

https://code.google.com/ · C · 205 lines · 124 code · 25 blank · 56 comment · 47 complexity · ee9da4484c01ce5ef1a02c5fa6cc1e2a MD5 · raw file

  1. /*****************************************************************************\
  2. * $Id$
  3. *****************************************************************************
  4. * Copyright (C) 2001-2006 The Regents of the University of California.
  5. * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
  6. * Written by Jim Garlick <garlick@llnl.gov>.
  7. * UCRL-CODE-2003-005.
  8. *
  9. * This file is part of Pdsh, a parallel remote shell program.
  10. * For details, see <http://www.llnl.gov/linux/pdsh/>.
  11. *
  12. * Pdsh is free software; you can redistribute it and/or modify it under
  13. * the terms of the GNU General Public License as published by the Free
  14. * Software Foundation; either version 2 of the License, or (at your option)
  15. * any later version.
  16. *
  17. * Pdsh is distributed in the hope that it will be useful, but WITHOUT ANY
  18. * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  19. * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  20. * details.
  21. *
  22. * You should have received a copy of the GNU General Public License along
  23. * with Pdsh; if not, write to the Free Software Foundation, Inc.,
  24. * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  25. \*****************************************************************************/
  26. /*
  27. * Error printing routines with variable arguments.
  28. */
  29. #if HAVE_CONFIG_H
  30. #include "config.h"
  31. #endif
  32. #include <stdarg.h>
  33. #include <netdb.h>
  34. #include <string.h>
  35. #include <assert.h>
  36. #if HAVE_UNISTD_H
  37. #include <unistd.h> /* gethostname */
  38. #endif
  39. #include <ctype.h>
  40. #include <stdlib.h> /* exit */
  41. #include "xstring.h"
  42. #include "xmalloc.h"
  43. #include "macros.h"
  44. static char *prog = NULL;
  45. static char *host = NULL;
  46. /*
  47. * Optionally leave domain on hostnames with _verr's %S
  48. */
  49. static bool keep_host_domain = false;
  50. /*
  51. * Call this before calling err() or errx(). Sets hostname and program name
  52. * for %H, %p, and %P.
  53. * str (IN) program name
  54. */
  55. void err_init(char *str)
  56. {
  57. char thishost[MAXHOSTNAMELEN];
  58. char *p;
  59. gethostname(thishost, MAXHOSTNAMELEN);
  60. if ((p = strchr(thishost, '.')) != NULL)
  61. *p = '\0';
  62. host = Strdup(thishost);
  63. prog = Strdup(str);
  64. }
  65. void err_no_strip_domain ()
  66. {
  67. keep_host_domain = true;
  68. }
  69. /*
  70. * Free heap storage allocated by err_init()
  71. */
  72. void err_cleanup(void)
  73. {
  74. Free((void **) &prog);
  75. Free((void **) &host);
  76. }
  77. /*
  78. * _verr() is like vfprintf, but handles (only) the following formats:
  79. * following formats:
  80. * %s string
  81. * %S string, but treat as hostname and truncate after dot
  82. * %c character
  83. * %m string (sys_errlist[errno])
  84. * %d int
  85. * %z equivalent to %.3d
  86. * %p program name with @host attached
  87. * %P program name
  88. * %H hostname for this host
  89. */
  90. static void _verr(FILE * stream, char *format, va_list ap)
  91. {
  92. char *buf = NULL;
  93. char *q;
  94. int percent = 0;
  95. char tmpstr[LINEBUFSIZE];
  96. /* Note: snprintf silently truncates if argument exceeds size of tmpstr */
  97. assert(prog != NULL && host != NULL);
  98. while (format && *format) { /* iterate thru chars */
  99. if (percent == 1) {
  100. percent = 0;
  101. if (*format == 's') { /* %s - string */
  102. xstrcat(&buf, va_arg(ap, char *));
  103. } else if (*format == 'S') { /* %S - string, trunc */
  104. snprintf(tmpstr, sizeof(tmpstr), "%s", va_arg(ap, char *));
  105. if ( !isdigit(*tmpstr)
  106. && !keep_host_domain
  107. && (q = strchr(tmpstr, '.')))
  108. *q = '\0';
  109. xstrcat(&buf, tmpstr);
  110. } else if (*format == 'z') { /* %z - same as %.3d */
  111. snprintf(tmpstr, sizeof(tmpstr), "%.3d", va_arg(ap, int));
  112. xstrcat(&buf, tmpstr);
  113. } else if (*format == 'c') { /* %c - character */
  114. xstrcatchar(&buf, va_arg(ap, int));
  115. } else if (*format == 'd') { /* %d - integer */
  116. snprintf(tmpstr, sizeof(tmpstr), "%d", va_arg(ap, int));
  117. xstrcat(&buf, tmpstr);
  118. } else if (*format == 'm') { /* %m - error code */
  119. xstrerrorcat(&buf);
  120. } else if (*format == 'P') { /* %P - prog name */
  121. assert(prog != NULL);
  122. xstrcat(&buf, prog);
  123. } else if (*format == 'H') { /* %H - this host */
  124. assert(host != NULL);
  125. xstrcat(&buf, host);
  126. } else if (*format == 'p') { /* %p - prog@host */
  127. assert(prog != NULL);
  128. assert(host != NULL);
  129. snprintf(tmpstr, sizeof(tmpstr), "%s@%s", prog, host);
  130. xstrcat(&buf, tmpstr);
  131. } else /* pass thru */
  132. xstrcatchar(&buf, *format);
  133. } else if (*format == '%')
  134. percent = 1; /* remember % */
  135. else
  136. xstrcatchar(&buf, *format); /* pass thru */
  137. format++;
  138. }
  139. fputs(buf, stream); /* print it */
  140. Free((void **) &buf); /* clean up */
  141. }
  142. void err(char *format, ...)
  143. {
  144. va_list ap;
  145. va_start(ap, format);
  146. _verr(stderr, format, ap);
  147. va_end(ap);
  148. }
  149. void errx(char *format, ...)
  150. {
  151. va_list ap;
  152. va_start(ap, format);
  153. _verr(stderr, format, ap);
  154. va_end(ap);
  155. exit(1);
  156. }
  157. void out(char *format, ...)
  158. {
  159. va_list ap;
  160. va_start(ap, format);
  161. _verr(stdout, format, ap);
  162. va_end(ap);
  163. }
  164. void errf(FILE *stream, char *format, va_list ap)
  165. {
  166. if (!stream)
  167. return;
  168. _verr(stream, format, ap);
  169. }
  170. void lsd_fatal_error(char *file, int line, char *mesg)
  171. {
  172. errx ("%p: %s:%d: %s\n", file, line, mesg);
  173. }
  174. void lsd_nomem_error(char *file, int line, char *mesg)
  175. {
  176. errx ("%p: %s:%d: %s: Out of memory\n", file, line, mesg);
  177. }
  178. /*
  179. * vi:tabstop=4 shiftwidth=4 expandtab
  180. */