Exemple #1
0
hash_table *
hash_table_new(hash_func hash_f, hash_comp hash_c, hash_free hash_fr)
{
	hash_table *hash_t;

	hash_t = (struct _hash_table *) diag_malloc(sizeof(hash_table));
	if (hash_t == NULL)
		diag_fatal("Unable to allocate memory\n");

	hash_t->size = HASH_TABLE_MIN_SIZE;
	hash_t->nnodes = 0;
	if (hash_f)
		hash_t->hash_func = default_hash_func;
	else
		hash_t->hash_func = hash_f;
	if (hash_c)
		hash_t->hash_comp = default_compare_func;
	else
		hash_t->hash_comp = hash_c;
	hash_t->hash_free = hash_fr;
	hash_t->nodes = (hash_node **) diag_malloc(sizeof(hash_node *) * hash_t->size);
	if (hash_t->nodes == NULL)
	{
		diag_free(hash_t);
		diag_fatal("Unable to allocate memory\n");
	}
	memset(hash_t->nodes, 0, sizeof(hash_node *) * hash_t->size);

	return hash_t;
}
Exemple #2
0
struct diag_command *diag_command_new(char **argv,
				      const char *dir,
				      const char *in,
				      const char *out,
				      const char *err)
{
	struct diag_command *command = diag_malloc(sizeof(*command));
	size_t argc;
	for (argc = 0; argv[argc]; argc++) ;
	command->argv = diag_calloc(argc + 1, sizeof(char *));
	size_t i;
	for (i = 0; i < argc; i++) {
		command->argv[i] = diag_strdup(argv[i]);
	}
	command->argv[argc] = NULL; /* NULL-terminated */
	command->file = argv[0];

	if (dir) {
		command->dir = diag_strdup(dir);
	} else {
		command->dir = diag_malloc(PATH_LENGTH);
		char *p;
#if defined(_WIN32) && defined(__MINGW32__)
		p = _getcwd(command->dir, PATH_LENGTH);
#elif defined(HAVE_UNISTD_H)
		p = getcwd(command->dir, PATH_LENGTH);
#endif
		if (!p) {
			perror(NULL);
			diag_fatal("failed to get current working directory");
		}
	}

	if (in) {
		command->in = diag_strdup(in);
	} else {
		command->in = NULL;
	}
	if (out) {
		command->out = diag_strdup(out);
	} else {
		command->out = NULL;
	}
	if (err) {
		command->err = diag_strdup(err);
	} else {
		command->err = NULL;
	}
	return command;
}
Exemple #3
0
int main(void)
{
	struct diag_vcdiff_pcode *pcodes;
	struct diag_vcdiff_script *script;
	uint8_t *result;
	size_t size, i;

	pcodes = diag_calloc(2, sizeof(struct diag_vcdiff_pcode));
	pcodes[0].inst = DIAG_VCD_RUN;
	pcodes[0].size = 1;
	pcodes[0].attr.byte = 'a';
	pcodes[1].inst = DIAG_VCD_COPY;
	pcodes[1].size = 20;
	pcodes[1].attr.addr = 0;
	script = diag_malloc(sizeof(struct diag_vcdiff_script));
	script->source = NULL;
	script->s_pcodes = 2;
	script->pcodes = pcodes;
	result = diag_vcdiff_expand(script, &size);
	ASSERT_NOT_NULL(result);
	ASSERT_EQ_UINT32(21, size);
	for (i = 0; i < size; i++) {
		ASSERT_EQ_UINT8('a', result[i]);
	}
	diag_free(result);
	diag_free(script);
	diag_free(pcodes);

	return EXIT_SUCCESS;
}
Exemple #4
0
/*
 * Caller must free returned buffer. Used if we don't
 * have readline, and when reading init or command files.
 * No line editing or history.
 */
