<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[Milhouse Ltd.]]></title>
  <link href="http://milhouse.co.uk/atom.xml" rel="self"/>
  <link href="http://milhouse.co.uk/"/>
  <updated>2012-02-12T18:08:33+00:00</updated>
  <id>http://milhouse.co.uk/</id>
  <author>
    <name><![CDATA[Patrick]]></name>
    <email><![CDATA[rss@milhouse.co.uk]]></email>
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[Mounting NFS Shares on OS X]]></title>
    <link href="http://milhouse.co.uk/blog/2010/02/23/mounting-nfs-shares-on-osx/"/>
    <updated>2010-02-23T00:00:00+00:00</updated>
    <id>http://milhouse.co.uk/blog/2010/02/23/mounting-nfs-shares-on-osx</id>
    <content type="html"><![CDATA[<p>When doing cross development I find it convenient to build any source code on an NFS mounted directory. This can then be accessed directly from embedded clients as well as the build machine without the need to ftp binaries to the host for executing. My NFS shares are exported from my Ubuntu server and I connect to them from my OS X build machine.</p>

<p>Under OS X it is really simple to access these shares using dynamic automounting. You can simply cd to the share without any setup at all using something like:</p>

<blockquote><p>$ cd /net/server.name/export/share</p></blockquote>

<p>Where server.name is the NFS server hostname, and /export/share is the exported directory. I create a soft link in my home directory so that I can cd directly to the shared directory after running Terminal.app.</p>

<p>This usually works well, NFS has been around for a long time and is well tested. However, I was sometimes getting problems accessing the NFS mount from OS X, sometimes I could access the drive and sometimes not. From the command line I would get the error:</p>

<blockquote><p>-bash: cd: dev: Operation timed out</p></blockquote>

<p>All the other machines on the network had no problems so I knew it was a problem on my MacBook Pro.</p>

<p>Well, after a bit of Googling it turns out that for security NFS requires that all requests originate on an internet port less than 1024. OS X does not always abide by this rule. It is possible on the server in the /etc/hosts file to override this by adding the insecure option to the export line. This is initially what I tried. But this didn’t seem to be 100% effective, it was still slow when accessing the NFS share for the first time and what’s more I wasn’t happy in circumventing an obvious security measure.</p>

<p>So after restoring /etc/exports and restarting the NFS daemon I tried the other approach, fix it on the OS X client end. There are two ways to do this, the first is to edit /etc/autofs.conf and look for the AUTOMOUNTD_MNTOPTS option. Add rescport to the end of the line so it looks something like:</p>

<blockquote><p>AUTOMOUNTD_MNTOPTS=nosuid,nodev,resvport</p></blockquote>

<p>This will force the Mac to use reserved ports for all NFS requests. The second way (which is the approach I took) is to edit /etc/auto_master. Find the line that starts /net, and add the resvport option to the end so it becomes:</p>

<blockquote><p>/net -hosts -nobrowse,hidefromfinder,nosuid,resvport</p></blockquote>

<p>This causes the Mac to use reserved ports only for those mounts under /net which are the dynamic mounts.</p>

<p>Since doing this NFS seems a lot faster and connects every time.</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Listing Local Users]]></title>
    <link href="http://milhouse.co.uk/blog/2009/05/18/listing-local-users/"/>
    <updated>2009-05-18T00:00:00+01:00</updated>
    <id>http://milhouse.co.uk/blog/2009/05/18/listing-local-users</id>
    <content type="html"><![CDATA[<p>Using Directory Services, it is quite easy to get a list of all the user accounts on your OS X computer. From the command line run:</p>

<blockquote><p>$ dscl localhost list /Search/Users</p></blockquote>

<p>Unfortunately, this also lists all the system accounts such as those used by the www and mysql daemons. So if we only want users then we have to do a bit of work to filter out these accounts. Now, when creating users on OS X (and most Unix based systems that I am aware of) they are assigned a User ID starting from 500. So we can simply ignore any accounts with a UID less than 500.</p>

<p>To be able to do this from Objective C within my Cocoa application I had to execute the dscl command from within an NSTask. The code listing below shows how I done this.</p>

<p>The first half of the function sets up the NSTask with the path to the dscl application and the arguments to be passed. The task is then run and the output piped to a file. This is then read into an NSString which we can now process to remove all system accounts. Using an NSScanner we iterate through the string calling the standard C library function getpwnam() to discover the UID of each account. If it is less than 500 then the user name is added to the array initialised at the start of the function.</p>

<p>Finally return the list of users as an NSArray.</p>

<p>I was doing it this way for a while and it is fine for local users. Problems arise when you need to list network users or need more flexibility so I have recently switched to using the CSIdentity framework.</p>

<p><em>Edited to add release for ‘task’ and ‘string’. Thanks go to Jason for spotting that.</em></p>

<figure class='code'><figcaption><span> (getLocalUsers.m)</span> <a href='http://milhouse.co.uk/downloads/code/getLocalUsers.m'>download</a></figcaption>
 <div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
<span class='line-number'>12</span>
<span class='line-number'>13</span>
<span class='line-number'>14</span>
<span class='line-number'>15</span>
<span class='line-number'>16</span>
<span class='line-number'>17</span>
<span class='line-number'>18</span>
<span class='line-number'>19</span>
<span class='line-number'>20</span>
<span class='line-number'>21</span>
<span class='line-number'>22</span>
<span class='line-number'>23</span>
<span class='line-number'>24</span>
<span class='line-number'>25</span>
<span class='line-number'>26</span>
<span class='line-number'>27</span>
<span class='line-number'>28</span>
<span class='line-number'>29</span>
<span class='line-number'>30</span>
<span class='line-number'>31</span>
<span class='line-number'>32</span>
<span class='line-number'>33</span>
<span class='line-number'>34</span>
<span class='line-number'>35</span>
<span class='line-number'>36</span>
<span class='line-number'>37</span>
<span class='line-number'>38</span>
<span class='line-number'>39</span>
<span class='line-number'>40</span>
<span class='line-number'>41</span>
<span class='line-number'>42</span>
<span class='line-number'>43</span>
<span class='line-number'>44</span>
<span class='line-number'>45</span>
<span class='line-number'>46</span>
<span class='line-number'>47</span>
<span class='line-number'>48</span>
<span class='line-number'>49</span>
<span class='line-number'>50</span>
<span class='line-number'>51</span>
<span class='line-number'>52</span>
</pre></td><td class='code'><pre><code class='objc'><span class='line'><span class="o">-</span><span class="p">(</span><span class="n">NSArray</span><span class="o">*</span><span class="p">)</span><span class="n">getLocalUsers</span>
</span><span class='line'><span class="p">{</span>
</span><span class='line'>   <span class="n">NSMutableArray</span> <span class="o">*</span><span class="n">users</span> <span class="o">=</span> <span class="p">[[</span><span class="n">NSMutableArray</span> <span class="n">alloc</span><span class="p">]</span> <span class="n">init</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'>   <span class="n">NSTask</span> <span class="o">*</span><span class="n">task</span><span class="p">;</span>
</span><span class='line'>   <span class="n">task</span> <span class="o">=</span> <span class="p">[[</span><span class="n">NSTask</span> <span class="n">alloc</span><span class="p">]</span> <span class="n">init</span><span class="p">];</span>
</span><span class='line'>   <span class="p">[</span><span class="n">task</span> <span class="nl">setLaunchPath:</span> <span class="s">@&quot;/usr/bin/dscl&quot;</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'>   <span class="n">NSArray</span> <span class="o">*</span><span class="n">arguments</span><span class="p">;</span>
</span><span class='line'>   <span class="n">arguments</span> <span class="o">=</span>
</span><span class='line'>      <span class="p">[</span><span class="n">NSArray</span> <span class="nl">arrayWithObjects:</span> <span class="s">@&quot;localhost&quot;</span><span class="p">,</span> <span class="s">@&quot;list&quot;</span><span class="p">,</span> <span class="s">@&quot;/Search/Users&quot;</span><span class="p">,</span> <span class="nb">nil</span><span class="p">];</span>
</span><span class='line'>   <span class="p">[</span><span class="n">task</span> <span class="nl">setArguments:</span> <span class="n">arguments</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'>   <span class="n">NSPipe</span> <span class="o">*</span><span class="n">pipe</span><span class="p">;</span>
</span><span class='line'>   <span class="n">pipe</span> <span class="o">=</span> <span class="p">[</span><span class="n">NSPipe</span> <span class="n">pipe</span><span class="p">];</span>
</span><span class='line'>   <span class="p">[</span><span class="n">task</span> <span class="nl">setStandardOutput:</span> <span class="n">pipe</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'>   <span class="n">NSFileHandle</span> <span class="o">*</span><span class="n">file</span><span class="p">;</span>
</span><span class='line'>   <span class="n">file</span> <span class="o">=</span> <span class="p">[</span><span class="n">pipe</span> <span class="n">fileHandleForReading</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'>   <span class="p">[</span><span class="n">task</span> <span class="n">launch</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'>   <span class="n">NSData</span> <span class="o">*</span><span class="n">data</span><span class="p">;</span>
</span><span class='line'>   <span class="n">data</span> <span class="o">=</span> <span class="p">[</span><span class="n">file</span> <span class="n">readDataToEndOfFile</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'>   <span class="n">NSString</span> <span class="o">*</span><span class="n">string</span><span class="p">;</span>
</span><span class='line'>   <span class="n">string</span> <span class="o">=</span> <span class="p">[[</span><span class="n">NSString</span> <span class="n">alloc</span><span class="p">]</span> <span class="nl">initWithData:</span> <span class="n">data</span> <span class="nl">encoding:</span><span class="n">NSUTF8StringEncoding</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'>   <span class="n">NSScanner</span> <span class="o">*</span><span class="n">theScanner</span> <span class="o">=</span> <span class="p">[</span><span class="n">NSScanner</span> <span class="nl">scannerWithString:</span><span class="n">string</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'>   <span class="k">while</span> <span class="p">(</span><span class="n">NO</span> <span class="o">==</span> <span class="p">[</span><span class="n">theScanner</span> <span class="n">isAtEnd</span><span class="p">])</span>
</span><span class='line'>   <span class="p">{</span>
</span><span class='line'>      <span class="n">NSString</span> <span class="o">*</span><span class="n">str</span><span class="p">;</span>
</span><span class='line'>      <span class="k">struct</span> <span class="n">passwd</span> <span class="o">*</span><span class="n">userInfo</span><span class="p">;</span>
</span><span class='line'>
</span><span class='line'>      <span class="k">if</span> <span class="p">([</span><span class="n">theScanner</span> <span class="nl">scanUpToCharactersFromSet:</span>
</span><span class='line'>            <span class="p">[</span><span class="n">NSCharacterSet</span> <span class="n">whitespaceAndNewlineCharacterSet</span><span class="p">]</span>
</span><span class='line'>            <span class="nl">intoString:</span><span class="o">&amp;</span><span class="n">str</span><span class="p">])</span>
</span><span class='line'>      <span class="p">{</span>
</span><span class='line'>         <span class="n">userInfo</span> <span class="o">=</span> <span class="n">getpwnam</span><span class="p">([</span><span class="n">str</span> <span class="n">UTF8String</span><span class="p">]);</span>
</span><span class='line'>         <span class="k">if</span> <span class="p">(</span><span class="n">userInfo</span><span class="o">-&gt;</span><span class="n">pw_uid</span> <span class="o">&gt;</span> <span class="mi">500</span><span class="p">)</span>
</span><span class='line'>         <span class="p">{</span>
</span><span class='line'>            <span class="p">[</span><span class="n">users</span> <span class="nl">addObject:</span> <span class="n">str</span><span class="p">];</span>
</span><span class='line'>         <span class="p">}</span>
</span><span class='line'>      <span class="p">}</span>
</span><span class='line'>   <span class="p">}</span>
</span><span class='line'>
</span><span class='line'>   <span class="p">[</span><span class="n">string</span> <span class="n">release</span><span class="p">];</span>
</span><span class='line'>   <span class="p">[</span><span class="n">task</span> <span class="n">release</span><span class="p">];</span>
</span><span class='line'>
</span><span class='line'>   <span class="k">return</span> <span class="p">[</span><span class="n">users</span> <span class="n">autorelease</span><span class="p">];</span>
</span><span class='line'><span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>

]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Debugging Preference Panes]]></title>
    <link href="http://milhouse.co.uk/blog/2009/05/09/debugging-preference-panes/"/>
    <updated>2009-05-09T00:00:00+01:00</updated>
    <id>http://milhouse.co.uk/blog/2009/05/09/debugging-preference-panes</id>
    <content type="html"><![CDATA[<p>I wrote my first OS X Preference Pane during the development of <strong>Authoritize</strong>. Creating the skeleton project is, as usual, very straightforward and you can immediately try out your PrefPane by dropping it into the ~/Library/PreferencePanes folder and opening System Preferences. It will appear in the Other category at the bottom of the System Preferences window.</p>

<p>But if you have a problem and need to resort to stepping through your code in the debugger it is not immediately obvious how to do so. Of course, <a href="http://www.google.com/search?hl=en&amp;client=safari&amp;rls=en-us&amp;q=debugging+prefpanes&amp;btnG=Search">Google knows</a>, but it took much longer than it should have done for me to drill down to find the answer. So to save you one or two mouse clicks here is how to do it, create a new custom executable (Project->New Custom Executable) and select the System Preferences app as the executable path.</p>

<p>That’s it, Simple eh?</p>
]]></content>
  </entry>
  
</feed>

