From ef7101f2e83f5a9a5f035fc0fee5843726ef6e1a Mon Sep 17 00:00:00 2001 From: Baptiste DURAND Date: Tue, 6 Jan 2015 11:08:23 +0100 Subject: [PATCH] Restore Popup/Graphical Mode that uses Notification Service This was deleted by commit Remove UI related code from pkgmgr-server e1077a0f11481a4b73ba04ccfe94af548dcf50c8 Change-Id: If8331cdbd424d64553c96ae6e028d81f54041ce6 Signed-off-by: Baptiste DURAND --- client/src/pkgmgr.c | 23 +++ comm/pkgmgr_installer.c | 11 +- comm/pkgmgr_installer_config.h | 1 + server/src/pkgmgr-server.c | 346 +++++++++++++++++++++++++++++++++++++++-- tool/pkg_cmd.c | 42 ++++- 5 files changed, 395 insertions(+), 28 deletions(-) diff --git a/client/src/pkgmgr.c b/client/src/pkgmgr.c index f938a20..9b6c81f 100644 --- a/client/src/pkgmgr.c +++ b/client/src/pkgmgr.c @@ -940,6 +940,8 @@ static int __move_pkg_process(pkgmgr_client * pc, const char *pkgid, uid_t uid, argv[argcnt++] = strdup("-t"); /* argv[6] */ argv[argcnt++] = strdup(buf); + /* argv[7] */ + argv[argcnt++] = strdup("-q"); /*** add quote in all string for special charactor like '\n'*** FIX */ for (i = 0; i < argcnt; i++) { @@ -1210,6 +1212,11 @@ API int pkgmgr_client_usr_install(pkgmgr_client * pc, const char *pkg_type, argv[argcnt++] = strdup(caller_pkgid); } + +/* argv[6] -q option should be located at the end of command !! */ + if (mode == PM_QUIET) + argv[argcnt++] = strdup("-q"); + /*** add quote in all string for special charactor like '\n'*** FIX */ for (i = 0; i < argcnt; i++) { temp = g_shell_quote(argv[i]); @@ -1339,6 +1346,10 @@ API int pkgmgr_client_usr_reinstall(pkgmgr_client * pc, const char *pkg_type, co argv[argcnt++] = strdup(optional_file); } + /* argv[5] -q option should be located at the end of command !! */ + if (mode == PM_QUIET) + argv[argcnt++] = strdup("-q"); + /*** add quote in all string for special charactor like '\n'*** FIX */ for (i = 0; i < argcnt; i++) { temp = g_shell_quote(argv[i]); @@ -1489,6 +1500,9 @@ API int pkgmgr_client_usr_uninstall(pkgmgr_client *pc, const char *pkg_type, argv[argcnt++] = strdup("-p"); argv[argcnt++] = caller_pkgid; } + /* argv[5] -q option should be located at the end of command !! */ + if (mode == PM_QUIET) + argv[argcnt++] = strdup("-q"); /*** add quote in all string for special charactor like '\n'*** FIX */ for (i = 0; i < argcnt; i++) { @@ -1609,6 +1623,9 @@ API int pkgmgr_client_usr_move(pkgmgr_client *pc, const char *pkg_type, argv[argcnt++] = strdup("-t"); /* argv[6] */ argv[argcnt++] = strdup(buf); + /* argv[7] -q option should be located at the end of command !! */ + if (mode == PM_QUIET) + argv[argcnt++] = strdup("-q"); /*** add quote in all string for special charactor like '\n'*** FIX */ for (i = 0; i < argcnt; i++) { @@ -1761,6 +1778,9 @@ API int pkgmgr_client_move_usr_pkg(pkgmgr_client *pc, const char *pkg_type, argv[argcnt++] = strdup("-t"); /* argv[6] */ argv[argcnt++] = strdup(buf); + /* argv[5] -q option should be located at the end of command !! */ + if (mode == PM_QUIET) + argv[argcnt++] = strdup("-q"); /*** add quote in all string for special charactor like '\n'*** FIX */ for (i = 0; i < argcnt; i++) { @@ -2135,6 +2155,9 @@ API int pkgmgr_client_usr_clear_user_data(pkgmgr_client *pc, const char *pkg_typ argv[argcnt++] = strdup("-c"); /* argv[4] */ argv[argcnt++] = strdup(appid); + /* argv[5] -q option should be located at the end of command !! */ + if (mode == PM_QUIET) + argv[argcnt++] = strdup("-q"); /*** add quote in all string for special charactor like '\n'*** FIX */ for (i = 0; i < argcnt; i++) { diff --git a/comm/pkgmgr_installer.c b/comm/pkgmgr_installer.c index bbf9299..39cc7df 100644 --- a/comm/pkgmgr_installer.c +++ b/comm/pkgmgr_installer.c @@ -54,6 +54,7 @@ /* ADT */ struct pkgmgr_installer { int request_type; + int quiet; int move_type; char *pkgmgr_info; char *session_id; @@ -125,6 +126,7 @@ API pkgmgr_installer *pkgmgr_installer_new(void) return ERR_PTR(-ENOMEM); pi->request_type = PKGMGR_REQ_INVALID; + pi->quiet = 0; return pi; } @@ -247,6 +249,10 @@ pkgmgr_installer_receive_request(pkgmgr_installer *pi, pi->move_type = atoi(optarg); break; + case 'q': /* quiet mode */ + pi->quiet = 1; + break; + case 'p': /* caller pkgid*/ if (pi->caller_pkgid) free(pi->caller_pkgid); @@ -280,8 +286,6 @@ pkgmgr_installer_receive_request(pkgmgr_installer *pi, } } - /* normal mode : get options from argv */ - RET: return r; } @@ -318,7 +322,8 @@ API const char *pkgmgr_installer_get_optional_data(pkgmgr_installer *pi) API int pkgmgr_installer_is_quiet(pkgmgr_installer *pi) { - return 1; + CHK_PI_RET(PKGMGR_REQ_INVALID); + return pi->quiet; } API int pkgmgr_installer_get_move_type(pkgmgr_installer *pi) diff --git a/comm/pkgmgr_installer_config.h b/comm/pkgmgr_installer_config.h index f3ae324..7163d72 100644 --- a/comm/pkgmgr_installer_config.h +++ b/comm/pkgmgr_installer_config.h @@ -45,6 +45,7 @@ const struct option long_opts[] = { { "reinstall", 0, NULL, 'r' }, { "caller-pkgid", 1, NULL, 'p' }, { "smack", 1, NULL, 's' }, + { "quiet", 1, NULL, 'q' }, { 0, 0, 0, 0 } /* sentinel */ }; diff --git a/server/src/pkgmgr-server.c b/server/src/pkgmgr-server.c index 49854f4..739baf0 100644 --- a/server/src/pkgmgr-server.c +++ b/server/src/pkgmgr-server.c @@ -91,6 +91,7 @@ FILE *___log = NULL; #define NO_MATCHING_FILE 11 static int backend_flag = 0; /* 0 means that backend process is not running */ +static int drawing_popup = 0; /* 0 means that pkgmgr-server has no popup now */ typedef struct { char **env; @@ -147,6 +148,12 @@ typedef enum { PMSVC_SVC_APP }pkgmgr_svc_app_component; +struct appdata { + pm_dbus_msg *item; + OPERATION_TYPE op_type; +}; + + static int __check_backend_status_for_exit(); static int __check_queue_status_for_exit(); static int __check_backend_mode(); @@ -156,6 +163,9 @@ static void __set_backend_free(int position); static int __is_backend_mode_quiet(int position); static void __set_backend_mode(int position); static void __unset_backend_mode(int position); +static void response_cb1(void *data, void *event_info); +static void response_cb2(void *data, void *event_info); +static int create_popup(struct appdata *ad); static void sighandler(int signo); static void _wait_backend(pid_t pid); static int __get_position_from_pkg_type(char *pkgtype); @@ -416,6 +426,103 @@ err: return ret; } +static +void response_cb1(void *data, void *event_info) +{ + struct appdata *ad = (struct appdata *)data; + int p = 0; + int ret = 0; + DBG("start of response_cb()\n"); + + /* YES */ + DBG("Uninstalling... [%s]\n", ad->item->pkgid); + + if (strlen(ad->item->pkgid) == 0) { + DBG("package_name is empty\n"); + } + + if (strlen(ad->item->pkg_type) == 0) { + DBG("Fail : Uninstalling... [%s]\n", + ad->item->pkgid); + free(ad->item); + drawing_popup = 0; + + return; + } + + DBG("pkg_type = [%s]\n", ad->item->pkg_type); + + ret = _pm_queue_push(ad->item); + p = __get_position_from_pkg_type(ad->item->pkg_type); + __unset_backend_mode(p); + + /* Free resource */ + free(ad->item); + /***************/ + if (ret == 0) + g_idle_add(queue_job, NULL); + + DBG("end of response_cb()\n"); + + drawing_popup = 0; + + return; +} + +static +void response_cb2(void *data, void *event_info) +{ + int p = 0; + struct appdata *ad = (struct appdata *)data; + + DBG("start of response_cb()\n"); + + /* NO */ + pkgmgr_installer *pi; + gboolean ret_parse; + gint argcp; + gchar **argvp; + GError *gerr = NULL; + + pi = pkgmgr_installer_new(); + if (!pi) { + DBG("Failure in creating the pkgmgr_installer object"); + return; + } + + ret_parse = g_shell_parse_argv(ad->item->args, + &argcp, &argvp, &gerr); + if (FALSE == ret_parse) { + DBG("Failed to split args: %s", ad->item->args); + DBG("messsage: %s", gerr->message); + pkgmgr_installer_free(pi); + return; + } + + pkgmgr_installer_receive_request(pi, argcp, argvp); + + pkgmgr_installer_send_signal(pi, ad->item->pkg_type, + ad->item->pkgid, "end", + "cancel"); + + pkgmgr_installer_free(pi); + p = __get_position_from_pkg_type(ad->item->pkg_type); + __set_backend_mode(p); + + /* Free resource */ + free(ad->item); + /***************/ + /* queue_job should be called for every request that is pushed + into queue. In "NO" case, request is not pushed so no need of + calling queue_job*/ + + DBG("end of response_cb()\n"); + + drawing_popup = 0; + + return; +} + #if 0 static char *__get_exe_path(const char *pkgid) { @@ -455,6 +562,162 @@ static char *__get_exe_path(const char *pkgid) } #endif +static +int create_popup(struct appdata *ad) +{ + DBG("start of create_popup()\n"); + + drawing_popup = 1; + + char sentence[MAX_PKG_ARGS_LEN] = { '\0' }; + char *pkgid = NULL; + char app_name[MAX_PKG_NAME_LEN] = { '\0' }; + + notification_h noti = NULL; + notification_error_e err = NOTIFICATION_ERROR_NONE; + + noti = notification_create(NOTIFICATION_TYPE_NOTI); + if (!noti) { + DBG("Failed to create a popup notification\n"); + drawing_popup = 0; + return -1; + } + + /* Sentence of popup */ + int ret; + + pkgid = strrchr(ad->item->pkgid, '/') == NULL ? + ad->item->pkgid : strrchr(ad->item->pkgid, '/') + 1; + + if (ad->op_type == OPERATION_INSTALL) { + snprintf(sentence, sizeof(sentence) - 1, "Install?"); + } else if (ad->op_type == OPERATION_UNINSTALL) { + char *label = NULL; + pkgmgrinfo_pkginfo_h handle; + ret = pkgmgrinfo_pkginfo_get_usr_pkginfo(pkgid, ad->item->uid, &handle); + + if (ret < 0){ + drawing_popup = 0; + notification_delete(noti); + return -1; + } + ret = pkgmgrinfo_pkginfo_get_label(handle, &label); + if (ret < 0){ + drawing_popup = 0; + notification_delete(noti); + return -1; + } + + snprintf(app_name, sizeof(app_name) - 1, label); + ret = pkgmgrinfo_pkginfo_destroy_pkginfo(handle); + if (ret < 0){ + drawing_popup = 0; + notification_delete(noti); + return -1; + } + + pkgid = app_name; + + snprintf(sentence, sizeof(sentence) - 1, "Uninstall?"); + } else if (ad->op_type == OPERATION_REINSTALL) { + snprintf(sentence, sizeof(sentence) - 1, "Reinstall?"); + } else + snprintf(sentence, sizeof(sentence) - 1, "Invalid request"); + + /***********************************/ + + err = notification_set_text(noti, + NOTIFICATION_TEXT_TYPE_TITLE, pkgid, + NULL, NOTIFICATION_VARIABLE_TYPE_NONE); + if (err != NOTIFICATION_ERROR_NONE) { + DBG("Failed to set popup notification title\n"); + drawing_popup = 0; + notification_delete(noti); + return -1; + } + + err = notification_set_text(noti, + NOTIFICATION_TEXT_TYPE_CONTENT, sentence, + NULL, NOTIFICATION_VARIABLE_TYPE_NONE); + if (err != NOTIFICATION_ERROR_NONE) { + DBG("Failed to set popup notification sentence\n"); + drawing_popup = 0; + notification_delete(noti); + return -1; + } + + /* Details of popup (timeout, buttons...) */ + bundle *b = NULL; + + b = bundle_create(); + if (!b) { + DBG("Failed to set popup notification details\n"); + drawing_popup = 0; + notification_delete(noti); + return -1; + } + + /* TRANSLATION DOES NOT WORK ; TO FIX ? + char *button1_text = dgettext("sys_string", "IDS_COM_SK_YES"); + char *button2_text = dgettext("sys_string", "IDS_COM_SK_NO"); + */ + char *button1_text = "Yes"; + char *button2_text = "No"; + char *buttons_text = malloc(strlen(button1_text) + + strlen(button2_text) + 2); + strcpy(buttons_text, button1_text); + strcat(buttons_text, ","); + strcat(buttons_text, button2_text); + + bundle_add (b, "timeout", "0"); + bundle_add (b, "noresize", "1"); + bundle_add (b, "buttons", buttons_text); + + free(buttons_text); + + err = notification_set_execute_option (noti, + NOTIFICATION_EXECUTE_TYPE_RESPONDING, + NULL, NULL, b); + if (err != NOTIFICATION_ERROR_NONE) { + DBG("Failed to set popup notification as interactive\n"); + drawing_popup = 0; + bundle_free(b); + notification_delete(noti); + return -1; + } + + /* Show the popup */ + err = notification_insert (noti, NULL); + if (err != NOTIFICATION_ERROR_NONE) { + DBG("Failed to set popup notification sentence\n"); + drawing_popup = 0; + bundle_free(b); + notification_delete(noti); + return -1; + } + + /* Catch user response */ + int button; + + err = notification_wait_response (noti, 10, &button, NULL); + if (err != NOTIFICATION_ERROR_NONE) { + DBG("Failed to wait for user response, defaulting to 'no'\n"); + button = 2; + } + + if (button == 1) { + response_cb1(ad, NULL); + } else if (button == 2) { + response_cb2(ad, NULL); + } + + bundle_free(b); + notification_delete(noti); + + DBG("end of create_popup()\n"); + return 0; +} + gboolean send_fail_signal(void *data) { DBG("send_fail_signal start\n"); @@ -600,6 +863,8 @@ void req_cb(void *cb_data, uid_t uid, const char *req_id, const int req_type, DBG(">> in callback >> Got request: [%s] [%d] [%s] [%s] [%s] [%s]", req_id, req_type, pkg_type, pkgid, args, cookie); + struct appdata *ad = (struct appdata *)cb_data; + pm_dbus_msg *item = calloc(1, sizeof(pm_dbus_msg)); memset(item, 0x00, sizeof(pm_dbus_msg)); @@ -643,7 +908,10 @@ void req_cb(void *cb_data, uid_t uid, const char *req_id, const int req_type, sig_reg = 1; } - DBG("req_type=(%d) backend_flag=(%d)\n", req_type, backend_flag); + DBG("req_type=(%d) drawing_popup=(%d) backend_flag=(%d)\n", req_type, + drawing_popup, backend_flag); + + char *quiet = NULL; switch (item->req_type) { case COMM_REQ_TO_INSTALLER: @@ -655,15 +923,57 @@ void req_cb(void *cb_data, uid_t uid, const char *req_id, const int req_type, goto err; } - /* quiet mode */ - err = _pm_queue_push(item); - p = __get_position_from_pkg_type(item->pkg_type); - __set_backend_mode(p); - /* Free resource */ - free(item); - if (err == 0) - g_idle_add(queue_job, NULL); - *ret = COMM_RET_OK; + /* -q option should be located at the end of command !! */ + if (((quiet = strstr(args, " -q")) && + (quiet[strlen(quiet)] == '\0')) || + ((quiet = strstr(args, " '-q'")) && + (quiet[strlen(quiet)] == '\0'))) { + /* quiet mode */ + err = _pm_queue_push(item); + p = __get_position_from_pkg_type(item->pkg_type); + __set_backend_mode(p); + /* Free resource */ + free(item); + if (err == 0) + g_idle_add(queue_job, NULL); + *ret = COMM_RET_OK; + } else { + /* non quiet mode */ + p = __get_position_from_pkg_type(item->pkg_type); + if (drawing_popup == 0 && + !__is_backend_busy(p) && + __check_backend_mode()) { + /* if there is no popup */ + ad->item = item; + + if (strstr(args, " -i ") + || strstr(args, " '-i' ")) + ad->op_type = OPERATION_INSTALL; + else if (strstr(args, " -d ") + || strstr(args, " '-d' ")) { + ad->op_type = OPERATION_UNINSTALL; + } else if (strstr(args, " -r ") + || strstr(args, " '-r' ")) + ad->op_type = OPERATION_REINSTALL; + else + ad->op_type = OPERATION_MAX; + + err = create_popup(ad); + if (err != 0) { + *ret = COMM_RET_ERROR; + DBG("create popup failed\n"); + goto err; + } else { + *ret = COMM_RET_OK; + } + } else { + DBG("info drawing_popup:%d, __is_backend_busy(p):%d, __check_backend_mode():%d\n", + drawing_popup, __is_backend_busy(p), __check_backend_mode()); + /* if popup is already being drawn */ + *ret = COMM_RET_ERROR; + goto err; + } + } break; case COMM_REQ_TO_ACTIVATOR: /* In case of activate, there is no popup */ @@ -715,7 +1025,8 @@ void req_cb(void *cb_data, uid_t uid, const char *req_id, const int req_type, *ret = COMM_RET_OK; break; case COMM_REQ_CANCEL: - _pm_queue_delete(item); + ad->item = item; + _pm_queue_delete(ad->item); p = __get_position_from_pkg_type(item->pkg_type); __unset_backend_mode(p); free(item); @@ -857,9 +1168,10 @@ gboolean exit_server(void *data) { DBG("exit_server Start\n"); if (__check_backend_status_for_exit() && - __check_queue_status_for_exit()) { + __check_queue_status_for_exit() && + drawing_popup == 0) { if (!getenv("PMS_STANDALONE") && ail_db_update) { - g_main_loop_quit(mainloop); + ecore_main_loop_quit(); return FALSE; } } @@ -1839,9 +2151,6 @@ int main(int argc, char *argv[]) return -1; } - /*Initialize inotify to monitor desktop file updates */ -/* _pm_desktop_file_monitor_init(); */ - /*Allocate memory for holding pid, pkgtype and pkgid*/ ptr = (backend_info*)calloc(num_of_backends, sizeof(backend_info)); if (ptr == NULL) { @@ -1858,15 +2167,18 @@ int main(int argc, char *argv[]) return -1; } + struct appdata ad; + DBG("Main loop is created."); PkgMgrObject *pkg_mgr; pkg_mgr = g_object_new(PKG_MGR_TYPE_OBJECT, NULL); - pkg_mgr_set_request_callback(pkg_mgr, req_cb, NULL); + pkg_mgr_set_request_callback(pkg_mgr, req_cb, &ad); DBG("pkg_mgr object is created, and request callback is registered."); g_main_loop_run(mainloop); + DBG("Quit main loop."); _pm_queue_final(); /*Free backend info */ diff --git a/tool/pkg_cmd.c b/tool/pkg_cmd.c index 453f377..e2882ad 100644 --- a/tool/pkg_cmd.c +++ b/tool/pkg_cmd.c @@ -83,6 +83,7 @@ const struct option long_options[] = { {"getsize-type", 1, NULL, 'T'}, {"csc", 1, NULL, 'S'}, {"global", 0, NULL, 'G'}, + {"quiet", 0, NULL, 'q'}, {"help", 0, NULL, 'h'}, {0, 0, 0, 0} /* sentinel */ }; @@ -113,6 +114,7 @@ struct pm_tool_args_t { char pkgid[PKG_NAME_STRING_LEN_MAX]; char des_path[PKG_NAME_STRING_LEN_MAX]; char label[PKG_NAME_STRING_LEN_MAX]; + int quiet; int global; int type; int result; @@ -305,17 +307,18 @@ static void __print_usage() printf("-n, --package-name provide package name\n"); printf("-t, --package-type provide package type\n"); printf("-T, --move-type provide move type [0 : move to internal /1: move to external]\n"); + printf("-q, --quiet quiet mode operation\n"); printf("-G, --global Global Mode [Warning user should be privilegied to use this mode] \n"); printf("-h, --help . print this help\n\n"); - printf("Usage: pkgcmd [options]\n"); - printf("pkgcmd -i -t (-d ) -p (-G)\n"); - printf("pkgcmd -u -n (-G)\n"); + printf("Usage: pkgcmd [options] (--quiet)\n"); + printf("pkgcmd -i -t (-d ) -p (-G) (-q)\n"); + printf("pkgcmd -u -n (-G) (-q)\n"); printf("pkgcmd -r -t -n (-G) \n"); printf("pkgcmd -l (-t ) \n"); - printf("pkgcmd -s -t -p \n"); - printf("pkgcmd -s -t -n \n"); - printf("pkgcmd -m -t -T -n \n\n"); + printf("pkgcmd -s -t -p (-q)\n"); + printf("pkgcmd -s -t -n (-q)\n"); + printf("pkgcmd -m -t -T -n (-q)\n\n"); printf("pkgcmd -g -T -n \n"); printf("pkgcmd -C -n \n"); printf("pkgcmd -k -n \n"); @@ -511,7 +514,7 @@ static int __pkg_list_cb (const pkgmgrinfo_pkginfo_h handle, void *user_data, ui static int __process_request(uid_t uid) { int ret = -1; - int mode = PM_QUIET; + int mode = PM_DEFAULT; pkgmgr_client *pc = NULL; char buf[1024] = {'\0'}; int pid = -1; @@ -531,6 +534,10 @@ static int __process_request(uid_t uid) data.result = PKGCMD_ERR_FATAL_ERROR; break; } + if (data.quiet == 0) + mode = PM_DEFAULT; + else + mode = PM_QUIET; if (data.des_path[0] == '\0') { ret = @@ -569,6 +576,10 @@ static int __process_request(uid_t uid) data.result = PKGCMD_ERR_FATAL_ERROR; break; } + if (data.quiet == 0) + mode = PM_DEFAULT; + else + mode = PM_QUIET; //if global ret = __is_app_installed(data.pkgid, uid); @@ -606,6 +617,7 @@ static int __process_request(uid_t uid) break; } + mode = PM_QUIET; ret = pkgmgr_client_usr_reinstall(pc, data.pkg_type, data.pkgid, NULL, mode, __return_cb, pc, uid); if (ret < 0){ data.result = PKGCMD_ERR_FATAL_ERROR; @@ -631,6 +643,10 @@ static int __process_request(uid_t uid) ret = -1; break; } + if (data.quiet == 0) + mode = PM_DEFAULT; + else + mode = PM_QUIET; ret = __is_app_installed(data.pkgid, uid); if (ret == -1) { printf("package is not installed\n"); @@ -734,7 +750,11 @@ static int __process_request(uid_t uid) printf("package is not installed\n"); break; } - ret = pkgmgr_client_usr_request_service(PM_REQUEST_MOVE, data.type, pc, NULL, data.pkgid, uid, NULL, NULL, NULL); + if (data.quiet == 0) + ret = pkgmgr_client_usr_move(pc, data.pkg_type, data.pkgid, data.type, mode, uid); + else + ret = pkgmgr_client_usr_request_service(PM_REQUEST_MOVE, data.type, pc, NULL, data.pkgid, uid, NULL, NULL, NULL); + printf("pkg[%s] move result = %d\n", data.pkgid, ret); if (ret < 0) @@ -980,6 +1000,7 @@ int main(int argc, char *argv[]) memset(data.pkgid, '\0', PKG_NAME_STRING_LEN_MAX); memset(data.pkg_type, '\0', PKG_TYPE_STRING_LEN_MAX); memset(data.label, '\0', PKG_TYPE_STRING_LEN_MAX); + data.quiet = 0; data.global = 0; //By default pkg_cmd will manage for the current user data.result = 0; data.type = -1; @@ -1097,6 +1118,11 @@ int main(int argc, char *argv[]) data.request = HELP_REQ; break; + case 'q': /* quiet mode */ + data.quiet = 1; + break; + + /* Otherwise */ case '?': /* Not an option */ __print_usage(); break; -- 2.7.4