Rixstep
 About | ACP | Buy | Industry Watch | Learning Curve | News | Products | Search | Substack
Home » Learning Curve » CLIX: Legally Hacking

CLIX: Legally Hacking II

You have to jailbreak an iPhone or an iPad to have this much fun.


Get It

Try It

You have to jailbreak an iPhone or an iPad to have this much fun. And we all know how Big Brother Steve feels about that. Even though the courts declared it to be completely legal. Then too you might get a Rick Astley desktop wallpaper. But what if you're more into Samantha Fox?

There certainly are advantages to using a 'real' operating system even today.

'Mise en Place'

You need a few tools open to begin hacking away.

  1. CLIX. Open a new CLIX document window. Perhaps save it already for safety's sake. Choose a name and location all by yourself.
  2. Terminal.app. This is easiest in the beginning as you experiment with commands. Don't know where to find it? Download Xfile or look in /Applications/Utilities.
  3. Knowledge of how the system's 'manpage' readouts work. You don't use your scroll bar - only arrow up, arrow down, space, and 'q'.
  4. Your wits and your hacker attitude.

With everything in place, you're ready to start. Try to make useful commands.

Checking virtual memory: systems slow down as virtual memory on disk builds up. This slowdown may be noticeable. There can come a time when your best recourse is to reboot.

Navigate in Terminal to /private/var/vm. (This is easier with Xfile.) You'll see a 'sleep image' along with your swap file(s).

The swap files are your virtual memory - what the system uses when it's running out of RAM. Hard drives are slower than memory chips; and it takes time and number crunching to keep 'swapping' things in and out. So there's a lot of (relatively slow) disk activity where there's normally little or none at all as everything still fits in your RAM (fresh boot).

The system starts you out with a 64 MB swapfile ('swapfile0') on boot. Your swap will expand as your system sees the need for it. The next swap file ('swapfile1') will be the same size. After that, things go ballistic pretty fast. Soon you can be carrying around several gig of swap files. And that's when things can start to really slow down.

That's not an ideal system but it's the system you have. David Cutler's approach is a lot simpler and makes more sense: start by allocating a swap file equal in size to primary (RAM) memory and tack on a few MB for internal bookkeeping. (This system also makes process generation a lot faster. But that's another story entirely.)

Your system will at any rate have a single swap file on startup. You can see this by burrowing down to /private/var/vm with Xfile and then opening Terminal there. (The 'test drive' version of Xfile might not have this feature enabled; you either purchase the registered version or make do without. Few things are really free.)

Once at the command line in the correct directory, you issue the following command.

$ ls

You might get back something like this after a cold boot.

sleepimage	swapfile0

After a while, it might look something like this. Perhaps you've run your browser? And Adobe Flash?

sleepimage	swapfile0	swapfile1

The command ls lists the contents of directories. You just used ls in its most primitive form. It only lists the files present. It doesn't tell you anything about them. But a check for some of the opportunities with that tool may help. And it might be nice to be reminded of the disk space they take.

There's no built-in help with ls. Try it.

$ ls --help
ls: illegal option -- -
usage: ls [-ABCFGHLOPRSTUWabcdefghiklmnopqrstuwx1] [file ...]

So you try a manpage. That sure is a lot of shit.

$ man ls
LS(1)                     BSD General Commands Manual                    LS(1)

NAME
     ls -- list directory contents

SYNOPSIS
     ls [-ABCFGHLOPRSTUW@abcdefghiklmnopqrstuwx1] [file ...]

