1*0Sigor@sysoev.ru 2*0Sigor@sysoev.ru /* 3*0Sigor@sysoev.ru * Copyright (C) Igor Sysoev 4*0Sigor@sysoev.ru * Copyright (C) NGINX, Inc. 5*0Sigor@sysoev.ru */ 6*0Sigor@sysoev.ru 7*0Sigor@sysoev.ru #include <nxt_main.h> 8*0Sigor@sysoev.ru 9*0Sigor@sysoev.ru 10*0Sigor@sysoev.ru /* 11*0Sigor@sysoev.ru * The strerror() messages are copied because: 12*0Sigor@sysoev.ru * 13*0Sigor@sysoev.ru * 1) strerror() and strerror_r() functions are not Async-Signal-Safe, 14*0Sigor@sysoev.ru * therefore, they can not be used in signal handlers; 15*0Sigor@sysoev.ru * 16*0Sigor@sysoev.ru * 2) a direct sys_errlist[] array may be used instead of these functions, 17*0Sigor@sysoev.ru * but Linux linker warns about this usage: 18*0Sigor@sysoev.ru * 19*0Sigor@sysoev.ru * warning: `sys_errlist' is deprecated; use `strerror' or `strerror_r' instead 20*0Sigor@sysoev.ru * warning: `sys_nerr' is deprecated; use `strerror' or `strerror_r' instead 21*0Sigor@sysoev.ru * 22*0Sigor@sysoev.ru * causing false bug reports. 23*0Sigor@sysoev.ru */ 24*0Sigor@sysoev.ru 25*0Sigor@sysoev.ru static u_char *nxt_bootstrap_strerror(nxt_err_t err, u_char *errstr, 26*0Sigor@sysoev.ru size_t size); 27*0Sigor@sysoev.ru static u_char *nxt_runtime_strerror(nxt_err_t err, u_char *errstr, size_t size); 28*0Sigor@sysoev.ru 29*0Sigor@sysoev.ru 30*0Sigor@sysoev.ru nxt_strerror_t nxt_strerror = nxt_bootstrap_strerror; 31*0Sigor@sysoev.ru static nxt_str_t *nxt_sys_errlist; 32*0Sigor@sysoev.ru static nxt_uint_t nxt_sys_nerr; 33*0Sigor@sysoev.ru 34*0Sigor@sysoev.ru 35*0Sigor@sysoev.ru nxt_int_t 36*0Sigor@sysoev.ru nxt_strerror_start(void) 37*0Sigor@sysoev.ru { 38*0Sigor@sysoev.ru char *msg; 39*0Sigor@sysoev.ru u_char *p; 40*0Sigor@sysoev.ru size_t size, len, n; 41*0Sigor@sysoev.ru nxt_uint_t err, invalid; 42*0Sigor@sysoev.ru 43*0Sigor@sysoev.ru /* The last entry. */ 44*0Sigor@sysoev.ru size = sizeof("Unknown error") - 1; 45*0Sigor@sysoev.ru 46*0Sigor@sysoev.ru /* 47*0Sigor@sysoev.ru * Linux has holes for error codes 41 and 58, so the loop 48*0Sigor@sysoev.ru * stops only after 100 invalid codes in succession. 49*0Sigor@sysoev.ru */ 50*0Sigor@sysoev.ru 51*0Sigor@sysoev.ru for (invalid = 0; invalid < 100 && nxt_sys_nerr < 65536; nxt_sys_nerr++) { 52*0Sigor@sysoev.ru 53*0Sigor@sysoev.ru nxt_set_errno(0); 54*0Sigor@sysoev.ru msg = strerror((int) nxt_sys_nerr); 55*0Sigor@sysoev.ru 56*0Sigor@sysoev.ru /* 57*0Sigor@sysoev.ru * strerror() behaviour on passing invalid error code depends 58*0Sigor@sysoev.ru * on OS and version: 59*0Sigor@sysoev.ru * Linux returns "Unknown error NN"; 60*0Sigor@sysoev.ru * FreeBSD, NetBSD and OpenBSD return "Unknown error: NN" 61*0Sigor@sysoev.ru * and set errno to EINVAL; 62*0Sigor@sysoev.ru * Solaris 10 returns "Unknown error" and sets errno to EINVAL; 63*0Sigor@sysoev.ru * Solaris 9 returns "Unknown error"; 64*0Sigor@sysoev.ru * Solaris 2 returns NULL; 65*0Sigor@sysoev.ru * MacOSX returns "Unknown error: NN"; 66*0Sigor@sysoev.ru * AIX returns "Error NNN occurred."; 67*0Sigor@sysoev.ru * HP-UX returns "Unknown error" for invalid codes lesser than 250 68*0Sigor@sysoev.ru * or empty string for larger codes. 69*0Sigor@sysoev.ru */ 70*0Sigor@sysoev.ru 71*0Sigor@sysoev.ru if (msg == NULL) { 72*0Sigor@sysoev.ru invalid++; 73*0Sigor@sysoev.ru continue; 74*0Sigor@sysoev.ru } 75*0Sigor@sysoev.ru 76*0Sigor@sysoev.ru len = nxt_strlen(msg); 77*0Sigor@sysoev.ru size += len; 78*0Sigor@sysoev.ru 79*0Sigor@sysoev.ru if (len == 0 /* HP-UX empty strings. */ 80*0Sigor@sysoev.ru || nxt_errno == NXT_EINVAL 81*0Sigor@sysoev.ru || nxt_memcmp(msg, "Unknown error", 13) == 0) 82*0Sigor@sysoev.ru { 83*0Sigor@sysoev.ru invalid++; 84*0Sigor@sysoev.ru continue; 85*0Sigor@sysoev.ru } 86*0Sigor@sysoev.ru 87*0Sigor@sysoev.ru #if (NXT_AIX) 88*0Sigor@sysoev.ru 89*0Sigor@sysoev.ru if (nxt_memcmp(msg, "Error ", 6) == 0 90*0Sigor@sysoev.ru && nxt_memcmp(msg + len - 10, " occurred.", 9) == 0) 91*0Sigor@sysoev.ru { 92*0Sigor@sysoev.ru invalid++; 93*0Sigor@sysoev.ru continue; 94*0Sigor@sysoev.ru } 95*0Sigor@sysoev.ru 96*0Sigor@sysoev.ru #endif 97*0Sigor@sysoev.ru } 98*0Sigor@sysoev.ru 99*0Sigor@sysoev.ru nxt_sys_nerr -= invalid; 100*0Sigor@sysoev.ru 101*0Sigor@sysoev.ru nxt_main_log_debug("sys_nerr: %d", nxt_sys_nerr); 102*0Sigor@sysoev.ru 103*0Sigor@sysoev.ru n = (nxt_sys_nerr + 1) * sizeof(nxt_str_t); 104*0Sigor@sysoev.ru 105*0Sigor@sysoev.ru nxt_sys_errlist = nxt_malloc(n + size); 106*0Sigor@sysoev.ru if (nxt_sys_errlist == NULL) { 107*0Sigor@sysoev.ru return NXT_ERROR; 108*0Sigor@sysoev.ru } 109*0Sigor@sysoev.ru 110*0Sigor@sysoev.ru p = (u_char *) nxt_sys_errlist + n; 111*0Sigor@sysoev.ru 112*0Sigor@sysoev.ru for (err = 0; err < nxt_sys_nerr; err++) { 113*0Sigor@sysoev.ru msg = strerror((int) err); 114*0Sigor@sysoev.ru len = nxt_strlen(msg); 115*0Sigor@sysoev.ru 116*0Sigor@sysoev.ru nxt_sys_errlist[err].len = len; 117*0Sigor@sysoev.ru nxt_sys_errlist[err].data = p; 118*0Sigor@sysoev.ru 119*0Sigor@sysoev.ru p = nxt_cpymem(p, msg, len); 120*0Sigor@sysoev.ru } 121*0Sigor@sysoev.ru 122*0Sigor@sysoev.ru nxt_sys_errlist[err].len = 13; 123*0Sigor@sysoev.ru nxt_sys_errlist[err].data = p; 124*0Sigor@sysoev.ru nxt_memcpy(p, "Unknown error", 13); 125*0Sigor@sysoev.ru 126*0Sigor@sysoev.ru nxt_strerror = nxt_runtime_strerror; 127*0Sigor@sysoev.ru 128*0Sigor@sysoev.ru return NXT_OK; 129*0Sigor@sysoev.ru } 130*0Sigor@sysoev.ru 131*0Sigor@sysoev.ru 132*0Sigor@sysoev.ru static u_char * 133*0Sigor@sysoev.ru nxt_bootstrap_strerror(nxt_err_t err, u_char *errstr, size_t size) 134*0Sigor@sysoev.ru { 135*0Sigor@sysoev.ru return nxt_cpystrn(errstr, (u_char *) strerror(err), size); 136*0Sigor@sysoev.ru } 137*0Sigor@sysoev.ru 138*0Sigor@sysoev.ru 139*0Sigor@sysoev.ru static u_char * 140*0Sigor@sysoev.ru nxt_runtime_strerror(nxt_err_t err, u_char *errstr, size_t size) 141*0Sigor@sysoev.ru { 142*0Sigor@sysoev.ru nxt_str_t *msg; 143*0Sigor@sysoev.ru nxt_uint_t n; 144*0Sigor@sysoev.ru 145*0Sigor@sysoev.ru n = nxt_min((nxt_uint_t) err, nxt_sys_nerr); 146*0Sigor@sysoev.ru 147*0Sigor@sysoev.ru msg = &nxt_sys_errlist[n]; 148*0Sigor@sysoev.ru 149*0Sigor@sysoev.ru size = nxt_min(size, msg->len); 150*0Sigor@sysoev.ru 151*0Sigor@sysoev.ru return nxt_cpymem(errstr, msg->data, size); 152*0Sigor@sysoev.ru } 153