From owner-freebsd-questions@FreeBSD.ORG Sat Oct 22 14:56:58 2011 Return-Path: Delivered-To: freebsd-questions@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id C27171065688 for ; Sat, 22 Oct 2011 14:56:58 +0000 (UTC) (envelope-from freebsd-listen@fabiankeil.de) Received: from smtprelay06.ispgateway.de (smtprelay06.ispgateway.de [80.67.31.95]) by mx1.freebsd.org (Postfix) with ESMTP id 540AD8FC16 for ; Sat, 22 Oct 2011 14:56:58 +0000 (UTC) Received: from [78.34.185.7] (helo=fabiankeil.de) by smtprelay06.ispgateway.de with esmtpsa (TLSv1:AES128-SHA:128) (Exim 4.68) (envelope-from ) id 1RHcp4-0007Zy-3Y; Sat, 22 Oct 2011 16:45:18 +0200 Date: Sat, 22 Oct 2011 16:45:08 +0200 From: Fabian Keil To: "Christopher J. Ruwe" Message-ID: <20111022164508.0dcca5aa@fabiankeil.de> In-Reply-To: <20111022160453.35dac1f3@dijkstra> References: <20111021185333.7c197a2a@dijkstra> <20111022160453.35dac1f3@dijkstra> Mime-Version: 1.0 Content-Type: multipart/signed; micalg=PGP-SHA1; boundary="Sig_/clBAzwN7k+pWFspR8vJncnk"; protocol="application/pgp-signature" X-Df-Sender: Nzc1MDY3 Cc: freebsd-questions@freebsd.org Subject: Re: trying to learn systems programming, fear I have not understood and thus messed up X-BeenThere: freebsd-questions@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: User questions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 22 Oct 2011 14:56:58 -0000 --Sig_/clBAzwN7k+pWFspR8vJncnk Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable "Christopher J. Ruwe" wrote: > On Fri, 21 Oct 2011 18:53:33 +0200 > "Christopher J. Ruwe" wrote: >=20 > > [...] > >=20 > > I have tried to follow the suggestion from the comment by modifiying > > the else-statement thus: > >=20 > > } else { > > struct passwd *trgpwd; > > if (!(trgpwd =3D GETPWNAM(arg->val))) > > errx(EX_DATAERR, "User %s does not exist", arg->val); > > =20 > > if (strcmp(a_name->val,"root") =3D=3D 0) > > errx(EX_DATAERR, "can't change uid of `root' account"); > > if (strcmp(trgpwd->pw_name, "root") =3D=3D 0) > > warnx("WARNING: account `%s' will have a uid of 0 (superuser > > access!)", pwd->pw_name); > >=20 > > pwd->pw_uid =3D (uid_t) (trgpwd->pw_uid); =20 > > edited =3D 1; > > }=20 > >=20 > > 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. > >=20 > > 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. > >=20 > > I am grateful for any suggestions and/or correction.=20 >=20 > It seems I have indeed not understood GETPWNAM correctly. I have worked > out a method which works by calling GETPWNAM twice: >=20 > else { > /* > * operation as follows: > * a_name->val is passed as usermod > * arg->val is passed as -u > * > * 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 . > * store uid from that pwdent. > * get pwd to that of uname passed as usermod > * change uid of that latter uid to the one stored > */ > =20 > if(strcmp(a_name->val,"root") =3D=3D 0) > errx(EX_DATAERR, "can't change uid of `root' account"); >=20 > if(strcmp(arg->val, "root") =3D=3D 0) > warnx("WARNING: account `%s' will have a uid of 0 (superuser > access!)", pwd->pw_name); >=20 > if(!(pwd =3D GETPWNAM(arg->val))) /* -u */ > errx(EX_DATAERR, "User %s does not exist", arg->val); > int alias_uid =3D pwd->pw_uid;=20 >=20 > if(!(pwd =3D GETPWNAM(a_name->val))) /*usermod */ > errx(EX_DATAERR, "User %s does not exist", a_name->val); >=20 > pwd->pw_uid =3D (uid_t) alias_uid; > warnx("User %s's uid changed to %d", pwd->pw_name, pwd->pw_uid); > edited =3D 1; > } >=20 > 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 --Sig_/clBAzwN7k+pWFspR8vJncnk Content-Type: application/pgp-signature; name=signature.asc Content-Disposition: attachment; filename=signature.asc -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.18 (FreeBSD) iEYEARECAAYFAk6i1wQACgkQBYqIVf93VJ3jSgCeKDcUdfe6BHfGGlguNJbazKc5 7+EAn1zSVJRSKblZTD9SLZSH0x2pytTN =MiUO -----END PGP SIGNATURE----- --Sig_/clBAzwN7k+pWFspR8vJncnk--