DESCRIPTION
     For each operand that names a file of a type other than directory, ls
     displays its name as well as any requested, associated information.  For
     each operand that names a file of type directory, ls displays the names
     of files contained within that directory, as well as any requested, asso-
     ciated information.

     If no operands are given, the contents of the current directory are dis-
     played.  If more than one operand is given, non-directory operands are
     displayed first; directory and non-directory operands are sorted sepa-
     rately and in lexicographical order.

     The following options are available:

     -@      Display extended attribute keys and sizes in long (-l) output.

     -1      (The numeric digit ``one''.)  Force output to be one entry per
             line.  This is the default when output is not to a terminal.

     -A      List all entries except for . and ...  Always set for the super-
             user.

     -a      Include directory entries whose names begin with a dot (.).

     -B      Force printing of non-printable characters (as defined by
             ctype(3) and current locale settings) in file names as \xxx,
             where xxx is the numeric value of the character in octal.

     -b      As -B, but use C escape codes whenever possible.

     -C      Force multi-column output; this is the default when output is to
             a terminal.

     -c      Use time when file status was last changed for sorting (-t) or
             long printing (-l).

     -d      Directories are listed as plain files (not searched recursively).

     -e      Print the Access Control List (ACL) associated with the file, if
             present, in long (-l) output.

     -F      Display a slash (`/') immediately after each pathname that is a
             directory, an asterisk (`*') after each that is executable, an at
             sign (`@') after each symbolic link, an equals sign (`=') after
             each socket, a percent sign (`%') after each whiteout, and a ver-
             tical bar (`|') after each that is a FIFO.

     -f      Output is not sorted.  This option turns on the -a option.

     -G      Enable colorized output.  This option is equivalent to defining
             CLICOLOR in the environment.  (See below.)

     -g      This option is only available for compatibility with POSIX; it is
             used to display the group name in the long (-l) format output
             (the owner name is suppressed).

     -H      Symbolic links on the command line are followed.  This option is
             assumed if none of the -F, -d, or -l options are specified.

     -h      When used with the -l option, use unit suffixes: Byte, Kilobyte,
             Megabyte, Gigabyte, Terabyte and Petabyte in order to reduce the
             number of digits to three or less using base 2 for sizes.

     -i      For each file, print the file's file serial number (inode num-
             ber).

     -k      If the -s option is specified, print the file size allocation in
             kilobytes, not blocks.  This option overrides the environment
             variable BLOCKSIZE.

     -L      Follow all symbolic links to final target and list the file or
             directory the link references rather than the link itself.  This
             option cancels the -P option.

     -l      (The lowercase letter ``ell''.)  List in long format.  (See
             below.)  If the output is to a terminal, a total sum for all the
             file sizes is output on a line before the long listing.

     -m      Stream output format; list files across the page, separated by
             commas.

     -n      Display user and group IDs numerically, rather than converting to
             a user or group name in a long (-l) output.  This option turns on
             the -l option.

     -O      Include the file flags in a long (-l) output.

     -o      List in long format, but omit the group id.

     -P      If argument is a symbolic link, list the link itself rather than
             the object the link references.  This option cancels the -H and
             -L options.

     -p      Write a slash (`/') after each filename if that file is a direc-
             tory.

     -q      Force printing of non-graphic characters in file names as the
             character `?'; this is the default when output is to a terminal.

     -R      Recursively list subdirectories encountered.

     -r      Reverse the order of the sort to get reverse lexicographical
             order or the oldest entries first (or largest files last, if com-
             bined with sort by size

     -S      Sort files by size

     -s      Display the number of file system blocks actually used by each
             file, in units of 512 bytes, where partial units are rounded up
             to the next integer value.  If the output is to a terminal, a
             total sum for all the file sizes is output on a line before the
             listing.  The environment variable BLOCKSIZE overrides the unit
             size of 512 bytes.

     -T      When used with the -l (lowercase letter ``ell'') option, display
             complete time information for the file, including month, day,
             hour, minute, second, and year.

     -t      Sort by time modified (most recently modified first) before sort-
             ing the operands by lexicographical order.

     -u      Use time of last access, instead of last modification of the file
             for sorting (-t) or long printing (-l).

     -U      Use time of file creation, instead of last modification for sort-
             ing (-t) or long output (-l).

     -v      Force unedited printing of non-graphic characters; this is the
             default when output is not to a terminal.

     -W      Display whiteouts when scanning directories.  (-S) flag).

     -w      Force raw printing of non-printable characters.  This is the
             default when output is not to a terminal.

     -x      The same as -C, except that the multi-column output is produced
             with entries sorted across, rather than down, the columns.

     The -1, -C, -x, and -l options all override each other; the last one
     specified determines the format used.

     The -c and -u options override each other; the last one specified deter-
     mines the file time used.

     The -B, -b, -w, and -q options all override each other; the last one
     specified determines the format used for non-printable characters.

     The -H, -L and -P options all override each other (either partially or
     fully); they are applied in the order specified.

     By default, ls lists one entry per line to standard output; the excep-
     tions are to terminals or when the -C or -x options are specified.

     File information is displayed with one or more s separating the
     information associated with the -i, -s, and -l options.

   The Long Format
     If the -l option is given, the following information is displayed for
     each file: file mode, number of links, owner name, group name, number of
     bytes in the file, abbreviated month, day-of-month file was last modi-
     fied, hour file last modified, minute file last modified, and the path-
     name.  In addition, for each directory whose contents are displayed, the
     total number of 512-byte blocks used by the files in the directory is
     displayed on a line by itself, immediately before the information for the
     files in the directory.  If the file or directory has extended
     attributes, the permissions field printed by the -l option is followed by
     a '@' character.  Otherwise, if the file or directory has extended secu-
     rity information (such as an access control list), the permissions field
     printed by the -l option is followed by a '+' character.

     If the modification time of the file is more than 6 months in the past or
     future, then the year of the last modification is displayed in place of
     the hour and minute fields.

     If the owner or group names are not a known user or group name, or the -n
     option is given, the numeric ID's are displayed.

     If the file is a character special or block special file, the major and
     minor device numbers for the file are displayed in the size field.  If
     the file is a symbolic link, the pathname of the linked-to file is pre-
     ceded by ``->''.

     The file mode printed under the -l option consists of the entry type,
     owner permissions, and group permissions.  The entry type character
     describes the type of file, as follows:

           b     Block special file.
           c     Character special file.
           d     Directory.
           l     Symbolic link.
           s     Socket link.
           p     FIFO.
           -     Regular file.

     The next three fields are three characters each: owner permissions, group
     permissions, and other permissions.  Each field has three character posi-
     tions:

           1.   If r, the file is readable; if -, it is not readable.

           2.   If w, the file is writable; if -, it is not writable.

           3.   The first of the following that applies:

                      S     If in the owner permissions, the file is not exe-
                            cutable and set-user-ID mode is set.  If in the
                            group permissions, the file is not executable and
                            set-group-ID mode is set.

                      s     If in the owner permissions, the file is exe-
                            cutable and set-user-ID mode is set.  If in the
                            group permissions, the file is executable and set-
                            group-ID mode is set.

                      x     The file is executable or the directory is search-
                            able.

                      -     The file is neither readable, writable, exe-
                            cutable, nor set-user-ID nor set-group-ID mode,
                            nor sticky.  (See below.)

                These next two apply only to the third character in the last
                group (other permissions).

                      T     The sticky bit is set (mode 1000), but not execute
                            or search permission.  (See chmod(1) or
                            sticky(8).)

                      t     The sticky bit is set (mode 1000), and is search-
                            able or executable.  (See chmod(1) or sticky(8).)

EXAMPLES
     The following is how to do an ls listing sorted by increasing size

           ls -lrS

DIAGNOSTICS
     The ls utility exits 0 on success, and >0 if an error occurs.

ENVIRONMENT
     The following environment variables affect the execution of ls:

     BLOCKSIZE       If the environment variable BLOCKSIZE is set, the block
                     counts (see -s) will be displayed in units of that size
                     block.

     CLICOLOR        Use ANSI color sequences to distinguish file types.  See
                     LSCOLORS below.  In addition to the file types mentioned
                     in the -F option some extra attributes (setuid bit set,
                     etc.) are also displayed.  The colorization is dependent
                     on a terminal type with the proper termcap(5) capabili-
                     ties.  The default ``cons25'' console has the proper
                     capabilities, but to display the colors in an xterm(1),
                     for example, the TERM variable must be set to
                     ``xterm-color''.  Other terminal types may require simi-
                     lar adjustments.  Colorization is silently disabled if
                     the output isn't directed to a terminal unless the
                     CLICOLOR_FORCE variable is defined.

     CLICOLOR_FORCE  Color sequences are normally disabled if the output isn't
                     directed to a terminal.  This can be overridden by set-
                     ting this flag.  The TERM variable still needs to refer-
                     ence a color capable terminal however otherwise it is not
                     possible to determine which color sequences to use.

     COLUMNS         If this variable contains a string representing a decimal
                     integer, it is used as the column position width for dis-
                     playing multiple-text-column output.  The ls utility cal-
                     culates how many pathname text columns to display based
                     on the width provided.  (See -C and -x.)

     LANG            The locale to use when determining the order of day and
                     month in the long -l format output.  See environ(7) for
                     more information.

     LSCOLORS        The value of this variable describes what color to use
                     for which attribute when colors are enabled with
                     CLICOLOR.  This string is a concatenation of pairs of the
                     format fb, where f is the foreground color and b is the
                     background color.

                     The color designators are as follows:

                           a     black
                           b     red
                           c     green
                           d     brown
                           e     blue
                           f     magenta
                           g     cyan
                           h     light grey
                           A     bold black, usually shows up as dark grey
                           B     bold red
                           C     bold green
                           D     bold brown, usually shows up as yellow
                           E     bold blue
                           F     bold magenta
                           G     bold cyan
                           H     bold light grey; looks like bright white
                           x     default foreground or background

                     Note that the above are standard ANSI colors.  The actual
                     display may differ depending on the color capabilities of
                     the terminal in use.

                     The order of the attributes are as follows:

                           1.   directory
                           2.   symbolic link
                           3.   socket
                           4.   pipe
                           5.   executable
                           6.   block special
                           7.   character special
                           8.   executable with setuid bit set
                           9.   executable with setgid bit set
                           10.  directory writable to others, with sticky bit
                           11.  directory writable to others, without sticky
                                bit

                     The default is "exfxcxdxbxegedabagacad", i.e. blue fore-
                     ground and default background for regular directories,
                     black foreground and red background for setuid executa-
                     bles, etc.

     LS_COLWIDTHS    If this variable is set, it is considered to be a colon-
                     delimited list of minimum column widths.  Unreasonable
                     and insufficient widths are ignored (thus zero signifies
                     a dynamically sized column).  Not all columns have
                     changeable widths.  The fields are, in order: inode,
                     block count, number of links, user name, group name,
                     flags, file size, file name.

     TERM            The CLICOLOR functionality depends on a terminal type
                     with color capabilities.

     TZ              The timezone to use when displaying dates.  See
                     environ(7) for more information.

COMPATIBILITY
     The group field is now automatically included in the long listing for
     files in order to be compatible with the IEEE Std 1003.2 (``POSIX.2'')
     specification.

LEGACY DESCRIPTION
     In legacy mode, the -f option does not turn on the -a option and the -g,
     -n, and -o options do not turn on the -l option.

     Also, the -o option causes the file flags to be included in a long (-l)
     output; there is no -O option.

     When -H is specified (and not overridden by -L or -P) and a file argument
     is a symlink that resolves to a non-directory file, the output will
     reflect the nature of the link, rather than that of the file.  In legacy
     operation, the output will describe the file.

     For more information about legacy mode, see compat(5).

SEE ALSO
     chflags(1), chmod(1), sort(1), xterm(1), compat(5), termcap(5),
     symlink(7), sticky(8)

STANDARDS
     The ls utility conforms to IEEE Std 1003.1-2001 (``POSIX.1'').

HISTORY
     An ls command appeared in Version 1 AT&T UNIX.

BUGS
     To maintain backward compatibility, the relationships between the many
     options are quite complex.

BSD                              May 19, 2002                              BSD

Yep, that sure is a lot of shit. But that's what hacking's about. For ls is one of the most powerful commands in the Unix arsenal. And it's said that if you understand ls, then you understand Unix. (It's been said by the engineers at Rixstep. They should know.)

So what do you add to ls to find out what's wasted on swap? This part is important.

     -l      (The lowercase letter ``ell''.)  List in long format.  (See
             below.)  If the output is to a terminal, a total sum for all the
             file sizes is output on a line before the long listing.

Try it.

$ ls -l
total 2228224
-rw------T  1 root  wheel  1073741824 May  9 13:55 sleepimage
-rw-------  1 root  wheel    67108864 May  8 22:33 swapfile0

Now you can see the sizes in the centre of your readout.

You're going to leave 'sleepimage' alone. You could remove it and your system should be fine, but you'd see it regenerated in no time. (The system updates it continually - it's a complete map of your RAM.) And with a single swap file you're sitting good.

Play around a bit more (with Xcode, Interface Builder, Firefox, or anything from Adobe) and you'll get something like this.

$ ls -l
total 2359296
-rw------T  1 root  wheel  1073741824 May  9 13:55 sleepimage
-rw-------  1 root  wheel    67108864 May  8 22:33 swapfile0
-rw-------  1 root  wheel    67108864 May  9 16:09 swapfile1

Perhaps you don't want the 'sleepimage' listed all the time? Efficiency being the word?

$ ls -l swapfile*
-rw-------  1 root  wheel  67108864 May  8 22:33 swapfile0
-rw-------  1 root  wheel  67108864 May  9 16:09 swapfile1

Now you got rid of that 'total' too. Things are improving. But perhaps you want to go the other way - list everything?

     -a      Include directory entries whose names begin with a dot (.).

Try it.

$ ls -al
total 2359296
drwxr-xr-x   5 root  wheel         170 May  8 22:45 .
drwxr-xr-x  26 root  wheel         884 Sep 14  2009 ..
-rw------T   1 root  wheel  1073741824 May  9 13:55 sleepimage
-rw-------   1 root  wheel    67108864 May  8 22:33 swapfile0
-rw-------   1 root  wheel    67108864 May  9 16:09 swapfile1

There's a lot of nice juicy info there. Sizes, dates, ownership - and the two 'dot' directories.

One of the above commands is bound to suit your tastes. So it's time to make a CLIX command.

  1. Open a blank CLIX command sheet. This is the 'Add' command off the 'Edit' menu.
  2. Give the command a title. (Any title. This can be changed later. It can all be changed later.)
  3. Give it a 'category'. The category is entirely arbitrary. It's up to you. CLIX will use a secondary sort on this column if you're sorting by the first ('title') column so it pays to be consistent.
  4. Add a description. Or not. Again: it's entirely up to you. And it can be changed later.
  5. Add the command line. This is very important - and you can't use localised versions anymore: you have to use full paths. But a bit of a help: /var is actually a symlink that resolves to /private/var so you can save yourself a bit of typing. See the illustration below.

  6. Run the command once before clicking 'save' so you know it works correctly. You're not running much risk you'll wreck something at this stage if you type it wrong. So don't be afraid.
  7. Save the command to the file and save the file to disk once it's running correctly.

Additional Assistance

CLIX can help you quite a lot in your hacking. Double clicks and the option key are your friends. Open that command again ('Edit' from the 'Edit' menu) and try option-double-clicking things on that sheet. You should find that you don't get a reaction unless you're clicking inside the 'command line' field. Some double clicks will yield only the following.



But double-click 'ls' and you'll see something different.



'ls' is a Unix command aka a Unix program file aka a Unix utility in Bell Labs speak or a 'tool' in Apple speak. It's pretty easy to find on disk as well. Still got your Terminal open?

$ whereis ls
/bin/ls

So you could use the 'ls' command on itself.

$ /bin/ls /bin/ls
/bin/ls

Or for more info:

$ /bin/ls -l /bin/ls
-r-xr-xr-x  1 root  wheel  80688 Jul 14  2009 /bin/ls

Back to work. Time to find something else that's useful. Listing the contents of /private/tmp can be useful at times. Some applications leave junk behind there. This is normally cleaned out at every reboot but still and all. You use the same procedure as last time - you simply want to list the contents. A hint: even though /tmp is also a symlink like /var, you have to use the full /private/tmp path. (Perhaps you'll be able to explain that after a while.)



Applications will normally use their own directories under /tmp. But the ones in the illustration above aren't to be messed with. The same goes for the socket file 'icssuis501'. Don't touch them.

OS X has more than /tmp today for storing temporary files and caches. Most of these files are generated by the system. Try the following command.

$ ls -lR /var/folders

There are some hairy subdirectories there. Ignore the ones that give you 'permission denied'. Look only at the ones where you get to see something.

And here's something you may not have seen before. (And you won't have unless you're using Xfile.) It's the collection of 'device files' built by your system at each startup.

$ ls -alR /dev

The 'R' (upper case) again makes the listing a recursive one. You might see something funny at the tail end of that listing.

/dev/fd/3:
ls: 3: Not a directory
ls: 4: directory causes a cycle

Yup, that means Apple are up to some funky stuff in there. Go back a bit further and you may see something else suspicious.

/dev/fd:
total 0
crw--w----   1 rixstep  tty     16,   0 May  9 20:26 0
crw--w----   1 rixstep  tty     16,   0 May  9 20:26 1
crw--w----   1 rixstep  tty     16,   0 May  9 20:26 2
dr--------  15 rixstep  staff       510 May  1  2010 3
dr--r--r--   1 root     wheel         0 May  9 17:56 4

Suspicious? Yes. There aren't any 'dot' directories. List the same thing with Xfile and you'll get something else; list it again with GDE and you'll get something else again. Funky stuff. There are several levels of file listing APIs in Unix - Apple are putting in a bit of their own non-portable code between them.

You'll notice as well they have comma separated values instead of the standard size field. These values are the major and minor device numbers. They show up in the ACP framework info sheet as well - but hardly anywhere else.

The 'inode'

Unix has a clever thing Apple can't handle: the hard link.

Not to say Apple engineers haven't struggled with this and/or done the best they can, but when you're told HFS will simply not go away then you're pretty much stuck in it.

One of Ken Thompson's many brilliant ideas was that directories should contain no more than filenames and hooks into volume control blocks. Further: volume control blocks shouldn't contain file names.

This is an efficient proposal but it also offers more than perhaps one originally imagined. For if volume control blocks don't have file names, then it's theoretically possible for multiple file paths to point to the same information in the volume control block. In other words: you can have multiple names for the same file.

This turns out to have several benefits. You can do more 'legal hacking' with CLIX to see some of these benefits.

Navigate in Terminal to /bin. Do this either with Xfile or by typing the path in on your own ('cd /bin''). Do a long listing.

$ ls -al /bin
total 8640
drwxr-xr-x  39 root  wheel     1326 Mar 30  2010 .
drwxrwxr-t  31 root  admin     1122 May 20 15:57 ..
-r-xr-xr-x   2 root  wheel    63184 May 18  2009 [
-rwxr-xr-x   1 root  wheel  1346544 Feb 11  2010 bash
-r-xr-xr-x   1 root  wheel    44272 May 18  2009 cat
-r-xr-xr-x   1 root  wheel    62656 Jul 14  2009 chmod
-r-xr-xr-x   1 root  wheel    57632 Jul 14  2009 cp
-rwxr-xr-x   2 root  wheel   767200 Feb 11  2010 csh
-r-xr-xr-x   1 root  wheel    80848 May 18  2009 date
-r-xr-xr-x   1 root  wheel    60992 Jul 14  2009 dd
-r-xr-xr-x   1 root  wheel    48368 Jul 14  2009 df
-r-xr-xr-x   1 root  wheel    50816 May 19  2009 domainname
-r-xr-xr-x   1 root  wheel    50704 May 18  2009 echo
-r-xr-xr-x   1 root  wheel   117504 May 18  2009 ed
-r-xr-xr-x   1 root  wheel    67552 May 18  2009 expr
-r-xr-xr-x   1 root  wheel    50816 May 18  2009 hostname
-r-xr-xr-x   1 root  wheel    51024 May 18  2009 kill
-r-xr-xr-x   1 root  wheel  2186880 May 19  2009 ksh
-r-xr-xr-x   1 root  wheel   246720 Feb 11  2010 launchctl
-r-xr-xr-x   2 root  wheel    39552 Jul 14  2009 link
-r-xr-xr-x   2 root  wheel    39552 Jul 14  2009 ln
-r-xr-xr-x   1 root  wheel    80688 Jul 14  2009 ls
-r-xr-xr-x   1 root  wheel    35072 Jul 14  2009 mkdir
-r-xr-xr-x   1 root  wheel    44848 Jul 14  2009 mv
-r-xr-xr-x   1 root  wheel   238576 Jul 14  2009 pax
-r-sr-xr-x   1 root  wheel   134816 May 18  2009 ps
-r-xr-xr-x   1 root  wheel    50784 May 18  2009 pwd
-r-sr-xr-x   1 root  wheel    93376 May 19  2009 rcp
-r-xr-xr-x   2 root  wheel    44448 Jul 14  2009 rm
-r-xr-xr-x   1 root  wheel    34624 Jul 14  2009 rmdir
-r-xr-xr-x   1 root  wheel  1346624 Feb 11  2010 sh
-r-xr-xr-x   1 root  wheel    50752 May 18  2009 sleep
-r-xr-xr-x   1 root  wheel    88704 May 18  2009 stty
-r-xr-xr-x   1 root  wheel    50512 Feb 11  2010 sync
-rwxr-xr-x   2 root  wheel   767200 Feb 11  2010 tcsh
-r-xr-xr-x   2 root  wheel    63184 May 18  2009 test
-r-xr-xr-x   2 root  wheel    44448 Jul 14  2009 unlink
-r-xr-xr-x   1 root  wheel    50864 Feb 11  2010 wait4path
-rwxr-xr-x   1 root  wheel  1597200 May 11  2009 zsh

Now you might - if you're industrious - calculate the actual disk blocks used by each of those files and see if the total is 8640. But there's an easier way to see if something's awry here.

     -i      For each file, print the file's file serial number (inode num-
             ber).

The inode is a number that uniquely identifies a file on a volume. No two files can have the same inode. HFS actually discards inodes after they've been used and ultimately 'rolls over' when it reaches the highest possible value and looks for free ones the second time around. (But it didn't always do this. Something Apple had to fix fast for OS X Server. Ouch.)

So supposing files in /bin are not unique, you can perform a new listing with the '-i' switch added.

$ ls -ail /bin
total 8640
  24031 drwxr-xr-x  39 root  wheel     1326 Mar 30  2010 .
      2 drwxrwxr-t  31 root  admin     1122 May 20 15:57 ..
  25655 -r-xr-xr-x   2 root  wheel    63184 May 18  2009 [
2693806 -rwxr-xr-x   1 root  wheel  1346544 Feb 11  2010 bash
  25804 -r-xr-xr-x   1 root  wheel    44272 May 18  2009 cat
  24717 -r-xr-xr-x   1 root  wheel    62656 Jul 14  2009 chmod
  24718 -r-xr-xr-x   1 root  wheel    57632 Jul 14  2009 cp
2693807 -rwxr-xr-x   2 root  wheel   767200 Feb 11  2010 csh
  25656 -r-xr-xr-x   1 root  wheel    80848 May 18  2009 date
  24719 -r-xr-xr-x   1 root  wheel    60992 Jul 14  2009 dd
  24720 -r-xr-xr-x   1 root  wheel    48368 Jul 14  2009 df
  25635 -r-xr-xr-x   1 root  wheel    50816 May 19  2009 domainname
  25657 -r-xr-xr-x   1 root  wheel    50704 May 18  2009 echo
  25805 -r-xr-xr-x   1 root  wheel   117504 May 18  2009 ed
  25658 -r-xr-xr-x   1 root  wheel    67552 May 18  2009 expr
  25659 -r-xr-xr-x   1 root  wheel    50816 May 18  2009 hostname
  25660 -r-xr-xr-x   1 root  wheel    51024 May 18  2009 kill
  24921 -r-xr-xr-x   1 root  wheel  2186880 May 19  2009 ksh
2693808 -r-xr-xr-x   1 root  wheel   246720 Feb 11  2010 launchctl
  24721 -r-xr-xr-x   2 root  wheel    39552 Jul 14  2009 link
  24721 -r-xr-xr-x   2 root  wheel    39552 Jul 14  2009 ln
  24724 -r-xr-xr-x   1 root  wheel    80688 Jul 14  2009 ls
  24725 -r-xr-xr-x   1 root  wheel    35072 Jul 14  2009 mkdir
  24726 -r-xr-xr-x   1 root  wheel    44848 Jul 14  2009 mv
  24727 -r-xr-xr-x   1 root  wheel   238576 Jul 14  2009 pax
  24032 -r-sr-xr-x   1 root  wheel   134816 May 18  2009 ps
  25661 -r-xr-xr-x   1 root  wheel    50784 May 18  2009 pwd
  25636 -r-sr-xr-x   1 root  wheel    93376 May 19  2009 rcp
  24728 -r-xr-xr-x   2 root  wheel    44448 Jul 14  2009 rm
  24729 -r-xr-xr-x   1 root  wheel    34624 Jul 14  2009 rmdir
2693809 -r-xr-xr-x   1 root  wheel  1346624 Feb 11  2010 sh
  25662 -r-xr-xr-x   1 root  wheel    50752 May 18  2009 sleep
  24033 -r-xr-xr-x   1 root  wheel    88704 May 18  2009 stty
2693810 -r-xr-xr-x   1 root  wheel    50512 Feb 11  2010 sync
2693807 -rwxr-xr-x   2 root  wheel   767200 Feb 11  2010 tcsh
  25655 -r-xr-xr-x   2 root  wheel    63184 May 18  2009 test
  24728 -r-xr-xr-x   2 root  wheel    44448 Jul 14  2009 unlink
2693813 -r-xr-xr-x   1 root  wheel    50864 Feb 11  2010 wait4path
  26148 -rwxr-xr-x   1 root  wheel  1597200 May 11  2009 zsh

The inodes are listed in the leftmost column. This information, together with what used to be in the second but is now in the third column, should give you all you need to know. The third column is namely the number of links.

Directories always have at least two links - to '.' and '..'. The link count is comparable to Apple's HFS 'valence' field. But HFS doesn't have the 'dot' directories and so the valence should differ by 2.

Regular files that have a link count greater than one are hard linked (multi-linked in Apple parlance). Go through your latest listing and see which files are multi-linked and see if you can locate their 'alter egos'. Note: a hard link to a file need not be in the same directory; it can be anywhere on the same volume.

You should find four (4) pairs of multi-linked files.

[test
cshtcsh
linkln
rmunlink

So why the hard links?

[ and test are the invention of Steve Bourne who built the original sh shell (command interpreter). csh and tcsh are both the same 'shell' based on the original work at UC Berkeley. But the program behaves differently depending on the name you use to start it.

All Unix (C) programs get a list of 'arguments' used to invoke them; the very first argument is the path to the program itself. So csh/tcsh can see what was used to start things up and adjust behaviour accordingly.

Does this mean there are two programs in one? That doesn't sound particularly efficient. But no, it means there are certain features of the one program that will not be available in the other. And vice versa. So the technique actually cuts down on use of disk space and make lives a lot easier across the board.

link and ln are another such example. Check out the manpage for either and you'll see they respond to different syntax.

LN(1)                     BSD General Commands Manual                    LN(1)

NAME
     link, ln -- make links

SYNOPSIS
     ln [-Ffhinsv] source_file [target_file]
     ln [-Ffhinsv] source_file ... target_dir
     link source_file target_file

link is greatly simplified. See the end of the file for more of a clue.

STANDARDS
     The ln utility conforms to IEEE Std 1003.2-1992 (``POSIX.2'').

     The simplified link command conforms to Version 2 of the Single UNIX
     Specification (``SUSv2'').

Then a bit above you'll find this.

     When the utility is called as link, exactly two arguments must be sup-
     plied, neither of which may specify a directory.  No options may be sup-
     plied in this simple mode of operation, which performs a link(2) opera-
     tion using the two passed arguments.

So link is a bit of a 'Mickey Mouse' version of the real thing. (Note ln can create both hard links and symbolic links.)

The final pair is rm and unlink. Here too there's a difference in functionality depending on how you access the program.

RM(1)                     BSD General Commands Manual                    RM(1)

NAME
     rm, unlink -- remove directory entries

SYNOPSIS
     rm [-dfiPRrvW] file ...
     unlink file

DESCRIPTION
     The rm utility attempts to remove the non-directory type files specified
     on the command line.  If the permissions of the file do not permit writ-
     ing, and the standard input device is a terminal, the user is prompted
     (on the standard error output) for confirmation.

     The options are as follows:

     -d          Attempt to remove directories as well as other types of
                 files.

     -f          Attempt to remove the files without prompting for confirma-
                 tion, regardless of the file's permissions.  If the file does
                 not exist, do not display a diagnostic message or modify the
                 exit status to reflect an error.  The -f option overrides any
                 previous -i options.

     -i          Request confirmation before attempting to remove each file,
                 regardless of the file's permissions, or whether or not the
                 standard input device is a terminal.  The -i option overrides
                 any previous -f options.

     -P          Overwrite regular files before deleting them.  Files are
                 overwritten three times, first with the byte pattern 0xff,
                 then 0x00, and then 0xff again, before they are deleted.

     -R          Attempt to remove the file hierarchy rooted in each file
                 argument.  The -R option implies the -d option.  If the -i
                 option is specified, the user is prompted for confirmation
                 before each directory's contents are processed (as well as
                 before the attempt is made to remove the directory).  If the
                 user does not respond affirmatively, the file hierarchy
                 rooted in that directory is skipped.

     -r          Equivalent to -R.

     -v          Be verbose when deleting files, showing them as they are
                 removed.

     -W          Attempt to undelete the named files.  Currently, this option
                 can only be used to recover files covered by whiteouts.

     The rm utility removes symbolic links, not the files referenced by the
     links.

     It is an error to attempt to remove the files ``.'' or ``..''.

     When the utility is called as unlink, only one argument, which must not
     be a directory, may be supplied.  No options may be supplied in this sim-
     ple mode of operation, which performs an unlink(2) operation on the
     passed argument.

     The rm utility exits 0 if all of the named files or file hierarchies were
     removed, or if the -f option was specified and all of the existing files
     or file hierarchies were removed.  If an error occurs, rm exits with a
     value >0.

NOTE
     The rm command uses getopt(3) to parse its arguments, which allows it to
     accept the `--' option which will cause it to stop processing flag
     options at that point.  This will allow the removal of file names that
     begin with a dash (`-').  For example:
           rm -- -filename
     The same behavior can be obtained by using an absolute or relative path
     reference.  For example:
           rm /home/user/-filename
           rm ./-filename

SEE ALSO
     rmdir(1), undelete(2), unlink(2), fts(3), getopt(3), symlink(7)

BUGS
     The -P option assumes that the underlying file system is a fixed-block
     file system.  In addition, only regular files are overwritten, other
     types of files are not.

COMPATIBILITY
     The rm utility differs from historical implementations in that the -f
     option only masks attempts to remove non-existent files instead of mask-
     ing a large variety of errors.  The -v option is non-standard and its use
     in scripts is not recommended.

     Also, historical BSD implementations prompted on the standard output, not
     the standard error output.

STANDARDS
     The rm command is almost IEEE Std 1003.2 (``POSIX.2'') compatible, except
     that POSIX requires rm to act like rmdir(1) when the file specified is a
     directory.  This implementation requires the -d option if such behavior
     is desired.  This follows the historical behavior of rm with respect to
     directories.

     The simplified unlink command conforms to Version 2 of the Single UNIX
     Specification (``SUSv2'').

HISTORY
     A rm command appeared in Version 1 AT&T UNIX.

BSD                            January 28, 1999                            BSD

Again there's both a 'grownup' version (rm) and a 'Mickey Mouse version' (unlink) available.

     The simplified unlink command conforms to Version 2 of the Single UNIX
     Specification (``SUSv2'').

Both versions seem to be capable of performing the basic operation - removing a link to ('unlinking') a file.

Neither rm nor unlink remove a file from disk - all they do is remove a link. The file system itself will do this once the link count gets to zero. The file remains as long as there's still a link to it somewhere. All rm and unlink do is remove a file name from a directory - and that in turn gets the file system to decrement the link count.

Kernel Messages

The following command requires sudo. sudo was developed for OpenBSD but has since propagated to other BSDs as well. sudo gives you a means of escalating your privileges to root without actually enabling the root account. And that's a Good Thing™.

You normally have to be a member of the admin group to use sudo. (The first registered user on a system is a member.)

You use sudo by simply prefacing your command with the word. You're prompted for (what's normally) your admin password and then your command runs.

dmesg is a program that displays your system message buffer. You see this if you start your system in 'single user mode'; otherwise it's hidden. Try running it without sudo.

$ dmesg
Unable to obtain kernel buffer: Operation not permitted
usage: sudo dmesg

So try running it with sudo instead. (And no, you're not going to harm your computer no matter what you do.)

$ sudo dmesg
Password:
IOAPIC: Version 0x20 Vectors 64:87
ACPI: System State [S0 S3 S4 S5] (S3)
mbinit: done (64 MB memory set for mbuf pool)
Waiting on IOProviderClassIOResourcesIOResourceMatchboot-uuid-media
com.apple.AppleFSCompressionTypeZlib load succeeded
AppleIntelCPUPowerManagementClient: ready
Got boot device = IOService:/AppleACPIPlatformExpert/PCI0@0/AppleACPIPCI/SATA@1F,2/AppleAHCI/PRT2@2/IOAHCIDevice@0/AppleAHCIDiskDriver/IOAHCIBlockStorageDevice/IOBlockStorageDriver/FUJITSU MHW2120BH Media/IOGUIDPartitionScheme/Untitled@4
BSD root: disk0s4, major 14, minor 4
[Bluetooth::CSRHIDTransition] switchToHCIMode (legacy)
[Bluetooth::CSRHIDTransition] transition complete.
CSRUSBBluetoothHCIController::setupHardware super returned 0
AppleIntelCPUPowerManagement: initialization complete
Waiting for DSMOS...
IPv6 packet filtering initialized, default to accept, logging disabled
jnl: disk0s2: journal start/end pointers reset! (jnl 0x30e3e04; s 0x1aa200 e 0x1aa200)
Atheros: mac 12.2 phy 8.1 radio 12.0
Previous Shutdown Cause: 0
Warning - kext com.apple.iokit.CHUDProf has immediate dependencies on both com.apple.kernel* and com.apple.kpi.* components; use only one style.
AppleYukon2: Marvell Yukon Gigabit Adapter 88E8053 Singleport Copper SA
AppleYukon2: RxRingSize <= 1024, TxRingSize 256, RX_MAX_LE 1024, TX_MAX_LE 768, ST_MAX_LE 3328
DSMOS has arrived
IO80211Controller::dataLinkLayerAttachComplete():  adding AppleEFINVRAM notification
en1: Supported channels 1 2 3 4 5 6 7 8 9 10 11 12 13 36 40 44 48 52 56 60 64 100 104 108 112 116 120 124 128 132 136 140
AirPort: Link Up on en1
AirPort: RSN handshake complete on en1
hibernate image path: /var/vm/sleepimage
sizeof(IOHibernateImageHeader) == 512
Opened file /var/vm/sleepimage, size 1073741824, partition base 0xe05cc0000, maxio 400000
hibernate image major 14, minor 4, blocksize 512, pollers 5
hibernate_alloc_pages flags 00000000, gobbling 0 pages
hibernate_page_list_setall start
hibernate_page_list_setall time: 88 ms
pages 232335, wire 39100, act 42998, inact 595, spec 81, zf 2406, throt 0, could discard act 19333 inact 33143 purgeable 731 spec 93948
hibernate_page_list_setall found pageCount 85180
IOHibernatePollerOpen, ml_get_interrupts_enabled 0
IOHibernatePollerOpen(0)
writing 84957 pages
image1Size 73775104
PMStats: Hibernate write took 4542 ms
all time: 4542 ms, comp time: 637 ms, deco time: 0 ms,
image 151337984, uncompressed 348311552 (85037), compressed 150473776 (43%), sum1 173a5b4c, sum2 5f51712a
hibernate_write_image done(0)
sleep
Wake reason = EC LID0
System Wake
Previous Sleep Cause: 0
getWOW_PARAMETERS: Can't set wow params. Wow is not supported
getWOW_PARAMETERS: Can't set wow params. Wow is not supported

dmesg doesn't cache the entire buffer, only the most recent 4 KB (4096 bytes) of it. So the beginning of your readout might be a bit funky. The buffer's initialised on startup and should show you interesting things about your system (and even engineering shortcomings).

Use of sudo is always wrought with danger. But running your system as if you own it is even worse. Escalating to root only as needed spares your system damage from interlopers and also casual input error on your own behalf.

Be careful when testing commands that use sudo: try them first without sudo if at all possible. Use predefined CLIX commands. Be sure your admin password is secure and change it regularly.

sudo and CLIX

A website long forgotten posted a note shortly after the arrival of 10.6 Snow Leopard that CLIX wasn't compatible with the new system. The syntax for use of sudo in similar situations had changed. The program didn't need to change at all. Herp derp.

And it had nothing to do with Snow Leopard either. Herp derp. It had to do with a new version of sudo which Apple still hadn't passed onto their users. See the pertinent section of sudo's manpage.

       -S          The -S (stdin) option causes sudo to read the password from
                   the standard input instead of the terminal device.

As CLIX is not Terminal, this is where sudo will read your password. The manpage for sudo reveals a lot about how your system works, so it's a good read when you have the time.

$ man sudo
SUDO(8)                      MAINTENANCE COMMANDS                      SUDO(8)



NAME
       sudo - execute a command as another user

SYNOPSIS
       sudo [-n] -h | -K | -k | -L | -V | -v

       sudo -l[l] [-AnS] [-g groupname|#gid] [-U username] [-u username|#uid]
       [command]

       sudo [-AbEHnPS] [-C fd] [-g groupname|#gid] [-p prompt]
       [-u username|#uid] [VAR=value] [-i | -s] [command]

       sudoedit [-AnS] [-C fd] [-g groupname|#gid] [-p prompt]
       [-u username|#uid] file ...

DESCRIPTION
       sudo allows a permitted user to execute a command as the superuser or
       another user, as specified in the sudoers file.  The real and effective
       uid and gid are set to match those of the target user as specified in
       the passwd file and the group vector is initialized based on the group
       file (unless the -P option was specified).  If the invoking user is
       root or if the target user is the same as the invoking user, no
       password is required.  Otherwise, sudo requires that users authenticate
       themselves with a password by default (NOTE: in the default
       configuration this is the user's password, not the root password).
       Once a user has been authenticated, a timestamp is updated and the user
       may then use sudo without a password for a short period of time (5
       minutes unless overridden in sudoers).

       When invoked as sudoedit, the -e option (described below), is implied.

       sudo determines who is an authorized user by consulting the file
       /private/etc//sudoers.  By running sudo with the -v option, a user can
       update the time stamp without running a command. The password prompt
       itself will also time out if the user's password is not entered within
       0 minutes (unless overridden via sudoers).

       If a user who is not listed in the sudoers file tries to run a command
       via sudo, mail is sent to the proper authorities, as defined at
       configure time or in the sudoers file (defaults to root).  Note that
       the mail will not be sent if an unauthorized user tries to run sudo
       with the -l or -v option.  This allows users to determine for
       themselves whether or not they are allowed to use sudo.

       If sudo is run by root and the SUDO_USER environment variable is set,
       sudo will use this value to determine who the actual user is.  This can
       be used by a user to log commands through sudo even when a root shell
       has been invoked.  It also allows the -e option to remain useful even
       when being run via a sudo-run script or program.  Note however, that
       the sudoers lookup is still done for root, not the user specified by
       SUDO_USER.

       sudo can log both successful and unsuccessful attempts (as well as
       errors) to syslog(3), a log file, or both.  By default sudo will log
       via syslog(3) but this is changeable at configure time or via the
       sudoers file.

OPTIONS
       sudo accepts the following command line options:

       -A          Normally, if sudo requires a password, it will read it from
                   the current terminal.  If the -A (askpass) option is
                   specified, a helper program is executed to read the user's
                   password and output the password to the standard output.
                   If the SUDO_ASKPASS environment variable is set, it
                   specifies the path to the helper program.  Otherwise, the
                   value specified by the askpass option in sudoers(5) is
                   used.

       -b          The -b (background) option tells sudo to run the given
                   command in the background.  Note that if you use the -b
                   option you cannot use shell job control to manipulate the
                   process.

       -C fd       Normally, sudo will close all open file descriptors other
                   than standard input, standard output and standard error.
                   The -C (close from) option allows the user to specify a
                   starting point above the standard error (file descriptor
                   three).  Values less than three are not permitted.  This
                   option is only available if the administrator has enabled
                   the closefrom_override option in sudoers(5).

       -E          The -E (preserve environment) option will override the
                   env_reset option in sudoers(5)).  It is only available when
                   either the matching command has the SETENV tag or the
                   setenv option is set in sudoers(5).

       -e          The -e (edit) option indicates that, instead of running a
                   command, the user wishes to edit one or more files.  In
                   lieu of a command, the string "sudoedit" is used when
                   consulting the sudoers file.  If the user is authorized by
                   sudoers the following steps are taken:

                   1.  Temporary copies are made of the files to be edited
                       with the owner set to the invoking user.

                   2.  The editor specified by the SUDO_EDITOR, VISUAL or
                       EDITOR environment variables is run to edit the
                       temporary files.  If none of SUDO_EDITOR, VISUAL or
                       EDITOR are set, the first program listed in the editor
                       sudoers variable is used.

                   3.  If they have been modified, the temporary files are
                       copied back to their original location and the
                       temporary versions are removed.

                   If the specified file does not exist, it will be created.
                   Note that unlike most commands run by sudo, the editor is
                   run with the invoking user's environment unmodified.  If,
                   for some reason, sudo is unable to update a file with its
                   edited version, the user will receive a warning and the
                   edited copy will remain in a temporary file.

       -g group    Normally, sudo sets the primary group to the one specified
                   by the passwd database for the user the command is being
                   run as (by default, root).  The -g (group) option causes
                   sudo to run the specified command with the primary group
                   set to group.  To specify a gid instead of a group name,
                   use #gid.  When running commands as a gid, many shells
                   require that the '#' be escaped with a backslash ('\').  If
                   no -u option is specified, the command will be run as the
                   invoking user (not root).  In either case, the primary
                   group will be set to group.

       -H          The -H (HOME) option sets the HOME environment variable to
                   the homedir of the target user (root by default) as
                   specified in passwd(5).  By default, sudo does not modify
                   HOME (see set_home and always_set_home in sudoers(5)).

       -h          The -h (help) option causes sudo to print a usage message
                   and exit.

       -i [command]
                   The -i (simulate initial login) option runs the shell
                   specified in the passwd(5) entry of the target user as a
                   login shell.  This means that login-specific resource files
                   such as .profile or .login will be read by the shell.  If a
                   command is specified, it is passed to the shell for
                   execution.  Otherwise, an interactive shell is executed.
                   sudo attempts to change to that user's home directory
                   before running the shell.  It also initializes the
                   environment, leaving DISPLAY and TERM unchanged, setting
                   HOME, SHELL, USER, LOGNAME, and PATH, as well as the
                   contents of /etc/environment on Linux and AIX systems.  All
                   other environment variables are removed.

       -K          The -K (sure kill) option is like -k except that it removes
                   the user's timestamp entirely.  Like -k, this option does
                   not require a password.

       -k          The -k (kill) option to sudo invalidates the user's
                   timestamp by setting the time on it to the Epoch.  The next
                   time sudo is run a password will be required.  This option
                   does not require a password and was added to allow a user
                   to revoke sudo permissions from a .logout file.

       -L          The -L (list defaults) option will list out the parameters
                   that may be set in a Defaults line along with a short
                   description for each.  This option is useful in conjunction
                   with grep(1).

       -l[l] [command]
                   If no command is specified, the -l (list) option will list
                   the allowed (and forbidden) commands for the invoking user
                   (or the user specified by the -U option) on the current
                   host.  If a command is specified and is permitted by
                   sudoers, the fully-qualified path to the command is
                   displayed along with any command line arguments.  If
                   command is specified but not allowed, sudo will exit with a
                   status value of 1.  If the -l option is specified with an l
                   argument (i.e. -ll), or if -l is specified multiple times,
                   a longer list format is used.

       -n          The -n (non-interactive) option prevents sudo from
                   prompting the user for a password.  If a password is
                   required for the command to run, sudo will display an error
                   messages and exit.

       -P          The -P (preserve group vector) option causes sudo to
                   preserve the invoking user's group vector unaltered.  By
                   default, sudo will initialize the group vector to the list
                   of groups the target user is in.  The real and effective
                   group IDs, however, are still set to match the target user.

       -p prompt   The -p (prompt) option allows you to override the default
                   password prompt and use a custom one.  The following
                   percent (`%') escapes are supported:

                   %H  expanded to the local hostname including the domain
                       name (on if the machine's hostname is fully qualified
                       or the fqdn sudoers option is set)

                   %h  expanded to the local hostname without the domain name

                   %p  expanded to the user whose password is being asked for
                       (respects the rootpw, targetpw and runaspw flags in
                       sudoers)

                   %U  expanded to the login name of the user the command will
                       be run as (defaults to root)

                   %u  expanded to the invoking user's login name

                   %%  two consecutive % characters are collapsed into a
                       single % character

                   The prompt specified by the -p option will override the
                   system password prompt on systems that support PAM unless
                   the passprompt_override flag is disabled in sudoers.

       -S          The -S (stdin) option causes sudo to read the password from
                   the standard input instead of the terminal device.

       -s [command]
                   The -s (shell) option runs the shell specified by the SHELL
                   environment variable if it is set or the shell as specified
                   in passwd(5).  If a command is specified, it is passed to
                   the shell for execution.  Otherwise, an interactive shell
                   is executed.

       -U user     The -U (other user) option is used in conjunction with the
                   -l option to specify the user whose privileges should be
                   listed.  Only root or a user with sudo ALL on the current
                   host may use this option.

       -u user     The -u (user) option causes sudo to run the specified
                   command as a user other than root.  To specify a uid
                   instead of a user name, use #uid.  When running commands as
                   a uid, many shells require that the '#' be escaped with a
                   backslash ('\').  Note that if the targetpw Defaults option
                   is set (see sudoers(5)) it is not possible to run commands
                   with a uid not listed in the password database.

       -V          The -V (version) option causes sudo to print the version
                   number and exit.  If the invoking user is already root the
                   -V option will print out a list of the defaults sudo was
                   compiled with as well as the machine's local network
                   addresses.

       -v          If given the -v (validate) option, sudo will update the
                   user's timestamp, prompting for the user's password if
                   necessary.  This extends the sudo timeout for another 5
                   minutes (or whatever the timeout is set to in sudoers) but
                   does not run a command.

       --          The -- option indicates that sudo should stop processing
                   command line arguments.  It is most useful in conjunction
                   with the -s option.

       Environment variables to be set for the command may also be passed on
       the command line in the form of VAR=value, e.g.
       LD_LIBRARY_PATH=/usr/local/pkg/lib.  Variables passed on the command
       line are subject to the same restrictions as normal environment
       variables with one important exception.  If the setenv option is set in
       sudoers, the command to be run has the SETENV tag set or the command
       matched is ALL, the user may set variables that would overwise be
       forbidden.  See sudoers(5) for more information.

RETURN VALUES
       Upon successful execution of a program, the exit status from sudo will
       simply be the exit status of the program that was executed.

       Otherwise, sudo quits with an exit value of 1 if there is a
       configuration/permission problem or if sudo cannot execute the given
       command.  In the latter case the error string is printed to stderr.  If
       sudo cannot stat(2) one or more entries in the user's PATH an error is
       printed on stderr.  (If the directory does not exist or if it is not
       really a directory, the entry is ignored and no error is printed.)
       This should not happen under normal circumstances.  The most common
       reason for stat(2) to return "permission denied" is if you are running
       an automounter and one of the directories in your PATH is on a machine
       that is currently unreachable.

SECURITY NOTES
       sudo tries to be safe when executing external commands.

       There are two distinct ways to deal with environment variables.  By
       default, the env_reset sudoers option is enabled.  This causes commands
       to be executed with a minimal environment containing TERM, PATH, HOME,
       SHELL, LOGNAME, USER and USERNAME in addition to variables from the
       invoking process permitted by the env_check and env_keep sudoers
       options.  There is effectively a whitelist for environment variables.

       If, however, the env_reset option is disabled in sudoers, any variables
       not explicitly denied by the env_check and env_delete options are
       inherited from the invoking process.  In this case, env_check and
       env_delete behave like a blacklist.  Since it is not possible to
       blacklist all potentially dangerous environment variables, use of the
       default env_reset behavior is encouraged.

       In all cases, environment variables with a value beginning with () are
       removed as they could be interpreted as bash functions.  The list of
       environment variables that sudo allows or denies is contained in the
       output of sudo -V when run as root.  This list reflects the built-in
       defaults, which may be overridden in sudoers.

       On Mac OS X, sudoers has been configured to only whitelist a small set
       of environment variables by default.  See the sudoers file for more
       information.

       Note that the dynamic linker on most operating systems will remove
       variables that can control dynamic linking from the environment of
       setuid executables, including sudo.  Depending on the operating system
       this may include _RLD*, DYLD_*, LD_*, LDR_*, LIBPATH, SHLIB_PATH, and
       others.  These type of variables are removed from the environment
       before sudo even begins execution and, as such, it is not possible for
       sudo to preserve them.

       To prevent command spoofing, sudo checks "." and "" (both denoting
       current directory) last when searching for a command in the user's PATH
       (if one or both are in the PATH).  Note, however, that the actual PATH
       environment variable is not modified and is passed unchanged to the
       program that sudo executes.

       sudo will check the ownership of its timestamp directory (/var/db/sudo
       by default) and ignore the directory's contents if it is not owned by
       root or if it is writable by a user other than root.  On systems that
       allow non-root users to give away files via chown(2), if the timestamp
       directory is located in a directory writable by anyone (e.g., /tmp), it
       is possible for a user to create the timestamp directory before sudo is
       run.  However, because sudo checks the ownership and mode of the
       directory and its contents, the only damage that can be done is to
       "hide" files by putting them in the timestamp dir.  This is unlikely to
       happen since once the timestamp dir is owned by root and inaccessible
       by any other user, the user placing files there would be unable to get
       them back out.  To get around this issue you can use a directory that
       is not world-writable for the timestamps (/var/adm/sudo for instance)
       or create /var/db/sudo with the appropriate owner (root) and
       permissions (0700) in the system startup files.

       sudo will not honor timestamps set far in the future.  Timestamps with
       a date greater than current_time + 2 * TIMEOUT will be ignored and sudo
       will log and complain.  This is done to keep a user from creating
       his/her own timestamp with a bogus date on systems that allow users to
       give away files.

       Please note that sudo will normally only log the command it explicitly
       runs.  If a user runs a command such as sudo su or sudo sh, subsequent
       commands run from that shell will not be logged, nor will sudo's access
       control affect them.  The same is true for commands that offer shell
       escapes (including most editors).  Because of this, care must be taken
       when giving users access to commands via sudo to verify that the
       command does not inadvertently give the user an effective root shell.
       For more information, please see the PREVENTING SHELL ESCAPES section
       in sudoers(5).

ENVIRONMENT
       sudo utilizes the following environment variables:

       EDITOR          Default editor to use in -e (sudoedit) mode if neither
                       SUDO_EDITOR nor VISUAL is set

       HOME            In -s or -H mode (or if sudo was configured with the
                       --enable-shell-sets-home option), set to homedir of the
                       target user

       PATH            Set to a sane value if the secure_path sudoers option
                       is set.

       SHELL           Used to determine shell to run with -s option

       SUDO_ASKPASS    Specifies the path to a helper program used to read the
                       password if no terminal is available or if the -A
                       option is specified.

       SUDO_COMMAND    Set to the command run by sudo

       SUDO_EDITOR     Default editor to use in -e (sudoedit) mode

       SUDO_GID        Set to the group ID of the user who invoked sudo

       SUDO_PROMPT     Used as the default password prompt

       SUDO_PS1        If set, PS1 will be set to its value for the program
                       being run

       SUDO_UID        Set to the user ID of the user who invoked sudo

       SUDO_USER       Set to the login of the user who invoked sudo

       USER            Set to the target user (root unless the -u option is
                       specified)

       VISUAL          Default editor to use in -e (sudoedit) mode if
                       SUDO_EDITOR is not set

FILES
       /private/etc//sudoers   List of who can run what

       /var/db/sudo            Directory containing timestamps

       /etc/environment        Initial environment for -i mode on Linux and
                               AIX

EXAMPLES
       Note: the following examples assume suitable sudoers(5) entries.

       To get a file listing of an unreadable directory:

        $ sudo ls /usr/local/protected

       To list the home directory of user yazza on a machine where the file
       system holding ~yazza is not exported as root:

        $ sudo -u yazza ls ~yazza

       To edit the index.html file as user www:

        $ sudo -u www vi ~www/htdocs/index.html

       To shutdown a machine:

        $ sudo shutdown -r +15 "quick reboot"

       To make a usage listing of the directories in the /home partition.
       Note that this runs the commands in a sub-shell to make the cd and file
       redirection work.

        $ sudo sh -c "cd /home ; du -s * | sort -rn > USAGE"

SEE ALSO
       grep(1), su(1), stat(2), passwd(5), sudoers(5), visudo(8)

AUTHORS
       Many people have worked on sudo over the years; this version consists
       of code written primarily by:

               Todd C. Miller

       See the HISTORY file in the sudo distribution or visit
       http://www.sudo.ws/sudo/history.html for a short history of sudo.

CAVEATS
       There is no easy way to prevent a user from gaining a root shell if
       that user is allowed to run arbitrary commands via sudo.  Also, many
       programs (such as editors) allow the user to run commands via shell
       escapes, thus avoiding sudo's checks.  However, on most systems it is
       possible to prevent shell escapes with sudo's noexec functionality.
       See the sudoers(5) manual for details.

       It is not meaningful to run the cd command directly via sudo, e.g.,

        $ sudo cd /usr/local/protected

       since when the command exits the parent process (your shell) will still
       be the same.  Please see the EXAMPLES section for more information.

       If users have sudo ALL there is nothing to prevent them from creating
       their own program that gives them a root shell regardless of any '!'
       elements in the user specification.

       Running shell scripts via sudo can expose the same kernel bugs that
       make setuid shell scripts unsafe on some operating systems (if your OS
       has a /dev/fd/ directory, setuid shell scripts are generally safe).

BUGS
       If you feel you have found a bug in sudo, please submit a bug report at
       http://www.sudo.ws/sudo/bugs/

SUPPORT
       Limited free support is available via the sudo-users mailing list, see
       http://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or search
       the archives.

DISCLAIMER
       sudo is provided ``AS IS'' and any express or implied warranties,
       including, but not limited to, the implied warranties of
       merchantability and fitness for a particular purpose are disclaimed.
       See the LICENSE file distributed with sudo or
       http://www.sudo.ws/sudo/license.html for complete details.



1.7.0                          November 15, 2008                       SUDO(8)

See the 'CAVEATS' section for two important insights. The first: a word of real world caution.

CAVEATS
       There is no easy way to prevent a user from gaining a root shell if
       that user is allowed to run arbitrary commands via sudo.  Also, many
       programs (such as editors) allow the user to run commands via shell
       escapes, thus avoiding sudo's checks.  However, on most systems it is
       possible to prevent shell escapes with sudo's noexec functionality.
       See the sudoers(5) manual for details.

The second: a glimpse into the Unix concept of the 'shell'.

       It is not meaningful to run the cd command directly via sudo, e.g.,

        $ sudo cd /usr/local/protected

       since when the command exits the parent process (your shell) will still
       be the same.  Please see the EXAMPLES section for more information.

Ken Thompson and Dennis Ritchie were stuck there for two months when first building Unix. They'd use 'cd' to change directories but always ended up back where they started from. They ripped the system apart, debugged it intensely without success, until coins finally started dropping down the slots.

  1. Execution of any program on Unix invariably involves creating a new 'shell'. Think layers of an onion. Or better yet: hack a bit from Terminal.
    $ sh
    sh-3.2$ zsh
    % tcsh
    % csh
    % bash
    

  2. You have to issue 'exit' commands to get back where you started from. (And unfortunately Apple engineers introduced yet another bug in 10.6 which makes this problematic. Don't hold your breath for a fix.)

  3. But the basic idea is you have 'shells' overlapping each other: your initial shell calls 'sh' in the example above and then waits to continue until the new shell exits. The second shell calls a shell and then waits to continue until that shell exits; and so on.

  4. Finally: each shell has its own set of 'environment variables'. Such as the 'current working directory'.
    $ cd /bin
    $ set | grep PWD
    OLDPWD=/
    PWD=/bin
    $ set | grep ^PWD
    PWD=/bin
    $ echo $PWD
    /bin

  5. So using cd to change directories was fine; the code Ken and Dennis had written was correct; but the directory only changed in the new shell; and immediately the command ran, the system went back to the old shell again, where the directory hadn't changed.

  6. Ken Thompson did a 'code fix' to make cd propagate the new 'PWD' back to the calling shell.

  7. The behaviour of sudo is thus much the same as the 'pre-fix' cd.

All sudo really does is run your command as its own - as root - provided you pass all the 'tests'. But this command runs of course in its own shell (which exits immediately afterward). Thus the caveat.

So try the dmesg command in CLIX. (That's where you ultimately want it anyway.)



Something like the above. Then run it and save it.

Set UID & Scripts

Your kernel build should outlaw them but the option's there for those who want it: allowing ordinary shell script files to be marked 'set UID' and run as root. This is of course foolhardy and works hand in hand with world-writable files: they're no-nos.

So it follows that running external scripts through Terminal or CLIX or any program is ripe with risks. If you absolutely have to run a script as root then you might consider the following introductory snippet.

if [[ `stat -f %u%g $0` != "080" ]] ; then
echo "Script ownership is `stat -f %u:%g $0` but should be 0:80."
exit
fi
if [[ `stat -f %p $0` != "100550" ]] ; then
echo "Script mode is `stat -f %p $0` but should be 100550."
exit
fi

The first test makes sure the file is owned by root:admin. The second test makes sure the file is not writable (or even readable by anyone outside the admin group). And the script exits gracefully in either case.

You can also ask CLIX to prompt you any time sudo is invoked.

defaults write com.rixstep.CLIX SudoAlert 1

This is what happens next you use sudo within CLIX.

Click the default 'Allow Once' and the current invocation goes through; click 'Deny' and that's the end of that; click 'Allow All' and all invocations (for the current command only) are allowed. (The next sudo command will get you the same prompt again.)

But as pointed out in the CLIX documentation, this is not a complete or foolproof system.

[Note this isn't foolproof: a malfeasant sufficiently acquainted with your computing habits can delete the preferences file. Safest of all is to manually check external scripts before running or better yet to not run external scripts at all.]

Run the following command to find out if your kernel build allows set ID scripts.

$ sysctl kern.sugid_scripts
kern.sugid_scripts: 0

Better yet: filter out everything but the reply ('0' for 'no', '1' for 'yes').

$ sysctl kern.sugid_scripts | sed s/'kern.sugid_scripts: '//
0

Hopefully your system will have the same answer.

You turn CLIX sudo alerts off by reversing the original command.

defaults write com.rixstep.CLIX SudoAlert 1

Or better yet: by removing the key altogether.

defaults delete com.rixstep.CLIX SudoAlert

/bin

Time to venture out on your own. Navigate with Terminal to /bin and try to open a manpage for each file. See what you can find. You get a head start.

$ df
Filesystem    512-blocks     Used Available Capacity  Mounted on
devfs                218      218         0   100%    /dev
map -hosts             0        0         0   100%    /net
map auto_home          0        0         0   100%    /home

$ man df
DF(1)                     BSD General Commands Manual                    DF(1)

NAME
     df -- display free disk space

SYNOPSIS
     df [-b | -h | -H | -k | -m | -g | -P] [-ailn] [-t] [-T type]
        [file | filesystem ...]

LEGACY SYNOPSIS
     df [-b | -h | -H | -k | -m | -P] [-ailn] [-t type] [-T type] [file |
     filesystem ...]

DESCRIPTION
     The df utility displays statistics about the amount of free disk space on
     the specified filesystem or on the filesystem of which file is a part.
     Values are displayed in 512-byte per block counts.  If neither a file or
     a filesystem operand is specified, statistics for all mounted filesystems
     are displayed (subject to the -t option below).

     The following options are available:

     -a      Show all mount points, including those that were mounted with the
             MNT_IGNORE flag.

     -b      Use (the default) 512-byte blocks.  This is only useful as a way
             to override an BLOCKSIZE specification from the environment.

     -g      Use 1073741824-byte (1-Gbyte) blocks rather than the default.
             Note that this overrides the BLOCKSIZE specification from the
             environment.

     -H      "Human-readable" output.  Use unit suffixes: Byte, Kilobyte,
             Megabyte, Gigabyte, Terabyte and Petabyte in order to reduce the
             number of digits to three or less using base 10 for sizes.

     -h      "Human-readable" output.  Use unit suffixes: Byte, Kilobyte,
             Megabyte, Gigabyte, Terabyte and Petabyte in order to reduce the
             number of digits to three or less using base 2 for sizes.

     -i      Include statistics on the number of free inodes.

     -k      Use 1024-byte (1-Kbyte) blocks, rather than the default.  Note
             that this overrides the BLOCKSIZE specification from the environ-
             ment.

     -l      Only display information about locally-mounted filesystems.

     -m      Use 1048576-byte (1-Mbyte) blocks rather than the default.  Note
             that this overrides the BLOCKSIZE specification from the environ-
             ment.

     -n      Print out the previously obtained statistics from the filesys-
             tems.  This option should be used if it is possible that one or
             more filesystems are in a state such that they will not be able
             to provide statistics without a long delay.  When this option is
             specified, df will not request new statistics from the filesys-
             tems, but will respond with the possibly stale statistics that
             were previously obtained.

     -P      Use (the default) 512-byte blocks.  This is only useful as a way
             to override an BLOCKSIZE specification from the environment.

     -T      Only print out statistics for filesystems of the specified types.
             More than one type may be specified in a comma separated list.
             The list of filesystem types can be prefixed with ``no'' to spec-
             ify the filesystem types for which action should not be taken.
             For example, the df command:

                   df -T nonfs,mfs

             lists all filesystems except those of type NFS and MFS.  The
             lsvfs(1) command can be used to find out the types of filesystems
             that are available on the system.

     -t      If used with no arguments, this option is a no-op (Mac OS X
             already prints the total allocated-space figures).  If used with
             an argument, it acts like -T, but this usage is deprecated and
             should not be relied upon.

ENVIRONMENT
     BLOCKSIZE  If the environment variable BLOCKSIZE is set, the block counts
                will be displayed in units of that size block.

BUGS
     The -n and -t flags are ignored if a file or filesystem is specified.

LEGACY DESCRIPTION
     The "capacity" percentage is normally rounded up to the next higher inte-
     ger.  In legacy mode, it is rounded down to the next lower integer.

     When the -P option and the -k option are used together, sizes are
     reported in 1024-blocks.  In legacy mode, when the -P option and -k
     option are used together, the last option specified dictates the reported
     block size.

     The -t option is normally a no-op (Mac OS X already prints the total
     allocated-space figures).  In legacy mode, it is equivalent to -T.

     For more information about legacy mode, see compat(5).

SEE ALSO
     lsvfs(1), quota(1), fstatfs(2), getfsstat(2), statfs(2), getmntinfo(3),
     compat(5), fstab(5), mount(8), quot(8)

HISTORY
     A df command appeared in Version 1 AT&T UNIX.

BSD                               May 8, 1995                              BSD

A hint: always look for an option without command line switches. And don't run any command with sudo until you've studied the documentation and are sure you know what you're doing. Read carefully and happy hacking.

See Also
Rixstep FTP: CLIX Download
CLIX: Don't Sell a Man a Fish

About | ACP | Buy | Industry Watch | Learning Curve | News | Products | Search | Substack
Copyright © Rixstep. All rights reserved.