// Show Configuration static pwr_tStatus ShowConfiguration(xmenu_sMenuCall* ip) { pwr_tStatus sts; xtt_pndevice_sCtx* ctx; pwr_tFileName datafile; sprintf( datafile, "$pwrp_load/pwr_pn_%s.xml", id_to_string(ip->Pointed.Objid)); sts = xtt_pndevice_create_ctx(ip->Pointed, ip->EditorContext, &ctx); if (EVEN(sts)) return sts; ctx->attr = new GsdmlAttrQt( CoXHelpQt::get_widget(), ctx, 0, ctx->gsdml, 0, datafile, &sts); if (sts == PB__CONFIGABORTED) { delete ctx->attr; return 1; } ctx->attr->close_cb = xtt_pndevice_close_cb; ctx->attr->save_cb = xtt_pndevice_save_cb; ctx->attr->help_cb = xtt_pndevice_help_cb; #if 0 if (ODD(sts)) sts = pndevice_init(ctx); #endif if (EVEN(sts)) { ctx->attr->wow->DisplayError("Configuration load error", "Configuration load error\nCheck configuration data"); } return 1; }
const char* package_hygienic_id(typecheck_t* t) { assert(t->frame->package != NULL); package_t* pkg = (package_t*)ast_data(t->frame->package); size_t id = pkg->next_hygienic_id++; return id_to_string(pkg->id, id); }
void self_remove_avatar() { unset_avatar(&self.avatar); uint8_t hex_id[TOX_FRIEND_ADDRESS_SIZE * 2]; id_to_string(hex_id, self.id_binary); delete_saved_avatar(hex_id); tox_postmessage(TOX_AVATAR_UNSET, 0, 0, NULL); }
static void button_change_id_type_onpress(void) { edit_resetfocus(); if (self.id_buffer_length == TOX_FRIEND_ADDRESS_SIZE * 2) { self.id_buffer_length = bytes_to_emoji_string(self.id_buffer, sizeof(self.id_buffer), self.id_binary, TOX_FRIEND_ADDRESS_SIZE); edit_toxid.length = self.id_buffer_length; } else { id_to_string(self.id_buffer, self.id_binary); self.id_buffer_length = edit_toxid.length = TOX_FRIEND_ADDRESS_SIZE * 2; } }
const char *id_pair_to_string(XAuint32 id1, XAuint32 id2, const id_pair_to_string_t *table, size_t numEntries) { size_t i; for (i = 0; i < numEntries; ++i) { if (id1 == table[i].id1) { return id_to_string(id2, table[i].id2_table, table[i].id2_numEntries); } } return "Unknown"; }
int self_set_and_save_avatar(const uint8_t *data, uint32_t size) { if (self_set_avatar(data, size)) { uint8_t hex_id[TOX_FRIEND_ADDRESS_SIZE * 2]; id_to_string(hex_id, self.id_binary); save_avatar(hex_id, data, size); return 1; } else { return 0; } }
void accept_friend_request(Tox *tox, const uint8_t *public_key, const uint8_t *message, size_t length, void *userdata) { unsigned char tox_printable_id[TOX_ADDRESS_SIZE * 2 + 1]; int32_t friendnumber; TOX_ERR_FRIEND_ADD friend_add_error; log_printf(L_DEBUG, "Got friend request\n"); if(use_shared_secret) { if(!message) { log_printf(L_WARNING, "Friend sent NULL message - not accepting request"); return; } if(message[length - 1] != '\0') { log_printf(L_WARNING, "Message of size %u is not NULL terminated - not accepting request", length); return; } if(strncmp(message, shared_secret, TOX_MAX_FRIEND_REQUEST_LENGTH-1)) { log_printf(L_WARNING, "Received shared secret \"%s\" differs from our shared secret - not accepting request", message); return; } } memset(tox_printable_id, '\0', sizeof(tox_printable_id)); id_to_string(tox_printable_id, public_key); if(server_whitelist_mode) { allowed_toxid etmp, *found = NULL; memcpy(etmp.toxid, public_key, TOX_PUBLIC_KEY_SIZE); LL_SEARCH(allowed_toxids, found, &etmp, allowed_toxid_cmp); if(!found) { log_printf(L_WARNING, "Rejected friend request from non-whitelisted friend %s", tox_printable_id); return; } log_printf(L_DEBUG, "Friend %s passed whitelist check", tox_printable_id); } friendnumber = tox_friend_add_norequest(tox, public_key, &friend_add_error); if(friend_add_error != TOX_ERR_FRIEND_ADD_OK) { log_printf(L_WARNING, "Could not add friend: err %u", friend_add_error); return; } log_printf(L_INFO, "Accepted friend request from %s as %d\n", tox_printable_id, friendnumber); }
// Create a package AST, set up its state and add it to the given program ast_t* create_package(ast_t* program, const char* name, const char* qualified_name, pass_opt_t* opt) { ast_t* package = ast_blank(TK_PACKAGE); uint32_t pkg_id = program_assign_pkg_id(program); package_t* pkg = POOL_ALLOC(package_t); pkg->path = name; pkg->qualified_name = qualified_name; pkg->id = id_to_string(NULL, pkg_id); const char* p = strrchr(pkg->path, PATH_SLASH); if(p == NULL) p = pkg->path; else p = p + 1; pkg->filename = stringtab(p); if(pkg_id > 1) pkg->symbol = create_package_symbol(program, pkg->filename); else pkg->symbol = NULL; pkg->ast = package; package_set_init(&pkg->dependencies, 1); pkg->group = NULL; pkg->group_index = -1; pkg->next_hygienic_id = 0; pkg->low_index = -1; ast_setdata(package, pkg); ast_scope(package); ast_append(program, package); ast_set(program, pkg->path, package, SYM_NONE, false); ast_set(program, pkg->id, package, SYM_NONE, false); strlist_t* safe = opt->safe_packages; if((safe != NULL) && (strlist_find(safe, pkg->path) == NULL)) pkg->allow_ffi = false; else pkg->allow_ffi = true; pkg->on_stack = false; return package; }
// Create a package AST, set up its state and add it to the given program static ast_t* create_package(ast_t* program, const char* name) { ast_t* package = ast_blank(TK_PACKAGE); uint32_t pkg_id = program_assign_pkg_id(program); package_t* pkg = POOL_ALLOC(package_t); pkg->path = name; pkg->id = id_to_string(NULL, pkg_id); const char* p = strrchr(pkg->path, PATH_SLASH); if(p == NULL) p = pkg->path; else p = p + 1; pkg->filename = stringtab(p); if(pkg_id > 1) pkg->symbol = create_package_symbol(program, pkg->filename); else pkg->symbol = NULL; pkg->next_hygienic_id = 0; ast_setdata(package, pkg); ast_scope(package); ast_append(program, package); ast_set(program, pkg->path, package, SYM_NONE); ast_set(program, pkg->id, package, SYM_NONE); if((safe != NULL) && (strlist_find(safe, pkg->path) == NULL)) pkg->allow_ffi = false; else pkg->allow_ffi = true; return package; }
// Default Verbs void DumpVisitor::visit(Verb* v) { aq::Logger::getInstance().log(AQ_WARNING, "verb %s not implemented for DumpVisitor\n", id_to_string(v->getVerbType())); }
static void drawitem(ITEM *i, int UNUSED(x), int y) { drawitembox(i, y); switch(i->item) { case ITEM_FRIEND: { FRIEND *f = i->data; // draw avatar or default image if (friend_has_avatar(f)) { draw_avatar_image(f->avatar.image, LIST_AVATAR_X, y + LIST_AVATAR_Y, f->avatar.width, f->avatar.height, BM_CONTACT_WIDTH, BM_CONTACT_WIDTH); } else { drawalpha(BM_CONTACT, LIST_AVATAR_X, y + LIST_AVATAR_Y, BM_CONTACT_WIDTH, BM_CONTACT_WIDTH, (selected_item == i) ? COLOR_MAIN_TEXT : COLOR_LIST_TEXT); } if(f->alias){ drawname(i, y, f->alias, f->status_message, f->alias_length, f->status_length, 0, 0); } else { drawname(i, y, f->name, f->status_message, f->name_length, f->status_length, 0, 0); } uint8_t status = f->online ? f->status : 3; drawalpha(BM_ONLINE + status, LIST_RIGHT - SCALE * 12, y + ITEM_HEIGHT / 2 - BM_STATUS_WIDTH / 2, BM_STATUS_WIDTH, BM_STATUS_WIDTH, status_color[status]); if(f->notify) { drawalpha(BM_STATUS_NOTIFY, LIST_RIGHT - SCALE * 13, y + ITEM_HEIGHT / 2 - BM_STATUS_NOTIFY_WIDTH / 2, BM_STATUS_NOTIFY_WIDTH, BM_STATUS_NOTIFY_WIDTH, status_color[status]); } // tooltip_new(utf8tonative(snprint_t(f->name, sizeof(char_t)*8)); break; } case ITEM_GROUP: { GROUPCHAT *g = i->data; drawalpha(BM_GROUP, LIST_AVATAR_X, y + LIST_AVATAR_Y, BM_CONTACT_WIDTH, BM_CONTACT_WIDTH, (selected_item == i) ? COLOR_MAIN_TEXT : COLOR_LIST_TEXT); _Bool color_overide = 0; uint32_t color = 0; if (g->muted) { color_overide = 1; color = COLOR_GROUP_MUTED; } else { uint64_t time = get_time(); unsigned int j; for (j = 0; j < g->peers; ++j) { if (time - g->last_recv_audio[j] <= (uint64_t)1 * 1000 * 1000 * 1000) { color_overide = 1; color = COLOR_GROUP_AUDIO; break; } } } drawname(i, y, g->name, g->topic, g->name_length, g->topic_length, color_overide, color); break; } case ITEM_FRIEND_ADD: { FRIENDREQ *f = i->data; char_t name[TOX_FRIEND_ADDRESS_SIZE * 2]; id_to_string(name, f->id); drawalpha(BM_CONTACT, LIST_AVATAR_X, y + LIST_AVATAR_Y, BM_CONTACT_WIDTH, BM_CONTACT_WIDTH, (selected_item == i) ? COLOR_MAIN_TEXT : COLOR_LIST_TEXT); drawname(i, y, name, f->msg, sizeof(name), f->length, 0, 0); break; } } }
void tox_thread(void *UNUSED(args)) { Tox *tox; ToxAv *av; uint8_t id[TOX_FRIEND_ADDRESS_SIZE]; TOP:; debug("new tox object ipv6: %u no_udp: %u proxy: %u %s %u\n", options.ipv6enabled, options.udp_disabled, options.proxy_enabled, options.proxy_address, options.proxy_port); if((tox = tox_new(&options)) == NULL) { debug("trying without proxy\n"); if(!options.proxy_enabled || (options.proxy_enabled = 0, (tox = tox_new(&options)) == NULL)) { debug("trying without ipv6\n"); if(!options.ipv6enabled || (options.ipv6enabled = 0, (tox = tox_new(&options)) == NULL)) { debug("tox_new() failed\n"); exit(1); } dropdown_ipv6.selected = dropdown_ipv6.over = 1; } dropdown_proxy.selected = dropdown_proxy.over = 0; } if(!load_save(tox)) { debug("No save file, using defaults\n"); load_defaults(tox); } edit_setstr(&edit_name, self.name, self.name_length); edit_setstr(&edit_status, self.statusmsg, self.statusmsg_length); tox_get_address(tox, id); id_to_string(self.id, id); debug("Tox ID: %.*s\n", (int)sizeof(self.id), self.id); set_callbacks(tox); do_bootstrap(tox); av = toxav_new(tox, MAX_CALLS); set_av_callbacks(av); global_av = av; tox_thread_init = 1; thread(audio_thread, av); thread(video_thread, av); thread(toxav_thread, av); _Bool connected = 0, reconfig; uint64_t last_save = get_time(), time; while(1) { tox_do(tox); if(tox_isconnected(tox) != connected) { connected = !connected; postmessage(DHT_CONNECTED, connected, 0, NULL); debug("Connected to DHT: %u\n", connected); } time = get_time(); if(time - last_save >= (uint64_t)10 * 1000 * 1000 * 1000) { last_save = time; if(!connected) { do_bootstrap(tox); } write_save(tox); } if(tox_thread_msg) { TOX_MSG *msg = &tox_msg; if(!msg->msg) { reconfig = msg->param1; tox_thread_msg = 0; break; } tox_thread_message(tox, av, time, msg->msg, msg->param1, msg->param2, msg->data); tox_thread_msg = 0; } utox_thread_work_for_transfers(tox, time); utox_thread_work_for_typing_notifications(tox, time); uint32_t interval = tox_do_interval(tox); yieldcpu((interval > 20) ? 20 : interval); } write_save(tox); while(audio_thread_init || video_thread_init || toxav_thread_init) { yieldcpu(1); } debug("av_thread exit, tox thread ending\n"); toxav_kill(av); tox_kill(tox); if(reconfig) { goto TOP; } tox_thread_init = 0; }
int main(int argc, char *argv[]) { unsigned char tox_id[TOX_ADDRESS_SIZE]; unsigned char tox_printable_id[TOX_ADDRESS_SIZE * 2 + 1]; TOX_ERR_NEW tox_new_err; int oc; size_t save_size = 0; uint8_t *save_data = NULL; allowed_toxid *allowed_toxid_obj = NULL; log_init(); while ((oc = getopt(argc, argv, "L:pi:C:s:P:dqhSF:DU:")) != -1) { switch(oc) { case 'L': /* Local port forwarding */ client_mode = 1; client_local_port_mode = 1; if(parse_local_port_forward(optarg, &local_port, &remote_host, &remote_port) < 0) { log_printf(L_ERROR, "Invalid value for -L option - use something like -L 22:127.0.0.1:22\n"); exit(1); } if(min_log_level == L_UNSET) { min_log_level = L_INFO; } log_printf(L_DEBUG, "Forwarding remote port %d to local port %d\n", remote_port, local_port); break; case 'P': /* Pipe forwarding */ client_mode = 1; client_pipe_mode = 1; if(parse_pipe_port_forward(optarg, &remote_host, &remote_port) < 0) { log_printf(L_ERROR, "Invalid value for -P option - use something like -P 127.0.0.1:22\n"); exit(1); } if(min_log_level == L_UNSET) { min_log_level = L_ERROR; } log_printf(L_INFO, "Forwarding remote port %d to stdin/out\n", remote_port); break; case 'p': /* Ping */ client_mode = 1; ping_mode = 1; if(min_log_level == L_UNSET) { min_log_level = L_INFO; } break; case 'i': /* Tox ID */ server_whitelist_mode = 1; log_printf(L_DEBUG, "Server whitelist mode enabled"); allowed_toxid_obj = (allowed_toxid *)calloc(sizeof(allowed_toxid), 1); if(!allowed_toxid_obj) { log_printf(L_ERROR, "Could not allocate memory for allowed_toxid"); exit(1); } remote_tox_id = optarg; if(!string_to_id(allowed_toxid_obj->toxid, optarg)) { log_printf(L_ERROR, "Invalid Tox ID"); exit(1); } LL_APPEND(allowed_toxids, allowed_toxid_obj); break; case 'C': /* Config directory */ strncpy(config_path, optarg, sizeof(config_path) - 1); if(optarg[strlen(optarg) - 1] != '/') { int optarg_len = strlen(optarg); config_path[optarg_len] = '/'; config_path[optarg_len + 1] = '\0'; } load_saved_toxid_in_client_mode = 1; break; case 's': /* Shared secret */ use_shared_secret = 1; memset(shared_secret, 0, TOX_MAX_FRIEND_REQUEST_LENGTH); strncpy(shared_secret, optarg, TOX_MAX_FRIEND_REQUEST_LENGTH-1); break; case 'd': min_log_level = L_DEBUG; break; case 'q': min_log_level = L_ERROR; break; case 'S': use_syslog = 1; break; case 'D': daemonize = 1; use_syslog = 1; break; case 'F': pidfile = optarg; break; case 'U': daemon_username = optarg; break; case '?': case 'h': default: print_version(); help(); exit(1); } } if(!client_mode && min_log_level == L_UNSET) { min_log_level = L_INFO; } if(!client_mode && server_whitelist_mode) { log_printf(L_INFO, "Server in ToxID whitelisting mode - only clients listed with -i can connect"); } if(daemonize) { do_daemonize(); } atexit(cleanup); print_version(); /* Bootstrap tox */ tox_options_default(&tox_options); if((!client_mode) || load_saved_toxid_in_client_mode) { uint8_t *save_data = NULL; save_size = load_save(&save_data); if(save_data && save_size) { tox_options.savedata_type = TOX_SAVEDATA_TYPE_TOX_SAVE; tox_options.savedata_data = save_data; tox_options.savedata_length = save_size; } } tox = tox_new(&tox_options, &tox_new_err); if(tox == NULL) { log_printf(L_DEBUG, "tox_new() failed (%u) - trying without proxy\n", tox_new_err); if((tox_options.proxy_type != TOX_PROXY_TYPE_NONE) || (tox_options.proxy_type = TOX_PROXY_TYPE_NONE, (tox = tox_new(&tox_options, &tox_new_err)) == NULL)) { log_printf(L_DEBUG, "tox_new() failed (%u) - trying without IPv6\n", tox_new_err); if(!tox_options.ipv6_enabled || (tox_options.ipv6_enabled = 0, (tox = tox_new(&tox_options, &tox_new_err)) == NULL)) { log_printf(L_DEBUG, "tox_new() failed (%u) - trying with Tor\n", tox_new_err); if((tox_options.proxy_type = TOX_PROXY_TYPE_SOCKS5, tox_options.proxy_host="127.0.0.1", tox_options.proxy_port=9050, (tox = tox_new(&tox_options, &tox_new_err)) == NULL)) { log_printf(L_ERROR, "tox_new() failed (%u) - exiting\n", tox_new_err); exit(1); } } } } if(save_size && save_data) { free(save_data); } set_tox_username(tox); tox_callback_self_connection_status(tox, handle_connection_status_change, NULL); do_bootstrap(tox); if(client_mode) { tox_self_get_address(tox, tox_id); id_to_string(tox_printable_id, tox_id); tox_printable_id[TOX_ADDRESS_SIZE * 2] = '\0'; log_printf(L_DEBUG, "Generated Tox ID: %s\n", tox_printable_id); if(!remote_tox_id) { log_printf(L_ERROR, "Tox id is required in client mode. Use -i 58435984ABCDEF475...\n"); exit(1); } do_client_loop(remote_tox_id); } else { write_save(tox); if(!use_shared_secret) { log_printf(L_WARNING, "Shared secret authentication is not used - skilled attackers may connect to your tuntox server"); } tox_self_get_address(tox, tox_id); memset(tox_printable_id, '\0', sizeof(tox_printable_id)); id_to_string(tox_printable_id, tox_id); tox_printable_id[TOX_ADDRESS_SIZE * 2] = '\0'; log_printf(L_INFO, "Using Tox ID: %s\n", tox_printable_id); tox_callback_friend_request(tox, accept_friend_request, NULL); do_server_loop(); } return 0; }
int main() { int rv = 0,res =0,i = 0,j=0; char *ca[] = {"key.pub","key.prv","key.par"}; char *glb[] = {"gbl.act","gbl.rvk"}; char *epoch[] = {"epc.act","epc.rvk"}; char *facc = "last.acc"; char fname[MAX_ENVEL_NAME]; setup_params_t *setup = NULL; epoch_item_t *ep = NULL; id_list_t *actls= NULL, *rvkls = NULL; action_data_t *join = NULL; rv = setup_load (ca[0],ca[1],ca[2],&setup); if(rv < 0) pbgp_die("Cannot initialize setup\n Aborting. \n"); //genera epoca rv = claim_new_epoch(glb,epoch,facc,"last.epc",setup); if(rv < 0) pbgp_die("Cannot claim a new epoch\n"); rv = newepoch_init(&ep,setup); if(rv < 0) { pbgp_die("claim_new_init :: Cannot complete initialization process\n"); } rv = ids_init(&ep->epls.act,&ep->epls.rvk); if(rv < 0) { pbgp_die("ids_init :: Cannot create lists\n"); } rv = newepoch_load("last.epc",ep,setup); if(rv < 0) { pbgp_die("\n"); } //da usare per caricare i nomi dei file ids_init(&actls,&rvkls); ids_load(glb[0],actls); ids_load(glb[1],rvkls); join_init(&join,setup,NULL); if(join == NULL) pbgp_die("join is null. Abort."); printf("ACTIVE USER TEST:\n"); for(i=0; i < actls->size ; i++) { char *idstr = NULL; //carica join elem sprintf(fname,"id-%d.env",actls->head[i].asnum); join_load(fname,join); id_to_string(&idstr, join->ibk->id); printf("Verifying %s\n",idstr); id_to_string_clear(idstr); //update the witness witness_update(join->witness,join->ibk->id,setup, ep->epls.act,ep->epls.rvk); //check the presence of the AS into the accumulator rv = revokation_check(ep->acc,join->witness,join->signature, join->ibk->id->asnum,setup); //check the prefix list signatures TODO!!!!! aaggiusta sto codice -.- for(j=0; j < join->pfixlist->size; j++) { const uint8_t *buf_ina = (const uint8_t *) &join->pfixlist->ina[j]; size_t sina[1]; char as[40]; inet_net_ntop (AF_INET, &join->pfixlist->ina[j], join->pfixlist->netmask[j],as, 40); //sina[0] = sizeof(join->pfixlist->ina[j]); uint8_t to_vrfy[1][9]; uint8_t *p = to_vrfy; bzero(p,9); SERIALIZE_AUTH(p,&join->pfixlist->ina[j],&join->pfixlist->netmask[j],&join->pfixlist->tsca); sina[0] = 9; res = ibe_vrfy(join->pfixlist->pf_sign[j], setup,(const uint8_t **)&p,sina,NULL); if(res == SIGN_VALID) printf("The signature is valid! (%s)\n",as); else printf("Invalid signature :( \n"); } if(rv != 0) { pbgp_error("revokation_check :: %d have been revoked!\n",join->ibk->id->asnum); rv = -1; } else { printf("SUCCESS: User %d is still into the accumulator\n",join->ibk->id->asnum); join_save(join); } pfix_clear(join->pfixlist); } join_clear(join); // verifica che i revocati non sono nell'accumulatore join_init(&join,setup,NULL); if(join == NULL) pbgp_die("join is null. Abort."); printf("REVOKED USER TEST:\n"); for(i=0; i < rvkls->size ; i++) { char *idstr = NULL; //carica join elem sprintf(fname,"id-%d.env",rvkls->head[i].asnum); join_load(fname,join); id_to_string(&idstr, join->ibk->id); printf("Verifying %s\n",idstr); //aggiorna il witness witness_update(join->witness,join->ibk->id,setup, ep->epls.act,ep->epls.rvk); rv = revokation_check(ep->acc,join->witness,join->signature, join->ibk->id->asnum,setup); if(rv != 0) { pbgp_error("revokation_check :: %d have been revoked!\n",join->ibk->id->asnum); rv = -1; } else { printf("SUCCESS: User %d is still into the accumulator\n",join->ibk->id->asnum); join_save(join); } id_to_string_clear(idstr); } join_clear(join); ids_clear(actls,rvkls); setup_clear(setup); return 0; }
int try_mount_root() { // create the /rootfs directory if (mkdir("/rootfs", 0755) != 0) { fprintf(stderr, "init: failed to create /rootfs: %s\n", strerror(errno)); return -1; }; // get the list of devices size_t numDevs = 0; DIR *dirp = opendir("/dev"); if (dirp == NULL) { fprintf(stderr, "init: failed to scan /dev: %s\n", strerror(errno)); return -1; }; struct dirent *ent; while ((ent = readdir(dirp)) != NULL) { if (memcmp(ent->d_name, "sd", 2) == 0) { char *devname = (char*) malloc(strlen(ent->d_name) + strlen("/dev/") + 1); sprintf(devname, "/dev/%s", ent->d_name); devList = (char**) realloc(devList, sizeof(char*) * (numDevs+1)); devList[numDevs++] = devname; printf("init: detected candidate storage device: %s\n", devname); }; }; devList = (char**) realloc(devList, sizeof(char*) * (numDevs+1)); devList[numDevs] = NULL; closedir(dirp); char names[256*16]; int drvcount = (int) __syscall(__SYS_fsdrv, names, 256); if (drvcount == -1) { fprintf(stderr, "init: cannot get filesystem driver list: %s\n", strerror(errno)); return 1; }; struct system_state sst; if (__syscall(__SYS_systat, &sst, sizeof(struct system_state)) != 0) { fprintf(stderr, "init: failed to get system state: %s\n", strerror(errno)); }; char idbuf[33]; id_to_string(idbuf, sst.sst_bootid); printf("init: kernel boot ID is %s\n", idbuf); const char *scan = names; while (drvcount--) { const char *fstype = scan; scan += 16; if (try_mount_root_with_type(fstype, sst.sst_bootid) == 0) return 0; }; return -1; };