static char *
basic_get_input(const char *prompt)
{
	char *input;
	int do_prompt;

	if (diag_malloc(&input, INPUT_MAX))
			return NULL;

	do_prompt = 1;
	while (1) {
		if (do_prompt && prompt) {
			printf("%s", prompt);
			fflush(stdout);
		}
		do_prompt = 1;
		if (fgets(input, INPUT_MAX, instream)) {
			break;
		} else {
			if (feof(instream)) {
				free(input);
				return NULL;
			} else {
				/* Ignore error and try again, but don't prompt. */
				clearerr(instream);
				do_prompt = 0;
			}
		}
	}
	input[strcspn(input, "\r\n")] = '\0'; /* Remove trailing CR/LF */
	return input;
}
Exemple #5
0
long
hash_table_replace(hash_table * hash_t, void *key, void *value)
{
	hash_node **node;
	hash_node *pnode;
	long hash_val;

	node = hash_table_lookup_node(hash_t, key);

	if (node)
		(*node)->value = value;
	else
	{
		*node = (hash_node *) diag_malloc(sizeof(hash_node));
		if (*node == NULL)
			diag_fatal("Unable to allocate memory\n");
		(*node)->key = key;
		(*node)->value = value;
		hash_val = (*hash_t->hash_func) ((*node)->key, hash_t->size);
		(*node)->next = hash_t->nodes[hash_val];
		hash_t->nodes[hash_val] = (*node);
		hash_t->nnodes++;
		pnode = *node;
		hash_table_resize(hash_t);
	}

	return (long) pnode;
}
Exemple #6
0
static void
contract_and_expand(const char *data, size_t s_window, uint32_t base, size_t s_pcodes)
{
	struct diag_vcdiff_script *script;
	struct diag_rollinghash32 *rh;
	size_t size, s;
	uint8_t *result;
	char *result0;

	size = strlen(data);
	rh = (struct diag_rollinghash32 *)diag_rollinghash32_new_rabin_karp((const uint8_t *)data, size, s_window, base);
	ASSERT_NOT_NULL(rh);
	script = diag_vcdiff_contract(rh);
	ASSERT_NOT_NULL(script);
	dump_pcodes(script);
	ASSERT_EQ_UINT(s_pcodes, script->s_pcodes);
	result = diag_vcdiff_expand(script, &s);
	ASSERT_EQ_UINT(size, s);
	result0 = diag_malloc(s + 1);
	(void)memcpy(result0, result, s);
	result0[s] = '\0';
	ASSERT_EQ_STRING(data, result0);
	diag_free(result0);
	diag_free(result);
	diag_vcdiff_script_destroy(script);
	diag_rollinghash32_destroy(rh);
}
Exemple #7
0
char *
command_generator(const char *text, int state)
{
	static int list_index, length;
	const struct cmd_tbl_entry *cmd_entry;

	//a new word to complete
	if(state == 0) {
		list_index = 0;
		length = strlen(text);
	}

	//find the command
	while(completion_cmd_level[list_index].command != NULL) {
		cmd_entry = &completion_cmd_level[list_index];
		list_index++;
		if(strncmp(cmd_entry->command, text, length) == 0 && !(cmd_entry->flags & FLAG_HIDDEN)) {
			char *ret_name;
			//we must return a copy of the string; libreadline frees it for us
			if(diag_malloc(&ret_name, strlen(cmd_entry->command)+1) != 0)
				return (char *)NULL;
			strcpy(ret_name, cmd_entry->command);
			return ret_name;
		}
	}
	return (char *)NULL;
}
Exemple #8
0
char *diag_get_command_line(char **argv)
{
	assert(argv);

	char *line = diag_malloc(32768);
	char *lp = line;
	int i;
	for (i = 0; argv[i]; i++) {
		const char *s = argv[i];
		int slen = (int)strlen(s);
		if (lp + slen >= line + 32768) {
			diag_free(line);
			return NULL;
		}
		if (i > 0) {
			*lp++ = ' ';
		}
		if (contains_space(s)) {
			*lp++ = '"';
			strcpy(lp, s);
			lp += slen;
			*lp++ = '"';
		} else {
			strcpy(lp, s);
			lp += slen;
		}
	}
	*lp = '\0';
	return line;
}
Exemple #9
0
/*
 * Save dyno measures and results to a file
 */
static int cmd_dyno_save(int argc, char **argv) {
	char *filename;
	int rv;

	get_results();

	/* Check data */
	if (dyno_nb_results <= 0) {
		printf("Dyno run has not been done, please do a run first\n");
		return CMD_OK;
	}


	if (argc > 1) {
		/* Get filename from command arguments */
		size_t length = strlen(argv[1]);
		rv = diag_malloc(&filename, length + 1);
		if (rv != 0) {
			return rv;
		}
		strcpy(filename, argv[1]);
	} else {
		/* Get filename from user input */
		size_t nbytes = 256;
		rv = diag_malloc(&filename, nbytes + 1);
		if (rv != 0) {
			return rv;
		}

		printf("Enter filename: ");
		if (fgets(filename, (int)nbytes, stdin) == 0) {
			return CMD_OK;
		}

		/* Remove pending "\n" and "\r", if any */
		while ((filename[strlen(filename)-1] == '\n') ||
					 (filename[strlen(filename)-1] == '\r')) {
			filename[strlen(filename)-1] = '\0';
		}
	}

	dyno_save(filename, dyno_results, dyno_nb_results);
	printf("\n");

	free(filename);
	return CMD_OK;
}
Exemple #10
0
struct diag_delta *
diag_delta_new(enum diag_delta_type type)
{
	struct diag_delta *delta;

	delta = diag_malloc(sizeof(struct diag_delta));
	delta->type = type;
	return delta;
}
Exemple #11
0
struct diag_datum *diag_datum_create(uintptr_t id, intptr_t value)
{
	struct diag_datum *datum;

	datum = diag_malloc(sizeof(*datum));
	datum->tag = 0;
	datum->id = id;
	datum->value = value;
	return datum;
}
Exemple #12
0
struct diag_deque *diag_deque_new(void)
{
	struct diag_deque *deque;

