changeset 1439:ed28d4d9558d draft

Cleanups on useradd/groupadd/groupdel, and put TOYBOX_UID_SYS and TOYBOX_UID_USR in the top level Config.
author Rob Landley <rob@landley.net>
date Mon, 18 Aug 2014 19:10:45 -0500
parents 7a3afbc7fc8b
children 9f2a1afcf005
files Config.in lib/pending.h toys/pending/groupadd.c toys/pending/groupdel.c toys/pending/useradd.c
diffstat 5 files changed, 82 insertions(+), 95 deletions(-) [+]
line wrap: on
line diff
--- a/Config.in	Sat Aug 16 09:46:42 2014 -0500
+++ b/Config.in	Mon Aug 18 19:10:45 2014 -0500
@@ -8,6 +8,7 @@
 
 menu "Toybox global settings"
 
+# This entry controls the multiplexer, disabled for single command builds
 config TOYBOX
 	bool
 	default y
@@ -74,6 +75,19 @@
 	bool "Debugging tests"
 	default n
 	help
-	  Enable extra checks for debugging purposes.
+	  Enable extra checks for debugging purposes. All of them catch
+          things that can only go wrong at development time, not runtime.
+
+config TOYBOX_UID_SYS
+	int "First system UID"
+	default 100
+	help
+	  When commands like useradd/groupadd allocate system IDs, start here.
+
+config TOYBOX_UID_USR
+	int "First user UID"
+	default 500
+	help
+	  When commands like useradd/groupadd allocate user IDs, start here.
 
 endmenu
--- a/lib/pending.h	Sat Aug 16 09:46:42 2014 -0500
+++ b/lib/pending.h	Mon Aug 18 19:10:45 2014 -0500
@@ -2,8 +2,6 @@
 
 // password.c
 #define MAX_SALT_LEN  20 //3 for id, 16 for key, 1 for '\0'
-#define SYS_FIRST_ID  100
-#define SYS_LAST_ID   999
 void is_valid_username(const char *name);
 int read_password(char * buff, int buflen, char* mesg);
 int update_password(char *filename, char* username, char* encrypted);
