int next_request(struct remote *rx) { char *ptr; rx->r_match = NULL; if(rx->r_index >= rx->r_count){ return 1; } ptr = get_string_parse_katcl(rx->r_vector[rx->r_index], 0); if(ptr == NULL){ return -1; } if(ptr[0] != KATCP_REQUEST){ return -1; } if(append_parse_katcl(rx->r_line, rx->r_vector[rx->r_index]) < 0){ return -1; } rx->r_match = ptr + 1; rx->r_index++; return 0; }
int relay_katcl(struct katcl_line *lx, struct katcl_line *ly) { if(lx->l_ready == NULL){ return -1; } return append_parse_katcl(ly, lx->l_ready); }
int perform_sensor_update_katcp(struct katcp_dispatch *d, void *data) { struct katcp_shared *s; unsigned int i, j, count; struct katcp_flat *fx; struct katcp_group *gx; struct katcl_parse *px; s = d->d_shared; if(s == NULL){ return -1; } if(s->s_changes <= 0){ log_message_katcp(d, KATCP_LEVEL_WARN, NULL, "logic problem: scheduled device update, but nothing requires updating"); return -1; } px = create_referenced_parse_katcl(); if(px == NULL){ return -1; } add_string_parse_katcl(px, KATCP_FLAG_FIRST | KATCP_FLAG_STRING, KATCP_DEVICE_CHANGED_INFORM); add_string_parse_katcl(px, KATCP_FLAG_LAST | KATCP_FLAG_STRING, "sensor-list"); count = 0; for(j = 0; j < s->s_members; j++){ gx = s->s_groups[j]; for(i = 0; i < gx->g_count; i++){ fx = is_ready_flat_katcp(d, gx->g_flats[i]); if(fx){ if((fx->f_stale & KATCP_STALE_MASK_SENSOR) == KATCP_STALE_SENSOR_STALE){ fx->f_stale = KATCP_STALE_SENSOR_NAIVE; if((fx->f_flags & KATCP_FLAT_TOCLIENT) && (fx->f_flags & KATCP_FLAT_SEESKATCP)){ /* TODO: shouldn't we use the fancy queue infrastructure ? */ append_parse_katcl(fx->f_line, px); count++; } } } } } log_message_katcp(d, KATCP_LEVEL_DEBUG, NULL, "notified %u clients of %u sensor %s", count, s->s_changes, (s->s_changes == 1) ? "change" : "changes"); destroy_parse_katcl(px); s->s_changes = 0; return 0; }
void dump_katcl(struct katcl_line *l, FILE *fp) { fprintf(fp, "input: fd=%d\n", l->l_fd); dump_parse_katcl(l->l_ready, "ready", fp); dump_parse_katcl(l->l_next, "next", fp); fflush(fp); append_parse_katcl(l, l->l_ready); write_katcl(l); }
int main() { struct katcl_line *l; struct katcl_parse *p; int count, seed, i, k, fds[2], result, al, bl; char alpha[MAX_ARG_LEN], beta[MAX_ARG_LEN]; pid_t pid; seed = getpid(); printf("line test: seed is %d\n", seed); srand(seed); if(socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0){ fprintf(stderr, "line: unable to create socketpair\n"); return 1; } pid = fork(); if(pid < 0){ fprintf(stderr, "line: unable to fork\n"); return 1; } if(pid == 0){ close(fds[0]); echobuffer(fds[1]); return 0; } close(fds[1]); l = create_katcl(fds[0]); if(l == NULL){ fprintf(stderr, "main: unable to create katcl\n"); return 1; } for(i = 0; i < TEST_RUNS; i++){ #ifdef DEBUG fprintf(stderr, "line test: iteration %d\n", i); #endif p = create_referenced_parse_katcl(); if(p == NULL){ fprintf(stderr, "unable to create parse instance %d\n", i); return 1; } #ifdef DEBUG fprintf(stderr, "test: ref before submission %d\n", p->p_refs); #endif fill_random_test(p); dump_parse_katcl(p, "random", stderr); if(append_parse_katcl(l, p) < 0){ fprintf(stderr, "unable to add parse %d\n", i); return 1; } #ifdef DEBUG fprintf(stderr, "test: ref after submission %d\n", p->p_refs); #endif while((result = write_katcl(l)) == 0); #ifdef DEBUG fprintf(stderr, "test: ref after write %d\n", p->p_refs); #endif if(result < 0){ fprintf(stderr, "unable to write data\n"); return 1; } do{ result = read_katcl(l); if(result){ fprintf(stderr, "read result is %d\n", result); return 1; } } while(have_katcl(l) == 0); count = arg_count_katcl(l); for(k = 0; k < count; k++){ al = arg_buffer_katcl(l, k, alpha, MAX_ARG_LEN); bl = get_buffer_parse_katcl(p, k, beta, MAX_ARG_LEN); if((bl < 0) || (al < 0)){ fprintf(stderr, "al=%d, bl=%d\n", al, bl); return 1; } if(al != bl){ fprintf(stderr, "al=%d != bl=%d\n", al, bl); return 1; } if(memcmp(alpha, beta, al)){ fprintf(stderr, "mismatch: round=%d, arg=%d\n", i, k); return 1; } } fprintf(stderr, "parsed a line with %d words\n", count); destroy_parse_katcl(p); } destroy_katcl(l, 1); printf("line test: ok\n"); return 0; }
int main(int argc, char **argv) { #define BUFFER 64 char buffer[BUFFER]; char *level, *app, *server, *output; int run, fd, i, j, c, verbose, attempts, detach, result, truncate, flags; struct katcl_parse *p; struct katcl_line *ls, *lo; struct sigaction sa; time_t now; struct tm *local; i = j = 1; app = argv[0]; verbose = 0; attempts = 2; detach = 0; truncate = 0; server = getenv("KATCP_SERVER"); if(server == NULL){ server = "localhost"; } output = NULL; level = NULL; flags = 0; /* placate -Wall */ while (i < argc) { if (argv[i][0] == '-') { c = argv[i][j]; switch (c) { case 'h' : usage(app); return EX_OK; case 'v' : verbose++; j++; break; case 'd' : detach = 1; j++; break; case 'f' : detach = 0; j++; break; case 't' : truncate = 1; j++; break; case 'q' : verbose = 0; j++; break; case 'l' : case 'o' : case 'a' : case 's' : j++; if (argv[i][j] == '\0') { j = 0; i++; } if (i >= argc) { fprintf(stderr, "%s: usage: argument needs a parameter\n", app); return EX_USAGE; } switch(c){ case 'l' : level = argv[i] + j; break; case 'o' : output = argv[i] + j; break; case 'a' : attempts = atoi(argv[i] + j); break; case 's' : server = argv[i] + j; break; } i++; j = 1; break; case '-' : j++; break; case '\0': j = 1; i++; break; default: fprintf(stderr, "%s: usage: unknown option -%c\n", app, argv[i][j]); return EX_USAGE; } } else { if(output){ fprintf(stderr, "%s: usage: unexpected extra argument %s (can only save to one file)\n", app, argv[i]); return EX_USAGE; } output = argv[i]; i++; } } if(detach){ if(fork_parent() < 0){ fprintf(stderr, "%s: unable to detach process\n", app); return EX_OSERR; } } sa.sa_handler = handle_signal; #if 0 sa.sa_flags = SA_RESTART; #endif sa.sa_flags = 0; sigemptyset(&(sa.sa_mask)); sigaction(SIGHUP, &sa, NULL); sigaction(SIGUSR1, &sa, NULL); sigaction(SIGUSR2, &sa, NULL); if(server == NULL){ server = "localhost:7147"; } if(level){ log_changed = 1; log_level = log_to_code_katcl(level); if(log_level < 0){ fprintf(stderr, "%s: usage: invalid initial log priority %s\n", app, level); return EX_USAGE; } } if(output == NULL){ if(detach == 1){ fprintf(stderr, "%s: usage: need a filename as target\n", app); return EX_USAGE; } fd = STDOUT_FILENO; } else { flags = O_CREAT | O_WRONLY; if(truncate == 0){ flags |= O_APPEND; } fd = open(output, flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); if(fd < 0){ fprintf(stderr, "%s: unable to open file %s: %s\n", app, output, strerror(errno)); return EX_OSERR; } } lo = create_katcl(fd); if(lo == NULL){ fprintf(stderr, "%s: unable to allocate log state\n", app); return EX_OSERR; } /**********************/ while((attempts-- > 0) && ((fd = net_connect(server, 0, 0)) < 0)){ sleep(1); } if(attempts <= 0){ sync_message_katcl(lo, KATCP_LEVEL_FATAL, NAME, "unable to connect to %s", server); return EX_UNAVAILABLE; } ls = create_katcl(fd); if(ls == NULL){ sync_message_katcl(lo, KATCP_LEVEL_FATAL, NAME, "unable to allocate parser state"); return EX_OSERR; } if(detach){ fclose(stderr); } time(&now); local = localtime(&now); strftime(buffer, BUFFER - 1, "%Y-%m-%dT%H:%M:%S", local); sync_message_katcl(lo, KATCP_LEVEL_INFO, NAME, "monitor start for %s at %s", server, buffer); for(run = 1; run > 0;){ if(log_reload > 0){ if(output){ fd = open(output, flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); if(fd >= 0){ exchange_katcl(lo, fd); } } log_reload = 0; } /* WARNING: will only run after the next message - may have to interrupt syscall to get past this */ if(log_changed > 0){ level = log_to_string_katcl(log_level); if(level){ p = create_parse_katcl(); if(p){ add_string_parse_katcl(p, KATCP_FLAG_STRING | KATCP_FLAG_FIRST, "?log-level"); add_string_parse_katcl(p, KATCP_FLAG_STRING | KATCP_FLAG_LAST, level); append_parse_katcl(lo, p); /* dodgy refcount dealings: p is created with refcount = 0, so can only do write at end, otherwise may end up being deallocated */ append_parse_katcl(ls, p); write_katcl(ls); } } else { sync_message_katcl(lo, KATCP_LEVEL_ERROR, NAME, "invalid log priority number %d", level); } log_changed = 0; } result = read_katcl(ls); if(result < 0){ sync_message_katcl(lo, KATCP_LEVEL_FATAL, NAME, "read from network failed: %s", strerror(errno)); return EX_OSERR; } if(result == 1){ run = 0; } while(have_katcl(ls)){ p = ready_katcl(ls); if(p){ append_parse_katcl(lo, p); } } write_katcl(lo); } return EX_OK; #undef BUFFER }