error.c (2661B)
1 /* Public Domain --Kris Maglione */ 2 #include <errno.h> 3 #include <stdarg.h> 4 #include <stdio.h> 5 #include <stdlib.h> 6 #include <string.h> 7 #include "ixp_local.h" 8 9 static int 10 _vsnprint(char *buf, int nbuf, const char *fmt, va_list ap) { 11 return vsnprintf(buf, nbuf, fmt, ap); 12 } 13 14 static char* 15 _vsmprint(const char *fmt, va_list ap) { 16 va_list al; 17 char *buf = ""; 18 int n; 19 20 va_copy(al, ap); 21 n = vsnprintf(buf, 0, fmt, al); 22 va_end(al); 23 24 buf = malloc(++n); 25 if(buf) 26 vsnprintf(buf, n, fmt, ap); 27 return buf; 28 } 29 30 int (*ixp_vsnprint)(char*, int, const char*, va_list) = _vsnprint; 31 char* (*ixp_vsmprint)(const char*, va_list) = _vsmprint; 32 33 /* Approach to errno handling taken from Plan 9 Port. */ 34 enum { 35 EPLAN9 = 0x19283745, 36 }; 37 38 /** 39 * Function: ixp_errbuf 40 * Function: ixp_errstr 41 * Function: ixp_rerrstr 42 * Function: ixp_werrstr 43 * Variable: ixp_vsnprint 44 * 45 * Params: 46 * buf: The buffer to read and/or fill. 47 * nbuf: The size of the buffer. 48 * fmt: A format string with which to write the errstr. 49 * ...: Arguments to P<fmt>. 50 * 51 * These functions simulate Plan 9's errstr functionality. 52 * They replace errno in libixp. Note that these functions 53 * are not internationalized. 54 * 55 * F<ixp_errbuf> returns the errstr buffer for the current 56 * thread. F<ixp_rerrstr> fills P<buf> with the data from 57 * the current thread's error buffer, while F<ixp_errstr> 58 * exchanges P<buf>'s contents with those of the current 59 * thread's error buffer. F<ixp_werrstr> formats the given 60 * format string, P<fmt>, via V<ixp_vsnprint> and writes it to 61 * the error buffer. 62 * 63 * V<ixp_vsnprint> may be set to a function which will format 64 * its arguments write the result to the P<nbuf> length buffer 65 * V<buf>. The default value is F<vsnprintf>. The function must 66 * format '%s' as a nul-terminated string and may not consume 67 * any arguments not indicated by a %-prefixed format specifier, 68 * but may otherwise behave in any manner chosen by the user. 69 * 70 * See also: 71 * V<ixp_vsmprint> 72 */ 73 char* 74 ixp_errbuf() { 75 char *errbuf; 76 77 errbuf = thread->errbuf(); 78 if(errno == EINTR) 79 strncpy(errbuf, "interrupted", IXP_ERRMAX); 80 else if(errno != EPLAN9) 81 strncpy(errbuf, strerror(errno), IXP_ERRMAX); 82 return errbuf; 83 } 84 85 void 86 errstr(char *buf, int nbuf) { 87 char tmp[IXP_ERRMAX]; 88 89 strncpy(tmp, buf, sizeof tmp); 90 rerrstr(buf, nbuf); 91 strncpy(thread->errbuf(), tmp, IXP_ERRMAX); 92 errno = EPLAN9; 93 } 94 95 void 96 rerrstr(char *buf, int nbuf) { 97 strncpy(buf, ixp_errbuf(), nbuf); 98 } 99 100 void 101 werrstr(const char *fmt, ...) { 102 char tmp[IXP_ERRMAX]; 103 va_list ap; 104 105 va_start(ap, fmt); 106 ixp_vsnprint(tmp, sizeof tmp, fmt, ap); 107 va_end(ap); 108 strncpy(thread->errbuf(), tmp, IXP_ERRMAX); 109 errno = EPLAN9; 110 } 111