	deque = diag_malloc(sizeof(struct diag_deque));
	deque->first = NULL;
	deque->last = NULL;
	deque->length = 0;
	return deque;
}
Exemple #13
0
struct diag_cluster *
diag_cluster_new(size_t num_data)
{
	struct diag_cluster *cluster;
	size_t size;

	size = (size_t)(sizeof(struct diag_cluster)+num_data*sizeof(struct diag_datum *));
	cluster = diag_malloc(size);
	cluster->num_data = num_data;
	return cluster;
}
Exemple #14
0
/* Get measures for specified type */
static void get_measures(dyno_measure ** measures, int * nb_measures)
{
	/* allocate memory */
	(*nb_measures) = dyno_get_nb_measures();
	if ((*nb_measures)==0)
		return;
	if (diag_malloc(measures, (*nb_measures) * sizeof(dyno_measure)))
		return;

	/* get measures */
	dyno_get_measures((*measures), (*nb_measures));
}
Exemple #15
0
struct diag_code *
diag_code_new(struct diag_cluster *cluster, size_t num_deltas)
{
	struct diag_code *code;
	size_t size;

	size = (size_t)(sizeof(struct diag_code)+num_deltas*sizeof(struct diag_delta *));
	code = diag_malloc(size);
	code->cluster = cluster;
	code->num_deltas = num_deltas;
	return code;
}
Exemple #16
0
struct diag_customized_datum *
diag_customized_datum_create(uintptr_t id, intptr_t value,
			     diag_datum_finalizer finalize)
{
	struct diag_customized_datum *datum;

	datum = diag_malloc(sizeof(*datum));
	datum->tag = DIAG_TAG_CUSTOMIZED;
	datum->id = id;
	datum->value = value;
	datum->finalize = finalize;
	return datum;
}
Exemple #17
0
struct diag_analysis *
diag_analysis_new(size_t num_data, struct diag_datum **data)
{
	struct diag_analysis *analysis;
	size_t size;

	size = (size_t)(sizeof(struct diag_analysis)+num_data*sizeof(struct diag_code *));
	analysis = diag_malloc(size);
	analysis->num_data = num_data;
	analysis->data = data;
	analysis->metric = NULL;
	analysis->encoder = NULL;
	analysis->decoder = NULL;
	analysis->clusters = NULL;
	return analysis;
}
Exemple #18
0
/* Get the results in global vars */
static void get_results(void)
{
	/* allocating memory for the results table */
	if (dyno_results == NULL) {
		dyno_nb_results = dyno_get_nb_results();
		if (dyno_nb_results == 0)
			return;
		if (diag_malloc(&dyno_results, dyno_nb_results * sizeof(dyno_result)))
			return;
	}

	/* raw results */
	dyno_get_results(dyno_results, dyno_nb_results);

	/* smooth results */
	dyno_smooth_results(dyno_results, dyno_nb_results);
}
Exemple #19
0
static void
hash_table_resize(hash_table * hash_t)
{
	hash_node **new_nodes;
	hash_node *node;
	hash_node *next;
	long hash_val;
	long new_size;
	long i;

	if ((hash_t->size >= 3 * hash_t->nnodes && hash_t->size > HASH_TABLE_MIN_SIZE)
	    || (3 * hash_t->size <= hash_t->nnodes && hash_t->size < HASH_TABLE_MAX_SIZE))
	{

		new_size = get_closest(hash_t->nnodes);

		new_nodes = (hash_node **) diag_malloc(sizeof(hash_node *) * new_size);
		if (new_nodes == NULL)
		{
			diag_msg("Unable to allocate memory\n");
			return;
		}
		memset(new_nodes, 0, sizeof(hash_node *) * new_size);

		for (i = 0; i < hash_t->size; i++)
			for (node = hash_t->nodes[i]; node; node = next)
			{
				next = node->next;

				hash_val = (*hash_t->hash_func) (node->key, new_size);

				node->next = new_nodes[hash_val];
				new_nodes[hash_val] = node;
			}

		diag_free(hash_t->nodes);
		hash_t->nodes = new_nodes;
		hash_t->size = new_size;
	}
}
Exemple #20
0
long
hash_table_insert(hash_table * hash_t, void *key, void *value)
{
	hash_node **node;
	hash_node *pnode;

	node = hash_table_lookup_node(hash_t, key);

	if (!*node)
	{

		*node = (hash_node *) diag_malloc(sizeof(hash_node));
		if (*node == NULL)
			diag_fatal("Unable to allocate memory\n");
		(*node)->key = key;
		(*node)->value = value;
		(*node)->next = NULL;
		hash_t->nnodes++;
		pnode = *node;
		hash_table_resize(hash_t);
	}

	return (long) pnode;
}
Exemple #21
0
int diag_tty_open(struct diag_l0_device **ppdl0d, 
const char *subinterface,
const struct diag_l0 *dl0,
void *dl0_handle)
{
	int rv;
	struct diag_ttystate	*dt;
	struct diag_l0_device *dl0d;

	char *endptr;
	int iInterface;

	const char *tty_template ="/dev/obdII%d";

	if (rv=diag_calloc(&dl0d, 1))		//free'd in diag_tty_close
		return diag_iseterr(rv);

	dl0d->fd = -1;
	dl0d->dl0_handle = dl0_handle;
	dl0d->dl0 = dl0;

	if ((rv=diag_calloc(&dl0d->ttystate, 1))) {
		free(dl0d);
		return diag_iseterr(rv);
	}

	*ppdl0d = dl0d;

	/*
	 * XXX this should probably be removed... "historical compatibility" with what ?? Who ?
	
	 * For historical compatibility, if the subinterface decodes cleanly
	 * as an integer we will write it into a string to get the name.
	 * You can create a symlink to "/dev/obdII<NUMBER>" if you want to,
	 * or just set the subinterface to a valid device name.
	 */

	iInterface = strtol(subinterface, &endptr, 10);
	if (*endptr == 0) {
		/* Entire string is a valid number: Provide compatibility.  */
		size_t n = strlen(tty_template) + 32;
		printf("Warning : using deprecated /dev/obdII<x> subinterface definition.\n");
		printf("Support for this will be discontinued shortly...\n");

		if ((rv=diag_malloc(&dl0d->name, n))) {
			(void)diag_tty_close(ppdl0d);;
			return diag_iseterr(rv);
		}
		(void)snprintf(dl0d->name, n, tty_template, iInterface);
	} else {
		size_t n = strlen(subinterface) + 1;

		if ((rv=diag_malloc(&dl0d->name, n))) {
			(void)diag_tty_close(ppdl0d);;
			return diag_iseterr(rv);
		}
		strncpy(dl0d->name, subinterface, n);
	}

	errno = 0;
#if defined(__linux__) && (TRY_POSIX == 0)
	dl0d->fd = open(dl0d->name, O_RDWR);
#else
	/*
	+* For POSIX behavior:  Open serial device non-blocking to avoid
	+* modem control issues, then set to blocking.
	 */
	/* CODE BLOCK */
	{
		int fl;
		dl0d->fd = open(dl0d->name, O_RDWR | O_NONBLOCK);

		if (dl0d->fd > 0) {
			errno = 0;
			if ((fl = fcntl(dl0d->fd, F_GETFL, 0)) < 0) {
				fprintf(stderr,
					FLFMT "Can't get flags with fcntl on fd %d: %s.\n",
					FL, dl0d->fd, strerror(errno));
				(void)diag_tty_close(ppdl0d);;
				return diag_iseterr(DIAG_ERR_GENERAL);
			}
			fl &= ~O_NONBLOCK;
			errno = 0;
			if (fcntl(dl0d->fd, F_SETFL, fl) < 0) {
				fprintf(stderr,
					FLFMT "Can't set flags with fcntl on fd %d: %s.\n",
					FL, dl0d->fd, strerror(errno));
				(void)diag_tty_close(ppdl0d);
				return diag_iseterr(DIAG_ERR_GENERAL);
			}
		}
	}
#endif

	if (dl0d->fd >= 0) {
		if (diag_l0_debug & DIAG_DEBUG_OPEN)
			fprintf(stderr, FLFMT "Device %s opened, fd %d\n", 
				FL, dl0d->name, dl0d->fd);
	} else {
		fprintf(stderr,
			FLFMT "Open of device interface \"%s\" failed: %s\n", 
			FL, dl0d->name, strerror(errno));
		fprintf(stderr, FLFMT
			"(Make sure the device specified corresponds to the\n", FL );
		fprintf(stderr,
			FLFMT "serial device your interface is connected to.\n", FL);

		(void)diag_tty_close(ppdl0d);
		return diag_iseterr(DIAG_ERR_GENERAL);
	}
	dt = dl0d->ttystate;

	/*
	 * Save original settings so can reset
	 * device on close - we also set "current" settings to
	 * those we just read aswell
	 */

#if defined(__linux__) && (TRY_POSIX == 0)
	if (ioctl(dl0d->fd, TIOCGSERIAL, &dt->dt_osinfo) < 0)
	{
		fprintf(stderr,
			FLFMT "open: Ioctl TIOCGSERIAL failed %d\n", FL, errno);
		(void)diag_tty_close(ppdl0d);
		return diag_iseterr(DIAG_ERR_GENERAL);
	}
	dt->dt_sinfo = dt->dt_osinfo;
#endif

	if (ioctl(dl0d->fd, TIOCMGET, &dt->dt_modemflags) < 0)
	{
		fprintf(stderr,
			FLFMT "open: Ioctl TIOCMGET failed: %s\n", FL, strerror(errno));
		(void)diag_tty_close(ppdl0d);
		return diag_iseterr(DIAG_ERR_GENERAL);
	}

	if (tcgetattr(dl0d->fd, &dt->dt_otinfo) < 0)
	{
		fprintf(stderr, FLFMT "open: tcgetattr failed %s\n",
			FL, strerror(errno));
		(void)diag_tty_close(ppdl0d);
		return diag_iseterr(DIAG_ERR_GENERAL);
	}
	dt->dt_tinfo = dt->dt_otinfo;

	return 0;
}
Exemple #22
0
struct diag_process *diag_run_program(struct diag_command *command)
{
	assert(command);

