diff options
author | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2007-05-04 21:00:46 +0300 |
---|---|---|
committer | Artem Bityutskiy <Artem.Bityutskiy@nokia.com> | 2007-05-04 21:00:46 +0300 |
commit | 80cecea79cf13075d136e73067aa40439539bb0f (patch) | |
tree | f28acc5b3a124c3a7355f77ccdbad48753f55872 /ubi-utils/src/error.c | |
parent | 726ac243f051f0daee6149db66ac21ba621fb454 (diff) | |
parent | 22f90673165489fd50c893a91051a79c1b143d2a (diff) |
Merge branch 'ubi'
Diffstat (limited to 'ubi-utils/src/error.c')
-rw-r--r-- | ubi-utils/src/error.c | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/ubi-utils/src/error.c b/ubi-utils/src/error.c new file mode 100644 index 0000000..4aaedad --- /dev/null +++ b/ubi-utils/src/error.c @@ -0,0 +1,240 @@ +/* + * Copyright (c) International Business Machines Corp., 2006 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See + * the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stdio.h> +#include <stdarg.h> +#include <syslog.h> +#include <stdlib.h> +#include <sys/errno.h> +#include <string.h> +#include "error.h" + +#define MAXLINE 4096 +#define MAXWIDTH 80 + +static FILE *logfp = NULL; + +static void err_doit(int, int, const char *, va_list); + +int +read_procfile(FILE *fp_out, const char *procfile) +{ + FILE *fp; + + if (!fp_out) + return -ENXIO; + + fp = fopen(procfile, "r"); + if (!fp) + return -ENOENT; + + while(!feof(fp)) { + int c = fgetc(fp); + + if (c == EOF) + return 0; + + if (putc(c, fp_out) == EOF) + return -EIO; + + if (ferror(fp)) + return -EIO; + } + return fclose(fp); +} + +void +error_initlog(const char *logfile) +{ + if (!logfile) + return; + + logfp = fopen(logfile, "a+"); + read_procfile(logfp, "/proc/cpuinfo"); +} + +void +info_msg(const char *fmt, ...) +{ + FILE* fpout; + char buf[MAXLINE + 1]; + va_list ap; + int n; + + fpout = stdout; + + va_start(ap, fmt); + vsnprintf(buf, MAXLINE, fmt, ap); + n = strlen(buf); + strcat(buf, "\n"); + + fputs(buf, fpout); + fflush(fpout); + if (fpout != stdout) + fclose(fpout); + + va_end(ap); + return; +} + +void +__err_ret(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + err_doit(1, LOG_INFO, fmt, ap); + va_end(ap); + return; +} + +void +__err_sys(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + err_doit(1, LOG_ERR, fmt, ap); + va_end(ap); + exit(EXIT_FAILURE); +} + + +void +__err_msg(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + err_doit(0, LOG_INFO, fmt, ap); + va_end(ap); + + return; +} + +void +__err_quit(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + err_doit(0, LOG_ERR, fmt, ap); + va_end(ap); + exit(EXIT_FAILURE); +} + +void +__err_dump(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + err_doit(1, LOG_ERR, fmt, ap); + va_end(ap); + abort(); /* dump core and terminate */ + exit(EXIT_FAILURE); /* shouldn't get here */ +} + +/** + * If a logfile is used we must not print on stderr and stdout + * anymore. Since pfilfash might be used in a server context, it is + * even dangerous to write to those descriptors. + */ +static void +err_doit(int errnoflag, int level __attribute__((unused)), + const char *fmt, va_list ap) +{ + FILE* fpout; + int errno_save, n; + char buf[MAXLINE + 1]; + fpout = stderr; + + errno_save = errno; /* value caller might want printed */ + + vsnprintf(buf, MAXLINE, fmt, ap); /* safe */ + + n = strlen(buf); + + if (errnoflag) + snprintf(buf + n, MAXLINE - n, ": %s", strerror(errno_save)); + strcat(buf, "\n"); + + if (logfp) { + fputs(buf, logfp); + fflush(logfp); + return; /* exit when logging completes */ + } + + if (fpout == stderr) { + /* perform line wrap when outputting to stderr */ + int word_len, post_len, chars; + char *buf_ptr; + const char *frmt = "%*s%n %n"; + + chars = 0; + buf_ptr = buf; + while (sscanf(buf_ptr, frmt, &word_len, &post_len) != EOF) { + int i; + char word[word_len + 1]; + char post[post_len + 1]; + + strncpy(word, buf_ptr, word_len); + word[word_len] = '\0'; + buf_ptr += word_len; + post_len -= word_len; + + if (chars + word_len > MAXWIDTH) { + fputc('\n', fpout); + chars = 0; + } + fputs(word, fpout); + chars += word_len; + + if (post_len > 0) { + strncpy(post, buf_ptr, post_len); + post[post_len] = '\0'; + buf_ptr += post_len; + } + for (i = 0; i < post_len; i++) { + int inc = 1, chars_new; + + if (post[i] == '\t') + inc = 8; + if (post[i] == '\n') { + inc = 0; + chars_new = 0; + } else + chars_new = chars + inc; + + if (chars_new > MAXWIDTH) { + fputc('\n', fpout); + chars_new = inc; + } + fputc(post[i], fpout); + chars = chars_new; + } + } + } + else + fputs(buf, fpout); + fflush(fpout); + if (fpout != stderr) + fclose(fpout); + + return; +} |