/* * text-cutlass.c * * Text interface for testing cutlass functionality. * * Copyright (c) 2004 Todd MacDermid * Jack Lloyd * */ #include #include #include #include #include #include #include #include #include #include #include #include #define CUT_CMD_FAILED -1 #define CUT_CMD_SUCCEEDED 0 #define CUT_CMD_UNKNOWN 1 #define CUT_CMD_QUIT 2 const char *verstr= "%s: v0.1\n"; pthread_mutex_t input_mutex; int text_routing = 0; char routing_buffer[CUT_MSG_LEN_MAX] = {0}; void usage(char *cut_name) { printf("usage: %s [-ahfvV] [-k ] [-p ]\n", cut_name); exit(0); } void version(char *cut_name) { printf(verstr, cut_name); } int get_passphrase(const char* description, char *pass_buf, uint32_t max_pass) { int c; FILE *fp; struct termios term; struct termios saved_term; sigset_t sig; sigset_t saved_sig; char *ptr; if( (fp = fopen(ctermid(NULL), "r+")) == NULL) { fprintf(stderr, "get_passphrase: failure to open terminal device\n"); return(-1); } setbuf(fp, NULL); sigemptyset(&sig); sigaddset(&sig, SIGINT); sigaddset(&sig, SIGTSTP); sigprocmask(SIG_BLOCK, &sig, &saved_sig); tcgetattr(fileno(fp), &saved_term); term = saved_term; term.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL); tcsetattr(fileno(fp), TCSAFLUSH, &term); fputs("Enter passphrase:", fp); ptr = pass_buf; while((c = getc(fp)) != EOF && c != '\n') { if(ptr < &pass_buf[max_pass]) *ptr++ = c; } *ptr = 0; putc('\n', fp); tcsetattr(fileno(fp), TCSAFLUSH, &saved_term); sigprocmask(SIG_SETMASK, &saved_sig, NULL); fclose(fp); return(0); } int decode_hex(char *input, uint8_t *decoded) { char *next; next = input + 1; *decoded = 0; if((*input > 0x2F) && (*input < 0x3A)) { *decoded += ((*input - 0x30) << 4); } else if ((*input > 0x40) && (*input < 0x47)) { *decoded += ((*input - 0x37) << 4); } else if ((*input > 0x60) && (*input < 0x67)) { *decoded += ((*input - 0x57) << 4); } else { return(-1); } if((*next > 0x2F) && (*next < 0x3A)) { *decoded += *next - 0x30; } else if ((*next > 0x40) && (*next < 0x47)) { *decoded += *next - 0x37; } else if ((*next > 0x60) && (*next < 0x67)) { *decoded += *next - 0x57; } else { return(-1); } return(0); } int parse_fingerprint(char **string, uint8_t *fingerprint_buf) { char *tmp_ptr; int i = 0; int done = 0; if((NULL == string) || (NULL == *string) || (NULL == fingerprint_buf)) { fprintf(stderr, "parse_fingerprint: Passed a NULL pointer\n"); return(-1); } tmp_ptr = *string; while(!done) { if(*tmp_ptr == 0x20) { tmp_ptr++; } else { if(decode_hex(tmp_ptr, &(fingerprint_buf[i])) < 0) { fprintf(stderr, "parse_fingerprint: Bad hex at %s\n", tmp_ptr); return(-1); } i++; tmp_ptr += 2; if(i >= CUT_ID_LEN) { done = 1; } } } *string = tmp_ptr; return(0); } void print_conn_info(cutlass_t *cut_handle, uint8_t *fingerprint) { char *tmp_string; char tmp_array[INET_ADDRSTRLEN]; int j; int fd; struct sockaddr_in *tmp_addr; tmp_addr = cutlass_conn_addr(cut_handle, fingerprint); if(NULL == tmp_addr) { printf("No related address found\n"); } else { cutlass_ntop(AF_INET, &(tmp_addr->sin_addr), tmp_array, INET_ADDRSTRLEN); if((fd = cutlass_conn_fd(cut_handle, fingerprint)) > 0) { printf("Connection to %s: ", tmp_array); printf("to port %d ", ntohs(tmp_addr->sin_port)); printf("on file descriptor %d\n", fd); } else { printf("Connection from %s: ", tmp_array); printf("from port %d\n", ntohs(tmp_addr->sin_port)); } free(tmp_addr); } printf("ID:"); for(j = 0; j < CUT_ID_LEN; j++) { if(!(j%4)) { printf(" "); } printf("%02X", fingerprint[j]); } tmp_string = cutlass_conn_name(cut_handle, fingerprint); if(NULL == tmp_string) { printf("\nNo name found\n"); } else { printf("\nName: \"%s\"\n", tmp_string); free(tmp_string); } } void print_poll_info(cutlass_t *cut_handle, uint8_t *fingerprint) { int i; poll_t *poll_ptr; printf("Conn ID: "); for(i = 0; i < CUT_ID_LEN/2; i++) { printf("%02X", fingerprint[i]); } printf("\n"); for(i = 1; i < 2*CUT_NUM_CHANNELS; i++) { poll_ptr = cutlass_transport_poll(cut_handle, fingerprint, i); if(poll_ptr != NULL) { printf("Channel %d - %d out of %d bytes sent - state %d\n", i, poll_ptr->sent_bytes, poll_ptr->total_bytes, poll_ptr->channel_state); free(poll_ptr); } } } int cutlass_load_key(cutlass_t *cut_handle, const char *keyfile_name) { struct stat statbuf; FILE *new_key; cutlass_private_key private_key; char pass_buf[256]; if(stat(keyfile_name, &statbuf) == 0) { private_key = load_private_key(keyfile_name, get_passphrase); if(private_key.key == 0) { fprintf(stderr, "Error loading key from %s\n", keyfile_name); return(-1); } cut_handle->local_key = private_key; } else { fprintf(stderr, "No file %s: generating new key\n", keyfile_name); new_key = fopen(keyfile_name, "w+"); if(new_key == NULL) { fprintf(stderr, "Error creating file %s\n", keyfile_name); return(-1); } get_passphrase(keyfile_name, pass_buf, 256); private_key = generate_rsa_key(1024, NULL, NULL); if(private_key.key == 0) { fprintf(stderr, "Error generating key\n"); return(-1); } cut_handle->local_key = private_key; save_private_key(private_key, pass_buf, new_key); fclose(new_key); fprintf(stderr, "New key generated, saved in %s\n", keyfile_name); } return(0); } int string_to_sockaddr(char *string, struct sockaddr_in *addr) { char *tmp_ptr; char *second_tmp_ptr; uint16_t remote_port; struct hostent *hostent_ptr; tmp_ptr = string; bzero(addr, sizeof(addr)); addr->sin_family = AF_INET; addr->sin_port = htons(CUT_DEFAULT_PORT); second_tmp_ptr = strchr(tmp_ptr, ':'); if(second_tmp_ptr != NULL) { remote_port = atoi(second_tmp_ptr+1); addr->sin_port = htons(remote_port); *second_tmp_ptr = 0; } else { second_tmp_ptr = strchr(tmp_ptr, '\n'); if(second_tmp_ptr != NULL) { *second_tmp_ptr = 0; } second_tmp_ptr = strchr(tmp_ptr, ' '); if(second_tmp_ptr != NULL) { *second_tmp_ptr = 0; } } hostent_ptr = gethostbyname(tmp_ptr); if(NULL == hostent_ptr) { fprintf(stderr, "string_to_sockaddr: gethostbyname failed\n"); return(-1); } if(AF_INET != hostent_ptr->h_addrtype) { fprintf(stderr, "string_to_sockaddr: " "gethostbyname returned an unsupported address type\n"); return(-1); } memcpy(&(addr->sin_addr), hostent_ptr->h_addr_list[0], 4); return(0); } void print_connections(cutlass_t *cut_handle) { uint8_t fingerprint_array[CUT_HK_ARRAY_SZ * CUT_ID_LEN]; uint8_t *cur_fingerprint; int i; int num_conn; printf("List of all active connections: \n"); num_conn = cutlass_conn_list(cut_handle, fingerprint_array, CUT_HK_ARRAY_SZ); cur_fingerprint = fingerprint_array; for (i = 0; i < num_conn; i++) { print_conn_info(cut_handle, cur_fingerprint); cur_fingerprint += CUT_ID_LEN; } } void poll_connections(cutlass_t *cut_handle) { uint8_t fingerprint_array[CUT_HK_ARRAY_SZ * CUT_ID_LEN]; uint8_t *cur_fingerprint; int i; int num_conn; printf("List of all active transports: \n"); num_conn = cutlass_conn_list(cut_handle, fingerprint_array, CUT_HK_ARRAY_SZ); cur_fingerprint = fingerprint_array; for (i = 0; i < num_conn; i++) { print_poll_info(cut_handle, cur_fingerprint); cur_fingerprint += CUT_ID_LEN; } } void text_help(char *command) { char *tmp_ptr; if(command == NULL) { goto no_command; } tmp_ptr = strchr(command, '\n'); if(tmp_ptr != NULL) { *tmp_ptr = 0; } if(strstr(command, "conn") == command) { printf("connect - Connects to remote hostname or ip address\n"); printf("Usage: /connect [:optional port]\n"); } else if(strstr(command, "d") == command) { printf("disconnect - Disconnects from connections\n"); printf("Usage: /d \n"); } else if(strstr(command, "li") == command) { printf("list - Lists active connections\n"); printf("Usage: /list\n"); } else if(strstr(command, "n") == command) { printf("nick - Changes local nickname\n"); printf("Usage: /nick \n"); } else if(strstr(command, "q") == command) { printf("quit - Exits cutlass\n"); printf("Usage: /quit\n"); } else if(strstr(command, "s") == command) { printf("send - Send a file (Default is to offer to all connected)\n"); printf("Usage: /send [optional host]\n"); } else if(strstr(command, "o") == command) { printf("overload - Send a large text message to all connected\n"); printf("Usage: /overload\n"); } else if(strstr(command, "p") == command) { printf("poll - Show state of all transport sessions\n"); printf("Usage: /poll\n"); } else if(strstr(command, "r") == command) { printf("register - Register your entry with a directory server\n"); printf("Usage: /register \n"); } else if(strstr(command, "unr") == command) { printf("unregister - Remove your entry from a directory\n"); printf("Usage: /unregister \n"); } else if(strstr(command, "lo") == command) { printf("lookup - Look up a fingerprint from a directory\n"); printf("Usage: /look \n"); } else if(strstr(command, "ta") == command) { printf("talk - Open audio channel with remote hosts\n"); printf("Usage: /talk\n"); } else if(strstr(command, "unt") == command) { printf("untalk - Close audio channel with remote hosts\n"); printf("Usage: /untalk\n"); } else if(strstr(command, "th") == command) { printf("threshold - Set outbound audio microphone threshold\n"); printf("Usage: /threshold \n(Valid levels are 0-65000)\n"); } else if(strstr(command, "h") == command) { printf("help - Display help messages\n"); printf("Usage: /help [optional command]\n"); } else { printf("Command \"%s\" not recognized\n", command); goto no_command; } return; no_command: printf("Commands:\t"); printf("connect disconnect help list nick quit register unregister \n\t\tlookup send talk untalk threshold poll\n"); printf("Type /h for more details on a specific command.\n"); printf("Preface commands with '/' to use command.\n"); printf("Example: '/connect 10.0.0.15' will connect to host 10.0.0.15\n"); return; } int command_parse(char *command, cutlass_t *cut_handle) { char *tmp_ptr; char *second_tmp_ptr; char load_msg[2000]; float threshold; uint8_t fingerprint[CUT_ID_LEN]; uint8_t fingerprint2[CUT_ID_LEN]; struct sockaddr_in *dest_addr = NULL; int i; if(strstr(command, "q") == command) { return(CUT_CMD_QUIT); } else if((tmp_ptr = strstr(command, "h")) == command) { if((tmp_ptr = strchr(tmp_ptr, ' ')) != NULL) { tmp_ptr++; } text_help(tmp_ptr); } else if((tmp_ptr = strstr(command, "m")) == command) { cutlass_directory_dump(cut_handle); } else if((tmp_ptr = strstr(command, "s")) == command) { tmp_ptr = strchr(tmp_ptr, ' '); if(tmp_ptr !=NULL) { tmp_ptr++; second_tmp_ptr = strchr(tmp_ptr, '\n'); if(second_tmp_ptr != NULL) { *second_tmp_ptr = 0; } second_tmp_ptr = strchr(tmp_ptr, ' '); if(second_tmp_ptr != NULL) { *second_tmp_ptr = 0; } } cutlass_file_offer_all(cut_handle, tmp_ptr); } else if((tmp_ptr = strstr(command, "r")) == command) { tmp_ptr = strchr(tmp_ptr, ' '); if(tmp_ptr != NULL) { if(parse_fingerprint(&tmp_ptr, fingerprint) == 0) { cutlass_directory_advertise(cut_handle, fingerprint); } else { printf("Usage: /register \n"); } } else { printf("Usage: /register \n"); } } else if((tmp_ptr = strstr(command, "unr")) == command) { tmp_ptr = strchr(tmp_ptr, ' '); if(tmp_ptr != NULL) { if(parse_fingerprint(&tmp_ptr, fingerprint) == 0) { cutlass_directory_unadvertise(cut_handle, fingerprint); } else { printf("Usage: /unregister \n"); } } else { printf("Usage: /unregister \n"); } } else if((tmp_ptr = strstr(command, "lo")) == command) { tmp_ptr = strchr(tmp_ptr, ' '); if(tmp_ptr != NULL) { if((parse_fingerprint(&tmp_ptr, fingerprint) == 0) && (parse_fingerprint(&tmp_ptr, fingerprint2) == 0)) { cutlass_directory_lookup_print(cut_handle, fingerprint, fingerprint2); } } else { printf("Usage: /lookup \n"); } } else if((tmp_ptr = strstr(command, "th")) == command) { tmp_ptr = strchr(tmp_ptr, ' '); if(tmp_ptr != NULL) { threshold = atof(tmp_ptr); printf("Threshold set to %f\n", threshold); cutlass_audio_set_threshold(cut_handle, threshold); } else { printf("Usage: /threshold <0-65000>\n"); } } else if((tmp_ptr = strstr(command, "o")) == command) { for(i = 0; i < 2000; i++) { load_msg[i] = 'A'; } load_msg[1999] = 0; load_msg[1998] = '\n'; cutlass_msg_broadcast(cut_handle, load_msg); } else if((tmp_ptr = strstr(command, "p")) == command) { poll_connections(cut_handle); } else if((tmp_ptr = strstr(command, "li")) == command) { print_connections(cut_handle); } else if((tmp_ptr = strstr(command, "n")) == command) { if((tmp_ptr = strchr(tmp_ptr, ' ')) != NULL) { tmp_ptr++; cutlass_nick_change(cut_handle, tmp_ptr); } else { text_help("n"); } } else if ((tmp_ptr = strstr(command, "conn")) == command) { tmp_ptr = strchr(tmp_ptr, ' '); if(tmp_ptr !=NULL) { dest_addr = (struct sockaddr_in *)calloc (1, sizeof(struct sockaddr_in)); if (NULL == dest_addr) { fprintf(stderr, "Couldn't allocate address structure: %s\n", strerror(errno)); return (CUT_CMD_FAILED); } tmp_ptr++; if(string_to_sockaddr(tmp_ptr, dest_addr) < 0) { fprintf(stderr, "Could not get destination address\n"); return(CUT_CMD_FAILED); } if((cutlass_connect(cut_handle, dest_addr)) < 0) { return(CUT_CMD_FAILED); } /* free at last! */ free (dest_addr); dest_addr = NULL; } } else if ((tmp_ptr = strstr(command, "ta")) == command) { cutlass_audio_connect_all(cut_handle); } else if ((tmp_ptr = strstr(command, "unt")) == command) { cutlass_audio_disconnect_all(cut_handle); } else if ((tmp_ptr = strstr(command, "d")) == command) { tmp_ptr = strchr(tmp_ptr, ' '); if(tmp_ptr != NULL) { if(parse_fingerprint(&tmp_ptr, fingerprint) == 0) { cutlass_conn_shutdown(cut_handle, fingerprint); } else { printf("Usage: /disconnect \n"); } } else { printf("Usage: /disconnect \n"); } } else { return(CUT_CMD_UNKNOWN); } return(CUT_CMD_SUCCEEDED); } void text_input_loop(cutlass_t *cut_handle) { char user_input[CUT_MSG_LEN_MAX]; int command; int cut_continue; cut_continue = 1; while(cut_continue) { fgets(user_input, CUT_MSG_LEN_MAX, stdin); if(text_routing) { strncpy(routing_buffer, user_input, CUT_MSG_LEN_MAX-1); text_routing = 0; pthread_mutex_unlock(&input_mutex); } else { if(user_input[0] == '/') { command = command_parse(&(user_input[1]), cut_handle); switch(command) { case(CUT_CMD_QUIT): fprintf(stderr, "Exiting...\n"); cut_continue = 0; break; case(CUT_CMD_SUCCEEDED): break; case(CUT_CMD_FAILED): fprintf(stderr, "Command failed\n"); break; default: fprintf(stderr, "Unknown command\n"); break; } } else { cutlass_msg_broadcast(cut_handle, user_input); } } } } int conn_handler(cutlass_t *cut_handle, struct cut_action_obj *action_object) { char tmp_array[INET_ADDRSTRLEN]; struct in_addr *remote_addr; remote_addr = cutlass_action_addr(action_object); if(NULL == remote_addr) { fprintf(stderr, "Conn handler: " "Error retriving address from action object\n"); } else { printf("* %s is now connected to you\n", cutlass_ntop(AF_INET, remote_addr, tmp_array, INET_ADDRSTRLEN)); free(remote_addr); } return(0); } int drop_handler(cutlass_t *cut_handle, struct cut_action_obj *action_object) { char tmp_array[INET_ADDRSTRLEN]; char *rnick; struct in_addr *remote_addr; rnick = cutlass_action_rnick(action_object); if(rnick == NULL) { printf("Error getting remote drop nickname\n"); return(1); } remote_addr = cutlass_action_addr(action_object); if(NULL == remote_addr) { fprintf(stderr, "Drop handler: " "Error retriving address from action object\n"); } else { if(action_object->action_type == CUT_USER_TIMEOUT) { printf("* %s [%s] connection timed out\n", rnick, cutlass_ntop(AF_INET, remote_addr, tmp_array, INET_ADDRSTRLEN)); } else { printf("* %s [%s] has disconnected\n", rnick, cutlass_ntop(AF_INET, remote_addr, tmp_array, INET_ADDRSTRLEN)); } } free(rnick); free(remote_addr); return(0); } int file_offer_handler(cutlass_t *cut_handle, struct cut_action_obj *action_object) { char *filename; char *rnick; uint32_t file_size; char input_buf[CUTLASS_FILENAME_LEN]; char *tmp_ptr; filename = cutlass_action_fname(action_object); if(NULL == filename) { fprintf(stderr, "Error getting filename\n"); return(1); } rnick = cutlass_action_rnick(action_object); if(NULL == rnick) { fprintf(stderr, "Error getting remote nickname\n"); return(1); } file_size = cutlass_action_fsize(action_object); pthread_mutex_lock(&input_mutex); printf("** <%s> Offers the file %s (%d bytes)\n", rnick, filename, file_size); printf("** Accept? ( y / [n] ): "); fflush(stdout); text_routing = 1; pthread_mutex_lock(&input_mutex); strncpy(input_buf, routing_buffer, CUTLASS_FILENAME_LEN-1); if((strstr(input_buf, "y")) || (strstr(input_buf, "Y"))) { printf("** Save file as? [%s]: ", filename); fflush(stdout); text_routing = 1; pthread_mutex_lock(&input_mutex); strncpy(input_buf, routing_buffer, CUTLASS_FILENAME_LEN-1); tmp_ptr = strchr(input_buf, '\n'); if(tmp_ptr != NULL) { *tmp_ptr = 0; } if(input_buf[0] != 0) { cutlass_file_accept(action_object->cut_handle, action_object, input_buf); } else { cutlass_file_accept(action_object->cut_handle, action_object, NULL); } } else { cutlass_file_reject(action_object->cut_handle, action_object); } pthread_mutex_unlock(&input_mutex); free(filename); free(rnick); return(0); } int file_accept_handler(cutlass_t *cut_handle, struct cut_action_obj *action_object) { char *filename; char *rnick; filename = cutlass_action_fname(action_object); if(NULL == filename) { fprintf(stderr, "Error getting filename\n"); return(1); } rnick = cutlass_action_rnick(action_object); if(NULL == rnick) { fprintf(stderr, "Error getting remote nickname\n"); return(1); } printf("** <%s> accepts the file %s, starting transfer\n", rnick, filename); free(filename); free(rnick); return(0); } int file_reject_handler(cutlass_t *cut_handle, struct cut_action_obj *action_object) { char *filename; char *rnick; filename = cutlass_action_fname(action_object); if(NULL == filename) { fprintf(stderr, "Error getting filename\n"); return(1); } rnick = cutlass_action_rnick(action_object); if(NULL == rnick) { fprintf(stderr, "Error getting remote nickname\n"); return(1); } printf("** <%s> has rejected the file %s\n", rnick, filename); free(filename); free(rnick); return(0); } int file_recv_done_handler(cutlass_t *cut_handle, struct cut_action_obj *action_object) { char *filename; char *rnick; filename = cutlass_action_fname(action_object); if(NULL == filename) { fprintf(stderr, "Error getting filename\n"); return(1); } rnick = cutlass_action_rnick(action_object); if(NULL == rnick) { fprintf(stderr, "Error getting remote nickname\n"); return(1); } printf("** %s transfer from <%s> complete\n", filename, rnick); free(filename); free(rnick); return(0); } int file_send_done_handler(cutlass_t *cut_handle, struct cut_action_obj *action_object) { char *filename; char *rnick; filename = cutlass_action_fname(action_object); if(NULL == filename) { fprintf(stderr, "Error getting filename\n"); return(1); } rnick = cutlass_action_rnick(action_object); if(NULL == rnick) { fprintf(stderr, "Error getting remote nickname\n"); return(1); } printf("** %s transfer to <%s> complete\n", filename, rnick); free(filename); free(rnick); return(0); } int audio_start_handler(cutlass_t *cut_handle, struct cut_action_obj *action_object) { char tmp_array[INET_ADDRSTRLEN]; char *rnick; struct in_addr *remote_addr; rnick = cutlass_action_rnick(action_object); if(rnick == NULL) { printf("Error getting remote audio nickname\n"); return(1); } remote_addr = cutlass_action_addr(action_object); if(NULL == remote_addr) { fprintf(stderr, "Audio start handler: " "Error retriving address from action object\n"); } else { printf("* %s [%s] connection has activated audio\n", rnick, cutlass_ntop(AF_INET, remote_addr, tmp_array, INET_ADDRSTRLEN)); } cutlass_audio_set_threshold(cut_handle, 1000.0); /* cutlass_audio_play_file(cut_handle, "/home/tmacd/devel/cutlass/Sounds/Ring.snd"); */ free(rnick); free(remote_addr); return(0); } int audio_end_handler(cutlass_t *cut_handle, struct cut_action_obj *action_object) { char tmp_array[INET_ADDRSTRLEN]; char *rnick; struct in_addr *remote_addr; rnick = cutlass_action_rnick(action_object); if(rnick == NULL) { printf("Error getting remote audio nickname\n"); return(1); } remote_addr = cutlass_action_addr(action_object); if(NULL == remote_addr) { fprintf(stderr, "audio end handler: " "Error retriving address from action object\n"); } else { if(action_object->action_type == CUT_SND_REJECT) { printf("* %s [%s] connection has rejected audio\n", rnick, cutlass_ntop(AF_INET, remote_addr, tmp_array, INET_ADDRSTRLEN)); } else if (action_object->action_type == CUT_SND_DONE) { printf("* %s [%s] connection has closed audio session\n", rnick, cutlass_ntop(AF_INET, remote_addr, tmp_array, INET_ADDRSTRLEN)); /* cutlass_audio_play_file(cut_handle, "/home/tmacd/devel/cutlass/Sounds/Hangup.snd"); */ } } free(rnick); free(remote_addr); return(0); } int message_handler(cutlass_t *cut_handle, struct cut_action_obj *action_object) { char *rnick; char *msg; msg = cutlass_action_msg(action_object); if(NULL == msg) { fprintf(stderr, "Error getting mesage\n"); return(1); } rnick = cutlass_action_rnick(action_object); if(NULL == rnick) { fprintf(stderr, "Error getting remote nickname\n"); free(msg); return(1); } printf("<%s:%d> %s", rnick, strlen(msg), msg); free(msg); free(rnick); return(0); } int audio_handle(cutlass_t *cut_handle, struct cut_action_obj *action_object) { return(0); } int main(int argc, char **argv) { cutlass_t *cut_handle; cutlass_options* options = NULL; int option; int verbose; int got_key = 0; verbose = CUT_ERROR; cut_handle = cutlass_init(); if(cut_handle == NULL) exit(-1); options = load_options(".cut_options"); if(options == NULL) options = new_options(); else { if(get_str_option(options, "nick")) cutlass_set_nick(cut_handle, get_str_option(options, "nick")); if(get_str_option(options, "keyfile")) { /* Don't fail out if the key loading fails here, let -k or compile-time default cover us, and then save out the new keyfile if one of those worked */ if(cutlass_load_key(cut_handle, get_str_option(options, "keyfile")) >= 0) got_key = 1; } if(get_int_option(options, "port") != -1) cutlass_set_port(cut_handle, get_int_option(options, "port")); if(get_int_option(options, "verbosity") != -1) cutlass_set_verbose(cut_handle, get_int_option(options, "verbosity")); } cutlass_set_permission(cut_handle, CAN_RECV_MSGS, ALL_ALLOWED); pthread_mutex_init(&input_mutex, NULL); text_routing = 0; while ((option=getopt(argc, argv, "adfk:hn:p:r:tvV")) != -1) { switch(option) { case 'a': cutlass_set_permission(cut_handle, CAN_RECV_AUDIO, ALL_ALLOWED); break; case 'd': cutlass_set_permission(cut_handle, CAN_SERVE_DIR, ALL_ALLOWED); break; case 'f': cutlass_set_permission(cut_handle, CAN_RECV_FILES, USER_ALLOW_CHECK); break; case 'h': usage(argv[0]); break; case 'k': if(cutlass_load_key(cut_handle, optarg) < 0) { fprintf(stderr, "error loading keyfile %s\n", optarg); exit(-1); } set_str_option(options, "keyfile", optarg); got_key = 1; case 'n': cutlass_set_nick(cut_handle, optarg); set_str_option(options, "nick", optarg); break; case 'p': cutlass_set_port(cut_handle, atoi(optarg)); set_int_option(options, "port", atoi(optarg)); break; case 't': cut_handle->print_timestamp = 1; break; case 'v': version(argv[0]); break; case 'V': verbose++; break; } } if(!got_key) { if(cutlass_load_key(cut_handle, ".cutlass_key") < 0) { fprintf(stderr, "error loading keyfile .cutlass_key\n"); exit(-1); } else set_str_option(options, "keyfile", ".cutlass_key"); } cutlass_set_verbose(cut_handle, verbose); cutlass_register_action(cut_handle, CUT_USER_CONN, conn_handler); cutlass_register_action(cut_handle, CUT_USER_DROP, drop_handler); cutlass_register_action(cut_handle, CUT_USER_TIMEOUT, drop_handler); cutlass_register_action(cut_handle, CUT_MSG_RECV, message_handler); cutlass_register_action(cut_handle, CUT_FILE_SEND_DONE, file_send_done_handler); cutlass_register_action(cut_handle, CUT_FILE_RECV_DONE, file_recv_done_handler); cutlass_register_action(cut_handle, CUT_FILE_OFFER, file_offer_handler); cutlass_register_action(cut_handle, CUT_FILE_ACCEPT, file_accept_handler); cutlass_register_action(cut_handle, CUT_FILE_REJECT, file_reject_handler); cutlass_register_action(cut_handle, CUT_SND_ACCEPT, audio_start_handler); cutlass_register_action(cut_handle, CUT_SND_REJECT, audio_end_handler); cutlass_register_action(cut_handle, CUT_SND_DONE, audio_end_handler); cutlass_start(cut_handle); printf("Cutlass initialized - Type /h for help\n"); text_input_loop(cut_handle); cutlass_shutdown_all(cut_handle); return(0); }