Exemple #1
0
UINT8 sc4_state::read_input_matrix(int row)
{
	ioport_port* portnames[16] = { m_io1, m_io2, m_io3, m_io4, m_io5, m_io6, m_io7, m_io8, m_io9, m_io10, m_io11, m_io12 };
	UINT8 value;

	if (row<4)
		value = (read_safe(portnames[row], 0x00) & 0x1f) + ((read_safe(portnames[row+8], 0x00) & 0x07) << 5);
	else
		value = (read_safe(portnames[row], 0x00) & 0x1f) + ((read_safe(portnames[row+4], 0x00) & 0x18) << 2);

	return value;
}
void handle_reducer()
{
  char my_letter = (char)((int)'a' + process_number);
  int count = 0;
  char c;

  while(read_safe(reducer_pipes[process_number][READ_END], &c, 1) > 0)
  {
    if(c == my_letter)
    {
      count++;
    }
  }

  printf("count %c:\t%d\n", my_letter, count);
  fflush_safe(stdout);

  int i;
  for(i = 0; i < NUMBER_REDUCERS; i++)
  {
    close_safe(reducer_pipes[i][READ_END]);
  }

  exit(0);
}
void handle_mapper()
{
  char buffer[DEFAULT_BUFFER];
  int i;

  while(read_safe(mapper_pipes[process_number][READ_END], buffer, DEFAULT_BUFFER) > 0)
  {
    for(i = 0; i < strlen(buffer) && buffer[i] != '\n'; i++)
    {
      char letter = buffer[i];
      if((letter >= (int)'a') && (letter <= (int) 'z'))
      {
        int index = (int)letter - (int)'a';
        write_safe(reducer_pipes[index][WRITE_END], &letter, 1);
      }
    }
  }

  for(i = 0; i < NUMBER_MAPPERS; i++)
  {
    close_safe(mapper_pipes[i][READ_END]);
  }
  for(i = 0; i < NUMBER_REDUCERS; i++)
  {
    close_safe(reducer_pipes[i][WRITE_END]);
  }

  exit(0);
}
void dispatcher_send_message(Dispatcher *dispatcher, uint32_t message_type,
                             void *payload)
{
    DispatcherMessage *msg;
    uint32_t ack;
    int send_fd = dispatcher->send_fd;

    assert(dispatcher->max_message_type > message_type);
    assert(dispatcher->messages[message_type].handler);
    msg = &dispatcher->messages[message_type];
    pthread_mutex_lock(&dispatcher->lock);
    if (write_safe(send_fd, (uint8_t*)&message_type, sizeof(message_type)) == -1) {
        spice_printerr("error: failed to send message type for message %d",
                   message_type);
        goto unlock;
    }
    if (write_safe(send_fd, payload, msg->size) == -1) {
        spice_printerr("error: failed to send message body for message %d",
                   message_type);
        goto unlock;
    }
    if (msg->ack == DISPATCHER_ACK) {
        if (read_safe(send_fd, (uint8_t*)&ack, sizeof(ack), 1) == -1) {
            spice_printerr("error: failed to read ack");
        } else if (ack != ACK) {
            spice_printerr("error: got wrong ack value in dispatcher "
                       "for message %d\n", message_type);
            /* TODO handling error? */
        }
    }
unlock:
    pthread_mutex_unlock(&dispatcher->lock);
}
Exemple #5
0
static int dispatcher_handle_single_read(Dispatcher *dispatcher)
{
    int ret;
    uint32_t type;
    DispatcherMessage *msg = NULL;
    uint8_t *payload = dispatcher->priv->payload;
    uint32_t ack = ACK;

    if ((ret = read_safe(dispatcher->priv->recv_fd, (uint8_t*)&type, sizeof(type), 0)) == -1) {
        spice_printerr("error reading from dispatcher: %d", errno);
        return 0;
    }
    if (ret == 0) {
        /* no messsage */
        return 0;
    }
    msg = &dispatcher->priv->messages[type];
    if (read_safe(dispatcher->priv->recv_fd, payload, msg->size, 1) == -1) {
        spice_printerr("error reading from dispatcher: %d", errno);
        /* TODO: close socketpair? */
        return 0;
    }
    if (dispatcher->priv->any_handler) {
        dispatcher->priv->any_handler(dispatcher->priv->opaque, type, payload);
    }
    if (msg->handler) {
        msg->handler(dispatcher->priv->opaque, payload);
    } else {
        spice_printerr("error: no handler for message type %d", type);
    }
    if (msg->ack == DISPATCHER_ACK) {
        if (write_safe(dispatcher->priv->recv_fd,
                       (uint8_t*)&ack, sizeof(ack)) == -1) {
            spice_printerr("error writing ack for message %d", type);
            /* TODO: close socketpair? */
        }
    } else if (msg->ack == DISPATCHER_ASYNC && dispatcher->priv->handle_async_done) {
        dispatcher->priv->handle_async_done(dispatcher->priv->opaque, type,
                                      (void *)payload);
    }
    return 1;
}
Exemple #6
0
OrFalse <array <string> > f$file (const string &name) {
  struct stat stat_buf;
  dl::enter_critical_section();//OK
  int file_fd = open_safe (name.c_str(), O_RDONLY);
  if (file_fd < 0) {
    dl::leave_critical_section();
    return false;
  }
  if (fstat (file_fd, &stat_buf) < 0) {
    close_safe (file_fd);
    dl::leave_critical_section();
    return false;
  }

  if (!S_ISREG (stat_buf.st_mode)) {
    php_warning ("Regular file expected as first argument in function file, \"%s\" is given", name.c_str());
    close_safe (file_fd);
    dl::leave_critical_section();
    return false;
  }

  size_t size = stat_buf.st_size;
  if (size > string::max_size) {
    php_warning ("File \"%s\" is too large", name.c_str());
    close_safe (file_fd);
    dl::leave_critical_section();
    return false;
  }
  dl::leave_critical_section();

  string res ((dl::size_type)size, false);

  dl::enter_critical_section();//OK
  char *s = &res[0];
  if (read_safe (file_fd, s, size) < (ssize_t)size) {
    close_safe (file_fd);
    dl::leave_critical_section();
    return false;
  }

  close_safe (file_fd);
  dl::leave_critical_section();

  array <string> result;
  int prev = -1;
  for (int i = 0; i < (int)size; i++) {
    if (s[i] == '\n' || i + 1 == (int)size) {
      result.push_back (string (s + prev + 1, i - prev));
      prev = i;
    }
  }

  return result;
}
Exemple #7
0
int
flash_mtd_read(const char *mtd_part, int offset, unsigned char *buf, size_t count)
{
	int fd, ret;
	ssize_t r_len;
	struct mtd_info mi;

	if (!mtd_part || !buf || offset < 0 || count < 1)
		return -1;

	memset(&mi, 0, sizeof(mi));
	fd = mtd_dev_open(mtd_part, O_RDONLY|O_SYNC, &mi);
	if (fd < 0) {
		fprintf(stderr, "%s: failed to open MTD partition %s\n",
			__func__, mtd_part);
		return -2;
	}

	ret = 0;

	if (((size_t)offset + count) > mi.size) {
		fprintf(stderr, "%s: out of MTD partition (offset: 0x%x, count: 0x%x, %s size: 0x%x)\n",
			__func__, offset, count, mi.dev, mi.size);
		ret = -3;
		goto out_err;
	}

	if (lseek(fd, offset, SEEK_SET) == -1) {
		fprintf(stderr, "%s: failed to seek %s to offset 0x%x (errno: %d)\n",
			__func__, mi.dev, offset, errno);
		ret = 3;
		goto out_err;
	}

	r_len = read_safe(fd, buf, count);
	if (r_len < 0) {
		fprintf(stderr, "%s: failed to read %u bytes from %s (errno: %d)\n",
			__func__, count, mi.dev, errno);
		ret = -4;
		goto out_err;
	}

	if (r_len != count)
		ret = 1;

out_err:
	fflush(stderr);

	close(fd);

	return ret;
}
Exemple #8
0
void coco_pak_device::device_reset()
{
	if (m_cart->exists()) {
		cococart_line_value cart_line;

		cart_line = read_safe(machine().root_device().ioport(CART_AUTOSTART_TAG), 0x01)
			? COCOCART_LINE_VALUE_Q
			: COCOCART_LINE_VALUE_CLEAR;

		/* normal CoCo PAKs tie their CART line to Q - the system clock */
		m_owner->cart_set_line(COCOCART_LINE_CART,cart_line);
	}
}
Exemple #9
0
OrFalse <string> f$file_get_contents (const string &name) {
  if ((int)name.size() == 11 && !memcmp (name.c_str(), "php://input", 11)) {
    return raw_post_data;
  }

  struct stat stat_buf;
  dl::enter_critical_section();//OK
  int file_fd = open_safe (name.c_str(), O_RDONLY);
  if (file_fd < 0) {
    dl::leave_critical_section();
    return false;
  }
  if (fstat (file_fd, &stat_buf) < 0) {
    close_safe (file_fd);
    dl::leave_critical_section();
    return false;
  }

  if (!S_ISREG (stat_buf.st_mode)) {
    php_warning ("Regular file expected as first argument in function file_get_contents, \"%s\" is given", name.c_str());
    close_safe (file_fd);
    dl::leave_critical_section();
    return false;
  }

  size_t size = stat_buf.st_size;
  if (size > string::max_size) {
    php_warning ("File \"%s\" is too large", name.c_str());
    close_safe (file_fd);
    dl::leave_critical_section();
    return false;
  }
  dl::leave_critical_section();

  string res ((dl::size_type)size, false);

  dl::enter_critical_section();//OK
  if (read_safe (file_fd, &res[0], size) < (ssize_t)size) {
    close_safe (file_fd);
    dl::leave_critical_section();
    return false;
  }

  close_safe (file_fd);
  dl::leave_critical_section();
  return res;
}
Exemple #10
0
bool f$copy (const string &from, const string &to) {
  struct stat stat_buf;
  dl::enter_critical_section();//OK
  int read_fd = open (from.c_str(), O_RDONLY);
  if (read_fd < 0) {
    dl::leave_critical_section();
    return false;
  }
  if (fstat (read_fd, &stat_buf) < 0) {
    close (read_fd);
    dl::leave_critical_section();
    return false;
  }

  if (!S_ISREG (stat_buf.st_mode)) {
    php_warning ("Regular file expected as first argument in function copy, \"%s\" is given", from.c_str());
    close (read_fd);
    dl::leave_critical_section();
    return false;
  }

  int write_fd = open (to.c_str(), O_WRONLY | O_CREAT | O_TRUNC, stat_buf.st_mode);
  if (write_fd < 0) {
    close (read_fd);
    dl::leave_critical_section();
    return false;
  }

  size_t size = stat_buf.st_size;
  while (size > 0) {
    size_t len = min (size, (size_t)PHP_BUF_LEN);
    if (read_safe (read_fd, php_buf, len) < (ssize_t)len) {
      break;
    }
    if (write_safe (write_fd, php_buf, len) < (ssize_t)len) {
      break;
    }
    size -= len;
  }

  close (read_fd);
  close (write_fd);
  dl::leave_critical_section();
  return size == 0;
}
Exemple #11
0
static void read_proc_cmdline(char* cmdline, int size) {
  char path[64];
  snprintf(path, sizeof(path), "/proc/%d/cmdline", pid);
  int cmdline_fd = open(path, O_RDONLY);
  if (cmdline_fd < 0) {
    fprintf(stderr, "Could not open %s.\n", path);
    perror("open");
    cmdline[0] = '\0';
    return;
  }
  int length = read_safe(cmdline_fd, cmdline, size);
  if (length < 0) {
    fprintf(stderr, "Could not read %s.\n", path);
    perror("read");
    length = 0;
  }
  close(cmdline_fd);
  cmdline[length] = '\0';
}
Exemple #12
0
SLOT_INTERFACE_END


