Exemplo n.º 1
0
Arquivo: buffer.c Projeto: dmt4/ne
void free_chars(buffer *const b, char *const p, const int64_t len) {
	if (!b || !p || !len) return;

	char_pool *cp = get_char_pool(b, p);

	assert_char_pool(cp);

	assert(*p);
	assert(p[len - 1]);

	block_signals();

	memset(p, 0, len);
	b->free_chars += len;

	if (p == &cp->pool[cp->first_used]) while(cp->first_used <= cp->last_used && !cp->pool[cp->first_used]) cp->first_used++;
	if (p + len - 1 == &cp->pool[cp->last_used]) while(!cp->pool[cp->last_used] && cp->first_used <= cp->last_used) cp->last_used--;

	if (cp->last_used < cp->first_used) {
		rem(&cp->cp_node);
		b->allocated_chars -= cp->size;
		b->free_chars -= cp->size;
		free_char_pool(cp);
		release_signals();
		return;
	}

	assert_char_pool(cp);
	release_signals();
}
Exemplo n.º 2
0
QLuaConsole::Private::~Private()
{
  Q_ASSERT(console == this);
  // console thread
  command(KillCmd);
  wait();
  // file descriptors
  redirect(false);
  if (trueStdout)
    fclose(trueStdout);
  if (trueStderr)
    fclose(trueStderr);
  ::close(stdoutPipe[0]);
  ::close(stdoutPipe[1]);
  ::close(commandPipe[0]);
  ::close(commandPipe[1]);
  // signals
  release_signals(&savedSigSet);
  set_sigint_handler(SIG_DFL);
  // done
#if HAVE_READLINE
  rtty_done();
#endif
  console = 0;
}
Exemplo n.º 3
0
Arquivo: buffer.c Projeto: dmt4/ne
void free_buffer_contents(buffer * const b) {

	if (!b) return;

	block_signals();

	free_list(&b->line_desc_pool_list, free_line_desc_pool);
	free_list(&b->char_pool_list, free_char_pool);
	new_list(&b->line_desc_list);
	b->cur_line_desc = b->top_line_desc = NULL;

	b->allocated_chars = b->free_chars = 0;
	b->is_CRLF = false;
	b->encoding = ENC_ASCII;
	b->bookmark_mask = 0;
	b->mtime = 0;

	free_char_stream(b->last_deleted);
	b->last_deleted = NULL;

	free(b->filename);
	b->filename = NULL;

	reset_undo_buffer(&b->undo);
	b->is_modified = b->marking = b->recording = b->x_wanted = 0;

	release_signals();
}
Exemplo n.º 4
0
/*
 * Signal handler for signals that cause program's termination.
 */
