static bool parse_string(char **string,int *nr, int ngrps, char **grpname) { char *s, *sp; char c; while ((*string)[0]==' ') (*string)++; (*nr) = NOTSET; if (isquote((*string)[0])) { c=(*string)[0]; (*string)++; s = strdup((*string)); sp = strchr(s, c); if (sp!=NULL) { (*string) += sp-s + 1; sp[0]='\0'; (*nr) = find_group(s, ngrps, grpname); } } return (*nr) != NOTSET; }
/*! * \param[out] dest Output structure. * \param[out] destName Receives the name of the group if found. * \param[in] src Input index groups. * \param[in] name Name (or part of the name) of the group to extract. * \returns true if \p name is a valid group in \p src, false otherwise. * * Uses the Gromacs routine find_group() to find the actual group; * the comparison is case-insensitive. */ bool gmx_ana_indexgrps_find(gmx_ana_index_t *dest, std::string *destName, gmx_ana_indexgrps_t *src, const char *name) { const char **names; destName->clear(); snew(names, src->nr); for (int i = 0; i < src->nr; ++i) { names[i] = src->names[i].c_str(); } int n = find_group(const_cast<char *>(name), src->nr, const_cast<char **>(names)); sfree(names); if (n == NOTSET) { dest->isize = 0; return false; } return gmx_ana_indexgrps_extract(dest, destName, src, n); }
static int qgroup(int *a, int ngrps, char **grpname) { char s[STRLEN]; int aa; bool bInRange; do { fprintf(stderr,"Select a group: "); do { if ( scanf("%s",s)!=1 ) gmx_fatal(FARGS,"Cannot read from input"); trim(s); /* remove spaces */ } while (strlen(s)==0); aa = atoi(s); if (aa==0 && strcmp(s,"0")!=0 ) /* string entered */ aa = find_group(s, ngrps, grpname); bInRange = aa>=0 && aa<ngrps; if (!bInRange) printf("Error: No such group '%s'\n", s); } while (!bInRange); printf("Selected %d: '%s'\n", aa, grpname[aa]); *a = aa; return aa; }
/* * Sets the properties of the widget. This is used for both applying the * properties changed in the property editor, and also for loading. */ static void gb_radio_button_set_properties (GtkWidget * widget, GbWidgetSetArgData * data) { gboolean state, indicator; gchar *group_name; GSList *group = NULL, *current_group; GbFindGroupData find_group_data; if (gb_toolbar_is_toolbar_button (widget)) { gb_toolbar_input_child_label (widget, data, Label); gb_toolbar_input_child_icon (widget, data, Icon); } else { gb_widget_input_child_label (widget, data, Label); } state = gb_widget_input_bool (data, State); if (data->apply) { gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), state); if (state) data->widget_data->flags |= GLADE_ACTIVE; else data->widget_data->flags &= ~GLADE_ACTIVE; } indicator = gb_widget_input_bool (data, Indicator); if (data->apply) gtk_toggle_button_set_mode (GTK_TOGGLE_BUTTON (widget), indicator); /* Find any widgets in given group and set this widgets group. If group is NULL try to find radiobuttons with same parent and use their group. If these don't succeed, set group to NULL. */ group_name = gb_widget_input_combo (data, Group); if (data->apply) { if (group_name && group_name[0] == '\0') group_name = NULL; current_group = gtk_radio_button_group (GTK_RADIO_BUTTON (widget)); if (group_name == NULL) gtk_container_foreach (GTK_CONTAINER (widget->parent), (GtkCallback) find_parents_group, &group); else { find_group_data.group_name = group_name; find_group_data.group = NULL; find_group (gtk_widget_get_toplevel (widget), &find_group_data); group = find_group_data.group; } g_free (gtk_object_get_data (GTK_OBJECT (widget), Group)); gtk_object_set_data (GTK_OBJECT (widget), Group, g_strdup (group_name)); /* This crashes if we set the group to NULL, so we have to reset the group ourself. We only set the group if it has changed. */ if (group) { if (group != current_group) { if (current_group->data == widget) current_group = current_group->next; gtk_radio_button_set_group (GTK_RADIO_BUTTON (widget), group); gb_radio_button_update_radio_group (current_group); gb_radio_button_update_radio_group (gtk_radio_button_group (GTK_RADIO_BUTTON (widget))); } } else { if (g_slist_length (current_group) != 1) { current_group = gb_radio_button_reset_radio_group (widget); gb_radio_button_update_radio_group (current_group); gb_radio_button_update_radio_group (gtk_radio_button_group (GTK_RADIO_BUTTON (widget))); } } } }
/* s = service the command was sent to u = user the command was sent from */ void bs_assign(IRC_User *s, IRC_User *u) { char *channame, *bot_nick; MYSQL_RES *res; MYSQL_ROW row; ChanRecord *cr; IRC_User *user; int bid; channame = strtok(NULL, " "); bot_nick = strtok(NULL, ""); if(IsNull(channame) || *channame=='\0' || IsNull(bot_nick) || *bot_nick=='\0') { send_lang(u, s, BS_ASSIGN_SYNTAX); return; } else { cr = OpenCR(channame); if (!cr) { send_lang(u, s, BS_ASSIGN_NO_SUCH_CHANNEL, channame); return; } bs_group = find_group(AdminRole); if ((u->snid != cr->founder) && !is_sadmin(u->snid) && !is_member_of(u, bs_group)) { send_lang(u, s, BS_ASSIGN_NOT_ALLOWED, channame); return; } res = sql_query("SELECT bid FROM bs_chan WHERE scid=%d", cr->scid); row = sql_next_row(res); if (row) { send_lang(u, s, BS_ASSIGN_ALREADY_ASSIGNED, channame); sql_free(res); return; } sql_free(res); res = sql_query("SELECT bid FROM botserv WHERE nick=%s", sql_str(bot_nick)); row = sql_next_row(res); if (!row) { send_lang(u, s, BS_ASSIGN_NO_SUCH_BOT, bot_nick); sql_free(res); return; } bid = atoi(row[0]); sqlb_init("bs_chan"); sqlb_add_int("scid", cr->scid); sqlb_add_int("bid", bid); sqlb_add_int("kick", 0); sqlb_add_int("ttb", 0); sqlb_add_int("capsmin", 0); sqlb_add_int("capspercent", 0); sqlb_add_int("floodlines", 0); sqlb_add_int("floodsecs", 0); sqlb_add_int("repeattimes", 0); sqlb_add_int("bantype", 0); sqlb_add_int("banlast", 0); sql_execute("%s", sqlb_insert()); res = sql_query("SELECT bid,scid FROM bs_chan WHERE scid=%d AND bid=%d", cr->scid, bid); if (!res) { send_lang(u, s, BS_ASSIGN_FAILED, bot_nick, bid, channame); return; } sql_free(res); user = irc_FindLocalUser(bot_nick); if (user) { IRC_Chan *chan = irc_ChanJoin(user, channame, 0); irc_ChanMode(bsu->u, chan, "+ao %s %s", user->nick, user->nick); } send_lang(u, s, BS_ASSIGN_DONE, bot_nick, channame); return; } return; }
/* s = service the command was sent to u = user the command was sent from */ void bs_unassign(IRC_User *s, IRC_User *u) { char *channame; MYSQL_RES *res; MYSQL_ROW row; ChanRecord *cr; IRC_User *user; int bid; channame = strtok(NULL, ""); if(IsNull(channame) || *channame=='\0') { send_lang(u, s, BS_UNASSIGN_SYNTAX); return; } else { cr = OpenCR(channame); if (!cr) { send_lang(u, s, BS_UNASSIGN_NO_SUCH_CHANNEL, channame); return; } bs_group = find_group(AdminRole); if ((u->snid != cr->founder) && !is_sadmin(u->snid) && !is_member_of(u, bs_group)) { send_lang(u, s, BS_UNASSIGN_NOT_ALLOWED, channame); return; } res = sql_query("SELECT bid FROM bs_chan WHERE scid=%d", cr->scid); row = sql_next_row(res); if (!row) { send_lang(u, s, BS_UNASSIGN_NOT_ASSIGNED, channame); sql_free(res); return; } sql_free(res); bid = atoi(row[0]); res = sql_query("SELECT nick FROM botserv WHERE bid=%d", bid); row = sql_next_row(res); user = irc_FindLocalUser(row[0]); if (user) { IRC_Chan *chan = irc_FindChan(channame); irc_ChanPart(user, chan); } sql_execute("DELETE FROM bs_chan WHERE bid=%d AND scid=%d", bid, cr->scid); send_lang(u, s, BS_UNASSIGN_DONE, user->nick, channame); return; } return; }
void message_handle(kolibri_IPC_message_t *message){ char *msg = (char *)message+sizeof(kolibri_IPC_message_t); char cmd = msg[0]; thread_list_t *thread = find_tid(main_group_list, message->tid); group_list_t *group; int i; if (cmd == KOBRA_CMD_REGISTER && !thread) { kobra_register(message->tid); } else if (thread) { switch (cmd) { case KOBRA_CMD_JOIN: if (message->length < 3 || msg[message->length-1] != '\0') { // Here should be some error handler return; } if (!(group = find_group(msg+1))){ group = create_group(msg+1); } add_to_group(group, message->tid); break; case KOBRA_CMD_UNJOIN: if (message->length < 3 || msg[message->length-1] != '\0') { // Here should be some error handler return; } if ((group = find_group(msg+1)) && (thread = find_tid(group, message->tid))) { remove_from_group(group, thread); } break; case KOBRA_CMD_SEND: if (message->length < 4) { // Here should be some error handler return; } // Check if group name is correct for (i = 1; i < message->length-1 && msg[i]; ++i); if (msg[i]) { // Here should be some error handler return; } group = find_group(msg+1); if (!group) { // Here should be some error handler return; } send_group_message(group, message->tid, msg+i+1, message->length-i-1); break; case KOBRA_CMD_GET_LIST_NAME: // This is temporary realisation kolibri_IPC_send(message->tid, KOBRA_MEMAREA_NAME, KOBRA_MEMAREA_NAME_LENGTH); default: // Here should be some error handler return; } } }
/** * This is the main message reading loop. Messages are read, validated, * decrypted if necessary, then passed to the appropriate routine for handling. */ void mainloop(void) { struct uftp_h *header; struct group_list_t *group; unsigned char *buf, *decrypted, *message; char rxname[INET6_ADDRSTRLEN]; unsigned int decryptlen, meslen; int packetlen, rval, i, ecn; uint8_t version, *func, tos; uint16_t txseq; union sockaddr_u src; struct timeval *tv, rxtime; double new_grtt; log2(0, 0, 0, "%s", VERSIONSTR); for (i = 0; i < key_count; i++) { if (privkey_type[i] == KEYBLOB_RSA) { log2(0, 0, 0, "Loaded %d bit RSA key with fingerprint %s", RSA_keylen(privkey[i].rsa) * 8, print_key_fingerprint(privkey[i], KEYBLOB_RSA)); } else { log2(0, 0, 0, "Loaded ECDSA key with curve %s and fingerprint %s", curve_name(get_EC_curve(privkey[i].ec)), print_key_fingerprint(privkey[i], KEYBLOB_EC)); } } buf = safe_calloc(MAXMTU, 1); decrypted = safe_calloc(MAXMTU, 1); header = (struct uftp_h *)buf; while (1) { tv = getrecenttimeout(); if (tv) { log5(0, 0, 0, "read timeout: %d.%06d", tv->tv_sec, tv->tv_usec); } if (read_packet(listener, &src, buf, &packetlen, MAXMTU, tv, &tos) <= 0) { continue; } gettimeofday(&rxtime, NULL); if ((rval = getnameinfo((struct sockaddr *)&src, family_len(src), rxname, sizeof(rxname), NULL, 0, NI_NUMERICHOST)) != 0) { log1(0, 0, 0, "getnameinfo failed: %s", gai_strerror(rval)); } if (header->version == UFTP_VER_NUM) { version = header->version; group = find_group(ntohl(header->group_id), header->group_inst); } else { log1(0, 0, 0, "Invalid message from %s: not uftp packet " "or invalid version", rxname); continue; } if (packetlen < sizeof(struct uftp_h) + 4) { log1(0, 0, 0, "Invalid packet size from %s: %d", rxname, packetlen); continue; } txseq = htons(header->seq); // A KEY_INFO or ABORT could come from a proxy, so don't check the seq // TODO: need to account for these in the loss history if ((group != NULL) && (header->func != KEYINFO) && (header->func != ABORT)) { if ((int16_t)(group->max_txseq - txseq) > MAXMISORDER) { glog3(group, "seq out of range, dropping"); continue; } if (group->cc_type != CC_NONE) { ecn = ((tos & 0x3) == 3); update_loss_history(group, txseq, packetlen, ecn); } else if ((int16_t)(txseq - group->max_txseq) > 0) { group->max_txseq = txseq; } } if ((header->func == ENCRYPTED) && (group != NULL) && (group->keytype != KEY_NONE)) { if (group->phase == PHASE_REGISTERED) { glog1(group, "Got encrypted packet from %s " "but keys not established", rxname); } if (!validate_and_decrypt(buf, packetlen, &decrypted, &decryptlen, group->keytype, group->groupkey, group->groupsalt, group->ivlen, group->hashtype, group->grouphmackey, group->hmaclen, group->sigtype, group->keyextype, group->server_pubkey, group->server_pubkeylen)) { glog1(group, "Rejecting message from %s: " "decrypt/validate failed", rxname); continue; } func = (uint8_t *)decrypted; message = decrypted; meslen = decryptlen; } else { if ((group != NULL) && (group->keytype != KEY_NONE) && ((header->func == FILEINFO) || (header->func == FILESEG) || (header->func == DONE) || (header->func == DONE_CONF) || ((header->func == ABORT) && (group->phase != PHASE_REGISTERED)))) { glog1(group, "Rejecting %s message from %s: not encrypted", func_name(header->func), rxname); continue; } func = (uint8_t *)&header->func; message = buf + sizeof(struct uftp_h); meslen = packetlen - sizeof(struct uftp_h); } if (group != NULL) { new_grtt = unquantize_grtt(header->grtt); if (fabs(new_grtt - group->grtt) > 0.001) { group->grtt = new_grtt; set_timeout(group, 1); } group->gsize = unquantize_gsize(header->gsize); glog5(group, "grtt: %.3f", group->grtt); } if (header->func == PROXY_KEY) { handle_proxy_key(&src, message, meslen); continue; } if (header->func == HB_RESP) { handle_hb_response(listener, &src, message, meslen, hb_hosts, hbhost_count, privkey[0], privkey_type[0], uid); continue; } if (header->func == ANNOUNCE) { // Ignore any ANNOUNCE for a group we're already handling if (group == NULL) { handle_announce(&src, buf, packetlen, rxtime); } else if (group->phase == PHASE_MIDGROUP) { // Make sure we don't time out while waiting for other // clients to register with the server. set_timeout(group, 0); } } else { if (group == NULL) { // group / file ID not in list continue; } if (group->version != version) { glog1(group, "Version mismatch"); continue; } if (group->src_id != header->src_id) { glog1(group, "Source ID mismatch"); continue; } if (*func == ABORT) { handle_abort(group, message, meslen); continue; } switch (group->phase) { case PHASE_REGISTERED: if (group->keytype != KEY_NONE) { if (*func == KEYINFO) { handle_keyinfo(group, message, meslen, header->src_id); } else { glog1(group, "Expected KEYINFO, got %s", func_name(*func)); } } else if (group->keytype == KEY_NONE) { if (*func == REG_CONF) { handle_regconf(group, message, meslen); } else if (*func == FILEINFO) { handle_fileinfo(group, message, meslen, rxtime); } else { glog1(group, "Expected REG_CONF, got %s", func_name(*func)); } } break; case PHASE_MIDGROUP: if (*func == FILEINFO) { handle_fileinfo(group, message, meslen, rxtime); } else if (*func == KEYINFO) { handle_keyinfo(group, message, meslen, header->src_id); } else if (*func == DONE) { handle_done(group, message, meslen); } else { // Other clients may be still getting earlier files or // setting up, so silently ignore anything unexpected // and reset the timeout. set_timeout(group, 0); } break; case PHASE_RECEIVING: if (*func == FILEINFO) { handle_fileinfo(group, message, meslen, rxtime); } else if (*func == FILESEG) { handle_fileseg(group, message, meslen, txseq); } else if (*func == DONE) { handle_done(group, message, meslen); } else if (*func == CONG_CTRL) { handle_cong_ctrl(group, message, meslen, rxtime); } break; case PHASE_COMPLETE: if (*func == DONE_CONF) { handle_done_conf(group, message, meslen); } break; } } } }
/* s = service the command was sent to u = user the command was sent from */ void ns_group(IRC_User *s, IRC_User *u) { u_int32_t source_snid; u_int32_t snid; char *cmd; char *gname; char *nick; int memberc = 0; u_int32_t master_sgid; u_int32_t sgid; CHECK_IF_IDENTIFIED_NICK cmd = strtok(NULL, " "); gname = strtok(NULL, " "); /* base syntax validation */ if(IsNull(cmd)) send_lang(u, s, NS_GROUP_SYNTAX); else if(strcasecmp(cmd,"CREATE") == 0) { char *master; char *gdesc; char *umodes = NULL; master = strtok(NULL, " "); gdesc = strtok(NULL, ""); if(gname) /* first check if the name contains umodes */ { char *pumodes; char *eumodes; pumodes = strchr(gname,'['); if(pumodes && pumodes[0]) { *(pumodes++) = '\0'; eumodes = strchr(pumodes,']'); if(eumodes) { *eumodes = '\0'; umodes = pumodes; } } } /* syntax validation */ if(IsNull(gname) || IsNull(master)) send_lang(u, s, NS_GROUP_CREATE_SYNTAX); /* permissions validation */ else if(!is_sroot(source_snid)) send_lang(u, s, NICK_NOT_ROOT); /* check requirements */ else if((master_sgid = find_group(master)) == 0) send_lang(u, s, NS_GROUP_MASTER_NOT_FOUND, master); /* avoid duplicates */ else if((sgid = find_group(gname)) != 0) send_lang(u, s, NS_GROUP_ALREADY_EXISTS, gname); /* execute operation */ else if(group_create(gname, master_sgid, gdesc, umodes) > 0) /* report operation status */ send_lang(u, s, NS_GROUP_CREATE_OK, gname); else send_lang(u, s, UPDATE_FAIL); } else if(strcasecmp(cmd,"ADD") == 0) { u_int32_t duration = 0; time_t master_expire = 0; u_int32_t is_master_sgid; char *duration_str; nick = strtok(NULL, " "); duration_str = strtok(NULL, " "); if(duration_str) duration = time_str(duration_str); /* syntax validation */ if(IsNull(gname) || IsNull(nick)) send_lang(u, s, NS_GROUP_ADD_SYNTAX); /* check requirements */ else if((snid = nick2snid(nick)) == 0) send_lang(u, s, NO_SUCH_NICK_X, nick); else if((sgid = find_group(gname)) == 0) send_lang(u, s, NO_SUCH_GROUP_X, gname); /* privileges validation */ else if(group_is_full(sgid)) send_lang(u, s, NS_GROUP_IS_FULL_X); else if(((is_master_sgid = is_master(source_snid, sgid))== 0) && !is_sroot(source_snid)) send_lang(u, s, NOT_MASTER_OF_X, gname); /* avoid duplicates */ else if(sql_singlequery("SELECT t_expire FROM ns_group_users " " WHERE sgid=%d AND snid=%d", is_master_sgid, source_snid) && (master_expire = sql_field_i(0)) && duration) send_lang(u, s, NS_GROUP_CANT_DEFINE_TIME_X, gname); else if(is_member_of(snid, sgid)) send_lang(u, s, NICK_X_ALREADY_ON_X, nick, gname); /* execute operation */ else { time_t t_expire = 0; if(master_expire) t_expire = master_expire; else if(duration) t_expire = irc_CurrentTime + duration; if(add_to_group(sgid, snid, t_expire) > 0) /* report operation status */ { char *server = strchr(gname, '@'); IRC_User *user = irc_FindUser(nick); send_lang(u, s, NICK_ADDED_X_X, nick, gname); if(server) /* we have a server rule to be validated */ ++server; if(user && (!server || (strcasecmp(server,u->server->sname) == 0))) { if(user->extra[ED_GROUPS] == NULL) { user->extra[ED_GROUPS] = malloc(sizeof(darray)); array_init(user->extra[ED_GROUPS], 1, DA_INT); } array_add_int(user->extra[ED_GROUPS], sgid); } } else send_lang(u, s, UPDATE_FAIL); } } else if(strcasecmp(cmd,"DEL") == 0) { nick = strtok(NULL, " "); /* syntax validation */ if(IsNull(gname) || IsNull(nick)) send_lang(u, s, NS_GROUP_DEL_SYNTAX); /* check requirements */ else if((sgid = find_group(gname)) == 0) send_lang(u, s, NO_SUCH_GROUP_X, gname); else if((snid = nick2snid(nick)) == 0) send_lang(u, s, NO_SUCH_NICK_X, nick); /* privileges validation */ else if(!is_sroot(source_snid) && !is_master(source_snid, sgid)) send_lang(u, s, NOT_MASTER_OF_X, gname); else if(!is_member_of(snid, sgid)) send_lang(u, s, NICK_X_NOT_ON_GROUP_X, nick, gname); /* execute operation */ else if(del_from_group(sgid, snid) > 0) /* report operation status */ { IRC_User *user = irc_FindUser(nick); send_lang(u, s, NICK_DEL_X_X, nick, gname); if(user) array_del_int(user->extra[ED_GROUPS], sgid); } else send_lang(u, s, UPDATE_FAIL); } else if(strcasecmp(cmd,"INFO") == 0) { /* syntax validation */ if(IsNull(gname)) send_lang(u, s, NS_GROUP_INFO_SYNTAX); /* check requirements */ else if((sgid = find_group(gname)) == 0) send_lang(u, s, NO_SUCH_GROUP_X, gname); /* check privileges */ else if(!is_master(source_snid, sgid) && !is_member_of(source_snid, sgid)) send_lang(u, s, NOT_MASTER_OR_MEMBER_X, gname); else if((sgid = find_group(gname))) /* we need to get the group description */ { /* execute operation */ MYSQL_RES* res; master_sgid = 0; sql_singlequery("SELECT gdesc, master_sgid FROM ns_group WHERE sgid=%d", sgid); send_lang(u, s, NS_GROUP_INFO_X, gname); if(sql_field(0)) send_lang(u, s, NS_GROUP_INFO_DESC_X, sql_field(0)); master_sgid = sql_field_i(1); if(master_sgid != 0) { if(sql_singlequery("SELECT name FROM ns_group WHERE sgid=%d", master_sgid) > 0) { send_lang(u, s, NS_GROUP_INFO_MASTER_X, sql_field(0)); } } res = sql_query("SELECT n.nick, gm.t_expire FROM " "nickserv n, ns_group_users gm WHERE gm.sgid=%d AND n.snid=gm.snid", sgid); if(sql_next_row(res) == NULL) send_lang(u, s, NS_GROUP_EMPTY); else { do { char buf[64]; struct tm *tm; time_t t_expire = sql_field_i(1); buf[0] = '\0'; if(t_expire) { tm = localtime(&t_expire); strftime(buf, sizeof(buf), format_str(u, DATE_FORMAT), tm); send_lang(u,s, NS_GROUP_ITEM_X_X, sql_field(0), buf); } else send_lang(u,s, NS_GROUP_ITEM_X, sql_field(0)); ++memberc; } while(sql_next_row(res)); send_lang(u, s, NS_GROUP_MEMBERS_TAIL_X, memberc); } sql_free(res); } } else if(strcasecmp(cmd,"DROP") == 0) { /* syntax validation */ if(IsNull(gname)) send_lang(u, s, NS_GROUP_DROP_SYNTAX); /* privileges validation */ else if(!is_sroot(source_snid)) send_lang(u, s, NICK_NOT_ROOT); /* check requirements */ else if((sgid = find_group(gname)) == 0) send_lang(u, s, NO_SUCH_GROUP_X, gname); /* NOTE: The following sql_field( depends on previous find_group( */ else if(!sql_field(2) || (master_sgid = atoi(sql_field(2))) == 0) send_lang(u, s, CANT_DROP_ROOT); /* execute operation */ else if(drop_group(sgid)>0) /* report operation status */ send_lang(u, s, NS_GROUP_DROPPED_X, gname); else send_lang(u, s, UPDATE_FAIL); } else if(strcasecmp(cmd,"LIST") == 0) /* List groups */ { MYSQL_RES* res; MYSQL_ROW row; /* privileges validation */ if(!is_sroot(source_snid)) send_lang(u, s, NICK_NOT_ROOT); else { res = sql_query("SELECT name, master_sgid, gdesc FROM ns_group"); send_lang(u, s, NS_GROUP_LIST_HEADER); while((row = sql_next_row(res))) { char* mname = ""; if(row[1] && sql_singlequery("SELECT name FROM ns_group WHERE sgid=%d", atoi(row[1])) > 0) mname = sql_field(0); send_lang(u, s, NS_GROUP_LIST_X_X_X, row[0], mname, row[2] ? row[2] : ""); } send_lang(u, s, NS_GROUP_LIST_TAIL); sql_free(res); } } else if(strcasecmp(cmd,"SHOW") == 0) /* Show groups we belong to */ { /* groups count */ int gc = array_count(u->extra[ED_GROUPS]); if(gc == 0) send_lang(u, s, NO_GROUPS); else { MYSQL_RES *res; MYSQL_ROW row; char buf[64]; struct tm *tm; time_t t_expire; #if 0 int i; u_int32_t* data = array_data_int(u->extra[ED_GROUPS]); #endif send_lang(u, s, NS_GROUP_SHOW_HEADER); #if 0 for(i = 0; i < gc; ++i) { if(sql_singlequery("SELECT name,gdesc FROM ns_group WHERE sgid=%d", data[i]) > 0 ) send_lang(u, s, NS_GROUP_SHOW_X_X, sql_field(0), sql_field(1) ? sql_field(1) : ""); } #endif res = sql_query("SELECT g.name, g.gdesc, gu.t_expire FROM ns_group g, ns_group_users gu" " WHERE gu.snid=%d AND g.sgid=gu.sgid ORDER BY g.master_sgid", source_snid); while((row = sql_next_row(res))) { t_expire = sql_field_i(2); buf[0] = '\0'; if(t_expire) { tm = localtime(&t_expire); strftime(buf, sizeof(buf), format_str(u, DATE_FORMAT), tm); send_lang(u,s, NS_GROUP_SHOW_X_X_X, row[0], row[1] ? row[1] : "", buf); } else send_lang(u, s, NS_GROUP_SHOW_X_X, row[0], row[1] ? row[1] : ""); } send_lang(u, s, NS_GROUP_SHOW_TAIL); sql_free(res); } } else if(strcasecmp(cmd,"SET") == 0) { char *option; char *value ; option = strtok(NULL, " "); value = strtok(NULL, " "); /* syntax validation */ if(IsNull(gname) || IsNull(option)) send_lang(u, s, NS_GROUP_SET_SYNTAX); /* privileges validation */ else if(!is_sroot(source_snid)) send_lang(u, s, NICK_NOT_ROOT); /* check requirements */ else if((sgid = find_group(gname)) == 0) send_lang(u, s, NO_SUCH_GROUP_X, gname); else { if(strcasecmp(option,"AUTOMODES") == 0) STRING_SET("autoumodes", AUTOMODES_X_UNSET, AUTOMODES_X_CHANGED_TO_X) else if(strcasecmp(option,"DESC") == 0) STRING_SET("gdesc", DESC_X_UNSET, DESC_X_CHANGED_TO_X) else if(strcasecmp(option, "MAXUSERS") == 0) INT_SET("maxusers", NS_GROUP_SET_MAXUSERS_SET_X_X) else send_lang(u, s, SET_INVALID_OPTION_X, option); } }
int main(int ac, char **av) { struct database *db; struct group *group = NULL; char *line = NULL; size_t linesz = 0; if (!av[1]) { printf("%s database\n", av[0]); exit(1); } printf("dbtest\n"); db = open_db(av[1], 1); while (printf("> "), fflush(stdout), getline(&line, &linesz, stdin) > 0) { char *p = line + strlen(line) - 1; while (p >= line && isspace(*p)) *p-- = 0; switch (line[0]) { case 's': C(sync_db(db)); break; case 'q': C(close_db(db)); exit(0); case 'g': group = find_group(db, line + 1); if (group) printf("found\n"); break; case 'G': NEEDGROUP; C(delete_group(db, group)); group = NULL; break; case 'a': { int existed = 0; group = add_group(db, line + 1, &existed); if (existed) printf("existed\n"); break; } case 'v': NEEDGROUP; printf("%s\n", entry_val(group, line + 1)); break; case 'c': { p = line + 1; char *entry = strsep(&p, ","); NEEDGROUP; change_entry(db, group, entry, strsep(&p, "")); break; } case 'L': NEEDGROUP; clone_group(db, group, line + 1); break; case 'f': { struct group *g; p = line + 1; char *entry = strsep(&p, ","); char *val = strsep(&p, ""); g = NULL; int nr = 0; while ((g = find_entry(db, g, entry, val)) != NULL) { if (nr == 0) group = g; nr++; dump_group(group, stdout); } if (nr == 0) printf("not found\n"); break; } case 'C': NEEDGROUP; add_comment(db, group, line + 1); break; case 'd': NEEDGROUP; dump_group(group, stdout); break; case 'D': dump_database(db, stdout); break; default: usage(); break; } } return 0; }
/** * This is the main message reading loop. Messages are read, validated, * decrypted if necessary, then passed to the appropriate routine for handling. */ void mainloop() { struct uftp_h *header; unsigned char *buf, *decrypted, *message; int packetlen, listidx, hostidx, i; unsigned int decryptlen, meslen; uint8_t *func; struct sockaddr_in src; struct in_addr srcaddr; struct timeval *tv; const int bsize = 9000; // Roughly size of ethernet jumbo frame log0(0, 0, "%s", VERSIONSTR); for (i = 0; i < key_count; i++) { log(0, 0, "Loaded key with fingerprint %s", print_key_fingerprint(privkey[i])); } buf = calloc(bsize, 1); decrypted = calloc(bsize, 1); if ((buf == NULL) || (decrypted == NULL)) { syserror(0, 0, "calloc failed!"); exit(1); } header = (struct uftp_h *)buf; while (1) { tv = getrecenttimeout(); if (read_packet(listener, &src, buf, &packetlen, bsize, tv) <= 0) { continue; } if ((header->uftp_id != UFTP_VER_NUM) && (header->uftp_id != UFTP_3_0_VER)) { log(0, 0, "Invalid message from %s: not uftp packet " "or invalid version", inet_ntoa(src.sin_addr)); continue; } if (packetlen != sizeof(struct uftp_h) + ntohs(header->blsize)) { log(0, 0, "Invalid packet size from %s: got %d, expected %d", inet_ntoa(src.sin_addr), packetlen, sizeof(struct uftp_h) + ntohs(header->blsize)); continue; } if ((src.sin_addr.s_addr == out_addr.s_addr) && (src.sin_port == htons(port))) { // Packet from self -- drop continue; } if (header->func == HB_REQ) { handle_hb_request(&src, buf); continue; } if (header->func == HB_RESP) { handle_hb_response(listener, &src, buf, hb_hosts, hbhost_count, noname, privkey[0]); continue; } if (header->func == KEY_REQ) { handle_key_req(&src, buf); continue; } if (header->func == PROXY_KEY) { // Only clients handle these, so drop continue; } if ((proxy_type == SERVER_PROXY) && (down_addr.sin_addr.s_addr == INADDR_ANY)) { log(0, 0, "Rejecting message from %s: downstream address " "not established", inet_ntoa(src.sin_addr)); continue; } listidx = find_group(ntohl(header->group_id)); if (header->func == ANNOUNCE) { handle_announce(listidx, &src, buf); } else { if (listidx == -1) { continue; } if (proxy_type == SERVER_PROXY) { // Server proxies don't do anything outside of an ANNOUNCE. // Just send it on through. forward_message(listidx, &src, buf); continue; } if (header->func == ABORT) { handle_abort(listidx, &src, buf); continue; } if (!memcmp(&src, &group_list[listidx].up_addr, sizeof(src))) { // Downstream message if (header->func == KEYINFO) { handle_keyinfo(listidx, buf); } else if ((header->func == REG_CONF) && (group_list[listidx].keytype != KEY_NONE)) { handle_regconf(listidx, buf); } else { // If we don't need to process the message, don't bother // decrypting anything. Just forward it on. forward_message(listidx, &src, buf); } } else { // Upstream message // Decrypt first if necessary hostidx = find_client(listidx, header->srcaddr); if ((hostidx != -1) && (header->func == ENCRYPTED) && (group_list[listidx].keytype != KEY_NONE)) { if (!validate_and_decrypt(buf, &decrypted, &decryptlen, group_list[listidx].mtu,group_list[listidx].keytype, group_list[listidx].groupkey, group_list[listidx].groupsalt, group_list[listidx].ivlen, group_list[listidx].hashtype, group_list[listidx].grouphmackey, group_list[listidx].hmaclen, group_list[listidx].sigtype, group_list[listidx].destinfo[hostidx].pubkey, group_list[listidx].destinfo[hostidx].pubkeylen)) { log(ntohl(header->group_id), 0, "Rejecting message " "from %s: decrypt/validate failed", inet_ntoa(src.sin_addr)); continue; } func = (uint8_t *)decrypted; message = decrypted; meslen = decryptlen; } else { if ((hostidx != -1) && (group_list[listidx].keytype != KEY_NONE) && ((header->func == INFO_ACK) || (header->func == STATUS) || (header->func == COMPLETE))) { log(ntohl(header->group_id), 0, "Rejecting %s message " "from %s: not encrypted", func_name(header->func), inet_ntoa(src.sin_addr)); continue; } func = (uint8_t *)&header->func; message = buf + sizeof(struct uftp_h); meslen = ntohs(header->blsize); } if ((hostidx == -1) && (header->srcaddr == 0)) { srcaddr = src.sin_addr; } else { srcaddr.s_addr = header->srcaddr; } switch (*func) { case REGISTER: handle_register(listidx, hostidx, message, meslen, srcaddr.s_addr); break; case CLIENT_KEY: handle_clientkey(listidx, hostidx, message, meslen, srcaddr.s_addr); break; case INFO_ACK: handle_info_ack(listidx, hostidx, message, meslen); break; case STATUS: handle_status(listidx, hostidx, message, meslen); break; case COMPLETE: handle_complete(listidx, hostidx, message, meslen); break; default: forward_message(listidx, &src, buf); break; } } } } }
void main_loop(pDataStruct workingData){ char *commandList[] = {"set", "get", "add", "delete","exit","help","ls","cat","cd"}; char *setList[] = {"date", "user", "group","help"}; char *getList[] = {"date", "user", "group", "workingDir","help", "userlist", "grouplist", "usersingroup"}; char *addList[] = {"user", "group", "file", "directory", "usertogroup","perm", "appendfile","help"}; char *deleteList[] = {"user", "group", "file", "directory", "usertogroup","perm", "filebytes","help"}; char arg[16][MAXCOMMAND]; char command[MAXCOMMAND]; int argnum, i, j, tempNum, cmd, size; char *c; char temp[MAXPATH]; char *tempBuf; unsigned char *rcvBuf; pNode tempNode = NULL; pUser tempUser = NULL; pGroup tempGroup = NULL; pFile tempFile = NULL; pPerms tempPerms = NULL; pFileChunk tempFileChunk = NULL; pGroupUserList tempGroupUserList = NULL; while(1){ argnum = i = j = tempNum = cmd = 0; c = 0; bzero(temp, sizeof(temp)); tempBuf = NULL; tempNode = NULL; tempUser = NULL; tempGroup = NULL; tempFile = NULL; tempPerms = NULL; tempFileChunk = NULL; tempGroupUserList = NULL; bzero(command, sizeof(command)); print_prompt(workingData); get_string(command, MAXCOMMAND-1, ""); for (j = 0;j<16;j++){ bzero(arg[j],MAXCOMMAND); } argnum = parse_arg(arg, command); tempNum = 0; cmd = 100; for (i=0;i<sizeof(commandList)/4;i++){ if (strcmp(commandList[i],arg[0]) == 0 ){ cmd = i; } } switch(cmd) { case 0x0 : //set cmd = 100; for (i=0;i<sizeof(setList)/4;i++){ if (strcmp(setList[i],arg[1]) == 0){ cmd = i; } } switch(cmd) { case 0 : //set date workingData->date = get_time(); break;//end set date case 1 : //set user if ( strcmp(arg[2],"") == 0){ puts("missing user name or number"); break; } tempUser = find_user(arg[2],workingData); if ( tempUser != NULL ){ workingData->currentUser = tempUser; } else { printf("unknown user: @s\n",arg[2]); } break;//end set user case 2 : //set group if ( strcmp(arg[2], "") == 0){ puts("missing group name or number"); break; } tempGroup = find_group(arg[2], workingData); if ( tempGroup != NULL){ workingData->currentGroup = tempGroup; } else { printf("unknown group: @s\n",arg[2]); } break; case 3 : //set help print_help(setList,(sizeof(setList)/4)); break;//end set help default : printf("Invalid command: @s\n",arg[1]); } break;//end set case 1 ://get cmd = 100; for (i=0;i<sizeof(getList)/4;i++){ if (strcmp(getList[i],arg[1]) == 0){ cmd = i; } } switch(cmd) { case 0 : //get date strofdate( workingData->date); break;//end get date case 1 : //get user printf("@s\n",workingData->currentUser->name); break;//end get user case 2 : //get group printf("@s\n",workingData->currentGroup->name); break;//end get group case 3 : //get workingDir bzero(temp,MAXPATH); str_of_path( temp, workingData, workingData->workingDir); printf("@s/\n",temp); break;//end get workingDir case 4 : //get help print_help(getList,(sizeof(getList)/4)); break;//end get help case 5 : //get userlist print_user_list(workingData); break;//end get userlist case 6 : //get grouplist print_group_list(workingData); break;//end get grouplist case 7 : //get usersingroup if ( strcmp(arg[2], "") == 0){ puts("missing group name or number"); break; } tempGroup = find_group(arg[2], workingData); if ( tempGroup != NULL ){ print_users_in_group(tempGroup); break; } printf("unknown group: @s\n",arg[2]); break;//end get useringroup default : printf("Invalid command: @s\n",arg[1]); } break;//end get case 2 ://add cmd = 100; for (i=0;i<sizeof(addList)/4;i++){ if ( strcmp(addList[i],arg[1]) == 0 ){ cmd = i; } } switch(cmd) { case 0 : //add user if ( strcmp(arg[2],"") == 0 ){ bzero(temp,MAXPATH); get_string(temp, 128, "UserName"); strcpy(arg[2],temp); } tempUser = find_user( arg[2], workingData); if ( tempUser == NULL ){ add_user( arg[2], workingData ); } else { puts("Username already in use"); } break;//end add user case 1 : //add group if ( strcmp(arg[2],"") == 0 ){ bzero(temp,MAXPATH); get_string(temp, 128, "GroupName"); strcpy(arg[2], temp); } tempGroup = find_group( arg[2], workingData); if ( tempGroup == NULL ){ add_group( arg[2], workingData ); } else { puts("Groupname already in use"); } break;//end add group case 2 : //add file //add file name size tempNum = atoi(arg[3]); if (strcmp(arg[2],"") == 0){ puts("Filename required"); break; } if ( tempNum > MAXUPLOAD ){ puts("Too big"); break; } if ( find_node_by_name(arg[2],workingData->workingDir->directoryHeadNode) != NULL ){ puts("There is another file or directory with that name"); break; } if ( tempNum > 0){ rcvBuf = mallocOrDie(tempNum,"Failed to allocate tempBuf"); puts("-----Begin File-----");//five - if ( tempNum != receive_bytes(rcvBuf,tempNum) ){ die("Failed to reveive file"); break; } } else {rcvBuf = NULL;} tempNode = add_file( workingData->workingDir, workingData->date, tempNum, arg[2], (char *)rcvBuf, workingData->currentUser ); break;//end add file case 3 : //add directory if (strcmp(arg[2],"") == 0){ puts("Directory name required"); break; } if ( find_node_by_name(arg[2],workingData->workingDir->directoryHeadNode) != NULL ){ puts("There is another file or directory with that name"); break; } tempNode = add_directory( workingData->date, arg[2], workingData->workingDir, workingData->currentUser ); break;//end add directory case 4 : //add useringroup if (strcmp(arg[2],"") == 0){ puts("username or number required"); break; } tempUser = find_user( arg[2], workingData); if ( tempUser != NULL ){//user exists tempGroupUserList = is_user_in_group( tempUser, workingData->currentGroup ); if ( tempGroupUserList == NULL ){//user is not already in group add_user_to_group( tempUser, workingData->currentGroup ); } else {printf("@s is already in @s\n",arg[2], workingData->currentGroup->name);} } else { puts("User does not exist, add user first"); } break;//end add useringroup case 5 : //add perm if ( ( strcmp(arg[2],"") == 0 )||( strcmp(arg[2]," ") == 0 ) ){//arg[2] name of file or dir puts("name of file or directory required"); break; } if (!( (strcmp(arg[3],"user") == 0) ^ (strcmp(arg[3],"group") == 0) )) {//arg[3] user, group puts("'user' or 'group'"); break; } if (strcmp(arg[4],"") == 0){ puts("user name, group name, or number required");//arg[4] name or number of user or group break; } tempNode = find_node_by_name(arg[2],workingData->workingDir->directoryHeadNode );//validate file or dir if (tempNode == NULL){ puts("Invalid file or directory"); break; } if (tempNode->type == LINK){ tempNode = tempNode->directoryHeadNode; break; } if (strcmp(arg[3],"user") == 0){ tempUser = find_user(arg[4],workingData); tempGroup = NULL; if (tempUser == NULL){ printf("user @s not found\n",arg[4]); break; } } else { tempGroup = find_group(arg[4],workingData); tempUser = NULL; if (tempGroup == NULL){ printf("group @s not found\n",arg[4]); break; } } validate_current_perms(tempNode, workingData); tempPerms = add_perm(tempUser, tempGroup, tempNode ); break;//end add perm case 6 : //add appendfile tempNum = atoi(arg[3]); if (strcmp(arg[2],"") == 0){ puts("Filename required"); break; } if ( tempNum > MAXUPLOAD ){ puts("Too big"); break; } tempFile = find_file_by_name(arg[2],workingData->workingDir); if ( tempFile == NULL ){ puts("No file in working directory by that name"); break; } if ( tempNum > 0){ tempBuf = mallocOrDie(tempNum,"Failed to allocate tempBuf"); puts("-----Begin File-----");//five - if ( tempNum != receive_bytes((unsigned char *)tempBuf,tempNum) ){ die("Failed to reveive file"); break; } } else { tempBuf = NULL; puts("Can not add 0 bytes to file"); break; } tempFileChunk = add_file_chunk( tempBuf, tempFile, tempNum ); break;//end add appendfile case 7 : //add help print_help(addList, (sizeof(addList)/4)); break;//end add help default : printf("Invalid command: @s\n",arg[1]); } break;//end add case 3 ://delete cmd = 100; for (i=0;i<sizeof(deleteList)/4;i++){ if ( strcmp(deleteList[i],arg[1]) == 0 ){ cmd = i; } } switch(cmd) { case 0 : //delete user bzero(temp,MAXPATH); if ( strcmp(arg[2],"") == 0 ){ get_string(temp, 128, "User Name or number"); strcpy(arg[2],temp); } tempUser = find_user( arg[2], workingData); if ( tempUser != NULL ){ remove_user(tempUser , workingData ); } else { puts("No such user found"); } break;//end delete user case 1 : //delete group bzero(temp,MAXPATH); if ( strcmp(arg[2],"") == 0 ){ get_string(temp, 128, "Group Name or number"); strcpy(arg[2],temp); } tempGroup = find_group( arg[2], workingData); if ( tempGroup != NULL ){ remove_group(tempGroup , workingData ); } else { puts("no such group found"); } break;//end delete group case 2 : //delete file if (strcmp(arg[2],"") == 0){ puts("Filename required"); break; } tempNode = find_file_node_by_name(arg[2],workingData->workingDir); if (tempNode == NULL){ puts("No such file"); break; } delete_node(tempNode, workingData); break;//end delete file case 3 : //delete directory if (strcmp(arg[2],"") == 0){ puts("Directory name required"); break; } tempNode = find_directory_by_name(arg[2],workingData->workingDir); if (tempNode == NULL){ puts("No such directory"); break; } delete_node(tempNode, workingData); break;//end delete directory case 4 : //delete usertogroup if (strcmp(arg[2],"") == 0){ puts("User name required"); break; } if (strcmp(arg[3],"") == 0){ puts("group name required"); break; } tempUser = find_user(arg[2],workingData); if (tempUser == NULL){ puts("No such user"); break; } tempGroup = find_group(arg[3],workingData); if (tempGroup == NULL){ puts("No such group"); break; } tempGroupUserList = is_user_in_group(tempUser, tempGroup); if (tempGroupUserList == NULL){ puts("User is not in group"); break; } remove_user_from_group(tempUser, tempGroup); break;//end delete usertogroup case 5 : //delete perm if (strcmp(arg[3],"") == 0){ puts("User or group name required"); break; } if (strcmp(arg[2],"") == 0){ puts("file name required"); break; } tempNode = find_node_by_name(arg[2],workingData->workingDir->directoryHeadNode); if (tempNode == NULL){ puts("No such file"); break; } tempPerms = find_perm_by_name(arg[3],tempNode,workingData); if (tempPerms != NULL){ delete_perms(tempNode, tempPerms); } else { puts("No such user permission on file"); } break;//end delete perm case 6 : //delete filebytes [file] [numbytes] if (strcmp(arg[2],"") == 0){ puts("Filename required"); break; } size = strict_atoi(arg[3]); if (size == 0){ puts("zero bytes deleted"); break; } //validate file tempNode = find_file_node_by_name(arg[2],workingData->workingDir); tempFile = tempNode->file; if (tempNode == NULL){ puts("No such file"); printf("@s\n",arg[2]); break; } tempNum = get_file_size(tempFile); if (size > tempNum){ puts("Too many bytes"); } //tempNum is new file size tempNum = tempNum - size; delete_file_bytes(tempFile, tempNum); break;//end delete file case 7 : //delete help print_help(deleteList, (sizeof(deleteList)/4)); break;//end delete help default: print_help(deleteList, (sizeof(deleteList)/4)); //break;//end delete help } break;//end delete case 4 ://cgc_exit puts("exiting"); goto cgc_exit; break; case 5 ://help print_help(commandList, (sizeof(commandList)/4)); break; case 6 ://ls print_working_dir(workingData); break; case 7 ://cat if (strcmp(arg[1],"") == 0){ puts("Filename required"); break; } tempFile = find_file_by_name(arg[1], workingData->workingDir); if ( tempFile != NULL ){ tempFileChunk = tempFile->head; puts("-----Begin File-----");//five - while ( tempFileChunk != NULL ){ if (tempFileChunk->chunkSize != cgc_write(tempFileChunk,tempFileChunk->chunkSize)){ puts("file write failed"); } /* c = tempFileChunk->chunk; for ( i = 0; i < tempFileChunk->chunkSize; i++ ){//putc each byte of every chunk putc( *c); c++; } */ tempFileChunk = tempFileChunk->next; } puts("-----END File-----");//five - } break; case 8 ://cd if (strcmp(arg[1],"") == 0){ puts("directory required"); break; } if (strcmp(arg[1],"..") == 0){ if (workingData->workingDir->parent != NULL){ workingData->workingDir = workingData->workingDir->parent; } break; } tempNode = find_directory_by_name(arg[1],workingData->workingDir); if ( tempNode != NULL ){ workingData->workingDir = tempNode; break; } puts("No such directory in working directory"); break;//end cd default : printf("Invalid command @s\n",arg[0]); print_help(commandList, (sizeof(commandList)/4)); } } cgc_exit: return; }
/* * Read and process buxfer commands * Return -1 to indicate user has quit * Return 1 to indicate broadcast message must be sent to all other users * Return 0 otherwise */ int process_args(int cmd_argc, char **cmd_argv, Client *c, Pool *p) { Group *g; char *buf; char *username = c->username; if (cmd_argc <= 0) { return 0; } else if (strcmp(cmd_argv[0], "quit") == 0 && cmd_argc == 1) { return -1; // -1 indicates used has quit } else if (strcmp(cmd_argv[0], "add_group") == 0 && cmd_argc == 2) { // add group buf = add_group(&p->group, cmd_argv[1]); Write(c->soc, buf); // add user if ((g = find_group(p->group, cmd_argv[1])) == NULL) { buf = "Cannot add user. Group does not exist"; } else{ buf = add_user(g, username); strncpy(c->groupname, cmd_argv[1], MAXLINE); // set groupname for this client Write(c->soc, buf); return 1; // Return 1 indicates notification should be sent to all other users } } else if (strcmp(cmd_argv[0], "list_groups") == 0 && cmd_argc == 1) { buf = list_groups(p->group); } else if (strcmp(cmd_argv[0], "list_users") == 0 && cmd_argc == 2) { if ((g = find_group(p->group, cmd_argv[1])) == NULL) { buf = "Group does not exist"; } else { buf = list_users(g); } } else if (strcmp(cmd_argv[0], "user_balance") == 0 && cmd_argc == 2) { if ((g = find_group(p->group, cmd_argv[1])) == NULL) { buf = "Group does not exist"; } else { buf = user_balance(g, username); } } else if (strcmp(cmd_argv[0], "add_xct") == 0 && cmd_argc == 3) { if ((g = find_group(p->group, cmd_argv[1])) == NULL) { buf = "Group does not exist"; } else { char *end; double amount = strtod(cmd_argv[2], &end); if (end == cmd_argv[2]) { buf = "Incorrect number format"; } else { buf = add_xct(g, username, amount); } } } else { buf = "Incorrect syntax"; } // Write output to client Write(c->soc, buf); // Write output to client return 0; }