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; }
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; }
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; }
/* * 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; }
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; }
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); }
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; }
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; }
/* * 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; }
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; }
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; }
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; }
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; }
/* 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)); }
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; }
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; }
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; }
/* 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); }
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; } }
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; }
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; }
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; }
/* * 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; }
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; }
//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 }
//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