	char *out = NULL;
	if (!command->out) {
		out = diag_malloc(PATH_LENGTH);
	}
	char *err = NULL;
	if (!command->err) {
		err = diag_malloc(PATH_LENGTH);
	}
	pid_t pid = fork();
	if (pid < 0) {
		perror(command->file);
		diag_free(out);
		diag_free(err);
		return NULL;
	}
	if (pid == 0) {
		pid = getpid();
		if (!command->out) {
			build_path(command->dir, pid, "out", out);
			command->out = out;
		}
		if (!command->err) {
			build_path(command->dir, pid, "err", err);
			command->err = err;
		}
		if (command->in) { /* redirect stdin only when specified */
			if (!freopen(command->in, "rb", stdin)) {
				perror(command->in);
				_Exit(EXIT_FAILURE);
			}
		}
		/* Both stdout and stderr should be always redirected */
		if (!freopen(command->out, "wb", stdout)) {
			perror(command->out);
			_Exit(EXIT_FAILURE);
		}
		if (!freopen(command->err, "wb", stderr)) {
			perror(command->err);
 			_Exit(EXIT_FAILURE);
		}
		if (execvp(command->file, command->argv) == -1) {
			perror(command->file);
			_Exit(EXIT_FAILURE);
		}
	}
	if (!command->out) {
		build_path(command->dir, pid, "out", out);
		command->out = out;
	}
	if (!command->err) {
		build_path(command->dir, pid, "err", err);
		command->err = err;
	}
	struct diag_process *p = diag_malloc(sizeof(*p));
	p->pid = (intptr_t)pid;
	p->status = 0;
	return p;
}
Exemple #23
0
/*
 * References:
 *
 * How to spawn console processes with redirected standard handles
 * http://support.microsoft.com/kb/190351
 */
