int hgd_acmd_user_list_print(char **args) { struct hgd_user_list *list; int i, ret = HGD_FAIL; char *permstr = NULL; if (db == NULL) db = hgd_open_db(db_path, 0); if (db == NULL) goto clean; if (hgd_user_list(&list) != HGD_OK) goto clean; for (i = 0; i < list->n_users; i++) { hgd_gen_perms_str(list->users[i]->perms, &permstr); printf("%-20s %s\n", list->users[i]->name, permstr); free(permstr); } ret = HGD_OK; clean: if (list != NULL) { hgd_free_user_list(list); free(list); } return (ret); }
int hgd_acmd_user_del(char **args) { if (db == NULL) db = hgd_open_db(db_path, 0); if (db == NULL) return (HGD_FAIL); if (hgd_user_del(args[0]) != HGD_OK) return (HGD_FAIL); return (HGD_OK); }
int hgd_acmd_user_add_prompt(char **args) { char pass[HGD_MAX_PASS_SZ]; if (db == NULL) db = hgd_open_db(db_path, 0); if (db == NULL) return (HGD_FAIL); if (hgd_readpassphrase_confirmed(pass, NULL) != HGD_OK) return (HGD_FAIL); return (hgd_user_add(args[0], pass)); }
/* * remove old db and create new one */ int hgd_make_new_db(char *db_path) { int sql_res; sqlite3 *db; DPRINTF(HGD_D_INFO, "Creating new database: %s", db_path); if ((unlink(db_path) < 0) && (errno != ENOENT)) { DPRINTF(HGD_D_ERROR, "Could not unlink existing db: %s", SERROR); return (HGD_FAIL); } db = hgd_open_db(db_path, 1); /* and create */ if (!db) return (HGD_FAIL); /* no-one else should do this at the same time */ sql_res = sqlite3_exec(db, "BEGIN TRANSACTION", NULL, NULL, NULL); if (sql_res != SQLITE_OK) { DPRINTF(HGD_D_ERROR, "Can't initialise db: %s", DERROR); sqlite3_close(db); return (HGD_FAIL); } DPRINTF(HGD_D_DEBUG, "Making system table"); sql_res = sqlite3_exec(db, "CREATE TABLE system (" "id INTEGER PRIMARY KEY," "db_schema_version INTEGER)", NULL, NULL, NULL); if (sql_res != SQLITE_OK) { DPRINTF(HGD_D_ERROR, "Can't initialise db: %s", DERROR); sqlite3_close(db); return (HGD_FAIL); } /* the system table should only have one row with id 0 */ sql_res = sqlite3_exec(db, "INSERT into system VALUES(0, '" HGD_DB_SCHEMA_VERS "');", NULL, NULL, NULL); if (sql_res != SQLITE_OK) { DPRINTF(HGD_D_ERROR, "Can't initialise db: %s", DERROR); sqlite3_close(db); return (HGD_FAIL); } DPRINTF(HGD_D_DEBUG, "Making playlist table"); sql_res = sqlite3_exec(db, "CREATE TABLE playlist (" "id INTEGER PRIMARY KEY," "filename TEXT," "user TEXT," "playing INTEGER," "finished INTEGER," "tag_artist TEXT," "tag_title TEXT," "tag_album TEXT," "tag_genre TEXT," "tag_year INTEGER," "tag_channels INTEGER," "tag_samplerate INTEGER," "tag_duration INTEGER," "tag_bitrate INTEGER)", NULL, NULL, NULL); if (sql_res != SQLITE_OK) { DPRINTF(HGD_D_ERROR, "Can't initialise db: %s", DERROR); sqlite3_close(db); return (HGD_FAIL); } DPRINTF(HGD_D_DEBUG, "making votes table"); sql_res = sqlite3_exec(db, "CREATE TABLE votes (" "user TEXT PRIMARY KEY)", NULL, NULL, NULL); if (sql_res != SQLITE_OK) { DPRINTF(HGD_D_ERROR, "Can't initialise db: %s", DERROR); sqlite3_close(db); return (HGD_FAIL); } DPRINTF(HGD_D_DEBUG, "making user table"); sql_res = sqlite3_exec(db, "CREATE TABLE users (" "username TEXT PRIMARY KEY, " "hash TEXT, " /* sha1 */ "salt TEXT, " "perms INTEGER" ");", NULL, NULL, NULL); if (sql_res != SQLITE_OK) { DPRINTF(HGD_D_ERROR, "Can't initialise db: %s", DERROR); sqlite3_close(db); return (HGD_FAIL); } sql_res = sqlite3_exec(db, "COMMIT", NULL, NULL, NULL); if (sql_res != SQLITE_OK) { DPRINTF(HGD_D_ERROR, "Can't initialise db: %s", DERROR); sqlite3_close(db); return (HGD_FAIL); } sqlite3_close(db); return (HGD_OK); }
int main(int argc, char **argv) { char *xdg_config_home; char *config_path[4] = {NULL, NULL, NULL, NULL}; int num_config = 2, ch; /* as early as possible */ HGD_INIT_SYSLOG_DAEMON(); config_path[0] = NULL; xasprintf(&config_path[1], "%s", HGD_GLOBAL_CFG_DIR HGD_SERV_CFG ); xdg_config_home = getenv("XDG_CONFIG_HOME"); if (xdg_config_home == NULL) { xasprintf(&config_path[2], "%s%s", getenv("HOME"), HGD_USR_CFG_DIR HGD_SERV_CFG ); } else { xasprintf(&config_path[2], "%s%s", xdg_config_home , "/hgd" HGD_SERV_CFG); } /* if killed, die nicely */ hgd_register_sig_handlers(); state_path = xstrdup(HGD_DFL_DIR); ssl_key_path = xstrdup(HGD_DFL_KEY_FILE); ssl_cert_path = xstrdup(HGD_DFL_CERT_FILE); DPRINTF(HGD_D_DEBUG, "Parsing options:1"); while ((ch = getopt(argc, argv, "Bc:Dd:EefF:hk:n:p:s:S:vx:y:")) != -1) { switch (ch) { case 'c': if (num_config < 3) { num_config++; DPRINTF(HGD_D_DEBUG, "added config %d %s", num_config, optarg); config_path[num_config] = optarg; } else { DPRINTF(HGD_D_WARN, "Too many config files specified"); hgd_exit_nicely(); } break; case 'x': hgd_debug = atoi(optarg); if (hgd_debug > 3) hgd_debug = 3; DPRINTF(HGD_D_DEBUG, "set debug to %d", hgd_debug); break; default: break; /* next getopt will catch errors */ } } RESET_GETOPT(); /* cache HUP info */ if (hgd_cache_exec_context(argv) != HGD_OK) hgd_exit_nicely(); hgd_read_config(config_path + num_config); DPRINTF(HGD_D_DEBUG, "Parsing options:2"); while ((ch = getopt(argc, argv, "Bc:Dd:EefF:hk:n:p:s:S:vx:y:")) != -1) { switch (ch) { case 'B': background = 0; DPRINTF(HGD_D_DEBUG, "Not \"backgrounding\" daemon."); break; case 'c': break; /* already handled */ case 'D': DPRINTF(HGD_D_DEBUG, "No client DNS lookups"); lookup_client_dns = 0; break; case 'd': free(state_path); state_path = xstrdup(optarg); DPRINTF(HGD_D_DEBUG, "Set hgd dir to '%s'", state_path); break; case 'e': crypto_pref = HGD_CRYPTO_PREF_ALWAYS; DPRINTF(HGD_D_DEBUG, "Server will insist on crypto"); break; case 'E': crypto_pref = HGD_CRYPTO_PREF_NEVER; DPRINTF(HGD_D_WARN, "Encryption disabled manually"); break; case 'f': single_client = 1; DPRINTF(HGD_D_DEBUG, "Single client debug mode on"); break; case 'F': flood_limit = atoi(optarg); DPRINTF(HGD_D_DEBUG, "Set flood limit to %d", flood_limit); break; case 'k': free(ssl_key_path); ssl_key_path = optarg; DPRINTF(HGD_D_DEBUG, "set ssl private key path to '%s'", ssl_key_path); break; case 'n': req_votes = atoi(optarg); DPRINTF(HGD_D_DEBUG, "Set required-votes to %d", req_votes); break; case 'p': port = atoi(optarg); DPRINTF(HGD_D_DEBUG, "Set port to %d", port); break; case 's': /* XXX overflow? */ max_upload_size = atoi(optarg) * HGD_MB; DPRINTF(HGD_D_DEBUG, "Set max upload size to %d", (int) max_upload_size); break; case 'S': free(ssl_cert_path); ssl_cert_path = optarg; DPRINTF(HGD_D_DEBUG, "set ssl cert path to '%s'", ssl_cert_path); break; case 'v': hgd_print_version(); exit_ok = 1; hgd_exit_nicely(); break; case 'x': DPRINTF(HGD_D_DEBUG, "set debug to %d", atoi(optarg)); hgd_debug = atoi(optarg); if (hgd_debug > 3) hgd_debug = 3; break; /* already set but over-rideable */ case 'y': free(vote_sound); vote_sound = optarg; DPRINTF(HGD_D_DEBUG, "set voteoff sound %s", vote_sound); break; case 'h': default: hgd_usage(); exit_ok = 1; hgd_exit_nicely(); break; }; } argc -= optind; argv += optind; /* set up paths */ xasprintf(&db_path, "%s/%s", state_path, HGD_DB_NAME); xasprintf(&filestore_path, "%s/%s", state_path, HGD_FILESTORE_NAME); umask(~S_IRWXU); hgd_mk_state_dir(); db = hgd_open_db(db_path, 0); if (db == NULL) hgd_exit_nicely(); sqlite3_close(db); /* re-opened later */ db = NULL; /* unless the user actively disables SSL, we try to be capable */ if (crypto_pref != HGD_CRYPTO_PREF_NEVER) { if (hgd_setup_ssl_ctx(&method, &ctx, 1, ssl_cert_path, ssl_key_path) == 0) { DPRINTF(HGD_D_INFO, "Server is SSL capable"); ssl_capable = 1; } else { DPRINTF(HGD_D_WARN, "Server is SSL incapable"); } } else { DPRINTF(HGD_D_INFO, "Server was forced SSL incapable"); } /* if -e, but something screwed up in the above, bail */ if ((crypto_pref == HGD_CRYPTO_PREF_ALWAYS) && (ssl_capable != 1)) { DPRINTF(HGD_D_ERROR, "Crypto was forced on, but server is incapable"); hgd_exit_nicely(); } /* alright, everything looks good, lets be a daemon and background */ if (background) hgd_daemonise(); hgd_listen_loop(); exit_ok = 1; hgd_exit_nicely(); return (EXIT_SUCCESS); /* NOREACH */ }
/* main loop that deals with network requests */ void hgd_listen_loop(void) { struct sockaddr_in addr, cli_addr; int cli_fd, child_pid = 0; socklen_t cli_addr_len; int sockopt = 1, data_ready; struct pollfd pfd; start: DPRINTF(HGD_D_DEBUG, "Setting up socket"); if ((svr_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { DPRINTF(HGD_D_ERROR, "socket(): %s", SERROR); hgd_exit_nicely(); } /* allow socket to be re-used right away after we exit */ if (setsockopt(svr_fd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt)) < 0) { DPRINTF(HGD_D_WARN, "Can't set SO_REUSEADDR"); } /* configure socket */ memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(port); if (bind(svr_fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) { DPRINTF(HGD_D_ERROR, "Bind to port %d: %s", port, SERROR); hgd_exit_nicely(); } if (listen(svr_fd, sock_backlog) < 0) { DPRINTF(HGD_D_ERROR, "Listen: %s", SERROR); hgd_exit_nicely(); } DPRINTF(HGD_D_INFO, "Socket ready and listening on port %d", port); /* setup signal handler */ signal(SIGCHLD, hgd_sigchld); while (1) { DPRINTF(HGD_D_INFO, "waiting for client connection"); /* spin until something is ready */ pfd.fd = svr_fd; pfd.events = POLLIN; data_ready = 0; while (!dying && !restarting && !data_ready) { data_ready = poll(&pfd, 1, INFTIM); if (data_ready == -1) { if (errno != EINTR) { DPRINTF(HGD_D_ERROR, "Poll error"); dying = 1; } data_ready = 0; } } if (dying || restarting) { if (restarting) exit_ok = 1; hgd_exit_nicely(); } cli_addr_len = sizeof(cli_addr); cli_fd = accept(svr_fd, (struct sockaddr *) &cli_addr, &cli_addr_len); if (cli_fd < 0) { DPRINTF(HGD_D_WARN, "Server failed to accept"); close(svr_fd); /* * accept will fail next time aswell :\ * it seems the fix is to re-initialise the socket */ goto start; } if (setsockopt(cli_fd, SOL_SOCKET, SO_REUSEADDR, &sockopt, sizeof(sockopt)) < 0) { DPRINTF(HGD_D_WARN, "Can't set SO_REUSEADDR"); } /* ok, let's deal with that request then */ if (!single_client) child_pid = fork(); if (!child_pid) { /* turn off HUP handler */ //signal(SIGHUP, SIG_DFL); db = hgd_open_db(db_path, 0); if (db == NULL) hgd_exit_nicely(); hgd_service_client(cli_fd, &cli_addr); DPRINTF(HGD_D_DEBUG, "client service complete"); /* and we are done with this client */ if (shutdown(cli_fd, SHUT_RDWR) == -1) DPRINTF(HGD_D_WARN, "Can't shutdown socket"); close(cli_fd); close(svr_fd); svr_fd = -1; /* prevent shutdown of svr_fd */ exit_ok = 1; hgd_exit_nicely(); } /* child block ends */ close (cli_fd); DPRINTF(HGD_D_DEBUG, "client servicer PID = '%d'", child_pid); /* otherwise, back round for the next client */ } /* NOREACH */ }
int main(int argc, char **argv) { char *config_path[4] = {NULL, NULL, NULL, NULL}; int num_config = 2, ch; FILE *hgd_pid; /* early as possible */ hgd_register_sig_handlers(); HGD_INIT_SYSLOG_DAEMON(); #ifdef HAVE_LIBCONFIG config_path[0] = NULL; xasprintf(&config_path[1], "%s", HGD_GLOBAL_CFG_DIR HGD_SERV_CFG); config_path[2] = hgd_get_XDG_userprefs_location(playd); #endif state_path = xstrdup(HGD_DFL_DIR); DPRINTF(HGD_D_DEBUG, "Parsing options:1"); while ((ch = getopt(argc, argv, "Bc:Cd:hpP:qvx:")) != -1) { switch (ch) { case 'c': if (num_config < 3) { num_config++; DPRINTF(HGD_D_DEBUG, "added config %d %s", num_config, optarg); config_path[num_config] = optarg; } else { DPRINTF(HGD_D_WARN, "Too many config files specified"); hgd_exit_nicely(); } break; case 'x': hgd_debug = atoi(optarg); if (hgd_debug > 3) hgd_debug = 3; DPRINTF(HGD_D_DEBUG, "set debug level to %d", hgd_debug); break; default: break; /* catch badness in next getopt */ }; } hgd_read_config(config_path + num_config); while(num_config > 0) { if (config_path[num_config] != NULL) { free (config_path[num_config]); config_path[num_config] = NULL; } num_config--; } RESET_GETOPT(); if (hgd_cache_exec_context(argv) != HGD_OK) hgd_exit_nicely(); DPRINTF(HGD_D_DEBUG, "Parsing options"); while ((ch = getopt(argc, argv, "Bc:Cd:hpP:qvx:")) != -1) { switch (ch) { case 'B': background = 0; DPRINTF(HGD_D_DEBUG, "Not \"backgrounding\" daemon."); break; case 'c': break; /* already handled */ case 'C': clear_playlist_on_start = 1; DPRINTF(HGD_D_DEBUG, "will clear playlist '%s'", state_path); break; case 'd': free(state_path); state_path = xstrdup(optarg); DPRINTF(HGD_D_DEBUG, "set hgd dir to '%s'", state_path); break; case 'p': DPRINTF(HGD_D_DEBUG, "No purging from fs"); purge_finished_fs = 0; break; #ifdef HAVE_PYTHON case 'P': DPRINTF(HGD_D_DEBUG, "Setting python plugin dir"); if (hgd_py_plugin_dir != NULL) free(hgd_py_plugin_dir); hgd_py_plugin_dir = xstrdup(optarg); break; #endif case 'q': DPRINTF(HGD_D_DEBUG, "No purging from db"); purge_finished_db = 0; break; case 'v': hgd_print_version(); exit_ok = 1; hgd_exit_nicely(); break; case 'x': DPRINTF(HGD_D_DEBUG, "set debug to %d", atoi(optarg)); hgd_debug = atoi(optarg); if (hgd_debug > 3) hgd_debug = 3; break; /* already set but over-rideable */ case 'h': default: hgd_usage(); exit_ok = 1; hgd_exit_nicely(); break; }; } argc -= optind; argv += optind; xasprintf(&db_path, "%s/%s", state_path, HGD_DB_NAME); xasprintf(&filestore_path, "%s/%s", state_path, HGD_FILESTORE_NAME); xasprintf(&mplayer_fifo_path, "%s/%s", state_path, HGD_MPLAYER_PIPE_NAME); umask(~S_IRWXU); hgd_mk_state_dir(); if (hgd_check_mplayer_present() != HGD_OK) hgd_exit_nicely(); db = hgd_open_db(db_path, 0); if (db == NULL) hgd_exit_nicely(); if (hgd_init_playstate() != HGD_OK) hgd_exit_nicely(); if (clear_playlist_on_start) { if (hgd_clear_playlist() != HGD_OK) hgd_exit_nicely(); } if (hgd_open_pid_file(&hgd_pid) != HGD_OK) { DPRINTF(HGD_D_ERROR, "Can't open PID file"); return (HGD_FAIL); } /* start */ if (background) hgd_daemonise(); /* do the Python dance */ #ifdef HAVE_PYTHON if (hgd_embed_py(1) != HGD_OK) { DPRINTF(HGD_D_ERROR, "Failed to initialise Python"); hgd_exit_nicely(); } #endif if (hgd_write_pid_file(&hgd_pid) != HGD_OK) { DPRINTF(HGD_D_ERROR, "Can't write PID away"); return (HGD_FAIL); } if (hgd_play_loop() == HGD_OK) exit_ok = 1; if (hgd_unlink_pid_file() != HGD_OK) DPRINTF(HGD_D_ERROR, "Could not unlink pidfile"); hgd_exit_nicely(); _exit (EXIT_SUCCESS); /* NOREACH */ }