trying to learn systems programming, fear I have not understood and thus messed up

Christopher J. Ruwe cjr at cruwe.de
Sat Oct 22 16:54:28 UTC 2011


On Sat, 22 Oct 2011 16:45:08 +0200
Fabian Keil <freebsd-listen at fabiankeil.de> wrote:

> "Christopher J. Ruwe" <cjr at cruwe.de> wrote:
> 
> > On Fri, 21 Oct 2011 18:53:33 +0200
> > "Christopher J. Ruwe" <cjr at 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

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 834 bytes
Desc: not available
Url : http://lists.freebsd.org/pipermail/freebsd-questions/attachments/20111022/055f5649/signature.pgp


More information about the freebsd-questions mailing list