Re: trying to learn systems programming, fear I have not understood and thus messed up
On Fri, 21 Oct 2011 18:53:33 +0200 Christopher J. Ruwe c...@cruwe.de wrote: [...] I have tried to follow the suggestion from the comment by modifiying the else-statement thus: } else { struct passwd *trgpwd; if (!(trgpwd = GETPWNAM(arg-val))) errx(EX_DATAERR, User %s does not exist, arg-val); if (strcmp(a_name-val,root) == 0) errx(EX_DATAERR, can't change uid of `root' account); if (strcmp(trgpwd-pw_name, root) == 0) warnx(WARNING: account `%s' will have a uid of 0 (superuser access!), pwd-pw_name); pwd-pw_uid = (uid_t) (trgpwd-pw_uid); edited = 1; } What happens is not what I intended. I invoke as sudo ./pw usermod testuser1 -u testuser2. I can get testuser2's pwd-entry by GETPWNAM allright, but when I assign the pw_uid, so as to make testuser2's uid the same as testuser1's and imgaining to retain all other values, ./pw reports pw: user 'testuser2' disappeared during update and the testuser2's /etc/passwd entry is replaced by testuser1's. I fear I have not understood GETPWNAM correctly, as it seems to replace the struct pwd as some sort of sideeffect. I could manually set all pwd-members to the correct ones (those of testuser2), but I fear that I have messed something up beforehand. I am grateful for any suggestions and/or correction. It seems I have indeed not understood GETPWNAM correctly. I have worked out a method which works by calling GETPWNAM twice: else { /* * operation as follows: * a_name-val is passed as usermod uname * arg-val is passed as -u uname * * first check if we do someting stupid, i.e., want * to set root uid to some other users uid or * to set some user accout's uid to root uid. * then get pwd to that of uname passed as -u uname. * store uid from that pwdent. * get pwd to that of uname passed as usermod uname * change uid of that latter uid to the one stored */ if(strcmp(a_name-val,root) == 0) errx(EX_DATAERR, can't change uid of `root' account); if(strcmp(arg-val, root) == 0) warnx(WARNING: account `%s' will have a uid of 0 (superuser access!), pwd-pw_name); if(!(pwd = GETPWNAM(arg-val))) /* -u uname*/ errx(EX_DATAERR, User %s does not exist, arg-val); int alias_uid = pwd-pw_uid; if(!(pwd = GETPWNAM(a_name-val))) /*usermod uname*/ errx(EX_DATAERR, User %s does not exist, a_name-val); pwd-pw_uid = (uid_t) alias_uid; warnx(User %s's uid changed to %d, pwd-pw_name, pwd-pw_uid); edited = 1; } As I stil do not know why the latter variant of my code worked and the former does not, I would still appreciate any comment or explanation which would help me understanding GETPWNAM and getpwnam. Thanks and cheers, -- Christopher J. Ruwe TZ GMT + 2 signature.asc Description: PGP signature
Re: trying to learn systems programming, fear I have not understood and thus messed up
Christopher J. Ruwe c...@cruwe.de wrote: On Fri, 21 Oct 2011 18:53:33 +0200 Christopher J. Ruwe c...@cruwe.de wrote: [...] I have tried to follow the suggestion from the comment by modifiying the else-statement thus: } else { struct passwd *trgpwd; if (!(trgpwd = GETPWNAM(arg-val))) errx(EX_DATAERR, User %s does not exist, arg-val); if (strcmp(a_name-val,root) == 0) errx(EX_DATAERR, can't change uid of `root' account); if (strcmp(trgpwd-pw_name, root) == 0) warnx(WARNING: account `%s' will have a uid of 0 (superuser access!), pwd-pw_name); pwd-pw_uid = (uid_t) (trgpwd-pw_uid); edited = 1; } What happens is not what I intended. I invoke as sudo ./pw usermod testuser1 -u testuser2. I can get testuser2's pwd-entry by GETPWNAM allright, but when I assign the pw_uid, so as to make testuser2's uid the same as testuser1's and imgaining to retain all other values, ./pw reports pw: user 'testuser2' disappeared during update and the testuser2's /etc/passwd entry is replaced by testuser1's. I fear I have not understood GETPWNAM correctly, as it seems to replace the struct pwd as some sort of sideeffect. I could manually set all pwd-members to the correct ones (those of testuser2), but I fear that I have messed something up beforehand. I am grateful for any suggestions and/or correction. It seems I have indeed not understood GETPWNAM correctly. I have worked out a method which works by calling GETPWNAM twice: else { /* * operation as follows: * a_name-val is passed as usermod uname * arg-val is passed as -u uname * * first check if we do someting stupid, i.e., want * to set root uid to some other users uid or * to set some user accout's uid to root uid. * then get pwd to that of uname passed as -u uname. * store uid from that pwdent. * get pwd to that of uname passed as usermod uname * change uid of that latter uid to the one stored */ if(strcmp(a_name-val,root) == 0) errx(EX_DATAERR, can't change uid of `root' account); if(strcmp(arg-val, root) == 0) warnx(WARNING: account `%s' will have a uid of 0 (superuser access!), pwd-pw_name); if(!(pwd = GETPWNAM(arg-val))) /* -u uname*/ errx(EX_DATAERR, User %s does not exist, arg-val); int alias_uid = pwd-pw_uid; if(!(pwd = GETPWNAM(a_name-val))) /*usermod uname*/ errx(EX_DATAERR, User %s does not exist, a_name-val); pwd-pw_uid = (uid_t) alias_uid; warnx(User %s's uid changed to %d, pwd-pw_name, pwd-pw_uid); edited = 1; } As I stil do not know why the latter variant of my code worked and the former does not, I would still appreciate any comment or explanation which would help me understanding GETPWNAM and getpwnam. I'm not familiar with the code you're working with, but according to the man page getpwnam() isn't thread safe so you probably shouldn't mess with the returned pointer in the first place and only treat the one returned by the last call as valid. Did you try using getpwnam_r() instead? Fabian signature.asc Description: PGP signature
Re: trying to learn systems programming, fear I have not understood and thus messed up
On Sat, 22 Oct 2011 16:45:08 +0200 Fabian Keil freebsd-lis...@fabiankeil.de wrote: Christopher J. Ruwe c...@cruwe.de wrote: On Fri, 21 Oct 2011 18:53:33 +0200 Christopher J. Ruwe c...@cruwe.de wrote: [...] I have tried to follow the suggestion from the comment by modifiying the else-statement thus: } else { struct passwd *trgpwd; if (!(trgpwd = GETPWNAM(arg-val))) errx(EX_DATAERR, User %s does not exist, arg-val); if (strcmp(a_name-val,root) == 0) errx(EX_DATAERR, can't change uid of `root' account); if (strcmp(trgpwd-pw_name, root) == 0) warnx(WARNING: account `%s' will have a uid of 0 (superuser access!), pwd-pw_name); pwd-pw_uid = (uid_t) (trgpwd-pw_uid); edited = 1; } What happens is not what I intended. I invoke as sudo ./pw usermod testuser1 -u testuser2. I can get testuser2's pwd-entry by GETPWNAM allright, but when I assign the pw_uid, so as to make testuser2's uid the same as testuser1's and imgaining to retain all other values, ./pw reports pw: user 'testuser2' disappeared during update and the testuser2's /etc/passwd entry is replaced by testuser1's. I fear I have not understood GETPWNAM correctly, as it seems to replace the struct pwd as some sort of sideeffect. I could manually set all pwd-members to the correct ones (those of testuser2), but I fear that I have messed something up beforehand. I am grateful for any suggestions and/or correction. It seems I have indeed not understood GETPWNAM correctly. I have worked out a method which works by calling GETPWNAM twice: else { /* * operation as follows: * a_name-val is passed as usermod uname * arg-val is passed as -u uname * * first check if we do someting stupid, i.e., want * to set root uid to some other users uid or * to set some user accout's uid to root uid. * then get pwd to that of uname passed as -u uname. * store uid from that pwdent. * get pwd to that of uname passed as usermod uname * change uid of that latter uid to the one stored */ if(strcmp(a_name-val,root) == 0) errx(EX_DATAERR, can't change uid of `root' account); if(strcmp(arg-val, root) == 0) warnx(WARNING: account `%s' will have a uid of 0 (superuser access!), pwd-pw_name); if(!(pwd = GETPWNAM(arg-val))) /* -u uname*/ errx(EX_DATAERR, User %s does not exist, arg-val); int alias_uid = pwd-pw_uid; if(!(pwd = GETPWNAM(a_name-val))) /*usermod uname*/ errx(EX_DATAERR, User %s does not exist, a_name-val); pwd-pw_uid = (uid_t) alias_uid; warnx(User %s's uid changed to %d, pwd-pw_name, pwd-pw_uid); edited = 1; } As I stil do not know why the latter variant of my code worked and the former does not, I would still appreciate any comment or explanation which would help me understanding GETPWNAM and getpwnam. I'm not familiar with the code you're working with, but according to the man page getpwnam() isn't thread safe so you probably shouldn't mess with the returned pointer in the first place and only treat the one returned by the last call as valid. Did you try using getpwnam_r() instead? Fabian You are quite right, GETPWNAM() is a macro to getpwnam(), which is not thread safe. GETPWNAM() is called throughout the code of pw and pw itself is not threaded, so it should not matter whether the functions called are thread-safe or not. I am not completely sure on my last statement though. Do you have other experience regarding this topic? Anyways, thanks and cheers, -- Christopher J. Ruwe TZ GMT + 2 signature.asc Description: PGP signature
Re: trying to learn systems programming, fear I have not understood and thus messed up
Christopher J. Ruwe c...@cruwe.de wrote: On Sat, 22 Oct 2011 16:45:08 +0200 Fabian Keil freebsd-lis...@fabiankeil.de wrote: Christopher J. Ruwe c...@cruwe.de wrote: On Fri, 21 Oct 2011 18:53:33 +0200 Christopher J. Ruwe c...@cruwe.de wrote: As I stil do not know why the latter variant of my code worked and the former does not, I would still appreciate any comment or explanation which would help me understanding GETPWNAM and getpwnam. I'm not familiar with the code you're working with, but according to the man page getpwnam() isn't thread safe so you probably shouldn't mess with the returned pointer in the first place and only treat the one returned by the last call as valid. Did you try using getpwnam_r() instead? You are quite right, GETPWNAM() is a macro to getpwnam(), which is not thread safe. GETPWNAM() is called throughout the code of pw and pw itself is not threaded, so it should not matter whether the functions called are thread-safe or not. I am not completely sure on my last statement though. Do you have other experience regarding this topic? My point is that if getpwnam() isn't thread safe because separate calls are using the same static buffer to return their result (which I didn't verify), and you do something like: pwd = GETPWNAM(...) [...] trgpwd = GETPWNAM(...) pwd-pw_uid = (uid_t) (trgpwd-pw_uid); the second getpwnam() call is going to reuse the memory pointed to by pwd. While I assume your intention was to only change pwd-pw_uid, the second getpwnam() call already had the side effect of overwriting all the other members as well. This would happen in a single-threaded application as well. Fabian signature.asc Description: PGP signature
Re: trying to learn systems programming, fear I have not understood and thus messed up
On Fri, Oct 21, 2011 at 06:53:33PM +0200, Christopher J. Ruwe wrote: To improve on my C and to learn something about systems programming, I have begun to pick out bite-size bits from the bin-PRs. Currently, I am dispairing about bin/149972, which is about 1) adding error handling to pw being invoced pw -u username and 2) trying to get a uid from the (incorrectly) passed username. Currently, I cannot accomplish want I wanted to do, so I turn here for hints or help. [snip] Christopher, you're probably best off posting to hackers@ for programming problems pertaining to FreeBSD. Regards, -- Frank Contact info: http://www.shute.org.uk/misc/contact.html pgpMvw7dgrm0F.pgp Description: PGP signature
trying to learn systems programming, fear I have not understood and thus messed up
To improve on my C and to learn something about systems programming, I have begun to pick out bite-size bits from the bin-PRs. Currently, I am dispairing about bin/149972, which is about 1) adding error handling to pw being invoced pw -u username and 2) trying to get a uid from the (incorrectly) passed username. Currently, I cannot accomplish want I wanted to do, so I turn here for hints or help. Three developers which I have failed to reach by mail (gpf@, kibab@, bcr@) have added the necessary code if ((arg = getarg(args, 'u')) != NULL) { if(isdigit((unsigned char)*arg-val)) { pwd-pw_uid = (uid_t) atol(arg-val); edited = 1; if (pwd-pw_uid != 0 strcmp(pwd-pw_name, root) == 0) errx(EX_DATAERR, can't change uid of `root' account); if (pwd-pw_uid == 0 strcmp(pwd-pw_name, root) != 0) warnx(WARNING: account `%s' will have a uid of 0 (superuser access!), pwd-pw_name); } else { /* Found something, but not a number */ /* * XXX Shouldn't we try to map the passed string to the username? * man page however says that we're expecting numeric uid... */ errx(EX_DATAERR, Expected numeric user id as an argument to -u\n); } } I have tried to follow the suggestion from the comment by modifiying the else-statement thus: } else { struct passwd *trgpwd; if (!(trgpwd = GETPWNAM(arg-val))) errx(EX_DATAERR, User %s does not exist, arg-val); if (strcmp(a_name-val,root) == 0) errx(EX_DATAERR, can't change uid of `root' account); if (strcmp(trgpwd-pw_name, root) == 0) warnx(WARNING: account `%s' will have a uid of 0 (superuser access!), pwd-pw_name); pwd-pw_uid = (uid_t) (trgpwd-pw_uid); edited = 1; } What happens is not what I intended. I invoke as sudo ./pw usermod testuser1 -u testuser2. I can get testuser2's pwd-entry by GETPWNAM allright, but when I assign the pw_uid, so as to make testuser2's uid the same as testuser1's and imgaining to retain all other values, ./pw reports pw: user 'testuser2' disappeared during update and the testuser2's /etc/passwd entry is replaced by testuser1's. I fear I have not understood GETPWNAM correctly, as it seems to replace the struct pwd as some sort of sideeffect. I could manually set all pwd-members to the correct ones (those of testuser2), but I fear that I have messed something up beforehand. I am grateful for any suggestions and/or correction. -- Christopher J. Ruwe TZ GMT + 2 signature.asc Description: PGP signature