Test post babble

December 31, 2007

(This is a test blog post. Even so, it's not a meaningless post. It might stay around or get erased, depending on how things go with this blog. It's a good test of features that I have no idea how to use and need to learn.)

I've been playing with Leopard on a spare mac for about a week now. I've discovered a few things:

The Dock sucks, but you already knew that. I think both renditions -- shelf and no shelf -- suck. Why can't we just have icons floating at the bottom of the screen, bright for active, dim for not running? No shelf. No real-time (because gee, who can live without those?) reflections. No border. Nothing. Just icons.

The Subversion tools included are recent and fine. Leopard includes a bunch of daemon ids that start with _; one is _svn. I set up launchd to run svnserve as user _svn at boot, created some Subversion repositories, etc. The biggest time sink was figuring out launchd. launchd is pretty cool, now taht I've figured it out. I'm not sure I'll ever stop using cron, but for running daemons like svnserve, it's great. Die-hard inetd fans: ready to give that up for launchd?

Here's the launchd plist file:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" 
"http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>Disabled</key>
        <false/>
        <key>Debug</key>
    <false/>
    <key>Label</key>
    <string>org.tigris.subversion.svnserve</string>
    <key>UserName</key>
    <string>_svn</string>
    <key>GroupName</key>
    <string>_svn</string>
    <key>Umask</key>
    <integer>2</integer>
    <key>KeepAlive</key>
    <true/>
    <key>ProgramArguments</key>
    <array>
      <string>/usr/bin/svnserve</string>
      <string>--inetd</string>
      <string>--root=/usr/local/scm/svn/repositories</string>
    </array>
    <key>Sockets</key>
    <dict>
      <key>Listeners</key>
      <array>
        <dict>
          <key>SockFamily</key>
          <string>IPv4</string>
          <key>SockServiceName</key>
          <string>svn</string>
          <key>SockType</key>
          <string>stream</string>
        </dict>
        <dict>
          <key>SockFamily</key>
          <string>IPv6</string>
          <key>SockServiceName</key>
          <string>svn</string>
          <key>SockType</key>
          <string>stream</string>
        </dict>
      </array>
    </dict>
    <key>inetdCompatibility</key>
    <dict>
      <key>Wait</key>
      <false/>
    </dict>
  </dict>
</plist>

<!--

http://developer.apple.com/documentation/Darwin/Reference/ManPages/man5/launchd.plist.5.html

launchctl stop org.tigris.subversion.svnserve
launchctl unload /Library/LaunchDaemons/org.tigris.subversion.svnserve.plist
launchctl load /Library/LaunchDaemons/org.tigris.subversion.svnserve.plist
launchctl start org.tigris.subversion.svnserve

-->

My terminal setting of choice is Homebrew. Didn't think I'd ever go back to vintage green on black, but I did. So 1970's, like Panteras and Sanders ice cream. For those of us who like having the window a bit transparent (I use 90% opacity. Or is that 10% transparency?) I wish they'd put in a slider to adjust blur on the transparency, or just hardcode it to the same blur that sheets have now. There is a hack to do this called Blurminal:

http://ciaranwal.sh/2007/11/16/blurminal

but I'd rather have it in the code.

They finally fixed the menubar analog clock graphic. In Tiger, the hands were one pixel off. Actually the hands were fine -- the circle was a pixel off. On new Tiger installs, you'd always have to replace the files in the bundle with corrected ones to make it look right. No more!

In Mail.app, I still can't set the message header font to Lucida Grande. Why not? Why do you insist on not letting me do this most basic of things? Why do you insist on putting Helvetica in that one little place when the rest of the UI uses Lucida Grande?

