On Fri, Jul 16, 1999 at 07:21:27AM -0400, Greg Troxel wrote:
> I am guessing that the problems are due to incomplete conversion to
> the ntohl/htonl conversion just made to make the pdb
> endian-independent.

No, it was not related to that. The code was doing a read-modify-write
of the database record containing the maxids, and for some reason this
confused libdb. I managed to fix it by doing read-copy-modify-write.

> It would be nice if there were an 'pdbtool export' command that
> printed out the contents in plain ascii so that it could be edited if
> necessary and then fed into 'pdbtool import'.

Added this as well, I believe it will be a very useful feature. The dump
format mimics the format used by /etc/passwd and /etc/group. The
differences are that the first member of a group will be the group
owner. This information is currently not used, but in the future a group
owner should be able to add/remove groupmembers. And :'s in the group
names are encoded as %'s.

I also modified pdbtool to accept all commands from the commandline.
Because pdbtool used to consider first argument on the commandline as a
file to parse commands from, I've added a `source' command.

For those who are interested, I'll attach a patch against 5.2.7. Greg's
`ids' command to list the current maxids is also included.

>         Greg Troxel <[EMAIL PROTECTED]>

Jan
Index: pdbdb.c
===================================================================
RCS file: /afs/cs/project/coda-src/cvs/coda/coda-src/al/pdbdb.c,v
retrieving revision 1.8
diff -u -r1.8 pdbdb.c
--- pdbdb.c     1999/06/16 03:17:02     1.8
+++ pdbdb.c     1999/07/17 19:28:31
@@ -176,7 +176,7 @@
        int rc;
        char zero = 0;
        int32_t olduid, oldgid;
-       int32_t *ids = NULL;
+       int32_t ids[2];
        
        CODA_ASSERT(uid >= 0 && gid <= 0);
 
@@ -190,18 +190,16 @@
 
        if ( rc != RET_SUCCESS ) {
                CODA_ASSERT( (uid == 0) && (gid == 0) );
-               olduid = -1; 
-               oldgid = 1;
-               value.size = 2 * sizeof(int32_t);
-               ids = malloc(value.size);
-               value.data = (void *) ids;
-       } else {                
+               ids[0] = htonl(0);
+               ids[1] = htonl(0);
+       } else {
                CODA_ASSERT(value.size == 2*sizeof(int32_t));
-               ids = (int32_t *) value.data;
-               olduid = ntohl(ids[0]);
-               oldgid = ntohl(ids[1]);
-               CODA_ASSERT(olduid >= 0 || oldgid <= 0); 
+               ids[0] = ((int32_t *)value.data)[0];
+               ids[1] = ((int32_t *)value.data)[1];
        }
+       olduid = ntohl(ids[0]);
+       oldgid = ntohl(ids[1]);
+       CODA_ASSERT(olduid >= 0 || oldgid <= 0); 
 
        if ( mode != PDB_MAXID_FORCE ) {
                if (  uid > olduid )
@@ -214,6 +212,9 @@
                ids[1] = htonl(gid);
        }
 
+       value.size = 2 * sizeof(int32_t);
+       value.data = (void *) &ids;
+
         rc = h->main->put(h->main, &key, &value, 0);
        CODA_ASSERT(rc == RET_SUCCESS);
 }
@@ -361,7 +362,7 @@
 
        /* this record has a special 1-byte key equal to zero */
        memset(&key, 0, sizeof(DBT));
-       key.size = 1;
+       key.size = sizeof(zero);
        key.data = &zero;
 
        /* open the profile database in read mode */
Index: pdbtool.c
===================================================================
RCS file: /afs/cs/project/coda-src/cvs/coda/coda-src/al/pdbtool.c,v
retrieving revision 1.3
diff -u -r1.3 pdbtool.c
--- pdbtool.c   1999/03/17 00:57:55     1.3
+++ pdbtool.c   1999/07/17 19:28:31
@@ -379,6 +379,18 @@
        PDB_db_close(h);
 }
 
+/* SHOW MAXIDS */
+void tool_get_maxids(int argc,char *argv[]){
+      PDB_HANDLE h;
+      int maxuid, maxgid;
+      if(check_args_num(argc,1)){
+              printf("Usage: get_maxids\n");
+      }
+      h = PDB_db_open(O_RDWR);
+      PDB_db_maxids(h, &maxuid, &maxgid);
+      PDB_db_close(h);
+      printf("maxuid %d maxgid %d\n", maxuid, maxgid);
+}
 
 /* SET MAXIDS */
 void tool_maxids(int argc,char *argv[]){
@@ -425,26 +437,204 @@
        PDB_changeId(id,arg2);
 }
 
+/* dump/restore database contents */
+void tool_export(int argc, char *argv[])
+{
+    int32_t id, i;
+    PDB_profile rec;
+    PDB_HANDLE h;
+    FILE *userfile, *groupfile;
+    char *s;
+    int rc;
+
+    if (check_args_num(argc, 3)) {
+       printf("Usage: export <userfile> <groupfile>\n");
+       return;
+    }
+
+    userfile  = fopen(argv[1], "w");
+    groupfile = fopen(argv[2], "w");
+
+    h = PDB_db_open(O_RDONLY);
+    while ((rc = PDB_db_nextkey(h, &id))) {
+       if (rc == -1) continue;
+
+       PDB_readProfile(h, id, &rec);
+       {
+           if (PDB_ISUSER(rec.id)) {
+               /* users are dumped in an /etc/passwd like format
+                * "<username>:x:<userid>:500::/:" */
+               fprintf(userfile, "%s:*:%d:500::/:\n", rec.name, rec.id);
+           } else {
+               /* groups and group members are dumped in an /etc/group like
+                * format "<groupname>:x:<groupid>:<owner>[,<members>]*" */
+
+               /* escape the :'s in the group names */
+               s = rec.name; while ((s = strchr(s, ':')) != NULL) *s = '%';
+
+               fprintf(groupfile, "%s:*:%d:%s", rec.name, rec.id,
+                                                rec.owner_name);
+               for (i = 0; i < rec.groups_or_members.size; i++) {
+                   if (rec.groups_or_members.data[i] == rec.owner_id)
+                       continue;
+
+                   PDB_lookupById(rec.groups_or_members.data[i], &s);
+                   if (s == NULL) continue;
+
+                   fprintf(groupfile, ",%s", s);
+                   free(s);
+               }
+               fprintf(groupfile, "\n");
+           }
+       }
+       PDB_freeProfile(&rec);
+    }
+    PDB_db_close(h);
+
+    fclose(userfile);
+    fclose(groupfile);
+}
+
+void tool_import(int argc, char *argv[])
+{
+    FILE *userfile, *groupfile;
+    char user[64], group[64], owner_and_members[1024], *owner, *member, *s;
+    int32_t user_id, group_id, owner_id, member_id, create_id;
+    int rc;
+
+    if (check_args_num(argc, 3)) {
+       printf("Usage: import <userfile> <groupfile>\n");
+       return;
+    }
+
+    /* recreate all users */
+    userfile = fopen(argv[1], "r");
+    while(1) {
+       rc = fscanf(userfile, "%[^:]:%*[^:]:%d:%*s\n", user, &user_id);
+       if (rc < 0) break;
+
+       /* create user */
+       PDB_lookupById(user_id, &s);
+       if (s) {
+           printf("Duplicate user for id %d, found both %s and %s\n",
+                  user_id, s, user);
+           free(s);
+           continue;
+       }
+
+       PDB_createUser(user, &create_id);
+       PDB_changeId(create_id, user_id);
+       printf("Created user %s, id %d\n", user, user_id);
+    }
+    fclose(userfile);
+    
+    /* recreate groups */
+    groupfile = fopen(argv[2], "r");
+    while (1) {
+       rc = fscanf(groupfile, "%[^:]:%*[^:]:%d:%s\n",
+                   group, &group_id, owner_and_members);
+       if (rc < 0) break;
+
+       /* restore the :'s in the group name */
+       s = group; while ((s = strchr(s, '%')) != NULL) *s = ':';
+
+       owner = strtok(owner_and_members, ",");
+
+       /* create group */
+       PDB_lookupByName(owner, &owner_id);
+       if (owner_id == 0) {
+           printf("Group %s's owner %s cannot be found\n", group, owner);
+           continue;
+       }
+       if (!PDB_ISUSER(owner_id)) {
+           printf("Group %s's owner %s is a group but should be a user\n",
+                  group, owner);
+           continue;
+       }
+       PDB_createGroup(group, owner_id, &create_id);
+       PDB_changeId(create_id, group_id);
+       printf("Created group %s, id %d, owner %s\n", group, group_id, owner);
+    }   
+
+    /* add group members*/
+    rewind(groupfile);
+    while (1) {
+       rc = fscanf(groupfile, "%[^:]:%*[^:]:%d:%s\n",
+                   group, &group_id, owner_and_members);
+       if (rc < 0) break;
+
+       /* restore the :'s in the group name */
+       s = group; while ((s = strchr(s, '%')) != NULL) *s = ':';
+
+       /* skip the owner */
+       (void)strtok(owner_and_members, ",");
+
+       /* add group members */
+       printf("Adding members to %s\n\t", group);
+       while ((member = strtok(NULL, ",")) != NULL) {
+           /* restore the :'s in the name */
+           s = member; while ((s = strchr(s, '%')) != NULL) *s = ':';
+
+           PDB_lookupByName(member, &member_id);
+           if (member_id == 0) {
+               printf("\nGroup %s's member %s cannot be found\n\t",
+                      group, member);
+               continue;
+           }
+           PDB_addToGroup(member_id, group_id);
+           printf(" %s", member);
+       }
+       printf("\n");
+    }   
+    fclose(groupfile);
+}
+
+void tool_source(int argc, char *argv[])
+{
+       char line[1024];
+       char *nl;
+
+       FILE *file = fopen(argv[1], "r");
+       if ( !file ) {
+           perror("");
+           return;
+       }
+       while ( fgets(line, 1024, file) ) {
+           if ( (nl = strchr(line, '\n')) )
+               *nl = '\0';
+           execute_line(line);
+       }
+}
 
 
 /* HELP */
-void tool_help(int argc, char *argv[]){
-        printf("i\tread database by user ID\n");
-       printf("n\tread database by user name\n");
-       printf("nu\tcreate a new user\n");
-       printf("nui\tcreate a new user with id\n");
-       printf("ng\tcreate a new group\n");
-       printf("l\tlook up an ID by name\n");
-       printf("list\tlist all entries\n");
-       printf("cu\tclone a user\n");
-       printf("ag\tadd a group or user to a group\n");
-       printf("rg\tremove a group or user from a group\n");
-       printf("d\tdelete a user or a group\n");
-       printf("cm\tcompact the database (RARE)\n");
-       printf("ci\tchange the Id of a new user or group\n");
-       printf("cn\tchange the Name of a user\n");
-       printf("maxids\tset the database maxids\n");
-       printf("u\tupdate an id\n");
+void tool_help(int argc, char *argv[])
+{
+       if (argc > 1) {
+           Parser_help(argc, argv);
+           return;
+       }
+
+        printf("i <id>\t\t\t\tread database by ID\n");
+       printf("n <name>\t\t\tread database by name\n");
+       printf("nu <username>\t\t\tcreate a new user\n");
+       printf("nui <username> <userid>\t\tcreate a new user with id\n");
+       printf("ng <groupname> <ownerid>\tcreate a new group\n");
+       printf("l <name>\t\t\tlook up an ID by name\n");
+       printf("list\t\t\t\tlist all entries\n");
+       printf("cu <newusername> <userid>\tclone a user\n");
+       printf("ag <groupid> <id>\t\tadd a group or user to a group\n");
+       printf("rg <groupid> <id>\t\tremove a group or user from a group\n");
+       printf("d <id>\t\t\t\tdelete a user or a group\n");
+       printf("cm\t\t\t\tcompact the database (RARE)\n");
+       printf("ci <name> <newid>\t\tchange the Id of a user or group\n");
+       printf("cn <id> <newname>\t\tchange the Name of a user or group\n");
+       printf("u <id>\t\t\t\tupdate an id\n");
+       printf("ids\t\t\t\tget the database maxids\n");
+       printf("maxids <userid> <groupid>\tset the database maxids\n");
+       printf("export <userfile> <groupfile>\tdump the contents of the pdb 
+database\n");
+       printf("import <userfile> <groupfile>\tread a dumped pdb database\n");
+       printf("source <file>\t\t\tread commands from file\n");
 }
 
 command_t pdbcmds[] =
@@ -465,7 +655,11 @@
        {"ci", tool_changeId, 0, "change the Id of a user or group"},
        {"cn", tool_changeName, 0, "change the Name of a user"},
        {"u", tool_update, 0, "update an id"},
+       {"ids", tool_get_maxids, 0, "get the database maxids"},
        {"maxids", tool_maxids, 0, "set the database maxids"},
+       {"export", tool_export, 0, "dump the contents of the database"},
+       {"import", tool_import, 0, "load the contents of the database"},
+       {"source", tool_source, 0, "read commands from file"},
        {"help", tool_help, 0, "print help on commands"},
        {"quit", Parser_exit, 0, "get me out of here"},
        {"exit", Parser_exit, 0, "get me out of here"},
@@ -475,8 +669,7 @@
 
 int main(int argc, char **argv)
 {
-       char *nl;
-
+       int i;
        coda_assert_action = CODA_ASSERT_EXIT;
 
        PDB_setupdb();
@@ -485,16 +678,12 @@
                Parser_commands();
        else {
                char line[1024];
-               FILE *file = fopen(argv[1], "r");
-               if ( !file ) {
-                       perror("");
-                       return 1;
-               }
-               while ( fgets(line, 1024, file) ) {
-                       if ( (nl = strchr(line, '\n')) )
-                               *nl = '\0';
-                       execute_line(line);
+               strcpy(line, argv[1]);
+               for (i = 2; i < argc; i++) {
+                   strcat(line, " ");
+                   strcat(line, argv[i]);
                }
+               execute_line(line);
        }
        return 0;
 }

Reply via email to