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 5b493790cSbasabi * Common Development and Distribution License (the "License"). 6b493790cSbasabi * 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 */ 217c478bd9Sstevel@tonic-gate /* 22*e9a193fcSJohn.Zolnowsky@Sun.COM * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. 237c478bd9Sstevel@tonic-gate * 247c478bd9Sstevel@tonic-gate * logadm/err.c -- some basic error routines 257c478bd9Sstevel@tonic-gate * 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate #include <stdio.h> 297c478bd9Sstevel@tonic-gate #include <unistd.h> 307c478bd9Sstevel@tonic-gate #include <libintl.h> 317c478bd9Sstevel@tonic-gate #include <stdlib.h> 327c478bd9Sstevel@tonic-gate #include <stdarg.h> 337c478bd9Sstevel@tonic-gate #include <string.h> 347c478bd9Sstevel@tonic-gate #include <errno.h> 357c478bd9Sstevel@tonic-gate #include "err.h" 367c478bd9Sstevel@tonic-gate 37*e9a193fcSJohn.Zolnowsky@Sun.COM jmp_buf *Err_env_ptr; 387c478bd9Sstevel@tonic-gate static const char *Myname; 397c478bd9Sstevel@tonic-gate static int Exitcode; 407c478bd9Sstevel@tonic-gate static FILE *Errorfile; 417c478bd9Sstevel@tonic-gate 427c478bd9Sstevel@tonic-gate /* 437c478bd9Sstevel@tonic-gate * err_init -- initialize the error handling routine 447c478bd9Sstevel@tonic-gate * 457c478bd9Sstevel@tonic-gate */ 467c478bd9Sstevel@tonic-gate void 477c478bd9Sstevel@tonic-gate err_init(const char *myname) 487c478bd9Sstevel@tonic-gate { 497c478bd9Sstevel@tonic-gate char *ptr; 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate if ((ptr = strrchr(myname, '/')) == NULL) 527c478bd9Sstevel@tonic-gate Myname = myname; 537c478bd9Sstevel@tonic-gate else 547c478bd9Sstevel@tonic-gate Myname = ptr + 1; 557c478bd9Sstevel@tonic-gate } 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate static const char *File; 587c478bd9Sstevel@tonic-gate static int Line; 597c478bd9Sstevel@tonic-gate 607c478bd9Sstevel@tonic-gate /* 617c478bd9Sstevel@tonic-gate * err_fileline -- record the filename/line number for err(EF_FILE, ...) 627c478bd9Sstevel@tonic-gate */ 637c478bd9Sstevel@tonic-gate void 647c478bd9Sstevel@tonic-gate err_fileline(const char *file, int line) 657c478bd9Sstevel@tonic-gate { 667c478bd9Sstevel@tonic-gate File = file; 677c478bd9Sstevel@tonic-gate Line = line; 687c478bd9Sstevel@tonic-gate } 697c478bd9Sstevel@tonic-gate 707c478bd9Sstevel@tonic-gate /* 717c478bd9Sstevel@tonic-gate * err -- print an error message and return, exit or longjmp based on flags 727c478bd9Sstevel@tonic-gate * 737c478bd9Sstevel@tonic-gate * this routine calls gettext() to translate the fmt string. 747c478bd9Sstevel@tonic-gate */ 757c478bd9Sstevel@tonic-gate /*PRINTFLIKE2*/ 767c478bd9Sstevel@tonic-gate void 777c478bd9Sstevel@tonic-gate err(int flags, const char *fmt, ...) 787c478bd9Sstevel@tonic-gate { 797c478bd9Sstevel@tonic-gate va_list ap; 807c478bd9Sstevel@tonic-gate int safe_errno = errno; 817c478bd9Sstevel@tonic-gate char *errno_msg = NULL; 827c478bd9Sstevel@tonic-gate int as_is = 0; 837c478bd9Sstevel@tonic-gate int jump = 0; 847c478bd9Sstevel@tonic-gate int warning = 0; 857c478bd9Sstevel@tonic-gate int fileline = 0; 867c478bd9Sstevel@tonic-gate char *prefix = "Error: "; 877c478bd9Sstevel@tonic-gate const char *intlfmt; 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate va_start(ap, fmt); 907c478bd9Sstevel@tonic-gate intlfmt = gettext(fmt); 917c478bd9Sstevel@tonic-gate 927c478bd9Sstevel@tonic-gate if (flags & EF_WARN) { 937c478bd9Sstevel@tonic-gate warning = 1; 947c478bd9Sstevel@tonic-gate prefix = "Warning: "; 957c478bd9Sstevel@tonic-gate } 967c478bd9Sstevel@tonic-gate if (flags & EF_FILE) { 977c478bd9Sstevel@tonic-gate fileline = 1; 987c478bd9Sstevel@tonic-gate Exitcode++; 997c478bd9Sstevel@tonic-gate } 1007c478bd9Sstevel@tonic-gate if (flags & EF_SYS) 1017c478bd9Sstevel@tonic-gate errno_msg = strerror(safe_errno); 1027c478bd9Sstevel@tonic-gate if (flags & EF_JMP) 1037c478bd9Sstevel@tonic-gate jump = 1; 1047c478bd9Sstevel@tonic-gate if (flags & EF_RAW) 1057c478bd9Sstevel@tonic-gate as_is = 1; 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate /* print a copy to stderr */ 1087c478bd9Sstevel@tonic-gate if (!as_is) { 109b493790cSbasabi if (Myname != NULL) { 1107c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: ", Myname); 1117c478bd9Sstevel@tonic-gate if (Errorfile) 1127c478bd9Sstevel@tonic-gate (void) fprintf(Errorfile, "%s: ", Myname); 1137c478bd9Sstevel@tonic-gate } 1147c478bd9Sstevel@tonic-gate if (fileline && File) { 1157c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s line %d: ", File, Line); 1167c478bd9Sstevel@tonic-gate if (Errorfile) 1177c478bd9Sstevel@tonic-gate (void) fprintf(Errorfile, 1187c478bd9Sstevel@tonic-gate "%s line %d: ", File, Line); 1197c478bd9Sstevel@tonic-gate } 1207c478bd9Sstevel@tonic-gate (void) fputs(gettext(prefix), stderr); 1217c478bd9Sstevel@tonic-gate if (Errorfile) 1227c478bd9Sstevel@tonic-gate (void) fputs(gettext(prefix), Errorfile); 1237c478bd9Sstevel@tonic-gate } 1247c478bd9Sstevel@tonic-gate (void) vfprintf(stderr, intlfmt, ap); 1257c478bd9Sstevel@tonic-gate if (Errorfile) 1267c478bd9Sstevel@tonic-gate (void) vfprintf(Errorfile, intlfmt, ap); 127b493790cSbasabi if (errno_msg != NULL) { 1287c478bd9Sstevel@tonic-gate (void) fprintf(stderr, ": %s", errno_msg); 1297c478bd9Sstevel@tonic-gate if (Errorfile) 1307c478bd9Sstevel@tonic-gate (void) fprintf(Errorfile, ": %s", errno_msg); 1317c478bd9Sstevel@tonic-gate } 1327c478bd9Sstevel@tonic-gate if (!as_is) { 1337c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "\n"); 1347c478bd9Sstevel@tonic-gate if (Errorfile) 1357c478bd9Sstevel@tonic-gate (void) fprintf(Errorfile, "\n"); 1367c478bd9Sstevel@tonic-gate } 1377c478bd9Sstevel@tonic-gate (void) fflush(stderr); 1387c478bd9Sstevel@tonic-gate if (Errorfile) 1397c478bd9Sstevel@tonic-gate (void) fflush(Errorfile); 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate va_end(ap); 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate if (jump) 144*e9a193fcSJohn.Zolnowsky@Sun.COM longjmp(*Err_env_ptr, 1); 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate if (!warning && !fileline) { 1477c478bd9Sstevel@tonic-gate err_done(1); 1487c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 1497c478bd9Sstevel@tonic-gate } 1507c478bd9Sstevel@tonic-gate } 1517c478bd9Sstevel@tonic-gate 1527c478bd9Sstevel@tonic-gate /* 1537c478bd9Sstevel@tonic-gate * out -- print a message and return 1547c478bd9Sstevel@tonic-gate * 1557c478bd9Sstevel@tonic-gate * this routine calls gettext() to translate the fmt string. 1567c478bd9Sstevel@tonic-gate */ 1577c478bd9Sstevel@tonic-gate /*PRINTFLIKE1*/ 1587c478bd9Sstevel@tonic-gate void 1597c478bd9Sstevel@tonic-gate out(const char *fmt, ...) 1607c478bd9Sstevel@tonic-gate { 1617c478bd9Sstevel@tonic-gate va_list ap; 1627c478bd9Sstevel@tonic-gate 1637c478bd9Sstevel@tonic-gate va_start(ap, fmt); 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate (void) vfprintf(stdout, gettext(fmt), ap); 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate va_end(ap); 1687c478bd9Sstevel@tonic-gate } 1697c478bd9Sstevel@tonic-gate 1707c478bd9Sstevel@tonic-gate #define CHUNKSIZE 8192 /* for copying stderr */ 1717c478bd9Sstevel@tonic-gate /* 1727c478bd9Sstevel@tonic-gate * err_fromfd -- copy data from fd to stderr 1737c478bd9Sstevel@tonic-gate */ 1747c478bd9Sstevel@tonic-gate void 1757c478bd9Sstevel@tonic-gate err_fromfd(int fd) 1767c478bd9Sstevel@tonic-gate { 1777c478bd9Sstevel@tonic-gate char buf[CHUNKSIZE]; 1787c478bd9Sstevel@tonic-gate int count; 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate while ((count = read(fd, buf, CHUNKSIZE)) > 0) { 1817c478bd9Sstevel@tonic-gate (void) fwrite(buf, 1, count, stderr); 1827c478bd9Sstevel@tonic-gate if (Errorfile) 1837c478bd9Sstevel@tonic-gate (void) fwrite(buf, 1, count, Errorfile); 1847c478bd9Sstevel@tonic-gate } 1857c478bd9Sstevel@tonic-gate (void) fflush(stderr); 1867c478bd9Sstevel@tonic-gate if (Errorfile) 1877c478bd9Sstevel@tonic-gate (void) fflush(Errorfile); 1887c478bd9Sstevel@tonic-gate } 1897c478bd9Sstevel@tonic-gate 1907c478bd9Sstevel@tonic-gate /* 1917c478bd9Sstevel@tonic-gate * err_done -- exit the program 1927c478bd9Sstevel@tonic-gate */ 1937c478bd9Sstevel@tonic-gate void 1947c478bd9Sstevel@tonic-gate err_done(int exitcode) 1957c478bd9Sstevel@tonic-gate { 1967c478bd9Sstevel@tonic-gate /* send error mail if applicable */ 1977c478bd9Sstevel@tonic-gate err_mailto(NULL); 1987c478bd9Sstevel@tonic-gate 1997c478bd9Sstevel@tonic-gate if (exitcode) 2007c478bd9Sstevel@tonic-gate exit(exitcode); 2017c478bd9Sstevel@tonic-gate else 2027c478bd9Sstevel@tonic-gate exit(Exitcode); 2037c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 2047c478bd9Sstevel@tonic-gate } 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate #define MAXLINE 8192 /* for tmp file line buffer */ 2077c478bd9Sstevel@tonic-gate /* 2087c478bd9Sstevel@tonic-gate * err_mailto -- arrange for error output to be mailed to someone 2097c478bd9Sstevel@tonic-gate */ 2107c478bd9Sstevel@tonic-gate void 2117c478bd9Sstevel@tonic-gate err_mailto(const char *recipient) 2127c478bd9Sstevel@tonic-gate { 2137c478bd9Sstevel@tonic-gate static const char *lastrecipient; 2147c478bd9Sstevel@tonic-gate static char mailcmd[] = "/bin/mailx -s 'logadm error output'"; 2157c478bd9Sstevel@tonic-gate char *cmd; 2167c478bd9Sstevel@tonic-gate int len; 2177c478bd9Sstevel@tonic-gate FILE *pfp; 2187c478bd9Sstevel@tonic-gate char line[MAXLINE]; 2197c478bd9Sstevel@tonic-gate 220b493790cSbasabi if (lastrecipient != NULL) { 221b493790cSbasabi if (recipient != NULL && 222b493790cSbasabi strcmp(recipient, lastrecipient) == 0) 2237c478bd9Sstevel@tonic-gate return; /* keep going, same recipient */ 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate /* stop saving output for lastrecipient and send message */ 2267c478bd9Sstevel@tonic-gate if (ftell(Errorfile)) { 2277c478bd9Sstevel@tonic-gate rewind(Errorfile); 2287c478bd9Sstevel@tonic-gate len = strlen(lastrecipient) + strlen(mailcmd) + 2; 2297c478bd9Sstevel@tonic-gate cmd = MALLOC(len); 2307c478bd9Sstevel@tonic-gate (void) snprintf(cmd, len, "%s %s", 2317c478bd9Sstevel@tonic-gate mailcmd, lastrecipient); 2327c478bd9Sstevel@tonic-gate if ((pfp = popen(cmd, "w")) == NULL) 2337c478bd9Sstevel@tonic-gate err(EF_SYS, "popen to mailx"); 2347c478bd9Sstevel@tonic-gate while (fgets(line, MAXLINE, Errorfile) != NULL) 2357c478bd9Sstevel@tonic-gate (void) fputs(line, pfp); 2367c478bd9Sstevel@tonic-gate (void) pclose(pfp); 2377c478bd9Sstevel@tonic-gate } 2387c478bd9Sstevel@tonic-gate (void) fclose(Errorfile); 2397c478bd9Sstevel@tonic-gate Errorfile = NULL; 2407c478bd9Sstevel@tonic-gate } 2417c478bd9Sstevel@tonic-gate 242b493790cSbasabi if (recipient != NULL) { 2437c478bd9Sstevel@tonic-gate /* start saving error output for this recipient */ 2447c478bd9Sstevel@tonic-gate if ((Errorfile = tmpfile()) == NULL) 2457c478bd9Sstevel@tonic-gate err(EF_SYS, "tmpfile"); 2467c478bd9Sstevel@tonic-gate } 2477c478bd9Sstevel@tonic-gate lastrecipient = recipient; 2487c478bd9Sstevel@tonic-gate } 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate /* 2517c478bd9Sstevel@tonic-gate * err_malloc -- a malloc() with checks 2527c478bd9Sstevel@tonic-gate * 2537c478bd9Sstevel@tonic-gate * this routine is typically called via the MALLOC() macro in err.h 2547c478bd9Sstevel@tonic-gate */ 2557c478bd9Sstevel@tonic-gate void * 2567c478bd9Sstevel@tonic-gate err_malloc(int nbytes, const char *fname, int line) 2577c478bd9Sstevel@tonic-gate { 2587c478bd9Sstevel@tonic-gate void *retval = malloc(nbytes); 2597c478bd9Sstevel@tonic-gate 2607c478bd9Sstevel@tonic-gate if (retval == NULL) 2617c478bd9Sstevel@tonic-gate err(0, "%s:%d: out of memory", fname, line); 2627c478bd9Sstevel@tonic-gate 2637c478bd9Sstevel@tonic-gate return (retval); 2647c478bd9Sstevel@tonic-gate } 2657c478bd9Sstevel@tonic-gate 2667c478bd9Sstevel@tonic-gate /* 2677c478bd9Sstevel@tonic-gate * err_realloc -- a realloc() with checks 2687c478bd9Sstevel@tonic-gate * 2697c478bd9Sstevel@tonic-gate * this routine is typically called via the REALLOC() macro in err.h 2707c478bd9Sstevel@tonic-gate */ 2717c478bd9Sstevel@tonic-gate void * 2727c478bd9Sstevel@tonic-gate err_realloc(void *ptr, int nbytes, const char *fname, int line) 2737c478bd9Sstevel@tonic-gate { 2747c478bd9Sstevel@tonic-gate void *retval = realloc(ptr, nbytes); 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate if (retval == NULL) 2777c478bd9Sstevel@tonic-gate err(0, "%s:%d: out of memory", fname, line); 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate return (retval); 2807c478bd9Sstevel@tonic-gate } 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate /* 2837c478bd9Sstevel@tonic-gate * err_strdup -- a strdup() with checks 2847c478bd9Sstevel@tonic-gate * 2857c478bd9Sstevel@tonic-gate * this routine is typically called via the STRDUP() macro in err.h 2867c478bd9Sstevel@tonic-gate */ 2877c478bd9Sstevel@tonic-gate char * 2887c478bd9Sstevel@tonic-gate err_strdup(const char *ptr, const char *fname, int line) 2897c478bd9Sstevel@tonic-gate { 290b493790cSbasabi char *retval = NULL; 2917c478bd9Sstevel@tonic-gate 292b493790cSbasabi if (ptr != NULL) { 293b493790cSbasabi retval = strdup(ptr); 2947c478bd9Sstevel@tonic-gate if (retval == NULL) 2957c478bd9Sstevel@tonic-gate err(0, "%s:%d: out of memory", fname, line); 296b493790cSbasabi } else 297b493790cSbasabi err(0, "%s:%d: could not strdup", fname, line); 298b493790cSbasabi 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gate return (retval); 301b493790cSbasabi 3027c478bd9Sstevel@tonic-gate } 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate /* 3057c478bd9Sstevel@tonic-gate * err_free -- a free() with checks 3067c478bd9Sstevel@tonic-gate * 3077c478bd9Sstevel@tonic-gate * this routine is typically called via the FREE() macro in err.h 3087c478bd9Sstevel@tonic-gate */ 3097c478bd9Sstevel@tonic-gate /*ARGSUSED1*/ 3107c478bd9Sstevel@tonic-gate void 3117c478bd9Sstevel@tonic-gate err_free(void *ptr, const char *fname, int line) 3127c478bd9Sstevel@tonic-gate { 3137c478bd9Sstevel@tonic-gate /* nothing to check in this version */ 3147c478bd9Sstevel@tonic-gate free(ptr); 3157c478bd9Sstevel@tonic-gate } 3167c478bd9Sstevel@tonic-gate 3177c478bd9Sstevel@tonic-gate /* 3187c478bd9Sstevel@tonic-gate * err_exitcode -- set an error exit code for when done(0) is called 3197c478bd9Sstevel@tonic-gate */ 3207c478bd9Sstevel@tonic-gate void 3217c478bd9Sstevel@tonic-gate err_exitcode(int exitcode) 3227c478bd9Sstevel@tonic-gate { 3237c478bd9Sstevel@tonic-gate Exitcode = exitcode; 3247c478bd9Sstevel@tonic-gate } 325