Example #1
0
/*********************************************************************
 *
 * Function    :  init_log_module
 *
 * Description :  Initializes the logging module to log to stderr.
 *                Can only be called while stderr hasn't been closed
 *                yet and is only supposed to be called once.
 *
 * Parameters  :
 *          1  :  prog_name = The program name.
 *
 * Returns     :  Nothing.
 *
 *********************************************************************/
void init_log_module(void)
{
   lock_logfile();
   logfp = stderr;
   unlock_logfile();
   set_debug_level(debug);
}
Example #2
0
/**
 * @function logfile.flush
 * 
 * ### Synopsis
 * 
 * logfile.flush(handle);
 * 
 * Flush contents of shared memory block to the log file, reset memory block to "empty" state.
 * 
 * @param {object} handle - handle of logfile to flush.
 */
static JSVAL logfile_flush (JSARGS args) {
    STATE *state = HANDLE(args[0]);

    lock_logfile(state);
    flush_logfile(state);
    unlock_logfile(state);
    return Undefined();
}
Example #3
0
/**
 * @function logfile.flush
 * 
 * ### Synopsis
 * 
 * logfile.flush(handle);
 * 
 * Flush contents of shared memory block to the log file, reset memory block to "empty" state.
 * 
 * @param {object} handle - handle of logfile to flush.
 */
static JSVAL logfile_flush (JSARGS args) {
    HandleScope scope;
    STATE *state = log_HANDLE(args[0]);

    lock_logfile(state);
    flush_logfile(state);
    unlock_logfile(state);
    return Undefined();
}
Example #4
0
/*********************************************************************
 *
 * Function    :  disable_logging
 *
 * Description :  Disables logging.
 *
 * Parameters  :  None.
 *
 * Returns     :  Nothing.
 *
 *********************************************************************/
void disable_logging(void)
{
   if (logfp != NULL)
   {
      log_error(LOG_LEVEL_INFO,
         "No logfile configured. Please enable it before reporting any problems.");
      lock_logfile();
      fclose(logfp);
      logfp = NULL;
      unlock_logfile();
   }
}
Example #5
0
/**
 * @function logfile.write
 * 
 * ### Synopsis
 * 
 * logfile.write(handle, s);
 * logfile.write(handle, s, len);
 * 
 * Write a string to the log file.  
 * 
 * The string is appended to the shared memory block.  The memory block is first flushed to disk if there is not enough room for the string.
 * 
 * @param {object} handle - handle of the log file.
 * @param {string} s - string to write to the log file.
 * @param {int} len - optional length of string to write; defaults to strlen(s).
 * 
 */
static JSVAL logfile_write (JSARGS args) {
    STATE *state = HANDLE(args[0]);
    String::AsciiValue buf(args[1]);
    int len;
    if (args.Length() > 2) {
        len = args[2]->IntegerValue();
    }
    else {
        len = strlen(*buf);
    }
    lock_logfile(state);
    if (*state->length + len >= LOGFILE_CHUNK_SIZE) {
        flush_logfile(state);
    }
    memcpy(&state->logBuffer[*state->length], *buf, len);
    *state->length += len;
    unlock_logfile(state);
    return Undefined();
}
Example #6
0
/*********************************************************************
 *
 * Function    :  log_error
 *
 * Description :  This is the error-reporting and logging function.
 *
 * Parameters  :
 *          1  :  loglevel  = the type of message to be logged
 *          2  :  fmt       = the main string we want logged, printf-like
 *          3  :  ...       = arguments to be inserted in fmt (printf-like).
 *
 * Returns     :  N/A
 *
 *********************************************************************/
