Beispiel #1
0
FCITX_EXPORT_API
UT_array* fcitx_utils_split_string(const char* str, char delm)
{
    UT_array* array;
    char delm_s[2] = {delm, '\0'};
    utarray_new(array, fcitx_str_icd);
    return fcitx_utils_append_split_string(array, str, delm_s);
}
Beispiel #2
0
/**
 * 加载快速输入词典
 * @param void
 * @return void
 * @note 快速输入是在;的行为定义为2,并且输入;以后才可以使用的。
 * 加载快速输入词典.如:输入“zg”就直接出现“中华人民共和国”等等。
 * 文件中每一行数据的定义为:<字符组合> <短语>
 * 如:“zg 中华人民共和国”
 */
void LoadQuickPhrase(QuickPhraseState * qpstate)
{
    FILE *fp;
    char *buf = NULL;
    size_t len = 0;
    char *buf1 = NULL;

    QUICK_PHRASE tempQuickPhrase;

    qpstate->uQuickPhraseCount = 0;

    fp =  FcitxXDGGetFileWithPrefix("data", "QuickPhrase.mb", "r", NULL);
    if (!fp)
        return;

    // 这儿的处理比较简单。因为是单索引对单值。
    // 应该注意的是,它在内存中是以单链表保存的。
    utarray_new(qpstate->quickPhrases, &qp_icd);
    while (getline(&buf, &len, fp) != -1) {
        if (buf1)
            free(buf1);
        buf1 = fcitx_utils_trim(buf);
        char *p = buf1;

        while (*p && !isspace(*p))
            p ++;

        if (*p == '\0')
            continue;

        while (isspace(*p)) {
            *p = '\0';
            p ++;
        }

        if (strlen(buf1) >= QUICKPHRASE_CODE_LEN)
            continue;

        if (strlen(p) >= QUICKPHRASE_PHRASE_LEN * UTF8_MAX_LENGTH)
            continue;

        strcpy(tempQuickPhrase.strCode, buf1);
        strcpy(tempQuickPhrase.strPhrase, p);

        utarray_push_back(qpstate->quickPhrases, &tempQuickPhrase);
    }

    if (buf)
        free(buf);
    if (buf1)
        free(buf1);

    if (qpstate->quickPhrases) {
        utarray_sort(qpstate->quickPhrases, PhraseCmp);
    }

    fclose(fp);
}
Beispiel #3
0
int layout(char *buf, size_t sz, char **obuf, size_t *osz) {
  UT_array *namev,*hashv, *xv, *yv;
  int i, pos, rc=-1, x, y;
  unsigned char *s;
  unsigned h;

  utarray_new(namev, &ut_str_icd);
  utarray_new(hashv, &ut_int_icd);
  utarray_new(xv, &ut_int_icd);
  utarray_new(yv, &ut_int_icd);

  tpl_node *tn = tpl_map("A(s)", &s);
  if (tpl_load(tn, TPL_MEM, buf, sz)) goto done;
  while (tpl_unpack(tn,1) > 0) {
    h = get_hash(s);
    utarray_push_back(namev, &s);
    utarray_push_back(hashv, &h);
    free(s);
  }
  tpl_free(tn);

  for(pos=0; pos < utarray_len(namev); pos++) {
    place(pos,hashv,xv,yv);
  }

  /* every item has a place. prepare output. */
  tn = tpl_map("A(sii)", &s, &x, &y);
  for(i=0; i < utarray_len(namev); i++) {
    s = *(unsigned char**)utarray_eltptr(namev,i);
    x =            *(int*)utarray_eltptr(xv,i);
    y =            *(int*)utarray_eltptr(yv,i);
    tpl_pack(tn,1);
  }
  tpl_dump(tn, TPL_MEM, obuf, osz);
  tpl_free(tn);

  rc = 0;

 done:
  utarray_free(namev);
  utarray_free(hashv);
  utarray_free(xv);
  utarray_free(yv);
  return rc;
}
static inline void MPIR_T_cvar_env_init(void)
{
    static const UT_icd cvar_table_entry_icd =
                    {sizeof(cvar_table_entry_t), NULL, NULL, NULL};

    utarray_new(cvar_table, &cvar_table_entry_icd);
    cvar_hash = NULL;
    MPIR_T_cvar_init();
}
Beispiel #5
0
/* Constructs a new CFG.
   Must be called once for every function.  */