/***************************************************************************
    IMPLEMENTATION
***************************************************************************/
/*-------------------------------------------------
    real_time_clock
-------------------------------------------------*/

coco_rtc_type_t coco_fdc_device::real_time_clock()
{
	coco_rtc_type_t result = coco_rtc_type_t(read_safe(machine().root_device().ioport("real_time_clock"), RTC_NONE));

	/* check to make sure we don't have any invalid values */
	if (((result == RTC_DISTO) && (m_disto_msm6242 == nullptr))
		|| ((result == RTC_CLOUD9) && (m_ds1315 == nullptr)))
	{
		result = RTC_NONE;
	}

	return result;
}
Exemple #13
0
int main(int argc, char **argv)
{
	int fd, fd_s, ctl_fd;
	pid_t extpid;
	int pfd[2];
	int sk_bsize;
	int ret, snd, snd_size, rcv_size = 0, rcv_buf_size;

#ifdef ZDTM_TCP_LOCAL
	test_init(argc, argv);
#endif

	if (pipe(pfd)) {
		pr_perror("pipe() failed");
		return 1;
	}

	extpid = fork();
	if (extpid < 0) {
		pr_perror("fork() failed");
		return 1;
	} else if (extpid == 0) {
		int size;
		char c;

#ifndef ZDTM_TCP_LOCAL
		test_ext_init(argc, argv);
#endif

		close(pfd[1]);
		read_safe(pfd[0], &port, sizeof(port));

		fd = tcp_init_client(ZDTM_FAMILY, "127.0.0.1", port);
		if (fd < 0)
			return 1;

		ctl_fd = tcp_init_client(ZDTM_FAMILY, "127.0.0.1", port);
		if (fd < 0)
			return 1;

		snd_size = fill_sock_buf(fd);
		if (snd_size <= 0)
			return 1;

		write_safe(ctl_fd, &snd_size, sizeof(snd_size));

		read_safe(ctl_fd, &rcv_buf_size, sizeof(rcv_buf_size));

		while (1) {
			/* heart beat */
			read_safe(ctl_fd, &ret, sizeof(ret));
			if (ret < 0)
				break;
			rcv_buf_size += ret;

			snd = fill_sock_buf(fd);
			if (snd < 0)
				return -1;
			snd_size += snd;

			if (rcv_buf_size / 2) {
				ret = clean_sk_buf(fd, rcv_buf_size / 2);
				if (ret <= 0)
					return 1;
			} else
				ret = 0;

			rcv_buf_size -= ret;
			rcv_size += ret;

			write_safe(ctl_fd, &snd, sizeof(snd));
		}

		read_safe(ctl_fd, &ret, sizeof(ret));
		rcv_buf_size += ret;

		write_safe(ctl_fd, &snd_size, sizeof(snd_size));

		if (read(ctl_fd, &c, 1) != 0) {
			pr_perror("read");
			return 1;
		}

		if (shutdown(fd, SHUT_WR) == -1) {
			pr_perror("shutdown");
			return 1;
		}

		size = clean_sk_buf(fd, 0);
		if (size < 0)
			return 1;

		if (size != rcv_buf_size) {
			fail("the received buffer contains only %d bytes (%d)\n", size, rcv_buf_size);
		}

		rcv_size += size;

		write_safe(ctl_fd, &rcv_size, sizeof(rcv_size));
		close(fd);

		return 0;
	}

#ifndef ZDTM_TCP_LOCAL
	test_init(argc, argv);
#endif

	if ((fd_s = tcp_init_server(ZDTM_FAMILY, &port)) < 0) {
		pr_perror("initializing server failed");
		return 1;
	}

	close(pfd[0]);
	write_safe(pfd[1], &port, sizeof(port));
	close(pfd[1]);

	/*
	 * parent is server of TCP connection
	 */
	fd = tcp_accept_server(fd_s);
	if (fd < 0) {
		pr_perror("can't accept client connection %m");
		return 1;
	}

	ctl_fd = tcp_accept_server(fd_s);
	if (ctl_fd < 0) {
		pr_perror("can't accept client connection %m");
		return 1;
	}

	sk_bsize = TCP_MAX_BUF;
	if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF,
			&sk_bsize, sizeof(sk_bsize)) == -1) {
		pr_perror("Can't set snd buf");
		return 1;
	}

	sk_bsize = TCP_MAX_BUF;
	if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF,
			&sk_bsize, sizeof(sk_bsize)) == -1) {
		pr_perror("Can't set snd buf");
		return 1;
	}

	snd_size = fill_sock_buf(fd);
	if (snd_size <= 0)
		return 1;

	read_safe(ctl_fd, &rcv_buf_size, sizeof(rcv_buf_size));

	write_safe(ctl_fd, &snd_size, sizeof(snd_size));

	test_daemon();

	snd = 0;
	while (test_go()) {
		/* heart beat */
		if (rcv_buf_size / 2) {
			ret = clean_sk_buf(fd, rcv_buf_size / 2);
			if (ret <= 0)
				return 1;
		} else
			ret = 0;

		rcv_size += ret;
		rcv_buf_size -= ret;

		write_safe(ctl_fd, &snd, sizeof(snd));
		read_safe(ctl_fd, &ret, sizeof(ret));

		rcv_buf_size += ret;

		snd = fill_sock_buf(fd);
		if (snd < 0)
			return -1;
		snd_size += snd;
	}

	ret = -1;
	write_safe(ctl_fd, &ret, sizeof(ret));
	write_safe(ctl_fd, &snd, sizeof(ret));
	read_safe(ctl_fd, &snd, sizeof(snd));

	if (shutdown(ctl_fd, SHUT_WR) == -1) {
		pr_perror("shutdown");
		return 1;
	}

	if (shutdown(fd, SHUT_WR) == -1) {
		pr_perror("shutdown");
		return 1;
	}

	ret = clean_sk_buf(fd, 0);
	if (ret != rcv_buf_size) {
		fail("the received buffer contains only %d bytes (%d)\n", ret, rcv_buf_size);
	}
	rcv_size += ret;

	if (snd != rcv_size) {
		fail("The child sent %d bytes, but the parent received %d bytes\n", rcv_buf_size, rcv_size);
		return 1;
	}

	read_safe(ctl_fd, &ret, sizeof(ret));

	if (ret != snd_size) {
		fail("The parent sent %d bytes, but the child received %d bytes\n", snd_size, ret);
		return 1;
	}

	pass();
	return 0;
}
Exemple #14
0
int fileBrowser_DVD_readFile(fileBrowser_file* file, void* buffer, unsigned int length){
	int bytesread = read_safe(buffer,file->discoffset+file->offset,length);
	if(bytesread > 0)
		file->offset += bytesread;
	return bytesread;
}
Exemple #15
0
int
walkcontext(const ucontext_t *uptr, int (*operate_func)(uintptr_t, int, void *),
    void *usrarg)
{
	ucontext_t *oldctx = uptr->uc_link;

	int	fd;
	int 	sig;
#if defined(__sparc)
	int 	signo = 0;
#endif

	struct frame *savefp;
	uintptr_t savepc;

	/*
	 * snag frame point from ucontext... we'll see caller of
	 * getucontext since we'll start by working up the call
	 * stack by one
	 */

	struct frame *fp = (struct frame *)
	    ((uintptr_t)uptr->uc_mcontext.gregs[FRAME_PTR_REGISTER] +
	    STACK_BIAS);

	/*
	 * Since we don't write signo to the stack on sparc, we need
	 * to extract signo from the stack frames.
	 * An awkward interface is provided for this purpose:
	 * thr_sighndlrinfo; this is documented in
	 * /shared/sac/PSARC/1999/024.  When called, this function
	 * returns the PC of a special function (and its size) that
	 * will be present in the stack frame if a signal was
	 * delivered and will have the following signature
	 * __sighndlr(int sig, siginfo_t *si, ucontex_t *uc,
	 *	void (*hndlr)())
	 * Since this function is written in assembler and doesn't
	 * perturb its registers, we can then read sig out of arg0
	 * when the saved pc is inside this function.
	 */
#if defined(__sparc)

	uintptr_t special_pc = NULL;
	int special_size = 0;

	extern void thr_sighndlrinfo(void (**func)(), int *funcsize);

	thr_sighndlrinfo((void (**)())&special_pc, &special_size);
#endif /* sparc */


	if ((fd = open("/proc/self/as", O_RDONLY)) < 0)
		return (-1);

	while (fp != NULL) {

		sig = 0;

		/*
		 * get value of saved fp and pc w/o crashing
		 */

		if (read_safe(fd, fp, &savefp, &savepc) != 0) {
			(void) close(fd);
			return (-1);
		}

		if (savefp == NULL)
			break;

		/*
		 * note that the following checks to see if we've got a
		 * special signal stack frame present; this allows us to
		 * detect signals and pass that info to the user stack walker
		 */

		if (oldctx != NULL &&
		    CHECK_FOR_SIGFRAME((uintptr_t)savefp, (uintptr_t)oldctx)) {

#if defined(__i386) || defined(__amd64)
			/*
			 * i386 and amd64 store signo on stack;
			 * simple to detect and use
			 */
			sig = *((int *)(savefp + 1));
#endif

#if defined(__sparc)
			/*
			 * In the case of threads, since there are multiple
			 * complex routines between kernel and user handler,
			 * we need to figure out where we can read signal from
			 * using thr_sighndlrinfo - which we've already done
			 * for this signal, since it appeared on the stack
			 * before the signal frame.... sigh.
			 */
			sig = signo; /* already read - see below */
#endif
			/*
			 * this is the special signal frame, so cons up
			 * the saved fp & pc to pass to user's function
			 */

			savefp = (struct frame *)
			    ((uintptr_t)oldctx->
			    uc_mcontext.gregs[FRAME_PTR_REGISTER] +
			    STACK_BIAS);
			savepc = oldctx->uc_mcontext.gregs[PC_REGISTER];

			oldctx = oldctx->uc_link; /* handle nested signals */
		}
#if defined(__sparc)

		/*
		 * lookahead code to find right spot to read signo from...
		 */

		if (savepc >= special_pc && savepc <
		    (special_pc + special_size))
			signo = fp->fr_arg[0];
#endif

		/*
		 * call user-supplied function and quit if non-zero return.
		 */

		if (operate_func((uintptr_t)savepc, sig, usrarg) != 0)
			break;

		fp = savefp; /* up one in the call stack */
	}

	(void) close(fd);
	return (0);
}
Exemple #16
0
static int dump_process_heap(
    int mem_fd,
    FILE* fmaps,
    bool dump_also_allocs,
    bool pedantic,  // Enable pedantic consistency checks on memory counters.
    char* comment) {
  HeapStats stats;
  //time_t tm;
  char cmdline[512];

  //tm = time(NULL);
  read_proc_cmdline(cmdline, sizeof(cmdline));

  // Look for the mmap which contains the HeapStats in the target process vmem.
  // On Linux/Android, the libheap_profiler mmaps explicitly /dev/zero. The
  // region furthermore starts with a magic marker to disambiguate.
  bool stats_mmap_found = false;
  for (;;) {
    char line[1024];
    if (fgets(line, sizeof(line), fmaps) == NULL)
      break;

    uintptr_t start;
    uintptr_t end;
    char map_file[32];
    int ret = sscanf(line, "%"SCNxPTR"-%"SCNxPTR" rw-p %*s %*s %*s %31s",
                     &start, &end, map_file);
    const size_t size = end - start + 1;
    if (ret != 3 || strcmp(map_file, "/dev/zero") != 0 || size < sizeof(stats))
      continue;

    // The mmap looks promising. Let's check for the magic marker.
    lseek_abs(mem_fd, start);
    ssize_t rsize = read_safe(mem_fd, &stats, sizeof(stats));

    if (rsize == -1) {
      perror("read");
      return -1;
    }

    if (rsize < sizeof(stats))
      continue;

    if (stats.magic_start == HEAP_PROFILER_MAGIC_MARKER) {
      stats_mmap_found = true;
      break;
    }
  }

  if (!stats_mmap_found) {
    fprintf(stderr, "Could not find the HeapStats area. "
                    "It looks like libheap_profiler is not loaded.\n");
    return -1;
  }

  // Print JSON-formatted output.
//  printf("{\n");
//  printf("  \"pid\":             %d,\n", pid);
//  printf("  \"time\":            %ld,\n", tm);
//  printf("  \"comment\":         \"%s\",\n", comment);
//  printf("  \"cmdline\":         \"%s\",\n", cmdline);
//  printf("  \"pagesize\":        %d,\n", getpagesize());
//  printf("  \"total_allocated\": %zu,\n", stats.total_alloc_bytes);
//  printf("  \"num_allocs\":      %"PRIu32",\n", stats.num_allocs);
//  printf("  \"num_stacks\":      %"PRIu32",\n", stats.num_stack_traces);
  fprintf(fp,"heap profile: %"PRIu32": %zu: [ %"PRIu32": %zu] @ heapprofile\n",
		  stats.num_allocs,stats.total_alloc_bytes,
		  stats.num_allocs,stats.total_alloc_bytes);

  //uint32_t dbg_counted_allocs = 0;
  size_t dbg_counted_total_alloc_bytes = 0;
  //bool prepend_trailing_comma = false;  // JSON syntax, I hate you.
  uint32_t i;

  // Dump the optional allocation table.
  //if (dump_also_allocs) {
  /*
  if (0) {
    printf("  \"allocs\": {");
    lseek_abs(mem_fd, (uintptr_t) stats.allocs);
    for (i = 0; i < stats.max_allocs; ++i) {
      Alloc alloc;
      if (read_safe(mem_fd, &alloc, sizeof(alloc)) != sizeof(alloc)) {
        fprintf(stderr, "ERROR: cannot read allocation table\n");
        perror("read");
        return -1;
      }

      // Skip empty (i.e. freed) entries.
      if (alloc.start == 0 && alloc.end == 0)
        continue;

      if (alloc.end < alloc.start) {
        fprintf(stderr, "ERROR: found inconsistent alloc.\n");
        return -1;
      }

      size_t alloc_size = alloc.end - alloc.start + 1;
      size_t stack_idx = (
          (uintptr_t) alloc.st - (uintptr_t) stats.stack_traces) /
          sizeof(StacktraceEntry);
      dbg_counted_total_alloc_bytes += alloc_size;
      ++dbg_counted_allocs;

      if (prepend_trailing_comma)
        printf(",");
      prepend_trailing_comma = true;
      printf("\"%"PRIxPTR"\": {\"l\": %zu, \"f\": %"PRIu32", \"s\": \"%zx\"}",
             alloc.start, alloc_size, alloc.flags, stack_idx);
    }
    printf("},\n");

    if (pedantic && dbg_counted_allocs != stats.num_allocs) {
      fprintf(stderr,
              "ERROR: inconsistent alloc count (%"PRIu32" vs %"PRIu32").\n",
              dbg_counted_allocs, stats.num_allocs);
      return -1;
    }

    if (pedantic && dbg_counted_total_alloc_bytes != stats.total_alloc_bytes) {
      fprintf(stderr, "ERROR: inconsistent alloc totals (%zu vs %zu).\n",
              dbg_counted_total_alloc_bytes, stats.total_alloc_bytes);
      return -1;
    }
  }*/

  // Dump the distinct stack traces.
  //printf("  \"stacks\": {");
  //prepend_trailing_comma = false;
  dbg_counted_total_alloc_bytes = 0;
  lseek_abs(mem_fd, (uintptr_t) stats.stack_traces);
  for (i = 0; i < stats.max_stack_traces; ++i) {
    StacktraceEntry st;
    if (read_safe(mem_fd, &st, sizeof(st)) != sizeof(st)) {
      fprintf(stderr, "ERROR: cannot read stack trace table\n");
      perror("read");
      return -1;
    }

    // Skip empty (i.e. freed) entries.
    if (st.alloc_bytes == 0)
      continue;

    dbg_counted_total_alloc_bytes += st.alloc_bytes;

//    if (prepend_trailing_comma)
//      printf(",");
//    prepend_trailing_comma = true;

    //printf("\"%"PRIx32"\":{\"l\": %zu, \"f\": [", i, st.alloc_bytes);
	fprintf(fp," 1:  %zu [ 1: %d] @ ",st.alloc_bytes, st.alloc_bytes);
    size_t n = 0;
    for (;;) {
      fprintf(fp,"0x%"PRIxPTR"", st.frames[n]);
      ++n;
      if (n == HEAP_PROFILER_MAX_DEPTH || st.frames[n] == 0)
        break;
      else
        fprintf(fp," ");
    }
    //printf("]}");
	//printf(" 0x00000000\n");
	fprintf(fp,"\n");
  }
  //printf("}\n}\n");

  if (pedantic && dbg_counted_total_alloc_bytes != stats.total_alloc_bytes) {
    fprintf(stderr, "ERROR: inconsistent stacks totals (%zu vs %zu).\n",
            dbg_counted_total_alloc_bytes, stats.total_alloc_bytes);
    //return -1;
  }

  fprintf(fp,"\nMAPPED_LIBRARIES:\n");
  fseek(fmaps,0,SEEK_SET);
  for (;;) {
    char buf[1024];
	size_t got = fread(buf, 1, sizeof(buf), fmaps);
	fwrite(buf, 1, got, fp);
	if (feof(fmaps))
		break;
  }
  fflush(fp);
  return 0;
}
/********** MAIN PROGRAM ************************************************
 *
 * This program reads current weather data from a WS3600
 * and writes the data to a log file.
 *
 * Log file format:
 * Timestamp Date Time Ti To DP RHi RHo Wind Dir-degree Dir-text WC
 *              Rain1h Rain24h Rain-tot Rel-Press Tendency Forecast
 *
 * Just run the program without parameters for usage.
 *
 * It takes two parameters. The first is the log filename with path
 * The second is the config file name with path
 * If this parameter is omitted the program will look at the default paths
 * See the open3600.conf file for info
 *
 ***********************************************************************/