void log_error(int loglevel, const char *fmt, ...)
{
   va_list ap;
   char *outbuf = NULL;
   static char *outbuf_save = NULL;
   char tempbuf[BUFFER_SIZE];
   size_t length = 0;
   const char * src = fmt;
   long thread_id;
   char timestamp[30];
   /*
    * XXX: Make this a config option,
    * why else do we allocate instead of using
    * an array?
    */
   size_t log_buffer_size = BUFFER_SIZE;

#if defined(_WIN32) && !defined(_WIN_CONSOLE)
   /*
    * Irrespective of debug setting, a GET/POST/CONNECT makes
    * the taskbar icon animate.  (There is an option to disable
    * this but checking that is handled inside LogShowActivity()).
    */
   if ((loglevel == LOG_LEVEL_GPC) || (loglevel == LOG_LEVEL_CRUNCH))
   {
      LogShowActivity();
   }
#endif /* defined(_WIN32) && !defined(_WIN_CONSOLE) */

   /*
    * verify that the loglevel applies to current
    * settings and that logging is enabled.
    * Bail out otherwise.
    */
   if ((0 == (loglevel & debug))
#ifndef _WIN32
      || (logfp == NULL)
#endif
      )
   {
      if (loglevel == LOG_LEVEL_FATAL)
      {
         fatal_error("Fatal error. You're not supposed to"
            "see this message. Please file a bug report.");
      }
      return;
   }

   thread_id = get_thread_id();
   get_log_timestamp(timestamp, sizeof(timestamp));

   /* protect the whole function because of the static buffer (outbuf) */
   lock_logfile();

   if (NULL == outbuf_save)
   {
      outbuf_save = (char*)zalloc(log_buffer_size + 1); /* +1 for paranoia */
      if (NULL == outbuf_save)
      {
         snprintf(tempbuf, sizeof(tempbuf),
            "%s %08lx Fatal error: Out of memory in log_error().",
            timestamp, thread_id);
         fatal_error(tempbuf); /* Exit */
         return;
      }
   }
   outbuf = outbuf_save;

   /*
    * Memsetting the whole buffer to zero (in theory)
    * makes things easier later on.
    */
   memset(outbuf, 0, log_buffer_size);

   /* Add prefix for everything but Common Log Format messages */
   if (loglevel != LOG_LEVEL_CLF)
   {
      length = (size_t)snprintf(outbuf, log_buffer_size, "%s %08lx %s: ",
         timestamp, thread_id, get_log_level_string(loglevel));
   }

   /* get ready to scan var. args. */
   va_start(ap, fmt);

   /* build formatted message from fmt and var-args */
   while ((*src) && (length < log_buffer_size-2))
   {
      const char *sval = NULL; /* %N string  */
      int ival;                /* %N string length or an error code */
      unsigned uval;           /* %u value */
      long lval;               /* %l value */
      unsigned long ulval;     /* %ul value */
      char ch;
      const char *format_string = tempbuf;

      ch = *src++;
      if (ch != '%')
      {
         outbuf[length++] = ch;
         /*
          * XXX: Only necessary on platforms where multiple threads
          * can write to the buffer at the same time because we
          * don't support mutexes (OS/2 for example).
          */
         outbuf[length] = '\0';
         continue;
      }
      outbuf[length] = '\0';
      ch = *src++;
      switch (ch) {
         case '%':
            tempbuf[0] = '%';
            tempbuf[1] = '\0';
            break;
         case 'd':
            ival = va_arg(ap, int);
            snprintf(tempbuf, sizeof(tempbuf), "%d", ival);
            break;
         case 'u':
            uval = va_arg(ap, unsigned);
            snprintf(tempbuf, sizeof(tempbuf), "%u", uval);
            break;
         case 'l':
            /* this is a modifier that must be followed by u, lu, or d */
            ch = *src++;
            if (ch == 'd')
            {
               lval = va_arg(ap, long);
               snprintf(tempbuf, sizeof(tempbuf), "%ld", lval);
            }
            else if (ch == 'u')
            {
               ulval = va_arg(ap, unsigned long);
               snprintf(tempbuf, sizeof(tempbuf), "%lu", ulval);
            }
Example #7
0
/*********************************************************************
 *
 * Function    :  init_error_log
 *
 * Description :  Initializes the logging module to log to a file.
 *
 *                XXX: should be renamed.
 *
 * Parameters  :
 *          1  :  prog_name  = The program name.
 *          2  :  logfname   = The logfile to (re)open.
 *
 * Returns     :  N/A
 *
 *********************************************************************/
void init_error_log(const char *prog_name, const char *logfname)
{
   FILE *fp;

   assert(NULL != logfname);

   lock_loginit();

   if ((logfp != NULL) && (logfp != stderr))
   {
      log_error(LOG_LEVEL_INFO, "(Re-)Opening logfile \'%s\'", logfname);
   }

   /* set the designated log file */
   fp = fopen(logfname, "a");
   if ((NULL == fp) && (logfp != NULL))
   {
      /*
       * Some platforms (like OS/2) don't allow us to open
       * the same file twice, therefore we give it another
       * shot after closing the old file descriptor first.
       *
       * We don't do it right away because it prevents us
       * from logging the "can't open logfile" message to
       * the old logfile.
       *
       * XXX: this is a lame workaround and once the next
       * release is out we should stop bothering reopening
       * the logfile unless we have to.
       *
       * Currently we reopen it every time the config file
       * has been reloaded, but actually we only have to
       * reopen it if the file name changed or if the
       * configuration reload was caused by a SIGHUP.
       */
      log_error(LOG_LEVEL_INFO, "Failed to reopen logfile: \'%s\'. "
         "Retrying after closing the old file descriptor first. If that "
         "doesn't work, Privoxy will exit without being able to log a message.",
         logfname);
      lock_logfile();
      fclose(logfp);
      logfp = NULL;
      unlock_logfile();
      fp = fopen(logfname, "a");
   }

   if (NULL == fp)
   {
      log_error(LOG_LEVEL_FATAL, "init_error_log(): can't open logfile: \'%s\'", logfname);
   }

   /* set logging to be completely unbuffered */
   setbuf(fp, NULL);

   lock_logfile();
   if (logfp != NULL)
   {
      fclose(logfp);
   }
#ifdef unix
   if (daemon_mode && (logfp == stderr))
   {
      if (dup2(1, 2) == -1)
      {
         /*
          * We only use fatal_error() to clear the pid
          * file and to exit. Given that stderr has just
          * been closed, the user will not see the error
          * message.
          */
         fatal_error("Failed to reserve fd 2.");
      }
   }
#endif
   logfp = fp;
   unlock_logfile();

   show_version(prog_name);

   unlock_loginit();

} /* init_error_log */
Example #8
0
int
main(
    int		argc,
    char **	argv)
{
    extern int optind;
    int opt;
    GSList *dumpspecs = NULL;
    int fd;
    tapelist_t *needed_tapes = NULL;
    char *e;
    rst_flags_t *rst_flags;
    int minimum_arguments;
    config_overrides_t *cfg_ovr = NULL;
    disklist_t diskq;
    char * conf_diskfile = NULL;
    am_feature_t *our_features = am_init_feature_set();

    /*
     * Configure program for internationalization:
     *   1) Only set the message locale for now.
     *   2) Set textdomain for all amanda related programs to "amanda"
     *      We don't want to be forced to support dozens of message catalogs.
     */  
    setlocale(LC_MESSAGES, "C");
    textdomain("amanda"); 

    set_pname("amfetchdump");

    /* Don't die when child closes pipe */
    signal(SIGPIPE, SIG_IGN);

    dbopen(DBG_SUBDIR_SERVER);

    add_amanda_log_handler(amanda_log_stderr);
    error_exit_status = 2;

    rst_flags = new_rst_flags();
    rst_flags->wait_tape_prompt = 1;

    /* handle options */
    cfg_ovr = new_config_overrides(argc/2);
    while( (opt = getopt_long(argc, argv, "alht:scCpb:nwi:d:O:o:", long_options, NULL)) != -1) {
	switch(opt) {
	case 0:
	    switch (loptions) {
		case 1:
		    rst_flags->headers = 1;
		    if (strcmp(optarg, "-") == 0)
			rst_flags->header_to_fd = STDOUT_FILENO;
		    else
			rst_flags->header_to_fd = atoi(optarg);
		    if (fcntl(rst_flags->header_to_fd, F_GETFL, NULL) == -1) {
			error(_("fd %d: %s\n"), rst_flags->header_to_fd,
			      strerror(errno));
		    }
		    break;
		case 2:
		    rst_flags->headers = 1;
		    rst_flags->header_to_fd = open(optarg,
						 O_WRONLY | O_CREAT | O_TRUNC,
						 S_IRUSR | S_IWUSR);
		    if (rst_flags->header_to_fd == -1) {
			error(_("Can't create '%s': %s\n"), optarg,
			      strerror(errno));
		    }
		    break;
	    }
	    break;
	case 'b':
            rst_flags->blocksize = (ssize_t)strtol(optarg, &e, 10);
            if(*e == 'k' || *e == 'K') {
	        rst_flags->blocksize *= 1024;
	    } else if(*e == 'm' || *e == 'M') {
	        rst_flags->blocksize *= 1024 * 1024;
	    } else if(*e != '\0') {
	        error(_("invalid blocksize value \"%s\""), optarg);
		/*NOTREACHED*/
	    }
	    if(rst_flags->blocksize < DISK_BLOCK_BYTES) {
	        error(_("minimum block size is %dk"), DISK_BLOCK_BYTES / 1024);
		/*NOTREACHED*/
	    }
	    break;
	case 'c': rst_flags->compress = 1; break;
	case 'O': rst_flags->restore_dir = stralloc(optarg) ; break;
	case 'd': rst_flags->alt_tapedev = stralloc(optarg) ; break;
	case 'C':
	    rst_flags->compress = 1;
	    rst_flags->comp_type = COMPRESS_BEST_OPT;
	    break;
	case 'p': rst_flags->pipe_to_fd = STDOUT_FILENO; break;
	case 's': rst_flags->fsf = (off_t)0; break;
	case 'l': rst_flags->leave_comp = 1; break;
	case 'i': rst_flags->inventory_log = stralloc(optarg); break;
	case 'n': rst_flags->inline_assemble = 0; break;
	case 'w': rst_flags->delay_assemble = 1; break;
	case 'a': rst_flags->wait_tape_prompt = 0; break;
	case 'h': rst_flags->headers = 1; break;
	case 'o': add_config_override_opt(cfg_ovr, optarg); break;
	default:
	    usage();
	    /*NOTREACHED*/
	}
    }

    for(fd = 3; fd < (int)FD_SETSIZE; fd++) {
	if (fd != debug_fd() &&
	    fd != rst_flags->pipe_to_fd &&
	    fd != rst_flags->header_to_fd) {
	    /*
	     * Make sure nobody spoofs us with a lot of extra open files
	     * that would cause a successful open to get a very high file
	     * descriptor, which in turn might be used as an index into
	     * an array (e.g. an fd_set).
	     */
	    close(fd);
	}
    }

    /* Check some flags that affect inventorying */
    if(rst_flags->inventory_log){
	if(rst_flags->inline_assemble) rst_flags->delay_assemble = 1;
	rst_flags->inline_assemble = 0;
	rst_flags->leave_comp = 1;
	if(rst_flags->compress){
	    error(_("Cannot force compression when doing inventory/search"));
	    /*NOTREACHED*/
	}
	g_fprintf(stderr, _("Doing inventory/search, dumps will not be uncompressed or assembled on-the-fly.\n"));
    }
    else{
	if(rst_flags->delay_assemble){
	    g_fprintf(stderr, _("Using -w, split dumpfiles will *not* be automatically uncompressed.\n"));
	}
    }

    /* make sure our options all make sense otherwise */
    if(check_rst_flags(rst_flags) == -1) {
    	usage();
	/*NOTREACHED*/
    }

    if (rst_flags->inventory_log) {
        minimum_arguments = 1;
    } else {
        minimum_arguments = 2;
    }
 
    if(argc - optind < minimum_arguments) {
	usage();
	/*NOTREACHED*/
    }

    config_init(CONFIG_INIT_EXPLICIT_NAME, argv[optind++]);
    apply_config_overrides(cfg_ovr);

    conf_diskfile = config_dir_relative(getconf_str(CNF_DISKFILE));
    read_diskfile(conf_diskfile, &diskq);
    amfree(conf_diskfile);

    if (config_errors(NULL) >= CFGERR_WARNINGS) {
	config_print_errors();
	if (config_errors(NULL) >= CFGERR_ERRORS) {
	    g_critical(_("errors processing config file"));
	}
    }

    check_running_as(RUNNING_AS_DUMPUSER);

    dbrename(get_config_name(), DBG_SUBDIR_SERVER);

    dumpspecs = cmdline_parse_dumpspecs(argc - optind, argv + optind,
					CMDLINE_PARSE_DATESTAMP |
					CMDLINE_PARSE_LEVEL |
					CMDLINE_EMPTY_TO_WILDCARD);

    /*
     * We've been told explicitly to go and search through the tapes the hard
     * way.
     */
    if(rst_flags->inventory_log){
	g_fprintf(stderr, _("Beginning tape-by-tape search.\n"));
	search_tapes(stderr, stdin, rst_flags->alt_tapedev == NULL,
                     NULL, dumpspecs, rst_flags, our_features);
	dbclose();
	exit(0);
    }


    /* Decide what tapes we'll need */
    needed_tapes = list_needed_tapes(dumpspecs,
				     rst_flags->pipe_to_fd == STDOUT_FILENO,
				     &diskq);

    parent_pid = getpid();
    atexit(cleanup);
    get_lock = lock_logfile(); /* config is loaded, should be ok here */
    if(get_lock == 0) {
	char *process_name = get_master_process(rst_conf_logfile);
	error(_("%s exists: %s is already running, or you must run amcleanup"), rst_conf_logfile, process_name);
    }
    log_add(L_INFO, "%s pid %ld", get_pname(), (long)getpid());
    search_tapes(NULL, stdin, rst_flags->alt_tapedev == NULL,
                 needed_tapes, dumpspecs, rst_flags, our_features);
    cleanup();

    dumpspec_list_free(dumpspecs);

    if(rst_flags->inline_assemble || rst_flags->delay_assemble)
	flush_open_outputs(1, NULL);
    else flush_open_outputs(0, NULL);

    free_disklist(&diskq);
    free_rst_flags(rst_flags);

    dbclose();

    return(0);
}