struct diag_process *diag_run_program(struct diag_command *command)
{
	assert(command);

	if (!command->out) {
		command->out = diag_malloc(PATH_LENGTH);
		build_path(command->dir, local_pid, "out", command->out);
	}
	if (!command->err) {
		command->err = diag_malloc(PATH_LENGTH);
		build_path(command->dir, local_pid, "err", command->err);
	}
	local_pid++;

	SECURITY_ATTRIBUTES sa;
	sa.nLength = sizeof(sa);
	sa.bInheritHandle = TRUE;
	sa.lpSecurityDescriptor = NULL;

	HANDLE ih = NULL;
	if (command->in) {
		ih = CreateFile(command->in,
				GENERIC_READ,
				FILE_SHARE_READ,
				&sa,
				OPEN_EXISTING,
				0,
				NULL);
		if (ih == INVALID_HANDLE_VALUE) {
			diag_error("failed to open file: %s: 0x%x",
				   command->in,
				   (unsigned int)GetLastError());
			return NULL;
		}
	}

	HANDLE oh = CreateFile(command->out,
			       GENERIC_WRITE,
			       FILE_SHARE_WRITE|FILE_SHARE_DELETE,
			       &sa,
			       CREATE_NEW,
			       FILE_ATTRIBUTE_NORMAL,
			       NULL);
	if (oh == INVALID_HANDLE_VALUE) {
		diag_error("failed to open file: %s: 0x%x",
			   command->out,
			   (unsigned int)GetLastError());
		return NULL;
	}

	HANDLE eh = CreateFile(command->err,
			       GENERIC_WRITE,
			       FILE_SHARE_WRITE|FILE_SHARE_DELETE,
			       &sa,
			       CREATE_NEW,
			       FILE_ATTRIBUTE_NORMAL,
			       NULL);
	if (eh == INVALID_HANDLE_VALUE) {
		diag_error("failed to open file: %s: 0x%x",
			   command->err,
			   (unsigned int)GetLastError());
		return NULL;
	}

	STARTUPINFO si;
	GetStartupInfo(&si);
	si.dwFlags |= STARTF_USESTDHANDLES;
	si.hStdInput = ih;
	si.hStdOutput = oh;
	si.hStdError = eh;

	PROCESS_INFORMATION pi;
	ZeroMemory(&pi, sizeof(pi));

	char *line = diag_get_command_line(command->argv);

