On Wednesday 20 October 2010 16:36:48 Denys Vlasenko wrote:
> 2010/10/20 Alexander Shishkin <[email protected]>:
> > On Wed, Oct 20, 2010 at 01:26:24 +0200, Denys Vlasenko wrote:
> >> On Wed, Oct 20, 2010 at 2:56 AM, Alexander Shishkin <[email protected]>
> >> wrote:
> >> > 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
> >>
> >> 676 bytes is far too much for a simple pass over a text file.
> >>
> >> How about this?
> >>
> >> http://git.busybox.net/busybox/commit/?id=5be79ff27a5852567a9bdec80d67b061ad828290
> >
> > Well, the list version is more readable, imo.
>
> It's twice as big.
>
> > Also, splitting add and remove
> > into separate options seems quite pointless.
>
> What if I want one-applet version of add-shell?
> (.config with only one enabled has optimizations
> which skip applet table search, and therefore
> there is no applet table in the first place. etc...)
>
> > And I'm totally missing the point
> > of using stdout, but I'm sure there must be a good reason.
>
> How can you do O_EXCL open with fopen?
>
> > Otherwise seems fine,
> > thanks for spending time on this.
>
Hi,
just for fun a different approach to the add/remove shell problem.
This is really small. Bloat-o-meter says:
debian:~/Desktop/test/busybox$ scripts/bloat-o-meter busybox_old
busybox_unstripped
function old new delta
update_passwd 1273 1335 +62
dont_add 2 - -2
.rodata 135419 135406 -13
add_remove_shell_main 259 62 -197
------------------------------------------------------------------------------
(add/remove: 0/1 grow/shrink: 1/2 up/down: 62/-212) Total: -150 bytes
It is a little tested and seems to work fine for me.
It also adds argc check and usage message.
Hints and critics on how to shrink it even more are welcome!
Enjoy!
Ciao,
Tito
#include "libbb.h"
#define SHELLS_FILE "/etc/shells"
int add_remove_shell_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int add_remove_shell_main(int argc UNUSED_PARAM, char **argv)
{
if (argc < 2)
bb_show_usage();
argv++;
do {
if (update_passwd(SHELLS_FILE, *argv, "", NULL) < 0)
return EXIT_FAILURE;
} while (*++argv);
return EXIT_SUCCESS;
}
Signed-off-by: Tito Ragusa <[email protected]>
--- loginutils/add-remove-shell.c.orig 2010-10-20 14:41:23.000000000 +0200
+++ loginutils/add-remove-shell.c 2010-10-20 16:35:57.000000000 +0200
@@ -40,88 +40,16 @@
#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;
-
+ if (argc < 2)
+ bb_show_usage();
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);
- }
+ do {
+ if (update_passwd(SHELLS_FILE, *argv, "", NULL) < 0)
+ return EXIT_FAILURE;
+ } while (*++argv);
return EXIT_SUCCESS;
}
--- libbb/update_passwd.c.orig 2010-09-22 16:14:08.000000000 +0200
+++ libbb/update_passwd.c 2010-10-20 16:51:43.000000000 +0200
@@ -62,11 +62,21 @@
only if CONFIG_PASSWD=y and applet_name[0] == 'p' like in passwd
or if CONFIG_CHPASSWD=y and applet_name[0] == 'c' like in chpasswd
+ 8) add a shell: update_passwd(SHELLS_FILE, SHELL, "", NULL)
+ only if CONFIG_ADD_SHELL=y and applet_name[3] == '-' like in add-shell
+
+ 9) remove a shell: update_passwd(SHELLS_FILE, SHELL, "", NULL)
+ only if CONFIG_REMOVE_SHELL=y and applet_name[6] == '-' like in remove-shell
+
This function does not validate the arguments fed to it
so the calling program should take care of that.
Returns number of lines changed, or -1 on error.
*/
+
+#define REMOVE_SHELL (ENABLE_REMOVE_SHELL && (!ENABLE_ADD_SHELL || applet_name[6] == '-'))
+#define ADD_SHELL (ENABLE_ADD_SHELL && (!ENABLE_REMOVE_SHELL || applet_name[3] == '-'))
+
int FAST_FUNC update_passwd(const char *filename,
const char *name,
const char *new_passwd,
@@ -167,6 +177,18 @@
line = xmalloc_fgetline(old_fp);
if (!line) /* EOF/error */
break;
+#if ENABLE_ADD_SHELL || ENABLE_REMOVE_SHELL
+ if (ADD_SHELL || REMOVE_SHELL) {
+ /* remove colon */
+ name_colon[user_len - 1] = '\0';
+ if (strcmp(name_colon, line) != 0) {
+ fprintf(new_fp, "%s\n", line);
+ goto next;
+ } else if (REMOVE_SHELL) {
+ changed_lines++;
+ }
+ } else
+#endif
if (strncmp(name_colon, line, user_len) != 0) {
fprintf(new_fp, "%s\n", line);
goto next;
@@ -247,7 +269,7 @@
bb_error_msg("can't find %s in %s", member, filename);
}
#endif
- if ((ENABLE_ADDUSER || ENABLE_ADDGROUP)
+ if ((ENABLE_ADDUSER || ENABLE_ADDGROUP || ENABLE_ADD_SHELL)
&& applet_name[0] == 'a' && !member
) {
/* add user or group */
_______________________________________________
busybox mailing list
[email protected]
http://lists.busybox.net/mailman/listinfo/busybox