static struct control_flow_graph*
make_cfg (void)
{
  struct control_flow_graph* cfg = (struct control_flow_graph*)
      malloc (sizeof (struct control_flow_graph));
  memset (cfg, 0, sizeof (struct control_flow_graph));
  utarray_new (cfg->edge_list, &edge_icd_dtor);
  return cfg;
}
Beispiel #6
0
/**
 * Enable book help history.
 */
void book_add_help_history(const char *name)
{
    if (!book_help_history_enabled) {
        book_help_history_enabled = 1;
        utarray_new(book_help_history, &ut_str_icd);
    }

    utarray_push_back(book_help_history, &name);
}
tnn_error tnn_module_init_sum(tnn_module *m, tnn_state *input, tnn_state *output, tnn_param *io){
  tnn_error ret;
  tnn_module_sum *c;
  size_t i;
  UT_icd sarray_icd = {sizeof(tnn_state*), NULL, NULL, NULL};
  tnn_state *t;

  //Check the sizes and validness
  if(input->size % output->size != 0){
    return TNN_ERROR_STATE_INCOMP;
  }
  if(input->valid != true){
    return TNN_ERROR_STATE_INVALID;
  }

  //Defined type
  m->t = TNN_MODULE_TYPE_SUM;

  //Constant parameter is a new tnn_module_sum
  c = (tnn_module_sum *)malloc(sizeof(tnn_module_sum));
  m->c = c;

  //Allocate sub-states
  utarray_new(c->sarray, &sarray_icd);
  if(c->sarray == NULL){
    TNN_ERROR_ALLOC;
  }
  for(i = 0; i < input->size; i = i + output->size){
    //Alloc and initialize the state
    t = (tnn_state *)malloc(sizeof(tnn_state));
    if(t == NULL){
      return TNN_ERROR_ALLOC;
    }
    t->size = output->size;

    //Get the substate and store it
    TNN_MACRO_ERRORTEST(tnn_param_state_sub(io, input, t, i), ret);
    utarray_push_back(c->sarray, &t);
  }

  //Init the state
  tnn_state_init(&m->w, 0L);

  //Link the inputs and outputs
  m->input = input;
  m->output = output;

  //Store the functions
  m->bprop = &tnn_module_bprop_sum;
  m->fprop = &tnn_module_fprop_sum;
  m->randomize = &tnn_module_randomize_sum;
  m->destroy = &tnn_module_destroy_sum;
  m->clone = &tnn_module_clone_sum;
  m->debug = &tnn_module_debug_sum;
  
  return TNN_ERROR_SUCCESS;
}
static inline void MPIR_T_cat_env_init(void)
{
    static const UT_icd cat_table_entry_icd =
                    {sizeof(cat_table_entry_t), NULL, NULL, NULL};

    utarray_new(cat_table, &cat_table_entry_icd);
    cat_hash = NULL;
    cat_stamp = 0;
}
Beispiel #9
0
UT_array *qgram_tokenize_to_utarray(const char *str, const qgram_t *qtype) {

	int i;
	int init_len = strlen(str) + 1;
	char *tmp;

	//Mem corruption will occur otherwise...
	if(qtype->qgram_len < 1 || qtype->qgram_len > 3)
		return NULL;

	if(qtype->extended) {

		tmp = calloc((init_len + qtype->qgram_len), sizeof(char));

		for(i = 0; i < (qtype->qgram_len - 1); i++)
			strcat(tmp, QGRAM_SP);

		strcat(tmp, str);

		for(i = 0; i < (qtype->qgram_len - 1); i++)
			strcat(tmp, QGRAM_EP);

	} else {

		tmp = calloc(init_len, sizeof(char));
		strcpy(tmp, str);

	}

	UT_array *strs;
	utarray_new(strs, &ut_str_icd);

	int cp = 0;
	int len = strlen(tmp) - qtype->qgram_len + 1;
	char *t_ptr, *el;

	while(cp < len) {

		t_ptr = (char *)&tmp[cp];
		//Allocate all chars - plus terminator...
		el = calloc((qtype->qgram_len + 1), sizeof(char));
		//Copy bytes safely - strncpy should append the \0
		strncpy(el, t_ptr, (sizeof(char) * qtype->qgram_len));

		utarray_push_back(strs, &el);

		free(el);

		cp++;
	}

	free(tmp);

	return (strs);

}
Beispiel #10
0
static Token list_new(Cmdline *cmdline)
{
  Token token = {0};
  List *l = malloc(sizeof(List));
  ref_push(&cmdline->refs, l, VAR_LIST);
  token.var.v_type = VAR_LIST;
  utarray_new(l->items, &list_icd);
  token.var.vval.v_list = l;
  return token;
}
Beispiel #11
0
void dicom_import(const char *dirpath)
{
    DIR *dir;
    struct dirent *dirent;
    dicom_t dicom, *dptr;
    static UT_icd dicom_icd = {sizeof(dicom_t), NULL, NULL, NULL};
    UT_array *all_files;
    int w, h, d;    // Dimensions of the full data cube.
    int i;
    uint16_t *data;
    uvec4b_t *cube;

    // First we parse all the dicom images into a sorted array.
    // XXX: how to propery iter a directory?
    utarray_new(all_files, &dicom_icd);
    dir = opendir(dirpath);
    while ((dirent = readdir(dir))) {
        if (dirent->d_name[0] == '.') continue;
        asprintf(&dicom.path, "%s/%s", dirpath, dirent->d_name);
        dicom_load(dicom.path, &dicom, NULL, 0);
        CHECK(dicom.rows && dicom.columns);
        utarray_push_back(all_files, &dicom);
    }
    closedir(dir);
    utarray_sort(all_files, dicom_sort);

    // Read all the file data one by one into the data cube.
    w = dicom.columns;
    h = dicom.rows;
    d = utarray_len(all_files);
    data = calloc(w * h * d, 2);

    dptr = NULL;
    while( (dptr = (dicom_t*)utarray_next(all_files, dptr))) {
        i = utarray_eltidx(all_files, dptr);
        dicom_load(dptr->path, &dicom,
                   (char*)&data[w * h * i], w * h * 2);
        free(dptr->path);
    }
    utarray_free(all_files);

    // Generate 4 * 8bit RGBA values.
    // XXX: we should maybe support voxel data in 2 bytes monochrome.
    cube = malloc(w * h * d * sizeof(*cube));
    for (i = 0; i < w * h * d; i++) {
        cube[i] = uvec4b(255, 255, 255, clamp(data[i], 0, 255));
    }
    free(data);

    // This could belong to the caller function.
    mesh_blit(goxel()->image->active_layer->mesh, cube,
              -w / 2, -h / 2, -d / 2, w, h, d);

    free(cube);
}
tnn_error tnn_module_clone_sum(tnn_module *m1, tnn_module *m2, tnn_param *p, tnn_pstable *t){
  tnn_error ret;
  tnn_module_sum *c;
  tnn_state *s1, *s2, **s;
  UT_icd sarray_icd = {sizeof(tnn_state*), NULL, NULL, NULL};
  size_t i;

  //Routine check
  if(m1->t != TNN_MODULE_TYPE_SUM){
    return TNN_ERROR_MODULE_MISTYPE;
  }

  //Retrieve input and output
  TNN_MACRO_ERRORTEST(tnn_pstable_find(t, m1->input, &m2->input), ret);
  TNN_MACRO_ERRORTEST(tnn_pstable_find(t, m1->output, &m2->output), ret);
  if(m1->input->size != m2->input->size || m1->output->size != m2->output->size){
    return TNN_ERROR_STATE_INCOMP;
  }

  //Defined type
  m2->t = TNN_MODULE_TYPE_SUM;

  //Constant paramter is a new tnn_module_sum
  c = (void*)malloc(sizeof(tnn_module_sum));
  m2->c = c;

  //Allocate the state
  tnn_state_init(&m2->w, 0L);
  
  //Find the sub states
  utarray_new(c->sarray, &sarray_icd);
  for(i = 0; i < utarray_len(((tnn_module_sum*)m1->c)->sarray); i = i + 1){
    s2 = (tnn_state *) malloc(sizeof(tnn_state));
    if(s2 == NULL){
      return TNN_ERROR_ALLOC;
    }
    s = (tnn_state **)utarray_eltptr(((tnn_module_sum*)m1->c)->sarray, i);
    s1 = *s;
    TNN_MACRO_ERRORTEST(tnn_pstable_find(t, s1, &s2), ret);
    if (s1->size != s2->size){
      return TNN_ERROR_STATE_INCOMP;
    }
    utarray_push_back(c->sarray, &s2);
  }

  //Store the functions
  m2->bprop = &tnn_module_bprop_sum;
  m2->fprop = &tnn_module_fprop_sum;
  m2->randomize = &tnn_module_randomize_sum;
  m2->destroy = &tnn_module_destroy_sum;
  m2->debug = &tnn_module_debug_sum;
  m2->clone = &tnn_module_clone_sum;

  return TNN_ERROR_SUCCESS;
}
Beispiel #13
0
/*-----------------------------------------------------------------------------
*   Init functions
*----------------------------------------------------------------------------*/
DEFINE_init_module()
{
	input_buf = str_new(STR_SIZE);
	p = str_data(input_buf);

	input_stack	 = OBJ_NEW(List);
	input_stack->free_data = m_free_compat;

	init_sym();
	utarray_new(scan_state, &ut_scan_state_icd);
}
Beispiel #14
0
void compl_new(int size, int dynamic)
{
  log_msg("COMPL", "compl_new");
  compl_destroy(cur_cx);
  cur_cx->cmpl = malloc(sizeof(fn_compl));
  cur_cx->cmpl->rows    = malloc(size*sizeof(compl_item));
  utarray_new(cur_cx->cmpl->matches, &icd);
  cur_cx->cmpl->rowcount = size;
  cur_cx->cmpl->matchcount = 0;
  cur_cx->cmpl->comp_type = dynamic;
}
Beispiel #15
0
/*
 * Init Yap udi interface
 */