int main(int argc, char *argv[])
{
	WEATHERSTATION ws;
	FILE *fileptr;
	unsigned char logline[3000] = "";
	char datestring[50];        //used to hold the date stamp for the log file
	const char *directions[]= {"N","NNE","NE","ENE","E","ESE","SE","SSE",
	                           "S","SSW","SW","WSW","W","WNW","NW","NNW"};
	double winddir[6];
	char tendency[15];
	char forecast[15];
	time_t basictime;
	unsigned char data[32768];
	int read_result;
	int i;

	get_configuration(&config, argv[2]);

   /* Get log filename. */

	if (argc < 2 || argc > 3)
	{
		print_usage();
	}			

	fileptr = fopen(argv[1], "a+");
	if (fileptr == NULL)
	{
		printf("Cannot open file %s\n",argv[1]);
		exit(-1);
	}
  
  i = 0;
  do {
    ws = open_weatherstation(config.serial_device_name);
    read_result = read_safe(ws, 0, HISTORY_BUFFER_ADR,data, NULL);
    close_weatherstation(ws);
    i++;
  } while (i < 4 && read_result == -1);
  
  if (read_result == -1)
	{
    printf("\nError reading data\n");
	  exit(0);
  }

	/* READ TEMPERATURE INDOOR */
	
	sprintf(logline,"%s%.1f ", logline,
	        temperature_indoor(data));
	

	/* READ TEMPERATURE OUTDOOR */

	sprintf(logline,"%s%.1f ", logline,
	        temperature_outdoor(data));
	
	
	/* READ DEWPOINT */

	sprintf(logline,"%s%.1f ", logline,
	        dewpoint(data));
	
	
	/* READ RELATIVE HUMIDITY INDOOR */

	sprintf(logline,"%s%d ", logline, humidity_indoor(data));	
	
	
	/* READ RELATIVE HUMIDITY OUTDOOR */

	sprintf(logline,"%s%d ", logline, humidity_outdoor(data));	 


	/* READ WIND SPEED AND DIRECTION */

  sprintf(logline,"%s%.1f ", logline,
	       wind_current(data, winddir));
	sprintf(logline,"%s%.1f %s ", logline, winddir[0], directions[(int)(winddir[0]/22.5)]);


	/* READ WINDCHILL */
	
	sprintf(logline,"%s%.1f ", logline,
	        windchill(data));

	
	/* READ RAIN 1H */
	sprintf(logline,"%s%.2f ", logline,
	        rain_1h(data));
	
	/* READ RAIN 24H */

	sprintf(logline,"%s%.2f ", logline,
	        rain_24h(data));

  	// READ RAIN 1W

  sprintf(logline, "%s%.2f ", logline,
		rain_1w(data));
	        
	// READ RAIN 1M

  sprintf(logline, "%s%.2f ", logline,
		rain_1m(data));
	
	/* READ RAIN TOTAL */
	
	sprintf(logline,"%s%.2f ", logline,
	        rain_total(data));

	
	/* READ RELATIVE PRESSURE */

	sprintf(logline,"%s%.3f ", logline,
	        rel_pressure(data));
	

	/* READ TENDENCY AND FORECAST */
	
	tendency_forecast(data, tendency, forecast);
	sprintf(logline,"%s%s %s", logline, tendency, forecast);


	/* GET DATE AND TIME FOR LOG FILE, PLACE BEFORE ALL DATA IN LOG LINE */
	
	time(&basictime);
	strftime(datestring,sizeof(datestring),"%Y%m%d%H%M%S %Y-%b-%d %H:%M:%S",
	         localtime(&basictime));

	// Print out and leave

	// printf("%s %s\n",datestring, logline); //disabled to be used in cron job
	fprintf(fileptr,"%s %s\n",datestring, logline);

//	close_weatherstation(ws);
	
	fclose(fileptr);

	exit(0);
	
	return 0;
}
/********** MAIN PROGRAM ************************************************
 *
 * This program reads the history records from a WS3600
 * weather station at a given record range
 * and prints the data to stdout and to a file.
 * Just run the program without parameters for usage.
 *
 * It uses the config file for device name.
 * Config file locations - see open3600.conf
 *
 ***********************************************************************/
