/* Callback: "a message is received to a registered object path" */ static DBusHandlerResult message_received(DBusConnection* conn, DBusMessage* msg, void* data) { const char* member = dbus_message_get_member(msg); VERB1 log("%s(method:'%s')", __func__, member); set_client_name(dbus_message_get_sender(msg)); DBusMessage* reply = dbus_message_new_method_return(msg); int r = -1; if (strcmp(member, "DeleteDebugDump") == 0) r = handle_DeleteDebugDump(msg, reply); // NB: C++ binding also handles "Introspect" method, which returns a string. // It was sending "dummy" introspection answer whick looks like this: // "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\"\n" // "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n" // "<node>\n" // "</node>\n" // Apart from a warning from abrt-gui, just sending error back works as well. // NB2: we may want to handle "Disconnected" here too. if (r < 0) { /* handle_XXX experienced an error (and did not send any reply) */ dbus_message_unref(reply); if (dbus_message_get_type(msg) == DBUS_MESSAGE_TYPE_METHOD_CALL) { /* Create and send error reply */ reply = dbus_message_new_error(msg, DBUS_ERROR_FAILED, "not supported"); if (!reply) die_out_of_memory(); send_flush_and_unref(reply); } } set_client_name(NULL); return DBUS_HANDLER_RESULT_HANDLED; }
/* register new midi synth port */ int snd_seq_midisynth_register_port(snd_seq_device_t *dev) { seq_midisynth_client_t *client; seq_midisynth_t *msynth, *ms; snd_seq_port_info_t port; snd_rawmidi_info_t info; int newclient = 0; unsigned int p, ports; snd_seq_client_callback_t callbacks; snd_seq_port_callback_t pcallbacks; snd_card_t *card = dev->card; int device = dev->device; unsigned int input_count = 0, output_count = 0; snd_assert(card != NULL && device >= 0 && device < SNDRV_RAWMIDI_DEVICES, return -EINVAL); info.device = device; info.stream = SNDRV_RAWMIDI_STREAM_OUTPUT; info.subdevice = 0; if (snd_rawmidi_info_select(card, &info) >= 0) output_count = info.subdevices_count; info.stream = SNDRV_RAWMIDI_STREAM_INPUT; if (snd_rawmidi_info_select(card, &info) >= 0) { input_count = info.subdevices_count; } ports = output_count; if (ports < input_count) ports = input_count; if (ports == 0) return -ENODEV; if (ports > (256 / SNDRV_RAWMIDI_DEVICES)) ports = 256 / SNDRV_RAWMIDI_DEVICES; down(®ister_mutex); client = synths[card->number]; if (client == NULL) { newclient = 1; client = kcalloc(1, sizeof(*client), GFP_KERNEL); if (client == NULL) { up(®ister_mutex); return -ENOMEM; } memset(&callbacks, 0, sizeof(callbacks)); callbacks.private_data = client; callbacks.allow_input = callbacks.allow_output = 1; client->seq_client = snd_seq_create_kernel_client(card, 0, &callbacks); if (client->seq_client < 0) { kfree(client); up(®ister_mutex); return -ENOMEM; } set_client_name(client, card, &info); } else if (device == 0) set_client_name(client, card, &info); /* use the first device's name */ msynth = kcalloc(ports, sizeof(seq_midisynth_t), GFP_KERNEL); if (msynth == NULL) goto __nomem; for (p = 0; p < ports; p++) { ms = &msynth[p]; if (snd_seq_midisynth_new(ms, card, device, p) < 0) goto __nomem; /* declare port */ memset(&port, 0, sizeof(port)); port.addr.client = client->seq_client; port.addr.port = device * (256 / SNDRV_RAWMIDI_DEVICES) + p; port.flags = SNDRV_SEQ_PORT_FLG_GIVEN_PORT; memset(&info, 0, sizeof(info)); info.device = device; if (p < output_count) info.stream = SNDRV_RAWMIDI_STREAM_OUTPUT; else info.stream = SNDRV_RAWMIDI_STREAM_INPUT; info.subdevice = p; if (snd_rawmidi_info_select(card, &info) >= 0) strcpy(port.name, info.subname); if (! port.name[0]) { if (info.name[0]) { if (ports > 1) snprintf(port.name, sizeof(port.name), "%s-%d", info.name, p); else snprintf(port.name, sizeof(port.name), "%s", info.name); } else { /* last resort */ if (ports > 1) sprintf(port.name, "MIDI %d-%d-%d", card->number, device, p); else sprintf(port.name, "MIDI %d-%d", card->number, device); } } if ((info.flags & SNDRV_RAWMIDI_INFO_OUTPUT) && p < output_count) port.capability |= SNDRV_SEQ_PORT_CAP_WRITE | SNDRV_SEQ_PORT_CAP_SYNC_WRITE | SNDRV_SEQ_PORT_CAP_SUBS_WRITE; if ((info.flags & SNDRV_RAWMIDI_INFO_INPUT) && p < input_count) port.capability |= SNDRV_SEQ_PORT_CAP_READ | SNDRV_SEQ_PORT_CAP_SYNC_READ | SNDRV_SEQ_PORT_CAP_SUBS_READ; if ((port.capability & (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ)) == (SNDRV_SEQ_PORT_CAP_WRITE|SNDRV_SEQ_PORT_CAP_READ) && info.flags & SNDRV_RAWMIDI_INFO_DUPLEX) port.capability |= SNDRV_SEQ_PORT_CAP_DUPLEX; port.type = SNDRV_SEQ_PORT_TYPE_MIDI_GENERIC; port.midi_channels = 16; memset(&pcallbacks, 0, sizeof(pcallbacks)); pcallbacks.owner = THIS_MODULE; pcallbacks.private_data = ms; pcallbacks.subscribe = midisynth_subscribe; pcallbacks.unsubscribe = midisynth_unsubscribe; pcallbacks.use = midisynth_use; pcallbacks.unuse = midisynth_unuse; pcallbacks.event_input = event_process_midi; port.kernel = &pcallbacks; if (snd_seq_kernel_client_ctl(client->seq_client, SNDRV_SEQ_IOCTL_CREATE_PORT, &port)<0) goto __nomem; ms->seq_client = client->seq_client; ms->seq_port = port.addr.port; } client->ports_per_device[device] = ports; client->ports[device] = msynth; client->num_ports++; if (newclient) synths[card->number] = client; up(®ister_mutex); return 0; /* success */ __nomem: if (msynth != NULL) { for (p = 0; p < ports; p++) snd_seq_midisynth_delete(&msynth[p]); kfree(msynth); } if (newclient) { snd_seq_delete_kernel_client(client->seq_client); kfree(client); } up(®ister_mutex); return -ENOMEM; }
int exec_cmd_node(cmd_node_t* cmd_node, client_node_t* client) { int pipe_count = cmd_node->pipe_count; int pid = -1; int input_pipe_fd = -1; int output_pipe_fd = -1; if(strcmp(cmd_node->cmd, "printenv") == 0) { char* env_name = cmd_node->args[1]; if(env_name != NULL) { char* env_val = getenv(env_name); printf("%s=%s\n", env_name, env_val); fflush(stdout); } decrease_all_pipe_node(client->pipe_list); return 0; } else if(strcmp(cmd_node->cmd, "setenv") == 0) { char* env_name = cmd_node->args[1]; char* env_val = cmd_node->args[2]; set_env_to_client_node(client, env_name, env_val); setenv(env_name, env_val, 1); decrease_all_pipe_node(client->pipe_list); return 0; } else if(strcmp(cmd_node->cmd, "exit") == 0) { char exit_msg[64]; bzero(exit_msg, 64); sprintf(exit_msg, "*** User '%s' left. ***\n", client->name); broad_cast(client, exit_msg); // clean message queues mq_clean(client->id); // remove global pipes remove_global_pipe(client->id, client->id, 0); // remove client from client list remove_client_node(client); // return logout status return -4; } else if(strcmp(cmd_node->cmd, "who") == 0) { who(client); decrease_all_pipe_node(client->pipe_list); return 0; } else if(strcmp(cmd_node->cmd, "tell") == 0) { int r = tell(client, cmd_node->args[1], cmd_node->args[2]); if(r == -1) { printf("*** Error: user #%s does not exist yet. ***\n", cmd_node->args[1]); fflush(stdout); } else { decrease_all_pipe_node(client->pipe_list); } return 0; } else if(strcmp(cmd_node->cmd, "yell") == 0) { char message[11000]; sprintf(message, "*** %s yelled ***: %s\n", client->name, cmd_node->args[1]); bzero(message, 11000); broad_cast(client, message); decrease_all_pipe_node(client->pipe_list); return 0; } else if(strcmp(cmd_node->cmd, "name") == 0) { char* name = cmd_node->args[1]; if(check_name_exist(name) == 1) { printf("*** User '%s' already exists. ***\n", name); fflush(stdout); } else { set_client_name(client->id, name); strcpy(client->name, name); char msg[40]; bzero(msg, 40); sprintf(msg, "*** User from %s/%d is named '%s'. ***\n", client->ip, client->port, client->name); broad_cast(client, msg); fflush(stdout); } decrease_all_pipe_node(client->pipe_list); return 0; } decrease_all_pipe_node(client->pipe_list); // get this process input source pipe_node_t* in_pipe_node = find_pipe_node_by_count(client->pipe_list, 0); if(in_pipe_node != NULL) { input_pipe_fd = in_pipe_node->in_fd; if(fcntl(in_pipe_node->out_fd, F_GETFD) != -1) { close(in_pipe_node->out_fd); } in_pipe_node->count--; } if(cmd_node->pipe_from_user == 1) { char data[2048]; bzero(data, 2048); int r = pull_global_pipe_data(cmd_node->from_user_id, client->id, data); if(r == -1) { inscrease_all_pipe_node(client->pipe_list); return -2; } int g_pipe[2]; pipe(g_pipe); write(g_pipe[1], r.msg, strlen(r.msg)); close(g_pipe[1]); input_pipe_fd = g_pipe[0]; } int tmp_global_pipe[2]; // get this process output source pipe_node_t* out_pipe_node = find_pipe_node_by_count(client->pipe_list, pipe_count); if(out_pipe_node != NULL) { output_pipe_fd = out_pipe_node->out_fd; } else if(cmd_node->pipe_to_file == 1){ output_pipe_fd = get_file_fd(cmd_node->filename); } else if(cmd_node->pipe_to_user == 1) { if(is_client_available(cmd_node->to_user_id) != 1) { printf("*** Error: user #%d does not exist yet. ***\n", cmd_node->to_user_id); fflush(stdout); close_unused_fd(client); return 0; } else if(is_global_pipe_exist(client->id, cmd_node->to_user_id) == 1) { close_unused_fd(client); return -3; } // global pipe // create global pipe node pipe(tmp_global_pipe); output_pipe_fd = tmp_global_pipe[1]; // broad cast message // *** (name) (#<client id>) just piped '(command line)' to (receiver's name) (#<receiver's client_id>) *** char* msg_temp = "*** %s (#%d) just piped '%s' to %s (#%d) ***\n"; char msg[128]; bzero(msg, 128); char to_client_name[30]; get_client_name(cmd_node->to_user_id, to_client_name); sprintf(msg, msg_temp, client->name, client->id, last_line, to_client_name, cmd_node->to_user_id); broad_cast(client, msg); fflush(stdout); } else if(cmd_node->pipe_count != 0) { int new_pipe_fd[2]; pipe(new_pipe_fd); out_pipe_node = malloc(sizeof(pipe_node_t)); out_pipe_node->count = cmd_node->pipe_count; out_pipe_node->in_fd = new_pipe_fd[0]; out_pipe_node->out_fd = new_pipe_fd[1]; out_pipe_node->next_node = NULL; insert_pipe_node(&(client->pipe_list), out_pipe_node); output_pipe_fd = new_pipe_fd[1]; } pid = fork(); if(pid == 0) { if(input_pipe_fd != -1) { // not use stdin close(0); dup(input_pipe_fd); close(input_pipe_fd); } // out if(out_pipe_node != NULL) { close(1); dup(out_pipe_node->out_fd); close(out_pipe_node->out_fd); } else if(cmd_node->pipe_to_file == 1) { close(1); dup(output_pipe_fd); close(output_pipe_fd); } else if(cmd_node->pipe_to_user == 1) { close(1); close(2); dup(output_pipe_fd); dup(output_pipe_fd); close(output_pipe_fd); } else { dup2(client->client_sc_fd, 1); } execvp(cmd_node->cmd, cmd_node->args); exit(-1); } else if(pipe_count != 0) { int status; wait(&status); // waitpid(pid, &status, 0); if(WEXITSTATUS(status) != 0){ inscrease_all_pipe_node(client->pipe_list); return -1; } else { if(input_pipe_fd != -1) { close(input_pipe_fd); } } } else { int status; wait(&status); // waitpid(pid, &status, 0); if(WEXITSTATUS(status) != 0){ inscrease_all_pipe_node(client->pipe_list); return -1; } else { if(in_pipe_node != NULL) { close(in_pipe_node->out_fd); in_pipe_node->count--; } if(cmd_node->pipe_to_user == 1) { if(fcntl(output_pipe_fd, F_GETFD) != -1) { close(output_pipe_fd); } char buffer[2048]; bzero(buffer, 2048); read(tmp_global_pipe[0], buffer, 2048); //printf("[DBG] Buffer:\n"); //printf("%s\n", buffer); add_global_pipe(client->id, cmd_node->to_user_id, buffer); close(tmp_global_pipe[0]); } close_unused_fd(client); } } if(cmd_node->pipe_from_user == 1) { char* msg_tmp = "*** %s (#%d) just received from %s (#%d) by '%s' ***\n"; char msg[100]; bzero(msg, 100); char from_client_name[30]; get_client_name(cmd_node->from_user_id, from_client_name); sprintf(msg, msg_tmp, client->name, client->id, from_client_name, cmd_node->from_user_id, last_line); broad_cast(client, msg); remove_global_pipe(cmd_node->from_user_id, client->id, 1); } return 0; }