	BOOL b = CreateProcess(NULL,
			       line,
			       NULL,
			       NULL,
			       TRUE,
			       0,
			       NULL,
			       NULL,
			       &si,
			       &pi);
	if (!b) {
		diag_error("could not create process: %s: 0x%x",
			   line,
			   (unsigned int)GetLastError());
		// should follow GetLastError()
		diag_free(line);
		if (ih) CloseHandle(ih);
		CloseHandle(oh);
		CloseHandle(eh);
		return NULL;
	}

	/* We do not want WaitForInputIdle() because there is no interaction
	   between the parent process and this child */

	diag_free(line);
	if (ih) CloseHandle(ih);
	CloseHandle(oh);
	CloseHandle(eh);

	CloseHandle(pi.hThread);

	struct diag_process *p = diag_malloc(sizeof(*p));
	p->pid = (intptr_t)pi.hProcess;
	return p;
}
Exemple #24
0
int diag_tty_open(struct diag_l0_device *dl0d,
	const char *portname)
{
	int rv;
	struct unix_tty_int *uti;
#if defined(_POSIX_TIMERS) && (SEL_TIMEOUT==S_POSIX || SEL_TIMEOUT==S_AUTO)
	struct sigevent to_sigev;
	struct sigaction sa;
	clockid_t timeout_clkid;
#endif

	assert(dl0d != NULL);
	if (dl0d->tty_int) return diag_iseterr(DIAG_ERR_GENERAL);

	if ((rv=diag_calloc(&uti,1))) {
		return diag_iseterr(rv);
	}

#if defined(_POSIX_TIMERS) && (SEL_TIMEOUT==S_POSIX || SEL_TIMEOUT==S_AUTO)
	//set-up the r/w timeouts clock - here we just create it; it will be armed when needed
	#ifdef _POSIX_MONOTONIC_CLOCK
	timeout_clkid = CLOCK_MONOTONIC;
	#else
	timeout_clkid = CLOCK_REALTIME;
	#endif // _POSIX_MONOTONIC_CLOCK
	sa.sa_flags = SA_SIGINFO;
	sa.sa_sigaction = diag_tty_rw_timeout_handler;
	sigemptyset(&sa.sa_mask);
	if(sigaction(SIGUSR1, &sa, NULL) != 0) {
		fprintf(stderr, FLFMT "Could not set-up action for timeout timer... report this\n", FL);
		free(uti);
		return diag_iseterr(DIAG_ERR_GENERAL);
	}

	to_sigev.sigev_notify = SIGEV_SIGNAL;
	to_sigev.sigev_signo = SIGUSR1;
	to_sigev.sigev_value.sival_ptr = uti;
	if(timer_create(timeout_clkid, &to_sigev, &uti->timerid) != 0) {
		fprintf(stderr, FLFMT "Could not create timeout timer... report this\n", FL);
		free(uti);
		return diag_iseterr(DIAG_ERR_GENERAL);
	}
#endif

	uti->fd = DL0D_INVALIDHANDLE;

	size_t n = strlen(portname) + 1;

	if ((rv=diag_malloc(&uti->name, n))) {
		free(uti);
		return diag_iseterr(rv);
	}
	strncpy(uti->name, portname, n);
	dl0d->tty_int = uti;
	//past this point, we can call diag_tty_close(dl0d) to abort in case of errors

	errno = 0;

#if defined(O_NONBLOCK) && (SEL_TTYOPEN==S_ALT1 || SEL_TTYOPEN==S_AUTO)
	/*
	 * For POSIX behavior:  Open serial device non-blocking to avoid
	 * modem control issues, then set to blocking.
	 */
	{
		int fl;
		uti->fd = open(uti->name, O_RDWR | O_NONBLOCK);

		if (uti->fd > 0) {
			errno = 0;
			if ((fl = fcntl(uti->fd, F_GETFL, 0)) < 0) {
				fprintf(stderr,
					FLFMT "Can't get flags with fcntl on fd %d: %s.\n",
					FL, uti->fd, strerror(errno));
				diag_tty_close(dl0d);
				return diag_iseterr(DIAG_ERR_GENERAL);
			}
			fl &= ~O_NONBLOCK;
			errno = 0;
			if (fcntl(uti->fd, F_SETFL, fl) < 0) {
				fprintf(stderr,
					FLFMT "Can't set flags with fcntl on fd %d: %s.\n",
					FL, uti->fd, strerror(errno));
				diag_tty_close(dl0d);
				return diag_iseterr(DIAG_ERR_GENERAL);
			}
		}
	}
#else
	#ifndef O_NONBLOCK
	#warning No O_NONBLOCK on your system ?! Please report this
	#endif
	uti->fd = open(uti->name, O_RDWR);

#endif // O_NONBLOCK

	if (uti->fd >= 0) {
		if (diag_l0_debug & DIAG_DEBUG_OPEN)
			fprintf(stderr, FLFMT "Device %s opened, fd %d\n",
				FL, uti->name, uti->fd);
	} else {
		fprintf(stderr,
			FLFMT "Could not open \"%s\" : %s. "
			"Make sure the device specified corresponds to the "
			"serial device your interface is connected to.\n",
			FL, uti->name, strerror(errno));
		diag_tty_close(dl0d);
		return diag_iseterr(DIAG_ERR_GENERAL);
	}

	/*
	 * Save original settings so can reset
	 * device on close - we also set "current" settings to
	 * those we just read aswell
	 */

#if defined(__linux__)
	if (ioctl(uti->fd, TIOCGSERIAL, &uti->ss_orig) < 0) {
		fprintf(stderr,
			FLFMT "open: TIOCGSERIAL failed: %s\n", FL, strerror(errno));
		uti->tioc_works = 0;
	} else {
		uti->ss_cur = uti->ss_orig;
		uti->tioc_works = 1;
	}
#endif

	if (ioctl(uti->fd, TIOCMGET, &uti->modemflags) < 0) {
		fprintf(stderr,
			FLFMT "open: TIOCMGET failed: %s\n", FL, strerror(errno));
		diag_tty_close(dl0d);
		return diag_iseterr(DIAG_ERR_GENERAL);
	}

#ifdef 	USE_TERMIOS2
	rv = ioctl(uti->fd, TCGETS, &uti->st_orig);
#else
	rv = tcgetattr(uti->fd, &uti->st_orig);
#endif
	if (rv != 0) {
		fprintf(stderr, FLFMT "open: could not get orig settings: %s\n",
			FL, strerror(errno));
		diag_tty_close(dl0d);
		return diag_iseterr(DIAG_ERR_GENERAL);
	}

	//and set common flags
	uti->st_cur = uti->st_orig;

	/* "stty raw"-like iflag settings: */
	/* Clear a bunch of un-needed flags */
	uti->st_cur.c_iflag &= ~ (IGNBRK | BRKINT | IGNPAR | PARMRK
		| INPCK | ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXOFF
		| IXANY | IMAXBEL);
#ifdef __linux__
	uti->st_cur.c_iflag  &= ~(IUCLC);   /* non-posix; disable ucase/lcase conversion */
#endif

	uti->st_cur.c_oflag &= ~(OPOST);	//disable impl-defined output processing

	/* Disable canonical input and keyboard signals.
	+* There is no need to also clear the many ECHOXX flags, both because
	+* many systems have non-POSIX flags and also because the ECHO
	+* flags don't don't matter when ICANON is clear.
	 */
	/* CJH: However, taking 'man termios' at its word, the ECHO flag is
	 *not* affected by ICANON, and it seems we do need to clear it  */
	uti->st_cur.c_lflag &= ~( ICANON | ISIG | ECHO | IEXTEN);

	uti->st_cur.c_cflag &= ~( CRTSCTS );	//non-posix; disables hardware flow ctl
	uti->st_cur.c_cflag |= (CLOCAL | CREAD);	//ignore modem control lines; enable read

	uti->st_cur.c_cc[VMIN] = 1;		//Minimum # of bytes before read() returns (default: 0!!!)

	//and update termios with new flags.
#ifdef USE_TERMIOS2
	rv = ioctl(uti->fd, TCSETS, &uti->st_cur);
	rv |= ioctl(uti->fd, TCGETS2, &uti->st2_cur);
#else
	rv=tcsetattr(uti->fd, TCSAFLUSH, &uti->st_cur);
#endif
	if (rv != 0) {
		fprintf(stderr, FLFMT "open: can't set input flags: %s.\n",
				FL, strerror(errno));
		diag_tty_close(dl0d);
		return diag_iseterr(DIAG_ERR_GENERAL);
	}

	//arbitrarily set the single byte write timeout to 1ms
	uti->byte_write_timeout_us = 1000ul;

	return 0;
}
Exemple #25
0
//rc_file : returns CMD_OK or CMD_EXIT only.
static int
rc_file(void)
{
	int rv;
	//this loads either a $home/.<progname>.rc or ./<progname>.ini (in order of preference)
	//to load general settings.

	/*
	 * "." files don't play that well on some systems.
	 * USE_RCFILE is not defined by default.
	 */

#ifdef USE_RCFILE
	char *rchomeinit;
	char *homedir;
	homedir = getenv("HOME");
	FILE *newrcfile;

	if (homedir) {
		/* we add "/." and "rc" ... 4 characters */
		if (diag_malloc(&rchomeinit, strlen(homedir) + strlen(progname) + 5)) {
			diag_iseterr(DIAG_ERR_NOMEM);
			return CMD_OK;
		}
		strcpy(rchomeinit, homedir);
		strcat(rchomeinit, "/.");
		strcat(rchomeinit, projname);
		strcat(rchomeinit, "rc");

		rv=command_file(rchomeinit);
		if (rv == CMD_FAILED) {
			fprintf(stderr, FLFMT "Could not load rc file %s; ", FL, rchomeinit);
			newrcfile=fopen(rchomeinit,"a");
			if (newrcfile) {
				//create the file if it didn't exist
				fprintf(newrcfile, "\n#empty rcfile auto created by %s\n",progname);
				fclose(newrcfile);
				fprintf(stderr, "empty file created.\n");
				free(rchomeinit);
				return CMD_OK;
			} else {
				//could not create empty rcfile
				fprintf(stderr, "could not create empty file %s.", rchomeinit);
				free(rchomeinit);
				return CMD_OK;
			}
		} else {
			//command_file was at least partly successful (rc file exists)
			printf("%s: Settings loaded from %s\n",progname,rchomeinit);
			free(rchomeinit);
			return CMD_OK;
		}

	}	//if (homedir)
#endif


#ifdef USE_INIFILE
	char * inihomeinit;
	if (diag_malloc(&inihomeinit, strlen(progname) + strlen(".ini") + 1)) {
		diag_iseterr(DIAG_ERR_NOMEM);
		return CMD_OK;
	}

	strcpy(inihomeinit, progname);
	strcat(inihomeinit, ".ini");

	rv=command_file(inihomeinit);
	if (rv == CMD_FAILED) {
		fprintf(stderr, FLFMT "Problem with %s, no configuration loaded\n", FL, inihomeinit);
		free(inihomeinit);
		return CMD_OK;
	}
	printf("%s: Settings loaded from %s\n", progname, inihomeinit);
	free(inihomeinit);
#endif
	return rv;	//could be CMD_EXIT

}
Exemple #26
0
//diag_tty_open : open specified port for L0
int diag_tty_open(struct diag_l0_device *dl0d,
                  const char *portname)
{
    int rv;
    struct tty_int *wti;
    size_t n = strlen(portname) + 1;
    COMMTIMEOUTS devtimeouts;

    if (!dl0d) return diag_iseterr(DIAG_ERR_GENERAL);

    if ((rv=diag_calloc(&wti,1))) {
        return diag_iseterr(rv);
    }

    dl0d->tty_int = wti;
    wti->fd = INVALID_HANDLE_VALUE;

    //allocate space for portname name
    if ((rv=diag_malloc(&wti->name, n))) {
        free(dl0d->tty_int);
        return diag_iseterr(rv);
    }
    //Now, in case of errors we can call diag_tty_close() on the dl0d since its members are alloc'ed
    strncpy(wti->name, portname, n);

    wti->fd=CreateFile(portname, GENERIC_READ | GENERIC_WRITE, 0, NULL,
                       OPEN_EXISTING,
                       FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING | FILE_FLAG_WRITE_THROUGH,
                       NULL);
    //File hande is created as non-overlapped. This may change eventually.

    if (wti->fd != INVALID_HANDLE_VALUE) {
        if (diag_l0_debug & DIAG_DEBUG_OPEN)
            fprintf(stderr, FLFMT "Device %s opened, fd %p\n",
                    FL, wti->name, wti->fd);
    } else {
        fprintf(stderr,
                FLFMT "Open of device interface \"%s\" failed: %s\n",
                FL, wti->name, diag_os_geterr(0));
        fprintf(stderr, FLFMT
                "(Make sure the device specified corresponds to the\n", FL );
        fprintf(stderr,
                FLFMT "serial device your interface is connected to.\n", FL);

        diag_tty_close(dl0d);
        return diag_iseterr(DIAG_ERR_GENERAL);
    }

    //purge & abort everything.
    PurgeComm(wti->fd,PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);

    //as opposed to the unix diag_tty.c ; this one doesn't save previous commstate. The next program to use the COM port
    //will need to deal with it...

    //We will load the DCB with the current comm state. This way we only need to call GetCommState once during a session
    //and the DCB should contain coherent initial values
    if (! GetCommState(wti->fd, &wti->dcb)) {
        fprintf(stderr, FLFMT "Could not get comm state: %s\n",FL, diag_os_geterr(0));
        diag_tty_close(dl0d);
        return diag_iseterr(DIAG_ERR_GENERAL);
    }

    //Finally set COMMTIMEOUTS to reasonable values (all in ms) ?
    devtimeouts.ReadIntervalTimeout=30;	//i.e. more than 30ms between received bytes
    devtimeouts.ReadTotalTimeoutMultiplier=5;	//timeout per requested byte
    devtimeouts.ReadTotalTimeoutConstant=20;	// (constant + multiplier*numbytes) = total timeout on read(buf, numbytes)
    devtimeouts.WriteTotalTimeoutMultiplier=0;	//probably useless as all flow control will be disabled ??
    devtimeouts.WriteTotalTimeoutConstant=0;
    if (! SetCommTimeouts(wti->fd,&devtimeouts)) {
        fprintf(stderr, FLFMT "Could not set comm timeouts: %s\n",FL, diag_os_geterr(0));
        diag_tty_close(dl0d);
        return diag_iseterr(DIAG_ERR_GENERAL);
    }

    return 0;
} //diag_tty_open