void
signal_handler(int sig)
{

	release_signals();

	fatal(ERROR_SIGNAL, "killed by signal %d\n", sig);
}
Exemplo n.º 5
0
Arquivo: buffer.c Projeto: dmt4/ne
line_desc *alloc_line_desc(buffer * const b) {
	block_signals();
	
	line_desc_pool *ldp;
	for(ldp = (line_desc_pool *)b->line_desc_pool_list.head; ldp->ldp_node.next; ldp = (line_desc_pool *)ldp->ldp_node.next) {

		assert_line_desc_pool(ldp);

		if (ldp->free_list.head->next) {

			line_desc * const ld = (line_desc *)ldp->free_list.head;

			rem(&ld->ld_node);

			if (!ldp->free_list.head->next) {
				rem(&ldp->ldp_node);
				add_tail(&b->line_desc_pool_list, &ldp->ldp_node);
			}

			ldp->allocated_items++;

			ld->line = NULL;
			ld->line_len = 0;
			if (do_syntax) ld->highlight_state.state = -1;
			release_signals();
			return ld;
		}
	}

	/* No chances, all pools are full. Let's allocate a new one,
	using the standard pool size, and let's put it at the start
	of the list, so that it is always scanned first. */

	if (ldp = alloc_line_desc_pool(0)) {
		add_head(&b->line_desc_pool_list, &ldp->ldp_node);
		line_desc * const ld = (line_desc *)ldp->free_list.head;
		rem(&ld->ld_node);
		ldp->allocated_items = 1;
		if (do_syntax) ld->highlight_state.state = -1;
		release_signals();
		return ld;
	}

	release_signals();
	return NULL;
}
Exemplo n.º 6
0
Arquivo: buffer.c Projeto: dmt4/ne
int64_t alloc_chars_around(buffer * const b, line_desc * const ld, const int64_t n, const bool check_first_before) {

	assert(ld->line != NULL);

	char_pool *cp = get_char_pool(b, ld->line);

	assert_char_pool(cp);

	block_signals();

	char *before = ld->line - 1;
	char *after = ld->line + ld->line_len;

	if (check_first_before) {
		while(before >= cp->pool && !*before && (ld->line - 1) - before < n)
			before--;
		while(after < cp->pool + cp->size && !*after && (after - (ld->line + ld->line_len)) + ((ld->line - 1) - before)<n)
			after++;
	}
	else {
		while(after < cp->pool + cp->size && !*after && after - (ld->line + ld->line_len)<n)
			after++;
		while(before >= cp->pool && !*before && (after - (ld->line + ld->line_len)) + ((ld->line - 1) - before)<n)
			before--;
	}

	assert(((ld->line - 1) - before) + (after - (ld->line + ld->line_len)) <= n);
	assert(((ld->line - 1) - before) + (after - (ld->line + ld->line_len)) >= 0);

	if (((ld->line - 1) - before) + (after - (ld->line + ld->line_len)) == n) {
		if (cp->pool + cp->first_used == ld->line) cp->first_used = (before + 1) - cp->pool;
		if (cp->pool + cp->last_used == ld->line + ld->line_len - 1) cp->last_used = (after - 1) - cp->pool;
		b->free_chars -= n;

		release_signals();
		return after - (ld->line + ld->line_len);
	}

	release_signals();
	return ERROR;
}
Exemplo n.º 7
0
void
QLuaConsole::Private::run()
{
  // --- This runs from the console thread.
  // accept signals in this thread.
  set_sigint_handler(SIG_DFL);
  release_signals(&savedSigSet);
  // loop
  while (! killConsole)
    {
      int fds[2];
      int nfd = 0;
      if (! throttleActive)
        fds[nfd++] = stdoutPipe[0];
      fds[nfd++] = commandPipe[0];
      int fd = wait_for_input(nfd, fds);
      mutex.lock();
      if (! throttleActive)
        copyout();
      if (fd == commandPipe[0])
        {
          char c = (char)NoCmd;
          if (::read(commandPipe[0], &c, 1) > 0)
            switch( (enum Command)c )
              {
              case HandlerCmd:
                sethandler();
                break;
              case DrainCmd:
                msleep(10);
                copyout(throttleActive = false);
                drain.wakeAll();
                break;
              case BreakCmd:
                if (lua && breakStopsLua) 
                  lua->stop();
                emit q->ttyBreak();
                break;
              case ReadlineCmd:
                readline();
                break;
              case KillCmd:
                killConsole = true;
              default:
                break;
              }
        }
      pulse.wakeAll();
      mutex.unlock();
    }
  // reset signals
  set_sigint_handler(SIG_DFL);
}
Exemplo n.º 8
0
Arquivo: buffer.c Projeto: dmt4/ne
int delete_one_line(buffer * const b, line_desc * const ld, const int64_t line) {
	assert_line_desc(ld, b->encoding);
	assert_buffer(b);

	block_signals();

	if (ld->line_len && (b->last_deleted = reset_stream(b->last_deleted))) add_to_stream(b->last_deleted, ld->line, ld->line_len);

	/* We delete a line by delete_stream()ing its length plus one. However, if
		we are on the last line of text, there is no terminating line feed. */

	const int error = delete_stream(b, ld, line, 0, ld->line_len + (ld->ld_node.next->next ? 1 : 0));
	release_signals();

	return error;
}
Exemplo n.º 9
0
Arquivo: buffer.c Projeto: dmt4/ne
void clear_buffer(buffer * const b) {
	if (!b) return;

	block_signals();

	free_buffer_contents(b);

	line_desc * const ld = alloc_line_desc(b);
	add_head(&b->line_desc_list, &ld->ld_node);
	if (do_syntax) {
		ld->highlight_state.state = 0;
		ld->highlight_state.stack = NULL;
		ld->highlight_state.saved_s[0] = 0;
	}

	b->num_lines = 1;
	reset_position_to_sof(b);

	assert_buffer(b);

	release_signals();
}
Exemplo n.º 10
0
Arquivo: buffer.c Projeto: dmt4/ne
void free_line_desc(buffer * const b, line_desc * const ld) {
	/* We scan the pool list in order to find where the given
	line descriptor lives. */

	line_desc_pool *ldp;
	for(ldp = (line_desc_pool *)b->line_desc_pool_list.head; ldp->ldp_node.next; ldp = (line_desc_pool *)ldp->ldp_node.next) {
		assert_line_desc_pool(ldp);
		if (ld >= ldp->pool && (do_syntax && ld < ldp->pool + ldp->size || !do_syntax && ld < (line_desc*)((no_syntax_line_desc *)ldp->pool + ldp->size))) break;
	}

	assert(ldp->ldp_node.next != NULL);

	block_signals();

	add_head(&ldp->free_list, &ld->ld_node);

	if (--ldp->allocated_items == 0) {
		rem(&ldp->ldp_node);
		free_line_desc_pool(ldp);
	}

	release_signals();
}
Exemplo n.º 11
0
int
main(int argc, char *argv[])

