summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorAlexander Shishkin <virtuoso@slind.org>2010-10-20 13:22:24 +0200
committerDenys Vlasenko <dvlasenk@redhat.com>2010-10-20 13:22:58 +0200
commit5be79ff27a5852567a9bdec80d67b061ad828290 (patch)
tree6c3b1d7ee70394a36c0efdf7d3f3d12ba1e5b9ab
parentbec588878b6d435c33d9b0aae6247715c259e3a4 (diff)
add-shell, remove-shell: new applets
function old new delta add_remove_shell_main - 259 +259 packed_usage 27408 27438 +30 applet_names 2326 2349 +23 applet_main 1364 1372 +8 applet_nameofs 682 686 +4 run_applet_and_exit 700 703 +3 dont_add - 2 +2 applet_install_loc 171 172 +1 ------------------------------------------------------------------------------ (add/remove: 3/0 grow/shrink: 6/0 up/down: 330/0) Total: 330 bytes Signed-off-by: Alexander Shishkin <virtuoso@slind.org> Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
-rw-r--r--loginutils/add-remove-shell.c127
1 files changed, 127 insertions, 0 deletions
diff --git a/loginutils/add-remove-shell.c b/loginutils/add-remove-shell.c
new file mode 100644
index 000000000..986fe57c5
--- /dev/null
+++ b/loginutils/add-remove-shell.c
@@ -0,0 +1,127 @@
+/*
+ * add-shell and remove-shell implementation for busybox
+ *
+ * Copyright (C) 2010 Nokia Corporation. All rights reserved.
+ * Written by Alexander Shishkin <virtuoso@slind.org>
+ *
+ * Licensed under GPLv2 or later, see the LICENSE file in this source tree
+ * for details.
+ */
+
+//applet:IF_ADD_SHELL( APPLET_ODDNAME(add-shell , add_remove_shell, _BB_DIR_USR_BIN, _BB_SUID_DROP, add_shell ))
+//applet:IF_REMOVE_SHELL(APPLET_ODDNAME(remove-shell, add_remove_shell, _BB_DIR_USR_BIN, _BB_SUID_DROP, remove_shell))
+
+//kbuild:lib-$(CONFIG_ADD_SHELL) += add-remove-shell.o
+//kbuild:lib-$(CONFIG_REMOVE_SHELL) += add-remove-shell.o
+
+//config:config ADD_SHELL
+//config: bool "add-shell"
+//config: default y if DESKTOP
+//config: help
+//config: Add shells to /etc/shells.
+//config:
+//config:config REMOVE_SHELL
+//config: bool "remove-shell"
+//config: default y if DESKTOP
+//config: help
+//config: Remove shells from /etc/shells.
+
+//usage:#define add_shell_trivial_usage
+//usage: "SHELL..."
+//usage:#define add_shell_full_usage "\n\n"
+//usage: "Add SHELLs to /etc/shells"
+
+//usage:#define remove_shell_trivial_usage
+//usage: "SHELL..."
+//usage:#define remove_shell_full_usage "\n\n"
+//usage: "Remove SHELLs from /etc/shells"
+
+#include "libbb.h"
+
+#define SHELLS_FILE "/etc/shells"
+
+#define REMOVE_SHELL (ENABLE_REMOVE_SHELL && (!ENABLE_ADD_SHELL || applet_name[0] == 'r'))
+#define ADD_SHELL (ENABLE_ADD_SHELL && (!ENABLE_REMOVE_SHELL || applet_name[0] == 'a'))
+
+/* NB: we use the _address_, not the value, of this string
+ * as a "special value of pointer" in the code.
+ */
+static const char dont_add[] ALIGN1 = "\n";
+
+int add_remove_shell_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int add_remove_shell_main(int argc UNUSED_PARAM, char **argv)
+{
+ FILE *orig_fp;
+ char *orig_fn;
+ char *new_fn;
+
+ argv++;
+
+ orig_fn = xmalloc_follow_symlinks(SHELLS_FILE);
+ if (!orig_fn)
+ return EXIT_FAILURE;
+ orig_fp = fopen_for_read(orig_fn);
+
+ new_fn = xasprintf("%s.tmp", orig_fn);
+ xmove_fd(xopen(new_fn, O_WRONLY | O_CREAT | O_EXCL), STDOUT_FILENO);
+
+ /* TODO:
+ struct stat sb;
+ fstat(fileno(orig_fp), &sb);
+ xfchown(STDOUT_FILENO, sb.st_uid, sb.st_gid);
+ xfchmod(STDOUT_FILENO, sb.st_mode);
+ */
+
+ if (orig_fp) {
+ /* Copy old file, possibly skipping removed shell names */
+ char *line;
+ while ((line = xmalloc_fgetline(orig_fp)) != NULL) {
+ char **cpp = argv;
+ while (*cpp) {
+ if (strcmp(*cpp, line) == 0) {
+ /* Old file has this shell name */
+ if (REMOVE_SHELL) {
+ /* we are remove-shell */
+ /* delete this name by not copying it */
+ goto next_line;
+ }
+ /* we are add-shell */
+ /* mark this name as "do not add" */
+ *cpp = (char*)dont_add;
+ }
+ cpp++;
+ }
+ /* copy shell name from old to new file */
+ printf("%s\n", line);
+ next_line:
+ free(line);
+ }
+ if (ENABLE_FEATURE_CLEAN_UP)
+ fclose(orig_fp);
+ }
+
+ if (ADD_SHELL) {
+ char **cpp = argv;
+ while (*cpp) {
+ if (*cpp != dont_add)
+ printf("%s\n", *cpp);
+ cpp++;
+ }
+ }
+
+ /* Ensure we wrote out everything */
+ if (fclose(stdout) != 0) {
+ xunlink(new_fn);
+ bb_perror_msg_and_die("%s: write error", new_fn);
+ }
+
+ /* Small hole: if rename fails, /etc/shells.tmp is not removed */
+ xrename(new_fn, orig_fn);
+
+ if (ENABLE_FEATURE_CLEAN_UP) {
+ free(orig_fn);
+ free(new_fn);
+ }
+
+ return EXIT_SUCCESS;
+}