--- a/toys/pending/groupadd.c	Sat Aug 16 09:46:42 2014 -0500
+++ b/toys/pending/groupadd.c	Mon Aug 18 19:10:45 2014 -0500
@@ -38,25 +38,15 @@
 static void new_group()
 {
   char *entry = NULL;
-  int max = INT_MAX;
 
   if (toys.optflags & FLAG_g) {
     if (TT.gid > INT_MAX) error_exit("gid should be less than  '%d' ", INT_MAX);
     if (getgrgid(TT.gid)) error_exit("group '%ld' is in use", TT.gid);
   } else {
-    if (toys.optflags & FLAG_S) {
-      TT.gid = SYS_FIRST_ID;
-      max = SYS_LAST_ID;
-    } else {
-      TT.gid = SYS_LAST_ID + 1; //i.e. starting from 1000
-      max = 60000; // as per config file on Linux desktop
-    }
+    if (toys.optflags & FLAG_S) TT.gid = CFG_TOYBOX_UID_SYS;
+    else TT.gid = CFG_TOYBOX_UID_USR;
     //find unused gid
-    while (TT.gid <= max) {
-      if (!getgrgid(TT.gid)) break;
-      if (TT.gid == max) error_exit("no more free gids left");
-      TT.gid++;
-    }
+    while (getgrgid(TT.gid)) TT.gid++;
   }
 
   entry = xmprintf("%s:%s:%d:", *toys.optargs, "x", TT.gid);
--- a/toys/pending/groupdel.c	Sat Aug 16 09:46:42 2014 -0500
+++ b/toys/pending/groupdel.c	Mon Aug 18 19:10:45 2014 -0500
@@ -13,63 +13,70 @@
   default n
   help
     usage: delgroup [USER] GROUP
-    groupdel GROUP
+    usage: groupdel GROUP
 
-    Delete a group or delete a user from a group
+    Delete a group or remove a user from a group
 */
 
 #define FOR_groupdel
 #include "toys.h"
 
+char *comma_find(char *name, char *list)
+{
+  int len = strlen(name);
+
+  while (*list) {
+    while (*list == ',') list++;
+    if (!strncmp(name, list, len) && (!list[len] || list[len]==','))
+      return list;
+    while (*list && *list!=',') list++;
+  }
+
+  return 0;
+}
+
 void groupdel_main(void)
 {
-  struct group *grp = NULL;
-  char *entry = NULL;
+  struct group *grp = getgrnam(toys.optargs[toys.optc-1]);
+  char *entry = 0;
 
-  if (toys.optc == 2) {  //del user from group
-    //toys.optargs[0]- user, toys.optargs[1] - group
-    if (!getpwnam(toys.optargs[0])) 
-      error_exit("user '%s' does not exist", toys.optargs[0]);
-    if (!(grp = getgrnam(toys.optargs[1]))) 
-      error_exit("group '%s' does not exist", toys.optargs[1]);
-    if (!(grp = getgrnam(toys.optargs[1]))) 
-      error_exit("group '%s' does not exist", toys.optargs[1]);
-    if (!grp->gr_mem) return;
-    else {
-      int i, found = -1;
+  if (!grp) perror_exit("group '%s'", toys.optargs[toys.optc-1]);
 
-      for (i = 0; grp->gr_mem[i] && (found == -1); i++)
-        if (!strcmp(grp->gr_mem[i], *toys.optargs)) found = i;
+  // delete user from group
+  if (toys.optc == 2) {
+    int i, len = 0, found = -1;
+    char *s;
 
-      if (found == -1) {
-        xprintf("%s: The user '%s' is not a member of '%s'\n", toys.which->name,
-            toys.optargs[0], toys.optargs[1]);
-        return;
-      }
-      entry = xstrdup("");
-      for (i=0; grp->gr_mem[i]; i++) {
-        if (found != i) { //leave out user from grp member list
-          if (i && *entry) strcat(entry, ",");
-          entry = xrealloc(entry, strlen(entry) + strlen(grp->gr_mem[i]) + 2);
-          strcat(entry, grp->gr_mem[i]);
-        }
+    xgetpwnam(*toys.optargs);
+    if (grp->gr_mem) {
+      for (i = 0; grp->gr_mem[i]; i++) {
+        if (found == -1 && !strcmp(*toys.optargs, grp->gr_mem[i])) found = i;
+        else len += strlen(grp->gr_mem[i]) + 1;
       }
     }
-  } else {    //delete the group
-    struct passwd *pw = NULL;
+    if (found == -1)
+      error_exit("user '%s' not in group '%s'", *toys.optargs, toys.optargs[1]);
+
+    entry = s = xmalloc(len);
+    for (i = 0; grp->gr_mem[i]; ) {
+      if (i) *(s++) = ',';
+      s = stpcpy(s, grp->gr_mem[i]);
+    }
 
-    if (!(grp = getgrnam(*toys.optargs))) 
-      error_exit("group '%s' doesn't exist", *toys.optargs);
-    //is it a primary grp of user
-    while ((pw = getpwent())) {
-      if (pw->pw_gid == grp->gr_gid) {
-        endpwent();
-        error_exit("can't remove primary group of user '%s'", pw->pw_name);
-      }
+  // delete group
+  } else {
+    struct passwd *pw;
+
+    endpwent(); // possibly this should be in toy_init()?
+    for (;;) {
+      if (!(pw = getpwent())) break;
+      if (pw->pw_gid == grp->gr_gid) break;
     }
+    if (pw) error_exit("can't remove primary group of user '%s'", pw->pw_name);
     endpwent();
   }
+
   update_password("/etc/group", grp->gr_name, entry);
   update_password("/etc/gshadow", grp->gr_name, entry);
-  free(entry);
+  if (CFG_TOYBOX_FREE) free(entry);
 }
--- a/toys/pending/useradd.c	Sat Aug 16 09:46:42 2014 -0500
+++ b/toys/pending/useradd.c	Mon Aug 18 19:10:45 2014 -0500
@@ -111,55 +111,33 @@
 {
   struct passwd pwd;
   char *entry, *args[4];
-  int max = INT_MAX;
 
   pwd.pw_name = *toys.optargs;
-  pwd.pw_passwd = (char *)"x";
-  if (toys.optflags & FLAG_g) pwd.pw_gecos = TT.gecos;
-  else pwd.pw_gecos = "Linux User,";
-  if (toys.optflags & FLAG_h) pwd.pw_dir = TT.dir;
-  else pwd.pw_dir = xmprintf("/home/%s", *toys.optargs);
-  if (toys.optflags & FLAG_s) pwd.pw_shell = TT.shell;
-  else pwd.pw_shell = get_shell();
+  pwd.pw_passwd = "x";
+  pwd.pw_gecos = (toys.optflags & FLAG_g) ? TT.gecos : "Linux User,";
+  pwd.pw_dir = (toys.optflags & FLAG_h) ? TT.dir
+    : xmprintf("/home/%s", *toys.optargs);
+  pwd.pw_shell = (toys.optflags & FLAG_s) ? TT.shell : get_shell();
 
   if (toys.optflags & FLAG_u) {
-    if (TT.uid > INT_MAX) error_exit("uid should be less than  '%d' ", INT_MAX);
-    if (getpwuid(TT.uid)) error_exit("user '%ld' is in use", TT.uid);
-    pwd.pw_uid = TT.uid;
+    if (TT.uid > INT_MAX) error_exit("bad uid");
+    if (getpwuid(TT.uid)) error_exit("uid '%ld' in use", TT.uid);
   } else {
-    if (toys.optflags & FLAG_S) {
-      TT.uid = SYS_FIRST_ID;
-      max = SYS_LAST_ID;
-    } else {
-      TT.uid = SYS_LAST_ID + 1; //i.e. starting from 1000
-      max = 60000; // as per config file on Linux desktop
-    }
+    if (toys.optflags & FLAG_S) TT.uid = CFG_TOYBOX_UID_SYS;
+    else TT.uid = CFG_TOYBOX_UID_USR;
     //find unused uid
-    while (TT.uid <= max) {
-      if (!getpwuid(TT.uid)) break;
-      if (TT.uid == max) error_exit("no more free uids left");
-      TT.uid++;
-    }
-    pwd.pw_uid = TT.uid;
+    while (getpwuid(TT.uid)) TT.uid++;
   }
+  pwd.pw_uid = TT.uid;
 
-  if (toys.optflags & FLAG_G) {
-    struct group *gr = getgrnam(TT.u_grp);
-    if (!gr) error_exit("The group '%s' doesn't exist", TT.u_grp);
-    TT.gid = gr->gr_gid;
-  } else {
+  if (toys.optflags & FLAG_G) TT.gid = xgetgrnam(TT.u_grp)->gr_gid;
+  else {
     // Set the GID for the user, if not specified
-    if (toys.optflags & FLAG_S) {
-      TT.gid = SYS_FIRST_ID;
-      max = SYS_LAST_ID;
-    } else TT.gid = ((TT.uid > SYS_LAST_ID) ? TT.uid : SYS_LAST_ID + 1);
-    if (getgrnam(pwd.pw_name)) error_exit("group '%s' is in use", pwd.pw_name);
+    if (toys.optflags & FLAG_S) TT.gid = CFG_TOYBOX_UID_SYS;
+    else TT.gid = CFG_TOYBOX_UID_USR;
+    if (getgrnam(pwd.pw_name)) error_exit("group '%s' in use", pwd.pw_name);
     //find unused gid
-    while (TT.gid <= max) {
-      if (!getgrgid(TT.gid)) break;
-      if (TT.gid == max) error_exit("no more free gids left");
-      TT.gid++;   
-    }
+    while (getgrgid(TT.gid)) TT.gid++;
   }
   pwd.pw_gid = TT.gid;