int main(int argc, char *argv[])
{
	WEATHERSTATION ws;
	FILE *fileptr;
	unsigned char logline[3000] = "";
	unsigned char data[32768];
	long counter;
	char ch;
	char datestring[50];        //used to hold the date stamp for the log file
	time_t time_lastlog, time_tmp = 0, time_now;
	struct tm time_lastlog_tm, time_tm;
	int current_record, next_record, record_count;
	double temperature_in;
	double temperature_out;
	double dewpoint;
	double windchill;
	double pressure;
	int humidity_in;
	int humidity_out;
	double rain, current_rain;
	double prev_rain = 0;
	
	double windspeed;
	double windgust;
	double winddir_degrees;
	const char *directions[]= {"N","NNE","NE","ENE","E","ESE","SE","SSE",
	                           "S","SSW","SW","WSW","W","WNW","NW","NNW"};
  int minute;

	int temp_int1, temp_int2;
	int read_result;
	int i,j;

	if (argc < 2 || argc > 2)
	{
		print_usage();
	}	
	
	// Get serial port from config file

	get_configuration(&config, "");

    // Setup serial port

    // Get in-data and select mode.
	fileptr = fopen(argv[1], "ab+");
	if (fileptr == NULL)
	{
		printf("Cannot open file %s\n",argv[1]);
		exit(0);
	}
	
	fseek(fileptr, 1L, SEEK_END);
	counter = 60;
	do
	{
		counter++;
		if (fseek(fileptr, -counter, SEEK_END) < 0 )
			break;
		ch = getc(fileptr);
	} while (ch != '\n' && ch != '\r');
	if (fscanf(fileptr,"%4d%2d%2d%2d%2d", &temp_int1, &temp_int2,
	           &time_lastlog_tm.tm_mday, &time_lastlog_tm.tm_hour,
	           &time_lastlog_tm.tm_min) == 5)
	{
		time_lastlog_tm.tm_year = temp_int1 - 1900;
		time_lastlog_tm.tm_mon = temp_int2 - 1;	
		time_lastlog_tm.tm_sec = 0;
		time_lastlog_tm.tm_isdst = -1;
	}
	else
	{	//if no valid log we set the date to 1 Jan 1990 0:00
		time_lastlog_tm.tm_year = 1990; 
		time_lastlog_tm.tm_mon = 0;	
		time_lastlog_tm.tm_mday = 1;
		time_lastlog_tm.tm_hour = 0;
	  time_lastlog_tm.tm_min = 0;
		time_lastlog_tm.tm_sec = 0;
		time_lastlog_tm.tm_isdst = -1;
	}
	//printf("%4d,%2d,%2d,%2d,%2d\n", temp_int1, temp_int2,
	//           time_lastlog_tm.tm_mday, time_lastlog_tm.tm_hour,
	//           time_lastlog_tm.tm_min);
	
	time_lastlog = mktime(&time_lastlog_tm);
	i = 0;
	//time_now varialbe will be used to check correctness of time in history records
  time(&time_now);
  //add 10h margin for lower sensitivity of history time (history time may be max 10h higher than local computer time)
  time_now += 36000;
  do {
    ws = open_weatherstation(config.serial_device_name);
    read_result = read_safe(ws, HISTORY_BUFFER_ADR,0x7fff - HISTORY_BUFFER_ADR + 1,data, NULL);
    close_weatherstation(ws);
    i++;
    
    if (read_result != -1)
    {
      //check dates in history
      for (j = 0; j < HISTORY_REC_NO; j++)
      {
        read_history_record(data, j, &config,
  	                        &temperature_in,
  	                        &temperature_out,
  	                        &pressure,
  	                        &humidity_in,
  	                        &humidity_out,
  	                        &rain,
  	                        &windspeed,
  	                        &windgust,
  	                        &winddir_degrees,
  	                        &dewpoint,
  	                        &windchill,
                            &time_tm);
  
        if (time_tm.tm_min != 0xff)
        {
          time_tmp = mktime(&time_tm);
          if (time_tmp > time_now)
          {
            print_log(2,"wrong date in history");
            strftime(datestring,sizeof(datestring),"%Y%m%d%H%M%S %Y-%b-%d %H:%M:%S",
    		         &time_tm);
    		    print_log(2,datestring);
            
            break;
          }
        }
      }
    }
  } while (i < 4 && read_result == -1 && time_tmp <= time_now);		
  
  if (time_lastlog_tm.tm_year == 1990)
  {
    //find oldest record
    
    //go to the end of buffer (FF in minutes)
    next_record = 0;
    do
    {
      current_record = next_record;
      //printf("record1=%i\n",current_record);
      next_record = read_history_record(data, current_record, &config,
	                        &temperature_in,
	                        &temperature_out,
	                        &pressure,
	                        &humidity_in,
	                        &humidity_out,
	                        &rain,
	                        &windspeed,
	                        &windgust,
	                        &winddir_degrees,
	                        &dewpoint,
	                        &windchill,
                          &time_tm);
    } while (time_tm.tm_min < 60);
    /*if (current_record == 0)
    {
      read_history_record(data, 1796, &config,
	                        &temperature_in,
	                        &temperature_out,
	                        &pressure,
	                        &humidity_in,
	                        &humidity_out,
	                        &rain,
	                        &windspeed,
	                        &windgust,
	                        &winddir_degrees,
	                        &dewpoint,
	                        &windchill,
                          &time_tm);
    }*/
    
    //ommit FF's between end and begin of buffer (is only one FF byte for longer used station - with completely filled buffer)
    record_count = 0;
    do
    {
      //printf("record2=%i\n",current_record);
      current_record = next_record;
      next_record = read_history_record(data, current_record, &config,
	                        &temperature_in,
	                        &temperature_out,
	                        &pressure,
	                        &humidity_in,
	                        &humidity_out,
	                        &rain,
	                        &windspeed,
	                        &windgust,
	                        &winddir_degrees,
	                        &dewpoint,
	                        &windchill,
                          &time_tm);
      record_count++;  
    } while (time_tm.tm_min >= 60 && record_count < HISTORY_REC_NO + 1);
      //first log record will have rain = 0 (we don't know previous state of rain counter)
      if (time_tm.tm_min < 60)
          prev_rain = rain;
    //we are at the beginning of buffer now!
  } else
  {
    //find oldest new record
    //go to the end of buffer (FF in minutes)
    next_record = 0;
    do
    {
      //printf("record2=%i\n",current_record);
      current_record = next_record;
      next_record = read_history_record(data, current_record, &config,
	                        &temperature_in,
	                        &temperature_out,
	                        &pressure,
	                        &humidity_in,
	                        &humidity_out,
	                        &rain,
	                        &windspeed,
	                        &windgust,
	                        &winddir_degrees,
	                        &dewpoint,
	                        &windchill,
                          &time_tm);
    } while (time_tm.tm_min < 60 && next_record != 0);
    
    //ommit FF's between end and begin of buffer (is only one FF byte for longer used station - with completely filled buffer)
    do
    {
      //printf("record2=%i\n",current_record);
      current_record = next_record;
      next_record = read_history_record(data, current_record, &config,
	                        &temperature_in,
	                        &temperature_out,
	                        &pressure,
	                        &humidity_in,
	                        &humidity_out,
	                        &rain,
	                        &windspeed,
	                        &windgust,
	                        &winddir_degrees,
	                        &dewpoint,
	                        &windchill,
                          &time_tm);
    } while (time_tm.tm_min >= 60 && next_record != 0);
    
    //find first new record
    record_count = 0;  
    do
    {
      current_record = next_record;
      //printf("record3=%i\n",current_record);
      next_record = read_history_record(data, next_record, &config,
	                        &temperature_in,
	                        &temperature_out,
	                        &pressure,
	                        &humidity_in,
	                        &humidity_out,
	                        &rain,
	                        &windspeed,
	                        &windgust,
	                        &winddir_degrees,
	                        &dewpoint,
	                        &windchill,
                          &time_tm);

      if (time_tm.tm_min < 60)
      {
        time_tmp = mktime(&time_tm);
      }
      
      if (time_tm.tm_min < 60 && time_tmp <= time_lastlog)
      {
        prev_rain = rain;
      }
      
      if (record_count == 0)
        prev_rain = rain;
        
      record_count++; 
      
    } while (time_tmp <= time_lastlog && record_count < HISTORY_REC_NO + 1);
    
    if (time_tmp <= time_lastlog && record_count == HISTORY_REC_NO + 1)
    {
      printf("\nNew records not found\n");
      close_weatherstation(ws);
      fclose(fileptr);
	    exit(0);
    }
  }
	
	//next_record = current_record;
	next_record = current_record;
	if (record_count < HISTORY_REC_NO + 1)
	{
  	do
  	{ 
  	  //printf("record4=%i\n",next_record);
  		next_record = read_history_record(data, next_record, &config,
  	                        &temperature_in,
  	                        &temperature_out,
  	                        &pressure,
  	                        &humidity_in,
  	                        &humidity_out,
  	                        &rain,
  	                        &windspeed,
  	                        &windgust,
  	                        &winddir_degrees,
  	                        &dewpoint,
  	                        &windchill,
                            &time_tm);
  		
  		strcpy(logline,"");
  		
  		// READ TEMPERATURE INDOOR
  		
  		sprintf(logline,"%s%.1f ", logline, temperature_in);
  		
  	
  		// READ TEMPERATURE OUTDOOR
  	
  		sprintf(logline,"%s%.1f ", logline, temperature_out);
  		
  		
  		// READ DEWPOINT
  	
  		sprintf(logline,"%s%.1f ", logline, dewpoint);
  		
  		
  		// READ RELATIVE HUMIDITY INDOOR
  	
  		sprintf(logline,"%s%d ", logline, humidity_in);	
  		
  		
  		// READ RELATIVE HUMIDITY OUTDOOR
  	
  		sprintf(logline,"%s%d ", logline, humidity_out);	 
  	
  	
  		// READ WIND SPEED AND DIRECTION aND WINDCHILL
  	
  		sprintf(logline,"%s%.1f ", logline, windspeed);
  		sprintf(logline,"%s%.1f %s ", logline, winddir_degrees, directions[(int)(winddir_degrees/22.5)]);
  		
  		// READ GUST
  		sprintf(logline,"%s%.2f ", logline, windgust);
  	
  	
  		// READ WINDCHILL
  		
  		sprintf(logline,"%s%.1f ", logline, windchill);
  	
  		
  		// READ RAIN 1H
  	
  		//	sprintf(logline,"%s%.2f ", logline,
  		//        rain_1h(ws, config.rain_conv_factor));
  		//	
  		
  		// READ RAIN 24H
  	
  		//
  		//sprintf(logline,"%s%.2f ", logline,
  		//        rain_24h(ws, config.rain_conv_factor));
  		//
  		
  		// READ RAIN IN INTERVAL
  		if (rain >= prev_rain)
        current_rain = rain - prev_rain;
      else
        current_rain = rain + 4096 - prev_rain;
  		sprintf(logline,"%s%.2f ", logline, current_rain * 0.518);
  		//sprintf(logline,"%s%.2f ", logline, rain);
  		prev_rain = rain;
  		
  		// READ ABSOLUTE PRESSURE
  	
  		sprintf(logline,"%s%.3f ", logline, pressure);
  		
  		
  	
  	
  		// GET DATE AND TIME FOR LOG FILE, PLACE BEFORE ALL DATA IN LOG LINE
  		
  		//	printf("time now: %d\n",time(&basictime));
  		//	time_lastrecord_tm.tm_hour=time_last.hour;
  
      minute = time_tm.tm_min;
  		if (minute < 60)
  		{
        mktime(&time_tm);                 //normalize time_lastlog_tm
  		
  		  strftime(datestring,sizeof(datestring),"%Y%m%d%H%M%S %Y-%b-%d %H:%M:%S",
  		         &time_tm);
  		
  		
  		  // Print out
  		  fseek(fileptr, 0L, SEEK_END);
  		  fprintf(fileptr,"%s %s\n",datestring, logline);
  		  fflush(NULL);
  		}
  	
  	} while (minute < 60);
  }

	// Goodbye and Goodnight
	//close_weatherstation(ws);
	fclose(fileptr);

	return(0);
}