📄 useradd.c
字号:
continue; } else if (strncasecmp (cp, "INACTIVE=", 9) == 0) { fprintf (new_fp, "INACTIVE=%li\n", data->inactive); inactive_written = 1; continue; } else if (strncasecmp (cp, "EXPIRE=", 7) == 0) { if (data->expire < 0) fputs ("EXPIRE=\n", new_fp); else fprintf (new_fp, "EXPIRE=%s\n", date2str (data->expire * SCALE)); expire_written = 1; continue; } else if (strncasecmp (cp, "SHELL=", 6) == 0) { fprintf (new_fp, "SHELL=%s\n", data->shell); shell_written = 1; continue; } else if (strncasecmp (cp, "SKEL=", 5) == 0) { fprintf (new_fp, "SKEL=%s\n", data->skel); skel_written = 1; continue; } else if (strncasecmp (cp, "GROUPS=", 7) == 0) { unsigned int i; fputs ("GROUPS=", new_fp); for (i = 0; i < data->groupscnt; i++) { if (i != 0) fputs (",", new_fp); fputs (data->groups[i], new_fp); } fputs ("\n", new_fp); groups_written = 1; continue; } else if (strncasecmp (cp, "CREATE_MAIL_SPOOL=", 18) == 0) { fprintf (new_fp, "CREATE_MAIL_SPOOL=%s\n", data->create_mail_spool?"yes":"no"); create_mail_spool_written = 1; continue; } fputs (buf, new_fp); } /* Now write all entries, for which we didn't had alredy an entry in the default useradd file. */ if (!group_written) fprintf (new_fp, "GROUP=%u\n", data->group); if (!home_written) fprintf (new_fp, "HOME=%s\n", data->home); if (!inactive_written) fprintf (new_fp, "INACTIVE=%li\n", data->inactive); if (!expire_written) { if (data->expire < 0) fputs ("EXPIRE=\n", new_fp); else fprintf (new_fp, "EXPIRE=%s\n", date2str (data->expire * SCALE)); } if (!shell_written) fprintf (new_fp, "SHELL=%s\n", data->shell); if (!skel_written) fprintf (new_fp, "SKEL=%s\n", data->skel); if (!groups_written) { unsigned int i; fputs ("GROUPS=", new_fp); for (i = 0; i < data->groupscnt; i++) { if (i != 0) fputs (",", new_fp); fputs (data->groups[i], new_fp); } fputs ("\n", new_fp); } if (!create_mail_spool_written) fprintf (new_fp, "CREATE_MAIL_SPOOL=%s\n", data->create_mail_spool?"yes":"no"); /* Close files. */ fclose (fp); fclose (new_fp); /* Rename temporary file back to config file name. */ ret = rename (tmpname, configfile); unlink (tmpname); if (buf) free (buf); /* return return value of rename, if rename succeds, everything is ok, else we have an error. */ return ret;}static struct passwd *files_getpwnam (const char *name){ enum nss_status status; static int buflen = 256; static char *buffer = NULL; static struct passwd resultbuf; if (buffer == NULL) buffer = malloc (buflen); while ((status = files_getpwnam_r (name, &resultbuf, buffer, buflen, &errno)) == NSS_STATUS_TRYAGAIN && errno == ERANGE) { errno = 0; buflen += 256; buffer = realloc (buffer, buflen); } if (status == NSS_STATUS_SUCCESS) return &resultbuf; else return NULL;}static struct passwd *files_getpwuid (uid_t uid){ enum nss_status status; static int buflen = 256; static char *buffer = NULL; static struct passwd resultbuf; if (buffer == NULL) buffer = malloc (buflen); while ((status = files_getpwuid_r (uid, &resultbuf, buffer, buflen, &errno)) == NSS_STATUS_TRYAGAIN && errno == ERANGE) { errno = 0; buflen += 256; buffer = realloc (buffer, buflen); } if (status == NSS_STATUS_SUCCESS) return &resultbuf; else return NULL;}static struct passwd *files_getpwent (void){ enum nss_status status; static int buflen = 256; static char *buffer = NULL; static struct passwd resultbuf; if (buffer == NULL) buffer = malloc (buflen); while ((status = files_getpwent_r (&resultbuf, buffer, buflen, &errno)) == NSS_STATUS_TRYAGAIN && errno == ERANGE) { errno = 0; buflen += 256; buffer = realloc (buffer, buflen); } if (status == NSS_STATUS_SUCCESS) return &resultbuf; else return NULL;}/* find_free_uid - find the first, free available UID. */static uid_tfind_free_uid (int is_system_account, int have_extrapath){ const struct passwd *pwd; uid_t userid, uid_min, uid_max; if (is_system_account) { /* Some special handling for LSB. LSB defines the UID range as: 1 - 99: fix assigned system accounts 100 - 499: dynamic assigned system accounts If we use -r, try to get a uid from the dynamic assigned range. */ uid_min = getlogindefs_unum ("SYSTEM_UID_MIN", 100); uid_max = getlogindefs_unum ("SYSTEM_UID_MAX", 499); } else { uid_min = getlogindefs_unum ("UID_MIN", 500); uid_max = getlogindefs_unum ("UID_MAX", 60000); } userid = uid_min; /* Search the entire password file, looking for the largest unused value. If uid_max does already exists, skip this. */ if (getpwuid (uid_max) == NULL) { setpwent (); while ((pwd = getpwent ())) { if (pwd->pw_uid >= userid) { if (pwd->pw_uid > uid_max) continue; userid = pwd->pw_uid + 1; } } if (have_extrapath && userid != uid_max + 1) { /* If the -P flag is given, not only search in the "official" database, but also in the extra one. */ while ((pwd = files_getpwent ())) { if (pwd->pw_uid >= userid) { if (pwd->pw_uid > uid_max) continue; userid = pwd->pw_uid + 1; } } } } else userid = uid_max + 1; /* uid_max exists, so this will be the result of the above loop. */ /* If the UID we found is equal to UID_MAX+1, we will step through the whole UID_MIN - UID_MAX range and search for the first free UID. */ if (userid == uid_max + 1) { for (userid = uid_min; userid < uid_max; userid++) if (getpwuid (userid) == NULL) { if (have_extrapath) { /* The UID is not used in the normal database, now look in the extra one, too. */ if (files_getpwuid (userid) == NULL) break; } else break; } if (userid == uid_max) { sec_log (program, MSG_NO_FREE_UID, uid_min, uid_max); fprintf (stderr, _("%s: Can't get unique uid in range %u - %u.\n"), program, uid_min, uid_max); exit (E_FAILURE); } } return userid;}static char **add_gr_mem (const char *name, char **gr_mem){ char **groups; unsigned int i; int already_added = 0; i = 0; while (gr_mem[i]) { if (strcmp (gr_mem[i], name) == 0) already_added = 1; ++i; } ++i; /* for trailing NULL pointer */ if (!already_added) ++i; groups = malloc (i * sizeof (char *)); i = 0; while (gr_mem[i]) { groups[i] = strdup (gr_mem[i]); ++i; } if (!already_added) { groups[i] = strdup (name); ++i; } groups[i] = NULL; return groups;}/* Create the users mail spool file if it does not exist. The permissions we be 600, if the mail directory is worldwide writeable, else 660 onwed by the user and group 'mail'. */static intcreate_mail_file (const char *user, uid_t uid, gid_t user_gid){ int mode = 0600; gid_t gid = user_gid; int fd; char *fname; struct stat st; char *cp; if ((fname = malloc (strlen (user) + strlen (_PATH_MAILDIR) + 2)) == NULL) { fputs ("running out of memory!\n", stderr); return E_MAIL_SPOOL; } cp = stpcpy (fname, _PATH_MAILDIR); *cp++ = '/'; strcpy (cp, user); if (access (fname, R_OK) == 0) return 0; if (stat (_PATH_MAILDIR, &st) == -1) { fprintf (stderr, _("%s: Can't stat `%s': %m\n"), program, _PATH_MAILDIR); free (fname); return E_MAIL_SPOOL; } /* if directory is not worldwide writeable, the new file needs write permissions for group 'mail'. */ if ((st.st_mode & S_IWOTH) != S_IWOTH) { int buflen = 256; char *buffer = alloca (buflen); struct group resultbuf; struct group *gr; while (getgrnam_r ("mail", &resultbuf, buffer, buflen, &gr) != 0 && errno == ERANGE) { errno = 0; buflen += 256; buffer = alloca (buflen); } /* Only writeable for group 'mail', if this group exists. */ if (gr) { gid = gr->gr_gid; mode = 0660; } else fprintf (stderr, _("%s: No group named \"mail\" exists, creating mail spool with mode 0600.\n"), program); } fd = open (fname, O_CREAT|O_EXCL|O_WRONLY|O_TRUNC, 0); if (fd == -1) { fprintf (stderr, _("%s: Can't create mail spool for user %s.\n"), program, user); free (fname); return E_MAIL_SPOOL; } else { if (fchown (fd, uid, gid) < 0) { fprintf (stderr, _("Cannot change owner/group for `%s': %s\n"), fname, strerror (errno)); unlink (fname); free (fname); close (fd); return E_MAIL_SPOOL; } if (fchmod (fd, mode) < 0) { fprintf (stderr, _("Cannot change permissions for `%s': %s\n"), fname, strerror (errno)); unlink (fname); free (fname); close (fd); return E_MAIL_SPOOL; } close (fd); } free (fname); return 0;}/* Create the users home directory if it does not exist. The permissions will be calculated from UMASK in /etc/login.defs. */static intcreate_home_directory (const char *home, uid_t uid, gid_t gid, const char *skeldir){ int retval = 0; if (home == NULL || *home == '\0') return E_HOMEDIR; if (access (home, F_OK) != 0) { char path[strlen (home) + 2]; char *bhome, *cp; path[0] = '\0'; bhome = strdup (home); ++bhome; /* Check for every part of the path, if the directory exists. If not, create it with permissions 755 and owner root:root. */ cp = strtok (bhome, "/"); while (cp) { strcat (path, "/"); strcat (path, cp); if (access (path, F_OK) != 0) { if (mkdir (path, 0) != 0) { fprintf (stderr, _("%s: Cannot create directory `%s'.\n"), program, path); return E_HOMEDIR; } if (chown (path, 0, 0) < 0) fprintf (stderr, _("%s: Warning: chown on `%s' failed: %m\n"), program, path); if (chmod (path, 0755) < 0) fprintf (stderr, _("%s: Warning: chmod on `%s' failed: %m\n"), program, path); } cp = strtok (NULL, "/"); } if (chown (home, uid, gid) < 0) { fprintf (stderr, _("Cannot change owner/group for `%s': %s\n"), home, strerror (errno)); retval = E_HOMEDIR; } if (chmod (home, 0777 & ~getlogindefs_num ("UMASK", 077)) < 0) { fprintf (stderr, _("Cannot change permissions for `%s': %s\n"), home, strerror (errno)); retval = E_HOMEDIR; } if (skeldir != NULL && *skeldir != '\0' && access (skeldir, F_OK) == 0) { if (copy_dir_rec (skeldir, home, 0, uid, gid) != 0) { fprintf (stderr, _("%s: Copying of skel directory failed.\n"), program); retval = E_HOMEDIR; } } } else if (skeldir != NULL && *skeldir != '\0') { /* Home directory already exits, don't copy skel directory again. */ fprintf (stderr, _("%s: Warning: home directory already exists, not modifying it.\n"), program); } return retval;}intmain (int argc, char **argv){ struct default_t dflt = { 100, "/home", -1, -1, "/bin/bash", "/etc/skel", 0, NULL, 0 }; struct option *long_options = long_options_all; const char *short_options = short_options_all; char *use_service = NULL;#ifdef USE_LDAP char *binddn = NULL;#endif char *skeldir = NULL; char *new_account; char *new_group = NULL; char *new_comment = ""; char *new_home = NULL; char *new_shell = NULL; char *new_password = "!"; char *new_groups_arg = NULL; char **new_groups = NULL; unsigned int new_groupscnt = 0; uid_t new_uid = 0; int know_uid = 0; int system_account = 0; int non_unique = 0; int have_extrapath = 0; int create_homedir = 0; int modify_defaults = 0; int broken_default_useradd = 0; setlocale (LC_ALL, ""); bindtextdomain (PACKAGE, LOCALEDIR); textdomain (PACKAGE); open_sec_log (program); /* Before going any further, raise the ulimit and ignore signals. */ init_environment (); broken_default_useradd = load_defaults (useradd_default_file, &dflt); /* If the first argument is "-D" and next one also starts with "-", go into edit mode. */ if ((argc == 2 && (strncmp (argv[1], "--show", 6) == 0 || strcmp (argv[1], "-D") == 0)) || (argc > 2 && (strncmp (argv[1], "--save", 6) == 0 || strcmp (argv[1], "-D") == 0) && argv[2][0] == '-')) { if (broken_default_useradd) { fprintf (stderr, _("%s: Reading of `%s' was not successful.\n"), program, useradd_default_file); return E_LOGIN_DEFS; } if (argc == 2) { print_defaults (&dflt); return E_SUCCESS; } short_options = short_options_D; long_options = long_options_D; modify_defaults = 1; } while (1) { int c; int option_index = 0; c = getopt_long (argc, argv, short_options, long_options, &option_index); if (c == (-1)) break; switch (c) { case 'c': if (strcspn (optarg, ":\n") != strlen (optarg)) { fprintf (stderr, _("%s: Invalid comment `%s'.\n"), program, optarg); return E_BAD_ARG; } new_comment = optarg; break; case '\250': case 'D':#ifdef USE_LDAP if (!modify_defaults) binddn = optarg;#endif break; case 'b': /* for compatibility with shadow useradd. */ case 'd': if (check_home (optarg) == -1) { fprintf (stderr, _("%s: Invalid home directory `%s'.\n"), program, optarg); return E_BAD_ARG; } new_home = optarg; break; case 'e': if (strcmp (optarg, "1969-12-31") == 0) dflt.expire = -1; else { long int expire; char *cp; expire = str2date (optarg); if (expire == -1)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -