17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*5aefb655Srie * Common Development and Distribution License (the "License"). 6*5aefb655Srie * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 21*5aefb655Srie 227c478bd9Sstevel@tonic-gate /* 23*5aefb655Srie * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 28*5aefb655Srie #define dgettext _dgettext 29*5aefb655Srie 30*5aefb655Srie #include <libintl.h> 31*5aefb655Srie #include <sys/varargs.h> 327c478bd9Sstevel@tonic-gate #include <stdio.h> 337c478bd9Sstevel@tonic-gate #include <string.h> 347c478bd9Sstevel@tonic-gate #include <stdlib.h> 35*5aefb655Srie #include <alist.h> 36*5aefb655Srie #include <debug.h> 37*5aefb655Srie #include <_debug.h> 38*5aefb655Srie #include <msg.h> 397c478bd9Sstevel@tonic-gate 40*5aefb655Srie /* 41*5aefb655Srie * Define a debug descriptor. Note, although this provides the default 42*5aefb655Srie * definition to which most users bind, ld.so.1 must provide its own definition, 43*5aefb655Srie * and thus interposition is expected. This item should be defined NODIRECT. 44*5aefb655Srie */ 45*5aefb655Srie static Dbg_desc _dbg_desc = { 0, 0, 0 }; 46*5aefb655Srie Dbg_desc *dbg_desc = &_dbg_desc; 477c478bd9Sstevel@tonic-gate 48*5aefb655Srie int _Dbg_cnt = 0; 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate /* 51*5aefb655Srie * Debugging initialization and processing. The dbg_options[] array defines 527c478bd9Sstevel@tonic-gate * a set of option strings that can be specified using the -D flag or from an 53*5aefb655Srie * environment variable. For each option, a class is enabled in the d_class 54*5aefb655Srie * bit mask, or an extra flag is enabled in the d_extra bit mask. 557c478bd9Sstevel@tonic-gate */ 56*5aefb655Srie DBG_options _Dbg_options[] = { 57*5aefb655Srie {MSG_ORIG(MSG_TOK_DETAIL), 0, DBG_E_DETAIL}, 58*5aefb655Srie {MSG_ORIG(MSG_TOK_LONG), 0, DBG_E_LONG}, 59*5aefb655Srie {MSG_ORIG(MSG_TOK_NAME), 0, DBG_E_SNAME}, 60*5aefb655Srie {MSG_ORIG(MSG_TOK_FULLNAME), 0, DBG_E_SNAME | DBG_E_FNAME}, 61*5aefb655Srie {MSG_ORIG(MSG_TOK_CLASS), 0, DBG_E_SNAME | DBG_E_CLASS}, 62*5aefb655Srie {MSG_ORIG(MSG_TOK_LMID), 0, DBG_E_LMID}, 63*5aefb655Srie 64*5aefb655Srie {MSG_ORIG(MSG_TOK_ALL), DBG_C_ALL, 0}, 65*5aefb655Srie {MSG_ORIG(MSG_TOK_ARGS), DBG_C_ARGS, 0}, 66*5aefb655Srie {MSG_ORIG(MSG_TOK_BASIC), DBG_C_BASIC, 0}, 67*5aefb655Srie {MSG_ORIG(MSG_TOK_BINDINGS), DBG_C_BINDINGS, 0}, 68*5aefb655Srie {MSG_ORIG(MSG_TOK_ENTRY), DBG_C_ENTRY, 0}, 69*5aefb655Srie {MSG_ORIG(MSG_TOK_FILES), DBG_C_FILES, 0}, 70*5aefb655Srie {MSG_ORIG(MSG_TOK_HELP), DBG_C_HELP, 0}, 71*5aefb655Srie {MSG_ORIG(MSG_TOK_LIBS), DBG_C_LIBS, 0}, 72*5aefb655Srie {MSG_ORIG(MSG_TOK_MAP), DBG_C_MAP, 0}, 73*5aefb655Srie {MSG_ORIG(MSG_TOK_RELOC), DBG_C_RELOC, 0}, 74*5aefb655Srie {MSG_ORIG(MSG_TOK_SECTIONS), DBG_C_SECTIONS, 0}, 75*5aefb655Srie {MSG_ORIG(MSG_TOK_SEGMENTS), DBG_C_SEGMENTS, 0}, 76*5aefb655Srie {MSG_ORIG(MSG_TOK_SUPPORT), DBG_C_SUPPORT, 0}, 77*5aefb655Srie {MSG_ORIG(MSG_TOK_SYMBOLS), DBG_C_SYMBOLS, 0}, 78*5aefb655Srie {MSG_ORIG(MSG_TOK_TLS), DBG_C_TLS, 0}, 79*5aefb655Srie {MSG_ORIG(MSG_TOK_AUDIT), DBG_C_AUDITING, 0}, 80*5aefb655Srie {MSG_ORIG(MSG_TOK_VERSIONS), DBG_C_VERSIONS, 0}, 81*5aefb655Srie {MSG_ORIG(MSG_TOK_GOT), DBG_C_GOT, 0}, 82*5aefb655Srie {MSG_ORIG(MSG_TOK_MOVE), DBG_C_MOVE, 0}, 83*5aefb655Srie {MSG_ORIG(MSG_TOK_STRTAB), DBG_C_STRTAB, 0}, 84*5aefb655Srie {MSG_ORIG(MSG_TOK_STATS), DBG_C_STATS, 0}, 85*5aefb655Srie {MSG_ORIG(MSG_TOK_UNUSED), DBG_C_UNUSED, 0}, 867c478bd9Sstevel@tonic-gate #ifdef DEMANGLE 87*5aefb655Srie {MSG_ORIG(MSG_TOK_DEMANGLE), DBG_C_DEMANGLE, 0}, 887c478bd9Sstevel@tonic-gate #endif 89*5aefb655Srie {MSG_ORIG(MSG_TOK_CAP), DBG_C_CAP, 0}, 90*5aefb655Srie {MSG_ORIG(MSG_TOK_INIT), DBG_C_INIT, 0}, 917c478bd9Sstevel@tonic-gate {NULL, NULL}, 927c478bd9Sstevel@tonic-gate }; 937c478bd9Sstevel@tonic-gate 94*5aefb655Srie /* 95*5aefb655Srie * Tokens may also define identifiers for diagnostics. Presently, only ld.so.1 96*5aefb655Srie * uses these strings to identify, or isolate its output to selected link-map 97*5aefb655Srie * lists. See ld.so.1:dbg_print(). 98*5aefb655Srie */ 99*5aefb655Srie const char *_Dbg_strs[] = { 100*5aefb655Srie MSG_ORIG(MSG_TOK_BASE), MSG_ORIG(MSG_TOK_LDSO), 101*5aefb655Srie MSG_ORIG(MSG_TOK_NEWLM), NULL 102*5aefb655Srie }; 103*5aefb655Srie 1047c478bd9Sstevel@tonic-gate /* 1057c478bd9Sstevel@tonic-gate * Provide a debugging usage message 1067c478bd9Sstevel@tonic-gate */ 107*5aefb655Srie void 108*5aefb655Srie Dbg_usage() 1097c478bd9Sstevel@tonic-gate { 110*5aefb655Srie Dbg_util_nl(0, DBG_NL_FRC); 111*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_A)); 112*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_B)); 113*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_C)); 114*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_D)); 115*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_E)); 116*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_F)); 117*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_G)); 118*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_H)); 119*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_I)); 120*5aefb655Srie Dbg_util_nl(0, DBG_NL_FRC); 121*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_J)); 122*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_K)); 123*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_L)); 124*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_M)); 125*5aefb655Srie Dbg_util_nl(0, DBG_NL_FRC); 126*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_N)); 127*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_O)); 128*5aefb655Srie Dbg_util_nl(0, DBG_NL_FRC); 129*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_P)); 130*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_Q)); 131*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_R)); 132*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RTLD_S)); 133*5aefb655Srie 134*5aefb655Srie Dbg_util_nl(0, DBG_NL_FRC); 135*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LD_A)); 136*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LD_B)); 137*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LD_C)); 138*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LD_D)); 139*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LD_E)); 140*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LD_F)); 141*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LD_G)); 142*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LD_H)); 143*5aefb655Srie Dbg_util_nl(0, DBG_NL_FRC); 144*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LD_I)); 145*5aefb655Srie Dbg_util_nl(0, DBG_NL_FRC); 146*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LD_J)); 147*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LD_K)); 148*5aefb655Srie Dbg_util_nl(0, DBG_NL_FRC); 149*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LD_L)); 150*5aefb655Srie Dbg_util_nl(0, DBG_NL_FRC); 151*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LD_M)); 152*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LD_N)); 153*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LD_O)); 154*5aefb655Srie 155*5aefb655Srie Dbg_util_nl(0, DBG_NL_FRC); 156*5aefb655Srie Dbg_util_nl(0, DBG_NL_FRC); 157*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_ARGS)); 158*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_AUDIT)); 159*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_BASIC)); 160*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_BINDINGS)); 161*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_BINDINGS_2)); 162*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_CAP)); 163*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_DETAIL)); 1647c478bd9Sstevel@tonic-gate #ifdef DEMANGLE 165*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_DEMANGLE)); 1667c478bd9Sstevel@tonic-gate #endif 167*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_ENTRY)); 168*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_FILES)); 169*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_GOT)); 170*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_HELP)); 171*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_INIT)); 172*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LIBS)); 173*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LIBS_2)); 174*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LMID)); 175*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_LONG)); 176*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_MAP)); 177*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_MOVE)); 178*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_RELOC)); 179*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_SECTIONS)); 180*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_SEGMENTS)); 181*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_SEGMENTS_2)); 182*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_STATS)); 183*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_STRTAB)); 184*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_STRTAB_2)); 185*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_SUPPORT)); 186*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_SYMBOLS)); 187*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_SYMBOLS_2)); 188*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_TLS)); 189*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_UNUSED)); 190*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_UNUSED_2)); 191*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_VERSIONS)); 192*5aefb655Srie Dbg_util_nl(0, DBG_NL_FRC); 193*5aefb655Srie } 194*5aefb655Srie 195*5aefb655Srie /* 196*5aefb655Srie * Messaging support - funnel everything through dgettext() as this provides 197*5aefb655Srie * the real binding to libc. 198*5aefb655Srie */ 199*5aefb655Srie const char * 200*5aefb655Srie _liblddbg_msg(Msg mid) 201*5aefb655Srie { 202*5aefb655Srie return (dgettext(MSG_ORIG(MSG_SUNW_OST_SGS), MSG_ORIG(mid))); 2037c478bd9Sstevel@tonic-gate } 2047c478bd9Sstevel@tonic-gate 2057c478bd9Sstevel@tonic-gate /* 2067c478bd9Sstevel@tonic-gate * Validate and enable the appropriate debugging classes. 2077c478bd9Sstevel@tonic-gate */ 208*5aefb655Srie uintptr_t 209*5aefb655Srie Dbg_setup(const char *string, Dbg_desc *dbp) 2107c478bd9Sstevel@tonic-gate { 211*5aefb655Srie char *name, *_name; /* buffer in which to perform */ 212*5aefb655Srie /* strtok_r() operations. */ 2137c478bd9Sstevel@tonic-gate char *lasts; 2147c478bd9Sstevel@tonic-gate const char *delimit = MSG_ORIG(MSG_STR_DELIMIT); 2157c478bd9Sstevel@tonic-gate 2167c478bd9Sstevel@tonic-gate if ((_name = (char *)malloc(strlen(string) + 1)) == 0) 217*5aefb655Srie return (S_ERROR); 2187c478bd9Sstevel@tonic-gate (void) strcpy(_name, string); 2197c478bd9Sstevel@tonic-gate 2207c478bd9Sstevel@tonic-gate /* 2217c478bd9Sstevel@tonic-gate * The token should be of the form "-Dtok,tok,tok,...". Separate the 2227c478bd9Sstevel@tonic-gate * pieces and build up the appropriate mask, unrecognized options are 2237c478bd9Sstevel@tonic-gate * flagged. 2247c478bd9Sstevel@tonic-gate */ 2257c478bd9Sstevel@tonic-gate if ((name = strtok_r(_name, delimit, &lasts)) != NULL) { 2267c478bd9Sstevel@tonic-gate do { 227*5aefb655Srie DBG_options *opt; 228*5aefb655Srie const char *str; 229*5aefb655Srie Boolean set, found = FALSE; 230*5aefb655Srie int ndx = 0; 231*5aefb655Srie 2327c478bd9Sstevel@tonic-gate if (name[0] == '!') { 2337c478bd9Sstevel@tonic-gate set = FALSE; 2347c478bd9Sstevel@tonic-gate name++; 235*5aefb655Srie } else 236*5aefb655Srie set = TRUE; 237*5aefb655Srie 238*5aefb655Srie /* 239*5aefb655Srie * First, determine if the token represents a class or 240*5aefb655Srie * extra. 241*5aefb655Srie */ 242*5aefb655Srie for (opt = _Dbg_options; opt->o_name != NULL; opt++) { 243*5aefb655Srie if (strcmp(name, opt->o_name) != 0) 244*5aefb655Srie continue; 245*5aefb655Srie 246*5aefb655Srie if (set == TRUE) { 247*5aefb655Srie if (opt->o_class) 248*5aefb655Srie dbp->d_class |= opt->o_class; 249*5aefb655Srie if (opt->o_extra) 250*5aefb655Srie dbp->d_extra |= opt->o_extra; 251*5aefb655Srie } else { 252*5aefb655Srie if (opt->o_class) 253*5aefb655Srie dbp->d_class &= ~(opt->o_class); 254*5aefb655Srie if (opt->o_extra) 255*5aefb655Srie dbp->d_extra &= ~(opt->o_extra); 256*5aefb655Srie } 257*5aefb655Srie found = TRUE; 258*5aefb655Srie break; 2597c478bd9Sstevel@tonic-gate } 260*5aefb655Srie if (found == TRUE) 261*5aefb655Srie continue; 262*5aefb655Srie 263*5aefb655Srie /* 264*5aefb655Srie * Second, determine if the token represents a known 265*5aefb655Srie * diagnostic identifier. Note, newlm identifiers are 266*5aefb655Srie * typically followed by a numeric id, for example 267*5aefb655Srie * newlm1, newlm2 ... Thus we only compare the 268*5aefb655Srie * initial text of the string. 269*5aefb655Srie */ 270*5aefb655Srie while ((str = _Dbg_strs[ndx++]) != NULL) { 271*5aefb655Srie char *tup; 272*5aefb655Srie 273*5aefb655Srie if (strncmp(name, str, strlen(str)) != 0) 274*5aefb655Srie continue; 275*5aefb655Srie 276*5aefb655Srie /* 277*5aefb655Srie * Translate lmid identifier to uppercase. 278*5aefb655Srie */ 279*5aefb655Srie for (tup = name; *tup; tup++) { 280*5aefb655Srie if ((*tup >= 'a') && (*tup <= 'z')) 281*5aefb655Srie *tup = *tup - ('a' - 'A'); 2827c478bd9Sstevel@tonic-gate } 283*5aefb655Srie 284*5aefb655Srie /* 285*5aefb655Srie * Save this lmid. The whole token buffer has 286*5aefb655Srie * been reallocated, so these names will remain 287*5aefb655Srie * once this routine returns. 288*5aefb655Srie */ 289*5aefb655Srie if (alist_append(&(dbp->d_list), &name, 290*5aefb655Srie sizeof (char *), AL_CNT_DEBUG) == 0) 291*5aefb655Srie return (S_ERROR); 292*5aefb655Srie 293*5aefb655Srie found = TRUE; 294*5aefb655Srie break; 2957c478bd9Sstevel@tonic-gate } 296*5aefb655Srie 2977c478bd9Sstevel@tonic-gate if (found == FALSE) 298*5aefb655Srie dbg_print(0, MSG_INTL(MSG_USE_UNRECOG), name); 299*5aefb655Srie 3007c478bd9Sstevel@tonic-gate } while ((name = strtok_r(NULL, delimit, &lasts)) != NULL); 3017c478bd9Sstevel@tonic-gate } 3027c478bd9Sstevel@tonic-gate 3037c478bd9Sstevel@tonic-gate /* 3047c478bd9Sstevel@tonic-gate * If the debug help option was specified dump a usage message. If 305*5aefb655Srie * this is the only debug class, return an indication that the user 3067c478bd9Sstevel@tonic-gate * should exit. 3077c478bd9Sstevel@tonic-gate */ 308*5aefb655Srie if ((_Dbg_cnt++ == 0) && (dbp->d_class & DBG_C_HELP)) { 309*5aefb655Srie Dbg_usage(); 310*5aefb655Srie if (dbp->d_class == DBG_C_HELP) 311*5aefb655Srie return (0); 3127c478bd9Sstevel@tonic-gate } 313*5aefb655Srie return (1); 3147c478bd9Sstevel@tonic-gate } 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate /* 317*5aefb655Srie * Define our own printing routine. This provides a basic fallback, as ld(1) 318*5aefb655Srie * and ld.so.1(1) provide their own routines that augment their diagnostic 319*5aefb655Srie * output, and direct the output to stderr. This item should be defined 320*5aefb655Srie * NODIRECT. 3217c478bd9Sstevel@tonic-gate */ 322*5aefb655Srie /* PRINTFLIKE2 */ 3237c478bd9Sstevel@tonic-gate void 324*5aefb655Srie dbg_print(Lm_list *lml, const char *format, ...) 3257c478bd9Sstevel@tonic-gate { 326*5aefb655Srie va_list ap; 3277c478bd9Sstevel@tonic-gate 328*5aefb655Srie #if defined(lint) 329*5aefb655Srie /* 330*5aefb655Srie * The lml argument is only meaningful for diagnostics sent to ld.so.1. 331*5aefb655Srie * Supress the lint error by making a dummy assignment. 332*5aefb655Srie */ 333*5aefb655Srie lml = 0; 334*5aefb655Srie #endif 335*5aefb655Srie va_start(ap, format); 336*5aefb655Srie (void) vprintf(format, ap); 337*5aefb655Srie (void) printf(MSG_ORIG(MSG_STR_NL)); 338*5aefb655Srie va_end(ap); 3397c478bd9Sstevel@tonic-gate } 340