source: MondoRescue/branches/3.3/mindi-busybox/loginutils/add-remove-shell.c@ 3622

Last change on this file since 3622 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

  • Property svn:eol-style set to native
File size: 3.6 KB
Line 
1/*
2 * add-shell and remove-shell implementation for busybox
3 *
4 * Copyright (C) 2010 Nokia Corporation. All rights reserved.
5 * Written by Alexander Shishkin <virtuoso@slind.org>
6 *
7 * Licensed under GPLv2 or later, see the LICENSE file in this source tree
8 * for details.
9 */
10//config:config ADD_SHELL
11//config: bool "add-shell"
12//config: default y if DESKTOP
13//config: help
14//config: Add shells to /etc/shells.
15//config:
16//config:config REMOVE_SHELL
17//config: bool "remove-shell"
18//config: default y if DESKTOP
19//config: help
20//config: Remove shells from /etc/shells.
21
22//applet:IF_ADD_SHELL( APPLET_ODDNAME(add-shell , add_remove_shell, BB_DIR_USR_SBIN, BB_SUID_DROP, add_shell ))
23//applet:IF_REMOVE_SHELL(APPLET_ODDNAME(remove-shell, add_remove_shell, BB_DIR_USR_SBIN, BB_SUID_DROP, remove_shell))
24
25//kbuild:lib-$(CONFIG_ADD_SHELL) += add-remove-shell.o
26//kbuild:lib-$(CONFIG_REMOVE_SHELL) += add-remove-shell.o
27
28//usage:#define add_shell_trivial_usage
29//usage: "SHELL..."
30//usage:#define add_shell_full_usage "\n\n"
31//usage: "Add SHELLs to /etc/shells"
32
33//usage:#define remove_shell_trivial_usage
34//usage: "SHELL..."
35//usage:#define remove_shell_full_usage "\n\n"
36//usage: "Remove SHELLs from /etc/shells"
37
38#include "libbb.h"
39
40#define SHELLS_FILE "/etc/shells"
41
42#define REMOVE_SHELL (ENABLE_REMOVE_SHELL && (!ENABLE_ADD_SHELL || applet_name[0] == 'r'))
43#define ADD_SHELL (ENABLE_ADD_SHELL && (!ENABLE_REMOVE_SHELL || applet_name[0] == 'a'))
44
45/* NB: we use the _address_, not the value, of this string
46 * as a "special value of pointer" in the code.
47 */
48static const char dont_add[] ALIGN1 = "\n";
49
50int add_remove_shell_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
51int add_remove_shell_main(int argc UNUSED_PARAM, char **argv)
52{
53 FILE *orig_fp;
54 char *orig_fn;
55 char *new_fn;
56
57 argv++;
58
59 orig_fn = xmalloc_follow_symlinks(SHELLS_FILE);
60 if (!orig_fn)
61 return EXIT_FAILURE;
62 orig_fp = fopen_for_read(orig_fn);
63
64 new_fn = xasprintf("%s.tmp", orig_fn);
65 /*
66 * O_TRUNC or O_EXCL? At the first glance, O_EXCL looks better,
67 * since it prevents races. But: (1) it requires a retry loop,
68 * (2) if /etc/shells.tmp is *stale*, then retry loop
69 * with O_EXCL will never succeed - it should have a timeout,
70 * after which it should revert to O_TRUNC.
71 * For now, I settle for O_TRUNC instead.
72 */
73 xmove_fd(xopen(new_fn, O_WRONLY | O_CREAT | O_TRUNC), STDOUT_FILENO);
74
75 /* TODO:
76 struct stat sb;
77 xfstat(fileno(orig_fp), &sb);
78 xfchown(STDOUT_FILENO, sb.st_uid, sb.st_gid);
79 xfchmod(STDOUT_FILENO, sb.st_mode);
80 */
81
82 if (orig_fp) {
83 /* Copy old file, possibly skipping removed shell names */
84 char *line;
85 while ((line = xmalloc_fgetline(orig_fp)) != NULL) {
86 char **cpp = argv;
87 while (*cpp) {
88 if (strcmp(*cpp, line) == 0) {
89 /* Old file has this shell name */
90 if (REMOVE_SHELL) {
91 /* we are remove-shell */
92 /* delete this name by not copying it */
93 goto next_line;
94 }
95 /* we are add-shell */
96 /* mark this name as "do not add" */
97 *cpp = (char*)dont_add;
98 }
99 cpp++;
100 }
101 /* copy shell name from old to new file */
102 puts(line);
103 next_line:
104 free(line);
105 }
106 if (ENABLE_FEATURE_CLEAN_UP)
107 fclose(orig_fp);
108 }
109
110 if (ADD_SHELL) {
111 char **cpp = argv;
112 while (*cpp) {
113 if (*cpp != dont_add)
114 puts(*cpp);
115 cpp++;
116 }
117 }
118
119 /* Ensure we wrote out everything */
120 if (fclose(stdout) != 0) {
121 xunlink(new_fn);
122 bb_perror_msg_and_die("%s: write error", new_fn);
123 }
124
125 /* Small hole: if rename fails, /etc/shells.tmp is not removed */
126 xrename(new_fn, orig_fn);
127
128 if (ENABLE_FEATURE_CLEAN_UP) {
129 free(orig_fn);
130 free(new_fn);
131 }
132
133 return EXIT_SUCCESS;
134}
Note: See TracBrowser for help on using the repository browser.