ccf05522ccaee8eef1e09a3c6bf0ceec6a292117
2 Copyright (C) 2001-2011 Ben Kibbey <bjk@luxsci.net>
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02110-1301 USA
26 #include <sys/types.h>
34 #ifdef _POSIX2_LINE_MAX
35 #define LINE_MAX _POSIX2_LINE_MAX
59 #include "../strsep.c"
71 #define ALLPERMS (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)
74 /* This is the order of options when the 'P' option is specified. It selects
75 * all available options. */
76 #define PASSWD_OPTION_ORDER "lpugicedsm"
77 #define PASSWD_OPTION_STRING "Plpugcedsmi:"
80 static char **strings
;
81 static char options
[11]; /* NULL terminated. */
82 static char *gecos_options
;
84 void add_string(char ***, const char *);
85 char *stamp(time_t, const char *);
86 char *safe_strncat(char *, const char *, size_t);
88 void ui_module_init(int *chainable
)
91 * Keep the password file open if possible (*BSD).
93 #ifdef HAVE_SETPASSENT
103 void ui_module_exit()
116 /* See if the gecos options are valid. */
117 static int parse_gecos_options(const char *args
)
121 for (i
= 0; i
< strlen(args
); i
++) {
137 /* Break up the gecos string into sections and add the sections to the output
138 * string array if needed. */
139 static void gecos_strings(char *str
)
143 const char *name
, *first
, *second
, *third
;
145 name
= first
= second
= third
= "-";
147 while ((buf
= strsep(&str
, ",")) != NULL
) {
169 for (i
= 0; i
< strlen(gecos_options
); i
++) {
170 switch (gecos_options
[i
]) {
172 add_string(&strings
, name
);
175 add_string(&strings
, first
);
178 add_string(&strings
, second
);
181 add_string(&strings
, third
);
184 add_string(&strings
, name
);
185 add_string(&strings
, first
);
186 add_string(&strings
, second
);
187 add_string(&strings
, third
);
195 /* Get all groups that a user is a member of. The primary group will be the
197 static void groups(const struct passwd
*pw
, const int multi
,
207 if ((grp
= getgrgid(pw
->pw_gid
)) == NULL
) {
208 snprintf(tmp
, sizeof(tmp
), "%li%s%s%s", (long) pw
->pw_gid
,
209 (verbose
) ? "(" : "", (verbose
) ? "!" : "",
210 (verbose
) ? ")" : "");
211 add_string(&strings
, tmp
);
215 primary
= grp
->gr_gid
;
216 snprintf(tmp
, sizeof(tmp
), "%li%s%s%s%c", (long) pw
->pw_gid
,
217 (verbose
) ? "(" : "", (verbose
) ? grp
->gr_name
: "",
218 (verbose
) ? ")" : "", multi
);
219 safe_strncat(line
, tmp
, sizeof(line
));
221 #ifdef HAVE_SETGROUPENT
227 while ((grp
= getgrent()) != NULL
) {
228 char **members
= grp
->gr_mem
;
231 if (strcmp(*members
++, pw
->pw_name
) == 0) {
232 if (grp
->gr_gid
== primary
)
235 snprintf(tmp
, sizeof(tmp
), "%li%s%s%s%c", (long) grp
->gr_gid
,
236 (verbose
) ? "(" : "", (verbose
) ? grp
->gr_name
: "",
237 (verbose
) ? ")" : "", multi
);
238 safe_strncat(line
, tmp
, sizeof(line
));
245 * Trim the remaining multi-string deliminator.
247 line
[strlen(line
) - 1] = '\0';
249 add_string(&strings
, line
);
252 /* This is output if the -h command line option is passed to the main program.
254 void ui_module_help()
256 printf(" Password/Group file information [-P (-%s)]:\n",
257 PASSWD_OPTION_ORDER
);
258 printf("\t-l login name\t\t");
259 printf("\t-p encrypted password\n");
260 printf("\t-u user id (uid)\t");
261 printf("\t-g group id (gid)\n");
262 printf("\t-c password change time");
263 printf("\t-e password expire time\n");
264 printf("\t-d home directory\t");
265 printf("\t-m home directory mode\n");
266 printf("\t-s login shell\n");
267 printf("\t-i gecos (any of [n]ame,[1]st,[2]nd,[3]rd or [a]ll)\n\n");
270 /* This is the equivalent to main() only without argc and argv available. */
271 int ui_module_exec(char ***s
, const struct passwd
*pw
, const int multi_char
,
272 const int verbose
, char *tf
)
278 struct spwd
*spwd
= NULL
;
283 if ((spwd
= getspnam(pw
->pw_name
)) == NULL
)
284 warnx("%s", "getspnam(): unknown error");
297 add_string(&strings
, "!");
301 snprintf(tmp
, sizeof(tmp
), "%li", (long) spwd
->sp_max
);
302 add_string(&strings
, tmp
);
306 add_string(&strings
, "!");
310 snprintf(tmp
, sizeof(tmp
), "%li", (long) spwd
->sp_expire
);
311 add_string(&strings
, tmp
);
315 #ifdef HAVE_PASSWD_CHANGE
316 snprintf(tmp
, sizeof(tmp
), "%li", (long) pw
->pw_change
);
317 add_string(&strings
, tmp
);
319 add_string(&strings
, "!");
323 #ifdef HAVE_PASSWD_EXPIRE
324 snprintf(tmp
, sizeof(tmp
), "%li", (long) pw
->pw_expire
);
325 add_string(&strings
, tmp
);
327 add_string(&strings
, "!");
332 add_string(&strings
, pw
->pw_name
);
335 add_string(&strings
, (pw
->pw_dir
&& pw
->pw_dir
[0]) ? pw
->pw_dir
: "-");
338 add_string(&strings
, (pw
->pw_shell
&& pw
->pw_shell
[0]) ? pw
->pw_shell
: "-");
343 add_string(&strings
, (pw
->pw_passwd
344 && pw
->pw_passwd
[0]) ? pw
->pw_passwd
: "-");
346 add_string(&strings
, (spwd
->sp_pwdp
347 && spwd
->sp_pwdp
[0]) ? spwd
->sp_pwdp
: "-");
349 add_string(&strings
, (pw
->pw_passwd
350 && pw
->pw_passwd
[0]) ? pw
->pw_passwd
: "-");
354 sprintf(tmp
, "%li", (long) pw
->pw_uid
);
355 add_string(&strings
, tmp
);
358 groups(pw
, multi_char
, verbose
);
361 if (stat(pw
->pw_dir
, &st
) == -1) {
362 add_string(&strings
, "!");
366 sprintf(tmp
, "%.4o", (unsigned) st
.st_mode
& ALLPERMS
);
367 add_string(&strings
, tmp
);
370 #ifdef HAVE_PASSWD_GECOS
371 gecos_strings(pw
->pw_gecos
);
373 add_string(&strings
, "!");
387 char *ui_module_options_init(char **defaults
)
390 return PASSWD_OPTION_STRING
;
393 /* Check module option validity. */
394 int ui_module_options(int argc
, char **argv
)
399 while ((opt
= getopt(argc
, argv
, PASSWD_OPTION_STRING
)) != -1) {
402 if (parse_gecos_options(optarg
))
405 gecos_options
= optarg
;
408 strncpy(options
, PASSWD_OPTION_ORDER
, sizeof(options
));
422 warnx("passwd: invalid option -- %c", optopt
);