void
Yap_udi_init(void)
{
  UdiControlBlocks = NULL;

  /*init indexing structures array*/
  utarray_new(indexing_structures, &udicb_icd);

  Yap_InitCPred("$udi_init", 1, p_new_udi, 0);
  /* TODO: decide if udi.yap should be loaded automaticaly in init.yap */
}
static inline void MPIR_T_pvar_env_init(void)
{
    int i;
    static const UT_icd pvar_table_entry_icd =
                    {sizeof(pvar_table_entry_t), NULL, NULL, NULL};

    utarray_new(pvar_table, &pvar_table_entry_icd);
    for (i = 0; i < MPIR_T_PVAR_CLASS_NUMBER; i++) {
        pvar_hashs[i] = NULL;
    }
}
Beispiel #17
0
void zway_location_add_device(zway_location_ptr location, zway_device_ptr device) {
    if (!device) {
        return;
    }
    
    if (!location->devices) {
        utarray_new(location->devices, &zway_device_ut_icd);
    }
    
    utarray_push_back(location->devices, device);
}
Beispiel #18
0
// Find all the harddisk address corresponding to target file
// 
// \param img_path          path of target image
// \param file_path         the target filename
// 
// Return NULL if error, otherwise a UT_array of (start, end) tuple will returned, where start and end are the harddisk byte addrsesses
UT_array* tsk_find_haddr_by_filename(const char* img_path, const char* file_path)
{
    TSK_IMG_TYPE_ENUM img_type ;
    TSK_IMG_INFO *img;
    TSK_VS_INFO *vs;
 
    find_file_data data;
    UT_array* ret = NULL;

    img_type = tsk_img_type_toid(QCOW_IMG_TYPE);

    //XXX([email protected]):need error handling.
    img = tsk_img_open_sing(img_path, img_type, 0);
    if(img == NULL)
    {
         printf("Image Open Failed!!\n");
         return NULL;
    }

    vs = tsk_vs_open(img, 0, TSK_VS_TYPE_DETECT);
    if(vs==NULL)
    {
        printf("Volume Open Failed!!\n");
        tsk_img_close(img);
        return NULL;
    }

    data.file_found = 0;
    data.full_path  = file_path;
    utarray_new(data.offsets_in_disk, &ut_tsk_daddr_tuple_icd);
    tsk_vs_part_walk(
            vs,                 // the volume system 
            0,                             // start from first partiton 
            vs->part_count - 1, // walk to last partiton
            TSK_VS_PART_FLAG_ALLOC,        // traverse all allocated partiton
            find_file_in_partiton,         // action for each partition
            &data                          // argument for action
            );

    if (data.file_found) {
        ret = data.offsets_in_disk;
    }
    else {
        tsk_vs_close(vs);
        tsk_img_close(img);
        return NULL;
    }

    tsk_vs_close(vs);
    tsk_img_close(img);

    return ret;
}
Beispiel #19
0
Datei: tld.c Projekt: Rafiot/faup
int faup_tld_array_populate(void)
{

	FILE *fp;
	char *tld_file = faup_datadir_get_file("mozilla.tlds", false);
	bool begin_icann_domains = 0;

	if (_tlds) {
		fprintf(stderr, "The tld array has already been populated!\n");
		free(tld_file);
		return -1;
	}
	utarray_new(_tlds, &ut_str_icd);

	fp = fopen(tld_file, "r");
	free(tld_file);
	if (fp) {
		char line[524]; // We have the control over our tld file

		while(fgets(line, sizeof(line), fp) != NULL) {
			size_t line_len = strlen(line);
			char *allocated_line = NULL;

			if (line_len > 0) {
				line[line_len - 1] = '\0';
				allocated_line = strdup((const char *)line);

				switch(line[0]) {
					case '/':
						if (!strncmp("// ===BEGIN ICANN DOMAINS===", allocated_line, 28)) {
							begin_icann_domains = 1;
						}
						break;
					case '\n':
					case '\r':
					case ' ':
					case '\0':
						break;
					default:
						if (line_len > 0) {
							if (begin_icann_domains) {
								utarray_push_back(_tlds, &allocated_line);
							}
						} // if (line_len > 0) {			
				} // switch(line[0]) {
				free(allocated_line);
			} // if (line_len > 0) {
		}
		fclose(fp);
	}

	return 0;
}
Beispiel #20
0
void cmdline_build(Cmdline *cmdline, char *line)
{
  log_msg("CMDSTR", "cmdline_build");
  cmdline->lvl = 0;
  cmdline->line = strdup(line);
  cmdline->len = strlen(line);
  cmdline->err = false;
  cmdline->cont = false;
  QUEUE_INIT(&cmdline->refs);
  utarray_new(cmdline->cmds,   &cmd_icd);
  utarray_new(cmdline->tokens, &list_icd);
  utarray_new(cmdline->vars,   &list_icd);
  utarray_new(cmdline->arys,   &ut_int_icd);

  cmdline_tokenize(cmdline);

  /* parse until empty */
  Token *word = NULL;
  do
    word = cmdline_parse(cmdline, word, cmdline->cmds);
  while (word);
}
Beispiel #21
0
void scan_spool(int do_unlink) {
  int i;
  glob_t g;
  struct stat sb;
  UT_array *files;
  UT_array *xtras;
  utarray_new(files,&ut_str_icd);
  utarray_new(xtras,&xtra_icd);
  char **f, *file;
  file_xtra x, *xp;

  if (chdir(dir) == -1) exit(-1);
  glob(wild, 0, NULL, &g);
  for(i=0; i < g.gl_pathc; i++) {
    utarray_push_back(files, &g.gl_pathv[i]);
  }
  utarray_sort(files, strsort);

  f=NULL;
  while ( (f=(char**)utarray_next(files,f))) {
    file = *f;
    stat(file,&sb);
    if (do_unlink) unlink(file);
    x.file_idx = utarray_eltidx(files,f);
    x.file_len = sb.st_size;
    utarray_push_back(xtras, &x);
  }
  utarray_sort(xtras, xtrasort);
  xp=NULL;
  while ( (xp=(file_xtra*)utarray_next(xtras,xp))) {
    f = (char**)utarray_eltptr(files,xp->file_idx);
    file = *f;
    printf("file %s, len %d\n", blot(file),xp->file_len);
  }
  globfree(&g);
  utarray_free(files);
  utarray_free(xtras);
}
/**
 * Return an array of size *returnSize.
 * Note: The returned array must be malloced, assume caller calls free().
 */
int* postorderTraversal(struct TreeNode* root, int* returnSize) {
    UT_array* vec;
    utarray_new(vec, &ut_int_icd);
    utarray_reserve(vec, 8);

    postorderRecursive(root, vec);
    *returnSize = utarray_len(vec);

    int bytes = utarray_len(vec) * sizeof(int);
    int* res = malloc(bytes);
    memcpy(res, vec->d, bytes);
    utarray_free(vec);
    return res;
}
Beispiel #23
0
FcitxComposeTable* _fcitx_compose_table_alloc(const char* locale)
{
    FcitxComposeTable* table = fcitx_utils_new(FcitxComposeTable);
    table->localeToTable = fcitx_dict_new(free);
    table->composeTable = utarray_new(&composeElementIcd);
    table->locale = locale ? strdup(locale) : strdup(_get_locale());
    char* p = table->locale;
    while(*p) {
        *p = fcitx_utils_toupper(*p);
        p++;
    }

    return fcitx_compose_table_ref(table);
}
Beispiel #24
0
int do_query(void) {
  int rc = -1;
  UT_array *files;
  UT_array *stats; 
  utarray_new(files,&ut_str_icd);
  utarray_new(stats,&stats_icd);
  if (get_files(files,stats) == -1) goto done;

  /* tally up their sizes */
  int64_t total_sz=0;
  file_stat_t *fs=NULL;
  while ( (fs=(file_stat_t*)utarray_next(stats,fs))) total_sz += fs->sb.st_size;

  char tsz[100],csz[100];
  syslog(LOG_INFO,"directory size: %s (limit %s)", hsz(total_sz, tsz, sizeof(tsz)), 
                                      hsz(cf.sz_bytes, csz, sizeof(csz)));

  rc = 0;

 done:
  utarray_free(files);
  utarray_free(stats);
  return rc;
}
Beispiel #25
0
int main() {
  UT_array *nums;
  long l, *p;
  UT_icd long_icd = {sizeof(long), NULL, NULL, NULL };
  utarray_new(nums, &long_icd);

  l=1; utarray_push_back(nums, &l);
  l=2; utarray_push_back(nums, &l);

  p=NULL;
  while( (p=(long*)utarray_next(nums,p)) != NULL ) printf("%ld\n", *p);

  utarray_free(nums);
  return 0;
}
Beispiel #26
0
/**
 * 为倒排列表分配存储空间并对其进行并初始化
 * @param[in] document_id 文档编号
 * @return 生成的倒排列表
 */
