How about this? (I left locking in place but applied other changes)

function                                             old     new   delta
add_shell_main                                         -     497    +497
.rodata                                           144696  144795     +99
packed_usage                                       27078   27114     +36
applet_names                                        2259    2282     +23
applet_main                                         2672    2688     +16
applet_nameofs                                       668     672      +4
applet_install_loc                                   167     168      +1
------------------------------------------------------------------------------
(add/remove: 2/0 grow/shrink: 6/0 up/down: 676/0)             Total: 676 bytes

Signed-off-by: Alexander Shishkin <[email protected]>
---
 debianutils/add-remove-shell.c |  119 ++++++++++++++++++++++++++++++++++++++++
 1 files changed, 119 insertions(+), 0 deletions(-)
 create mode 100644 debianutils/add-remove-shell.c

diff --git a/debianutils/add-remove-shell.c b/debianutils/add-remove-shell.c
new file mode 100644
index 0000000..b71690a
--- /dev/null
+++ b/debianutils/add-remove-shell.c
@@ -0,0 +1,119 @@
+/*
+ * add-shell and remove-shell implementation for busybox
+ *
+ * Copyright (C) 2010 Nokia Corporation. All rights reserved.
+ * Written by Alexander Shishkin <[email protected]>
+ *
+ * Licensed under GPLv2 or later, see the LICENSE file in this source tree
+ * for details.
+ */
+
+//applet:IF_ADD_REMOVE_SHELL(APPLET_ODDNAME(add-shell, add_shell, 
_BB_DIR_USR_BIN, _BB_SUID_DROP, add_shell))
+//applet:IF_ADD_REMOVE_SHELL(APPLET_ODDNAME(remove-shell, add_shell, 
_BB_DIR_USR_BIN, _BB_SUID_DROP, remove_shell))
+//kbuild:lib-$(CONFIG_ADD_REMOVE_SHELL)     += add-remove-shell.o
+
+//config:config ADD_REMOVE_SHELL
+//config:       bool "add-shell / remove-shell"
+//config:       default y if DESKTOP
+//config:       help
+//config:         Add/remove shells to/from /etc/shells.
+
+//usage:#define add_shell_trivial_usage
+//usage:       "shellname [shellname...]"
+//usage:#define add_shell_full_usage "\n\n"
+//usage:       "Add shells to the list of valid login shells\n"
+
+//usage:#define remove_shell_trivial_usage
+//usage:       "shellname [shellname...]"
+//usage:#define remove_shell_full_usage "\n\n"
+//usage:       "Remove shells to the list of valid login shells\n"
+
+#include "libbb.h"
+
+#define SHELLS_FILE    "/etc/shells"
+
+static int update_shells(llist_t *shell_list, int add)
+{
+       FILE *orig, *new;
+       struct flock lock;
+       char *orig_fn;
+       char *tmp_fn;
+
+       orig_fn = xmalloc_follow_symlinks(SHELLS_FILE);
+       if (!orig_fn)
+               return EXIT_FAILURE;
+
+       orig = fopen(orig_fn, "r+");
+
+       tmp_fn = xasprintf("%s.tmp", orig_fn);
+       new = xfopen_for_write(tmp_fn);
+
+       /* if shells file exists, read it */
+       if (orig) {
+               lock.l_type = F_WRLCK;
+               lock.l_whence = SEEK_SET;
+               lock.l_start = 0;
+               lock.l_len = 0;
+               if (fcntl(fileno(orig), F_SETLK, &lock) < 0)
+                       bb_perror_msg("warning: can't lock '%s'", orig_fn);
+               lock.l_type = F_UNLCK;
+
+               while (!feof(orig)) {
+                       char *line;
+                       llist_t *ours;
+
+                       line = xmalloc_fgetline(orig);
+                       if (!line)
+                               break;
+
+                       chomp(line);
+
+                       /* if it's on the list and we're add-shell, remove it */
+                       ours = llist_find_str(shell_list, line);
+                       if (ours && add)
+                               llist_unlink(&shell_list, ours);
+
+                       /* skip if we're remove-shell and it's on the list */
+                       if (add || !ours)
+                               fprintf(new, "%s\n", line);
+
+                       free(line);
+               }
+       }
+
+       /* append the what's left on the list */
+       if (add) {
+               char *line;
+
+               while ((line = llist_pop(&shell_list)))
+                       fprintf(new, "%s\n", line);
+       }
+       fclose(new);
+
+       if (orig) {
+               fcntl(fileno(orig), F_SETLK, &lock);
+               fclose(orig);
+       }
+
+       xrename(tmp_fn, orig_fn);
+
+       if (ENABLE_FEATURE_CLEAN_UP) {
+               free(orig_fn);
+               free(tmp_fn);
+       }
+
+       return EXIT_SUCCESS;
+}
+
+int add_shell_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int add_shell_main(int argc UNUSED_PARAM, char **argv)
+{
+       llist_t *shell_list = NULL;
+
+       /* there is nothing on the command line but the list of shells */
+       (void)*argv++;
+       while (*argv)
+               llist_add_to_end(&shell_list, *argv++);
+
+       return update_shells(shell_list, applet_name[0] == 'a');
+}
-- 
1.7.2.1.45.gb66c2

_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to