{
    char *env_top;
    char **preset_argv;
    int preset_argc = 0;
    void *mask;
    int need_mini = 1;

    struct statics statics;
    globalstate *gstate;

    /* get our name */
    if (argc > 0)
    {
	if ((myname = strrchr(argv[0], '/')) == 0)
	{
	    myname = argv[0];
	}
	else
	{
	    myname++;
	}
    }

    /* binary compatibility check */
#ifdef HAVE_UNAME
    {
	struct utsname uts;

	if (uname(&uts) == 0)
	{
	    if (strcmp(uts.machine, UNAME_HARDWARE) != 0)
	    {
		fprintf(stderr, "%s: incompatible hardware platform\n",
			myname);
		exit(EX_UNAVAILABLE);
	    }
	}
    }
#endif

    /* initialization */
    gstate = (globalstate *)calloc(1, sizeof(globalstate));
    gstate->statics = &statics;
    time_mark(NULL);

    /* preset defaults for various options */
    gstate->show_usernames = Yes;
    gstate->topn = DEFAULT_TOPN;
    gstate->delay = DEFAULT_DELAY;
    gstate->fulldraw = Yes;
    gstate->use_color = Yes;
    gstate->interactive = Maybe;

    /* preset defaults for process selection */
    gstate->pselect.idle = Yes;
    gstate->pselect.system = No;
    gstate->pselect.fullcmd = No;
    gstate->pselect.command = NULL;
    gstate->pselect.uid = -1;
    gstate->pselect.mode = 0;

    /* use a large buffer for stdout */
#ifdef HAVE_SETVBUF
    setvbuf(stdout, stdoutbuf, _IOFBF, BUFFERSIZE);
#else
#ifdef HAVE_SETBUFFER
    setbuffer(stdout, stdoutbuf, BUFFERSIZE);
#endif
#endif

    /* get preset options from the environment */
    if ((env_top = getenv("TOP")) != NULL)
    {
	preset_argv = argparse(env_top, &preset_argc);
	preset_argv[0] = myname;
	do_arguments(gstate, preset_argc, preset_argv);
    }

    /* process arguments */
    do_arguments(gstate, argc, argv);

#ifdef ENABLE_COLOR
    /* If colour has been turned on read in the settings. */
    env_top = getenv("TOPCOLOURS");
    if (!env_top)
    {
	env_top = getenv("TOPCOLORS");
    }
    /* must do something about error messages */
    color_env_parse(env_top);
    color_activate(gstate->use_color);
#endif

    /* in order to support forward compatability, we have to ensure that
       the entire statics structure is set to a known value before we call
       machine_init.  This way fields that a module does not know about
       will retain their default values */
    memzero((void *)&statics, sizeof(statics));
    statics.boottime = -1;

    /* call the platform-specific init */
    if (machine_init(&statics) == -1)
    {
	exit(EX_SOFTWARE);
    }

    /* create a helper list of sort order names */
    gstate->order_namelist = string_list(statics.order_names);

    /* look up chosen sorting order */
    if (gstate->order_name != NULL)
    {
	int i;

	if (statics.order_names == NULL)
	{
	    message_error(" This platform does not support arbitrary ordering");
	}
	else if ((i = string_index(gstate->order_name,
				   statics.order_names)) == -1)
	{
	    message_error(" Sort order `%s' not recognized", gstate->order_name);
	    message_error(" Recognized sort orders: %s", gstate->order_namelist);
	}
	else
	{
	    gstate->order_index = i;
	}
    }

    /* initialize extensions */
    init_username();

    /* initialize termcap */
    gstate->smart_terminal = screen_readtermcap(gstate->interactive);

    /* determine interactive state */
    if (gstate->interactive == Maybe)
    {
	gstate->interactive = smart_terminal;
    }

    /* if displays were not specified, choose an appropriate default */
    if (gstate->displays == 0)
    {
	gstate->displays = gstate->smart_terminal ? Infinity: 1;
    }

    /* we don't need a mini display when delay is less than 2
       seconds or when we are not on a smart terminal */
    if (gstate->delay <= 1 || !smart_terminal)
    {
	need_mini = 0;
    }

    /* set constants for username/uid display */
    if (gstate->show_usernames)
    {
	gstate->header_text = format_header("USERNAME");
	gstate->get_userid = username;
    }
    else
    {
	gstate->header_text = format_header("   UID  ");
	gstate->get_userid = itoa7;
    }
    gstate->pselect.usernames = gstate->show_usernames;

    /* initialize display */
    if ((gstate->max_topn = display_init(&statics)) == -1)
    {
	fprintf(stderr, "%s: can't allocate sufficient memory\n", myname);
	exit(EX_OSERR);
    }

    /* check for infinity and for overflowed screen */
    if (gstate->topn == Infinity)
    {
	gstate->topn = INT_MAX;
    }
    else if (gstate->topn > gstate->max_topn)
    {
#if 0
	message_error(" This terminal can only display %d processes",
		      gstate->max_topn);
#endif
    }

#ifdef ENABLE_COLOR
    /* producing a list of color tags is easy */
    if (gstate->show_tags)
    {
	color_dump(stdout);
	exit(EX_OK);
    }
#endif

    /* hold all signals while we initialize the screen */
    mask = hold_signals();
    screen_init();

    /* set the signal handlers */
    set_signals();

    /* longjmp re-entry point */
    /* set the jump buffer for long jumps out of signal handlers */
    if (setjmp(jmp_int) != 0)
    {
	/* this is where we end up after processing sigwinch or sigtstp */

	/* tell display to resize its buffers, and get the new length */
	if ((gstate->max_topn = display_resize()) == -1)
	{
	    /* thats bad */
	    quit(EX_OSERR);
	    /*NOTREACHED*/
	}

	/* set up for a full redraw, and get the current line count */
	gstate->fulldraw = Yes;

	/* safe to release the signals now */
	release_signals(mask);
    }
    else
    {
	/* release the signals */
	release_signals(mask);

	/* some systems require a warmup */
	/* always do a warmup for batch mode */
	if (gstate->interactive == 0 || statics.flags.warmup)
	{
	    struct system_info system_info;
	    struct timeval timeout;

	    time_mark(&(gstate->now));
	    get_system_info(&system_info);
	    (void)get_process_info(&system_info, &gstate->pselect, 0);
	    timeout.tv_sec = 1;
	    timeout.tv_usec = 0;
	    select(0, NULL, NULL, NULL, &timeout);

	    /* if we've warmed up, then we can show good states too */
	    gstate->show_cpustates = Yes;
	    need_mini = 0;
	}
    }

    /* main loop */
    while ((gstate->displays == -1) || (--gstate->displays > 0))
    {
	do_display(gstate);
	if (gstate->interactive)
	{
	    if (need_mini)
	    {
		do_minidisplay(gstate);
		need_mini = 0;
	    }
	    do_command(gstate);
	}
	else
	{
	    do_wait(gstate);
	}
    }

    /* do one last display */
    do_display(gstate);

    quit(EX_OK);
    /* NOTREACHED */
    return 1; /* Keep compiler quiet. */
}
Exemplo n.º 12
0
Arquivo: buffer.c Projeto: dmt4/ne
int insert_stream(buffer * const b, line_desc * ld, int64_t line, int64_t pos, const char * const stream, const int64_t stream_len) {
	if (!b || !ld || !stream || stream_len < 1 || pos > ld->line_len) return ERROR;

	assert_line_desc(ld, b->encoding);
	assert_buffer(b);

	block_signals();

	if (b->opt.do_undo && !(b->undoing || b->redoing)) {
		const int error = add_undo_step(b, line, pos, -stream_len);
		if (error) {
			release_signals();
			return error;
		}
	}

	const char *s = stream;
	while(s - stream < stream_len) {
		int64_t const len = strnlen_ne(s, stream_len - (s - stream));
		if (len) {

			/* First case; there is no character allocated on this line. We
			have to freshly allocate the line. */

			if (!ld->line) {
				if (ld->line = alloc_chars(b, len)) {
					memcpy(ld->line, s, len);
					ld->line_len = len;
				}
				else {
					release_signals();
					return OUT_OF_MEMORY;
				}
			}


			/* Second case. There are not enough characters around ld->line. Note
			that the value of the check_first_before parameter depends on
			the position at which the insertion will be done, and it is chosen
			in such a way to minimize the number of characters to move. */

			else {
				const int64_t result = alloc_chars_around(b, ld, len, pos < ld->line_len / 2);
				if (result < 0) {
					char * const p = alloc_chars(b, ld->line_len + len);
					if (p) {
						memcpy(p, ld->line, pos);
						memcpy(&p[pos], s, len);
						memcpy(&p[pos + len], ld->line + pos, ld->line_len - pos);
						free_chars(b, ld->line, ld->line_len);
						ld->line = p;
						ld->line_len += len;
					}
					else {
						release_signals();
						return OUT_OF_MEMORY;
					}
				}
				else { /* Third case. There are enough free characters around ld->line. */
					if (len - result) memmove(ld->line - (len - result), ld->line, pos);
					if (result) memmove(ld->line + pos + result, ld->line + pos, ld->line_len - pos);
					memcpy(ld->line - (len - result) + pos, s, len);
	
					ld->line -= (len - result);
					ld->line_len += len;
				}
			}
			b->is_modified = 1;

			/* We just inserted len chars at (line,pos); adjust bookmarks and mark accordingly. */
			if (b->marking && b->block_start_line == line && b->block_start_pos > pos) b->block_start_pos += len;

			for (int i = 0, mask = b->bookmark_mask; mask; i++, mask >>= 1) 
				if ((mask & 1) && b->bookmark[i].line == line && b->bookmark[i].pos > pos) b->bookmark[i].pos += len;
		}

		/* If the string we have inserted has a NULL at the end, we create a new
			line under the current one and set ld to point to it. */

		if (len + (s - stream) < stream_len) {
			line_desc *new_ld;

			if (new_ld = alloc_line_desc(b)) {

				add(&new_ld->ld_node, &ld->ld_node);
				b->num_lines++;

				if (pos + len < ld->line_len) {
					new_ld->line_len = ld->line_len - pos - len;
					new_ld->line = &ld->line[pos + len];
					ld->line_len = pos + len;
					if (pos + len == 0) ld->line = NULL;
				}

				b->is_modified = 1;
				ld = new_ld;

				/* We just inserted a line break at (line,pos);
				   adjust the buffer bookmarks and mark accordingly. */
				if (b->marking) {
					if (b->block_start_line == line && b->block_start_pos > pos) {
						b->block_start_pos -= pos;
						b->block_start_line++;
					}
					else if (b->block_start_line > line) b->block_start_line++;
				}
				for (int i = 0, mask=b->bookmark_mask; mask; i++, mask >>= 1) {
					if (mask & 1) {
						if (b->bookmark[i].line == line && b->bookmark[i].pos > pos) {
							b->bookmark[i].pos -= pos;
							b->bookmark[i].line++;
						}
						else if (b->bookmark[i].line > line) b->bookmark[i].line++;
					}
				}
				pos = 0;
				line++;
			}
			else {
Exemplo n.º 13
0
Arquivo: buffer.c Projeto: dmt4/ne
char *alloc_chars(buffer * const b, const int64_t len) {
	if (!len || !b) return NULL;

	assert_buffer(b);

	block_signals();

	char_pool *cp;
	for(cp = (char_pool *)b->char_pool_list.head; cp->cp_node.next; cp = (char_pool *)cp->cp_node.next) {
		assert_char_pool(cp);

		/* We try to allocate before the first used character,
		or after the last used character. If we succeed with a
		pool which is not the head of the list, we move it to
		the head in order to optimize the next try. */

		if (cp->first_used >= len) {

			cp->first_used -= len;
			b->free_chars -= len;

			if (cp != (char_pool *)b->char_pool_list.head) {
				rem(&cp->cp_node);
				add_head(&b->char_pool_list, &cp->cp_node);
			}

			release_signals();
			return cp->pool + cp->first_used;
		}
		else if (cp->size - cp->last_used > len) {

			cp->last_used += len;
			b->free_chars -= len;

			if (cp != (char_pool *)b->char_pool_list.head) {
				rem(&cp->cp_node);
				add_head(&b->char_pool_list, &cp->cp_node);
			}

			release_signals();
			return cp->pool + cp->last_used - len + 1;
		}
	}

	/* If no free space has been found, we allocate a new pool which is guaranteed
	to contain at least len characters. The pool is added to the head of the list. */

	if (cp = alloc_char_pool(len)) {
		add_head(&b->char_pool_list, &cp->cp_node);
		cp->last_used = len - 1;

		b->allocated_chars += cp->size;
		b->free_chars += cp->size - len;

		release_signals();
		return cp->pool;
	}

	release_signals();
	return NULL;
}