static postings_list *
create_new_postings_list(int document_id)
{
  postings_list *pl;

  pl = malloc(sizeof(postings_list));
  if (!pl) {
    print_error("cannot allocate memory for a postings list.");
    return NULL;
  }
  pl->document_id = document_id;
  pl->positions_count = 1;
  utarray_new(pl->positions, &ut_int_icd);

  return pl;
}
Beispiel #27
0
int main() {
  UT_array *a;
  int i, *p;
  utarray_new(a, &ut_int_icd);
  for(i=0;i<10;i++) utarray_push_back(a,&i);
  for(p=(int*)utarray_front(a); p; p=(int*)utarray_next(a,p)) printf("%d ",*p); 
  printf("\n");
  printf("len: %u\n\n", utarray_len(a));
  
  i=10; utarray_insert(a, &i, 10);
  while ( (p=(int*)utarray_next(a,p))) printf("%d ", *p); printf("\n");
  printf("len: %u\n\n", utarray_len(a));

  utarray_free(a);
  return 0;
}
Beispiel #28
0
/******************************************************************************
 * tv_scene_lights_at
 * Returns the light closest to the given position by a brute force search
 * through all the lights in the scene.
******************************************************************************/
tv_array *tv_scene_lights_at(tv_vector3 pos)
{
	tv_light *light;
	tv_array *ret;

	utarray_new(ret, &light_icd);
	/* find the light closest to the given position */
	for(light = (tv_light*)utarray_front(lights);
		light != NULL;
		light = (tv_light*)utarray_next(lights, light)) {
			if(tv_vector3_distance(((tv_component*)light)->entity->transform.pos, pos) < light->range) {
				utarray_push_back(ret, light);
			}
	}
	return ret;
}
Beispiel #29
0
int main() {
  UT_array *strs;
  char *s, **p;

  utarray_new(strs,&ut_str_icd);

  s = "hello"; utarray_push_back(strs, &s);
  s = "world"; utarray_push_back(strs, &s);
  p = NULL;
  while ( (p=(char**)utarray_next(strs,p)) != NULL ) {
    printf("%s\n",*p);
  }

  utarray_free(strs);

  return 0;
}
Beispiel #30
0
int main(int argc, char *argv[]) {
  cfg.prog = argv[0];
  cfg.prog=argv[0];
  cfg.pid = getpid();
  int n, signo, opt, *fd;
  siginfo_t info;
  utarray_new(cfg.fds,&ut_int_icd);

  while ( (opt=getopt(argc,argv,"vp:a:h")) != -1) {
    switch(opt) {
      case 'v': cfg.verbose++; break;
      case 'p': cfg.port=atoi(optarg); break; 
      case 'a': cfg.addr=inet_addr(optarg); break; 
      case 'h': default: usage(); break;
    }
  }
  if (cfg.addr == INADDR_NONE) usage();
  if (cfg.port==0) usage();

  /* block all signals. we only take signals synchronously in sigwaitinfo */
  sigset_t all;
  sigfillset(&all);
  sigprocmask(SIG_SETMASK,&all,NULL);

  /* make a set of the signals we accept in sigwaitinfo. others blocked */
  sigset_t sw;
  sigemptyset(&sw);
  for(n=0; n < sizeof(sigs)/sizeof(*sigs); n++) sigaddset(&sw, sigs[n]);

  if (setup_listener()) goto done;

  alarm(1);
  while ( (signo = sigwaitinfo(&sw, &info)) > 0) {
    switch (signo) {
      case SIGALRM: if ((++cfg.ticks % 10) == 0) periodic(); alarm(1); break;
      case SIGIO:   service_network();                                 break;
      default:     printf("got signal %d\n", signo);                   goto done;
    }
  }

done:
  fd=NULL;
  while ( (fd=(int*)utarray_next(cfg.fds,fd))) close(*fd);
  utarray_free(cfg.fds);
  return 0;
}