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;
}