So, um, expanding this rant a little, this goes for the whole UI: NO HELVETICA IN ANY AQUA UI ELEMENTS. IT MAY NOT BE (although I think it clearly is) WRONG, BUT IT'S UGLY. And it's always some oddball place where it happens and it just ruins the UI for me. Why is Helvetica being used in Address Book? Why in iCal? Why in the TimeMachine Preference Pane? Why anywhere? I swear, I'm going to figure out some hack to hijack all UI requests for Helvetica and give back Lucida Grande instead. I don't know if this is even possible. (First blog post rookie mistake, saying I'm going to do something I know nothing about.)

Enough small talk. Now for some serious jibber jabber. I haven't seen this talked about anywhere else, so we may have an NSDetroit Breaking News Poop, I mean Scoop, here. There's a serious problem with Migration Assistant. Or is the problem with Tiger, and Migration Assistant is just working GIGO? Film at 11.

The problem's origins: In Tiger, a new group is created with the same name is the user when new users are created. After days -- DAYS -- of messing around, installing Leopard, migrating a few users, inspecting the migration anomalies and everything about the Directory Services db... then starting over with a fresh Erase and Install... I concluded that Migration Assistant was being fed bad information.

Problem 1, part 1

In Tiger, your account is a member of a group of the same name, but that group is empty. Tiger created the group and named it after you, but never actually put you in it:

[jtrammel@Tiger ~]% dscl . read /users/jtrammel
_shadow_passwd: 
_writers_hint: jtrammel
_writers_passwd: jtrammel
_writers_picture: jtrammel
_writers_realname: jtrammel
_writers_tim_password: jtrammel
sharedDir: 
AppleMetaNodeLocation: /NetInfo/DefaultLocalNode
AuthenticationAuthority: ;ShadowHash;HASHLIST:<SALTED-SHA1,SMB-NT,SMB-LAN-MANAGER>
AuthenticationHint: 
GeneratedUID: 80378212-07A0-4EA9-8270-01C52DBD5E08
NFSHomeDirectory: /Users/jtrammel
Password: ********
Picture: /Library/User Pictures/Animals/Dog.tif
PrimaryGroupID: 502
RealName: James Trammell
RecordName: jtrammel
RecordType: dsRecTypeNative:users
UniqueID: 502
UserShell: /bin/tcsh


[jtrammel@Tiger ~]% dscl . read /groups/jtrammel
AppleMetaNodeLocation: /NetInfo/DefaultLocalNode
GeneratedUID: 639A1A43-21D8-418A-8092-102723D681B8
Password: *
PrimaryGroupID: 502
RecordName: jtrammel
RecordType: dsRecTypeNative:groups

See? you're not in there. There is no GroupMembership key at all. I never noticed this before because it just never came up in Tiger.

So when Leopard migrates your user, it recreates the group named after you, but it's still empty. Not because Migration Assistant is broken, but because it's being fed bad information to work with.

And then you get the Finder crashes when trying to mess with permissions from Get Info windows that all the kids are complaining about now.

Problem 1, part 2

This isn't the only problem. Leopard likes to have its users in group staff. Tiger didn't, but I can't think of a reason why it didn't. (It never bothered me until now. Maybe because I didn't think about it?) Migration Assistant in Leopard doesn't put your migrated user in group staff. I was expecting it to. For this reason, I again thought Migration Assistant was broken, but again, it's just another case of having garbage to work with. If your user is in group staff in Tiger, Migration Assistant will bring it over to Leopard and it WILL REMAIN in group staff.

Problem C (ha)

The final problem is weird. And has an appropriately weird solution.

If you create a new Leopard user from the Accounts pane, that user belongs to group staff, but also to a mysterious (to me, anyway!) group called com.apple.sharepoint.group.N. N is a number corresponding to something. It increases by 1 every time a new user is created using the Accounts pane. So when you install Leopard, and you create your admin user after the wonderfully hip music video ends, a group called com.apple.sharepoint.group.1 gets created, and your admin user is made a member of it.

Now you go and create your first Standard user, and guess what: com.apple.sharepoint.group.2 gets created, and your new user is put in that group. Seems logical enough. But wait. Your new user is now also a member of com.apple.sharepoint.group.1. And your admin user, that first user you created, now also belongs to the newly created com.apple.sharepoint.group.2.

system-janitors-powerbook-g4-15$ id adminuser
uid=501(adminuser) gid=20(staff) groups=20(staff),101(com.apple.sharepoint.group.1),
98(_lpadmin),81(_appserveradm),79(_appserverusr),80(admin)

(Create a Standard user "newuser" in Accounts)

system-janitors-powerbook-g4-15$ id adminuser
uid=501(adminuser) gid=20(staff) groups=20(staff),101(com.apple.sharepoint.group.1),
98(_lpadmin),81(_appserveradm),102(com.apple.sharepoint.group.2),79(_appserverusr),80(admin)


system-janitors-powerbook-g4-15$ id newuser
uid=502(newuser) gid=20(staff) groups=20(staff),101(com.apple.sharepoint.group.1),
98(_lpadmin),102(com.apple.sharepoint.group.2)

Fine. Mystery groups are as American as hookers and guns. So if this is how things work when I manually create users, then I should expect Migration Assistant to follow suit and create new com.apple.sharepoint.group.N mystery groups when it migrates users, right?

Wrong. It doesn't create a new sharepoint group.


system-janitors-powerbook-g4-15$ id migrateduser
uid=508(migrateduser) gid=508(migrateduser) groups=508(migrateduser),98(_lpadmin)

(But at least it properly added the migrated user to _lpadmin.)

Now, I don't claim to know what the sharepoint groups do, or what they're even for. All I want is for my account migrations from Tiger to Leopard to be consistent with manual user creation within Leopard. It doesn't sit well with me that manually created users get the stuff and migrated users don't.

Fixes

I wrote a couple of shell scripts to fix the problems.

Fix 1 for Problem 1 parts 1 and 2

The first problem can be fixed in two ways: You can fix your user in Tiger before migrating, or in Leopard after migrating. The following sequence of dscl invocations will do the trick:

shortname is the id in question.

gid is the group id that, in Tiger, is the same value as the uid for the shortname.

#remove shortname from group shortname
dscl . delete /Groups/shortname GroupMembership shortname

#remove group shortname
dscl . delete /Groups/shortname

#add user shortname to group staff
dscl . append /Groups/staff GroupMembership shortname

#set primary GID to staff
dscl . change /Users/username PrimaryGroupID gid 20

#set group on files
chgrp -R staff /Users/shortname

And if you want to just put it in a script, you can:

#!/bin/sh

shortname=$1
if [ "$shortname" != "" ]; then
        check=`id $shortname`
else
        echo "user not specified"
        exit 1
fi

if [ "$check" != "" ]; then
        gid=`id -g $shortname`

        #remove shortname from group shortname
        dscl . delete /Groups/${shortname} GroupMembership $shortname

        #remove group shortname
        dscl . delete /Groups/${shortname}

        #add user shortname to group staff
        dscl . append /Groups/staff GroupMembership $shortname

        #set primary GID to staff
        dscl . change /Users/${shortname} PrimaryGroupID $gid 20

        #set group on files
        chgrp -R staff /Users/${shortname}

else

        echo "user $shortname does not exist."
        exit 1

fi

exit 0

Call it fixmigrateduser.sh. Then run it like:

fixmigrateduser.sh migrateduser

Fix 2 for Problem C

This is a weird problem with a tricky fix. It's tricky because you need to know beforehand how many users you have on your system, and thus how many com.apple.sharepoint.group.N groups are there already. Then you will create com.apple.sharepoint.group.N+1.

If the system has 3 users on it already, it probably has sharepoint groups numbering up to 3. I say "probably" because again, I have no idea what purpose these groups serve in Leopard or the logic behind their creation. (Or deletion.)

Now, let's stop for a second and look at one of these groups. What's in it?


system-janitors-powerbook-g4-15$ dscl . read /groups/com.apple.sharepoint.group.2
AppleMetaNodeLocation: /Local/Default
GeneratedUID: 69508F77-E50B-4811-A861-C68FF581931E
GroupMembers: 11BF1FC8-50E4-45C3-B1AF-2E31B21A1A01
GroupMembership: newuser
NestedGroups: ABCDEFAB-CDEF-ABCD-EFAB-CDEF00000014 ABCDEFAB-CDEF-ABCD-EFAB-CDEF0000000C
PrimaryGroupID: 102
RealName: Public
RecordName: com.apple.sharepoint.group.2
RecordType: dsRecTypeNative:groups

Basically a bunch of mysterious keys with mysterious values. But if we break it down, we see that:

The GroupMembers key has the same value as newuser's GeneratedUID key.

The NestedGroups key has the same value across all the com.apple.sharepoint.group.N groups.

I'm not saying its guaranteed, because again I have no idea what these groups are doing here. But I have created and migrated several users into Leopard, and the value for this key never seems to change. Let's hope I'm right. FOR YOUR SAKE.

And finally, if you take the .N digit from com.apple.sharepoint.group.N and add 100, you get the value of PrimaryGroupID. Math is fun.

Here's a dump of the user newuser corresponding to the sharepoint group com.apple.sharepoint.group.2:

system-janitors-powerbook-g4-15$ dscl . read /users/newuser
dsAttrTypeNative:_writers_hint: newuser
dsAttrTypeNative:_writers_jpegphoto: newuser
dsAttrTypeNative:_writers_LinkedIdentity: newuser
dsAttrTypeNative:_writers_passwd: newuser
dsAttrTypeNative:_writers_picture: newuser
dsAttrTypeNative:_writers_realname: newuser
dsAttrTypeNative:_writers_UserCertificate: newuser
AppleMetaNodeLocation: /Local/Default
AuthenticationAuthority: ;ShadowHash; ;Kerberosv5;;newuser@LKDC:SHA1.F9A9F8916370DAC3B860...
AuthenticationHint:
GeneratedUID: 11BF1FC8-50E4-45C3-B1AF-2E31B21A1A01
NFSHomeDirectory: /Users/newuser
Password: ********
Picture:
 /Library/User Pictures/Animals/Butterfly.tif
PrimaryGroupID: 20
RealName: newuser
RecordName: newuser
RecordType: dsRecTypeNative:users
UniqueID: 502
UserShell: /bin/bash

Now back to Fix 2. We're using Migration Assistant to migrate a user over, remember? The Tiger user has been migrated. The shortname is migrateduser. Assuming we are fixing the 4th user added to the system, we need to create a com.apple.sharepoint.group.4 group. The following sequence of dscl invocations will do the trick:


dscl . create /Groups/com.apple.sharepoint.group.4

dscl . create /Groups/com.apple.sharepoint.group.4 PrimaryGroupID 104

dscl . create /Groups/com.apple.sharepoint.group.4 RealName Public

dscl . create /Groups/com.apple.sharepoint.group.4 GroupMembership migrateduser

dscl . create /Groups/com.apple.sharepoint.group.4 GroupMembers \
`dscl . read /users/migrateduser GeneratedUID | awk -F': ' '{print $2}'`

dscl . create /Groups/com.apple.sharepoint.group.4 NestedGroups \
`dscl . read /Groups/com.apple.sharepoint.group.1 NestedGroups | awk -F': ' '{print $2}'`


And if you want to just put it in a script, you can:


#!/bin/sh

guser=$1
gnum=$2
gpath="/Groups/com.apple.sharepoint.group.${gnum}"

dscl . create $gpath
dscl . create $gpath PrimaryGroupID 10${gnum}
dscl . create $gpath RealName Public
dscl . create $gpath GroupMembership $guser

dscl . create $gpath GroupMembers `dscl . read /users/${guser} \
GeneratedUID | awk -F': ' '{print $2}'`

dscl . create $gpath NestedGroups `dscl . read /Groups/com.apple.sharepoint.group.1 \
NestedGroups | awk -F': ' '{print $2}'`

exit 0

Call it fixsharepoint.sh. If user migrateduser is the 4th user on the system, then run it like:

fixsharepoint.sh migrateduser 4
And so on:
fixsharepoint.sh nextmigrateduser 5
fixsharepoint.sh nextmigrateduserafterthat 6
.
.
.

Run it:

system-janitors-powerbook-g4-15:~ root# /usr/local/bin/fixsharepoint.sh migrateduser 5

Check the results:

system-janitors-powerbook-g4-15:~ root# id migrateduser
uid=508(migrateduser) gid=20(staff) groups=20(staff),101(com.apple.sharepoint.group.1),
98(_lpadmin),103(com.apple.sharepoint.group.3),102(com.apple.sharepoint.group.2),
105(com.apple.sharepoint.group.5),104(com.apple.sharepoint.group.4)

It worked. We see that com.apple.sharepoint.group.5 was created, and migrated user was made a member of it.

But something else interesting happened. Every time a new sharepoint group is created and a new user is added to it, all of the existing users on the system are added to it as well. It's magic! We don't even have to do anything to make this happen!


system-janitors-powerbook-g4-15:~ root# id adminuser
uid=501(adminuser) gid=20(staff) groups=20(staff),101(com.apple.sharepoint.group.1),
98(_lpadmin),81(_appserveradm),103(com.apple.sharepoint.group.3),79(_appserverusr),
80(admin),102(com.apple.sharepoint.group.2),105(com.apple.sharepoint.group.5),
104(com.apple.sharepoint.group.4)


system-janitors-powerbook-g4-15:~ root# id newuser
uid=502(newuser) gid=20(staff) groups=20(staff),101(com.apple.sharepoint.group.1),
98(_lpadmin),103(com.apple.sharepoint.group.3),102(com.apple.sharepoint.group.2),
105(com.apple.sharepoint.group.5),104(com.apple.sharepoint.group.4)


system-janitors-powerbook-g4-15:~ root# id othermigrateduser
uid=507(othermigrateduser) gid=20(staff) groups=20(staff),101(com.apple.sharepoint.group.1),
98(_lpadmin),103(com.apple.sharepoint.group.3),102(com.apple.sharepoint.group.2),
105(com.apple.sharepoint.group.5),104(com.apple.sharepoint.group.4)

That's it. Those are the two fixes. It's a two-part problem, but I broke Problem 1 into two parts, so it looks like a three-part problem. I'm rich.

For the record, Apple has an official fix for this problem, but I neither like it nor understand it:

http://docs.info.apple.com/article.html?artnum=307128