ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/repos/CCSAdmin/chsh.c
(Generate patch)

Comparing CCSAdmin/chsh.c (file contents):
Revision 562 by douglas, 2005-08-27T21:46:39-07:00 vs.
Revision 582 by douglas, 2005-11-20T15:07:31-08:00

# Line 4 | Line 4
4   //
5   // Change Shell
6  
7 #include <sys/utsname.h>
8
7   #include "common.h"
8  
9   int main(int argc, char *argv[])
10   {
11 +        if (argc < 1)
12 +                return 1;
13 +
14 +        umask(S_IWGRP | S_IWOTH);
15 +        
16          int exception;
17          jmp_buf environment;
18  
# Line 30 | Line 33 | int main(int argc, char *argv[])
33          typedef struct
34          {
35                  const char *name;
36 <                char *freebsd, *linux, *darwin;
36 >                char *freebsd, *linux, *darwin, *solaris;
37          }
38 <        Shell;
38 >        Shells;
39  
40 <        typedef enum { sh, csh, tcsh, bash, ksh, zsh, _3sh, custom } Shells;
40 >        typedef enum { sh, csh, tcsh, bash, ksh, zsh, _3sh, custom } Shell;
41  
42 <        Shell shells[] = {
43 <                { "sh", "/bin/sh", "/bin/sh", "/bin/sh" },
44 <                { "csh", "/bin/csh", "/bin/csh", "/bin/csh" },
45 <                { "tcsh", "/bin/tcsh", "/bin/tcsh", "/bin/tcsh" },
46 <                { "bash", "/usr/local/bin/bash", "/bin/bash", "/bin/bash" },
47 <                { "ksh", "/usr/local/bin/ksh", "/bin/ksh", "/bin/ksh" },
48 <                { "zsh", "/usr/local/bin/zsh", "/bin/zsh", "/bin/zsh" },
49 <                { "3sh", "/ccs/bin/3sh", "/ccs/bin/3sh", "/ccs/bin/3sh" },
50 <                { "custom", NULL, NULL, NULL }
42 >        Shells shells[] = {
43 >                { "sh", "/bin/sh", "/bin/sh", "/bin/sh", "/usr/bin/sh" },
44 >                { "csh", "/bin/csh", "/bin/csh", "/bin/csh", "/usr/bin/csh" },
45 >                { "tcsh", "/bin/tcsh", "/bin/tcsh", "/bin/tcsh", "/usr/bin/tcsh" },
46 >                { "bash", "/usr/local/bin/bash", "/bin/bash", "/bin/bash", "/usr/bin/bash" },
47 >                { "ksh", "/usr/local/bin/ksh", "/bin/ksh", "/bin/ksh", "/usr/bin/ksh" },
48 >                { "zsh", "/usr/local/bin/zsh", "/bin/zsh", "/bin/zsh", "/usr/bin/zsh" },
49 >                { "3sh", "/ccs/bin/3sh", "/ccs/bin/3sh", "/ccs/bin/3sh", "/ccs/bin/3sh" },
50 >                { "custom", NULL, NULL, NULL, NULL }
51          };
52  
53 <        for (Shells shell = sh; shell != custom; ++shell)
54 <                printf("%s, ", shells[shell].name);
53 >        char *shell_regex = NULL;
54 >
55 >        {
56 >                size_t size = 0;
57 >
58 >                for (Shell shell = sh; shell <= custom; ++shell)
59 >                {
60 >                        shell_regex = shell_regex ? realloc(shell_regex, size += strlen(shells[shell].name) + (shell != custom ? 1 : 0)) : calloc(size += strlen(shells[shell].name) + 2, 1);
61 >                        strlcat(shell_regex, shells[shell].name, size);
62 >
63 >                        if (shell != custom)
64 >                                strlcat(shell_regex, "|", size);
65 >                }
66 >        }
67 >
68 >        char shell_regex_[strlen(shell_regex) + 12];
69 >
70 >        sprintf(shell_regex_, "^-shell=(%s)$", shell_regex);
71 >
72 >        regex_t shell_;
73 >
74 >        regcheck(regcomp(&shell_, shell_regex_, REG_EXTENDED), &shell_, environment);
75 >
76 >        char user[MAXLOGNAME] = "", *shell = NULL;
77 >
78 >        if (!getuid())
79 >        {
80 >                regex_t user_;
81 >
82 >                regcheck(regcomp(&user_, "^-user=([a-z0-9]{1,16})$", REG_EXTENDED), &user_, environment);
83 >
84 >                for (int index = 1; index != argc; ++index)
85 >                {
86 >                        regmatch_t match[2];
87 >
88 >                        if (!regcheck(regexec(&user_, argv[index], 2, match, 0), &user_, environment))
89 >                                strlcpy(user, argv[index] + match[1].rm_so, match[1].rm_eo - match[1].rm_so + 1);
90 >                        else if (!regcheck(regexec(&shell_, argv[index], 2, match, 0), &shell_, environment))
91 >                                shell = argv[index] + match[1].rm_so;
92 >                        else
93 >                        {
94 >                                printf("Usage: %s -user=user [-shell=%s]\n", argv[0], shell_regex);
95 >
96 >                                return 1;
97 >                        }
98 >                }
99 >
100 >                regfree(&user_);
101 >
102 >                if (strlen(user))
103 >                        goto on;
104 >                else
105 >                        longjmp(environment, (int)"Cannot change root shell");
106 >        }
107 >        else
108 >                for (int index = 1; index != argc; ++index)
109 >                {
110 >                        regmatch_t match[2];
111 >
112 >                        if (!regcheck(regexec(&shell_, argv[index], 2, match, 0), &shell_, environment))
113 >                                shell = argv[index] + match[1].rm_so;
114 >                        else
115 >                        {
116 >                                printf("Usage: %s [-shell=%s]\n", argv[0], shell_regex);
117 >
118 >                                return 1;
119 >                        }
120 >                }
121 >
122 >        struct passwd *entry = getpwuid(getuid());
123 >
124 >        if (!entry)
125 >                longjmp(environment, 1);
126 >
127 >        strlcpy(user, entry->pw_name, sizeof (user));
128 > on:     regfree(&shell_);
129 >        authenticate(argv[0], environment);
130 >
131 >        if (!shell)
132 >        {
133 >                sprintf(shell_regex_, "^%s$", shell_regex);
134 >                regcheck(regcomp(&shell_, shell_regex_, REG_EXTENDED), &shell_, environment);
135 >
136 >                do
137 >                {
138 >                        printf("Shell (");
139  
140 <        printf("%s\n", shells[custom].name);
140 >                        for (Shell shell = sh; shell <= custom; ++shell)
141 >                                printf(shell != custom ? "%s, " : "%s): ", shells[shell].name);
142 >
143 >                        size_t size;
144 >                        char *shell_ = fcheck(fgetln(stdin, &size), stdin, environment);
145 >
146 >                        shell = shell ? realloc(shell, size) : malloc(size);
147 >
148 >                        strlcpy(shell, shell_, size);
149 >                }
150 >                while (regcheck(regexec(&shell_, shell, 0, NULL, 0), &shell_, environment));
151 >
152 >                regfree(&shell_);
153 >        }
154 >
155 >        free(shell_regex);
156 >
157 >        Shells *shells_ = shells + custom;
158 >
159 >        for (Shell shell_ = sh; shell_ != custom; ++shell_)
160 >                if (!strcmp(shell, shells[shell_].name))
161 >                {
162 >                        shells_ = shells + shell_;
163 >
164 >                        goto no;
165 >                }
166 >
167 >        regex_t path;
168 >
169 >        regcheck(regcomp(&path, "^/.*[^/]$", REG_EXTENDED), &path, environment);
170 >        get("FreeBSD", &path, &shells_->freebsd, environment);
171 >        get("Linux", &path, &shells_->linux, environment);
172 >        get("Darwin", &path, &shells_->darwin, environment);
173 >        get("Solaris", &path, &shells_->solaris, environment);
174 >        regfree(&path);
175 >
176 > no:     check(setuid(geteuid()), environment);
177 >
178 >        pid_t bash_;
179 >
180 >        if (!(bash_ = check(fork(), environment)))
181 >        {
182 >                check(setenv("USER", user, 1), environment);
183 >                check(setenv("FREEBSD", shells_->freebsd, 1), environment);
184 >                check(setenv("LINUX", shells_->linux, 1), environment);
185 >                check(setenv("DARWIN", shells_->darwin, 1), environment);
186 >                check(setenv("SOLARIS", shells_->solaris, 1), environment);
187 >                check(execl("/ccs/bin/chsh.sh", argv[0], NULL), environment);
188 >        }
189 >
190 >        int status;
191 >
192 >        check(waitpid(bash_, &status, 0), environment);
193 >
194 >        if (WEXITSTATUS(status))
195 >                return 1;
196  
197          return 0;
198   }

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines