Page 1 of 2 12 LastLast
Results 1 to 10 of 14

Thread: Symbolic Links in Linux

  1. #1
    AO Curmudgeon rcgreen's Avatar
    Join Date
    Nov 2001
    Posts
    2,716

    Question Symbolic Links in Linux

    OK, I give up. I can't figure this out.
    RED HAT 6
    In /usr/sbin there is a program, mc (midnight commander)
    If you run mc, you get the mc program running,
    a file manager type prog with lots of features,
    including text editor etc.
    There is a symlink to mc called mcedit.
    if you run mcedit <filename>, you get the editor.
    If you run mc -e <filename> you also get the editor

    Here's my question. How does the symlink, mcedit
    pass an argument, -e, to mc?
    I have tried to create symlinks that pass
    arguments to the program they're linked to,
    but get a "broken link" error.

    If mcedit is merely a link to mc, according to man page,
    it is only a different name linked to the same file, mc.
    How does mcedit invoke the editor instead of the main
    program?
    I came in to the world with nothing. I still have most of it.

  2. #2
    PHP/PostgreSQL guy
    Join Date
    Dec 2001
    Posts
    1,164
    All a symbolic link is, is a pointer from one "file" to another "file". The reason those are in " is because *everything* in *nix is considered a file, whether it's a file, directory, block device, character device, tape drive, named pipe, etc... All arguments given to a symbolic link will be compared against the binary's to see if they can run and will run using the linked binary if possible. Example below:

    $ which ls
    /bin/ls

    $ ln -s /bin/ls $HOME/foo
    $ cd $HOME && ls -l foo
    lrwxr-xr-x 1 root sys 7 Jan 22 09:07 foo -> /bin/ls

    $ $HOME/foo -l
    <complete listing of your home here>


    Now, we created a symbolic link to ls to our $HOME dir (our login home) named foo. Passing
    the argument '-l' (for list) to the 'foo' command just got piped to the actual ls binary and it recognized '-l' as a valid argument and listed accordingly. Here's some more info from 'man ln' on my HP server at work:

    Hard links are created with the same ownerships and permissions as the
    file or directory to which they are linked. If ownership or
    permissions are changed on a link or file, the same changes appear on
    corresponding hard links. The ln command does not permit hard links
    to a directory.

    Symbolic links are created with the ownership of the creator and the
    permissions are of the creator's current umask. Once created, the
    symbolic link ownership and permissions will not change, since the
    mode and ownership of the symbolic link is ignored by the system.
    Also, you can't create hard links across file systems. They have to reside on the
    same file system. Hard links used to have it where if you modified them in any
    way, it would modify the original file. Example:

    $ touch foo (create foo)
    $ ln foo bar (bar is now a hardlink to foo, both a zero-length file)
    $ echo "test" >> bar (echo something into bar)
    $ ls -l foo bar
    -rw-r--r-- 2 root sys 5 Jan 22 09:13 bar
    -rw-r--r-- 2 root sys 5 Jan 22 09:13 foo


    As you can see, when you echoed "test" into bar, it updated foo. Now, if I removed
    foo or bar, the other would remain. It used to be where if you removed the hard link,
    it would remove the file (aka, rm bar would also rm foo) but that's since changed. Let
    me know if you want more info on this...symlinks and hardlinks are pretty interesting
    and may vary on different systems (info above is on HP systems). By default though,
    sym links don't share the same inode as the original file whereas hard links do, hence
    the removal of both when one or the other is removed.

    From what you wrote, it looks like 'mcedit' is perhaps a shell script that executes the
    editor. Having not run midnight commander, I don't know, but I could find out soon
    enough.
    We the willing, led by the unknowing, have been doing the impossible for the ungrateful. We have done so much with so little for so long that we are now qualified to do just about anything with almost nothing.

  3. #3
    AO Curmudgeon rcgreen's Avatar
    Join Date
    Nov 2001
    Posts
    2,716

    Thumbs up

    I get:

    #ls -l mcedit
    lrwxrwxrwx 1 root root 2 Oct 3 13:00 mcedit -> mc


    #mc
    (runs main prog)


    #mcedit
    (runs editor)

    this is undocumented, as far as I've been able to tell

    I've tried :

    #ln -s mcedit -e foo
    but foo is a "broken link", and doesn't function.

    They also do this with the cd music player, cdp

    #cdp
    (runs interactice cd player)

    #cdplay
    (plays music in background)

    cdplay is a symlink to cdp

    #ls -l cdplay
    lrwxrwxrwx 1 root root 3 Oct 3 12:41 cdplay -> cdp

    ??
    Thanks for your time.
    I came in to the world with nothing. I still have most of it.

  4. #4
    PHP/PostgreSQL guy
    Join Date
    Dec 2001
    Posts
    1,164
    Dude that's weird...lemme run through one time on what I know about symlinks that's known as fact:

    1: symlinks can cross file systems
    2: symlinks are owned by root and permissions are ignored on the link, permissions being checked on the actual file/directory it's linked to.
    3: removal of the symlink will keep the target file intact.
    4: removal of the target file will keep the symlink however, the symlink now points to a non-existent target (flashing red in 'ls' in RH)
    5: symlinks (and hard links) don't accept arguments to the target (your 'ln -s mcedit -e foo' command)

    I tried doing the same thing on my HP server, to the same effect. I created a 'foo' script that just takes a command line argument and prints it.

    #!/bin/sh

    case $1 in
    '-s')
    echo "$1 was specified"
    ;;
    '-t')
    echo "$1 was specified"
    ;;
    *)
    echo "Usage: $0 -(s|t)"
    ;;
    esac


    And then tried to link it with 'ln -s "./foo -s" bar' to see if encapsulation with " or ' quotes would work, and ... it failed. I was expecting it to, but still, at least I know now that it won't take command line options.

    The only way to do that is to edit your .profile (or edit /etc/profile) and add the following:

    alias foo='mc -e'

    This way, when you login, or re-source the file (. /etc/profile or . $HOME/.profile), you type 'alias' and see the alias for foo and what it does. This allows you to have multiple options or whatnot with an easily remembered word. The alias itself can only be one word (like shiggity_blakow_123 if you really wanted to), but the options it can do are limitless.

    alias foo='cd $HOME && . ./.new_profile || echo Profile not read.'

    This example would cd to your home and attempt to source the .new_profile. If that works, it'll ignore the || (false) and exit, otherwise it'll echo "Profile not read."[/b]

    Hope this helps some.
    We the willing, led by the unknowing, have been doing the impossible for the ungrateful. We have done so much with so little for so long that we are now qualified to do just about anything with almost nothing.

  5. #5
    AO Curmudgeon rcgreen's Avatar
    Join Date
    Nov 2001
    Posts
    2,716

    Thumbs up

    I looked for an alias or an environment variable
    to explain it but no such luck.
    I guess the people who created these links
    know something that I don't.
    Oh, well...
    I came in to the world with nothing. I still have most of it.

  6. #6
    Senior Member
    Join Date
    Nov 2001
    Posts
    1,255
    I think I've figured it out.

    I've been learning some C lately, and one thing I read in the beginning of the book I'm using was how to determine how your app was called. It's possible that Midnight Commander has this style of determining how to act.

    Try taking the MC binary and copying it to like, /home/user/mcedit and then from /home/user run ./mcedit filename

    There are no switches being passed by the link -- the actual application itself checks how it's being called and acts differently based on how it's being called.
    Chris Shepherd
    The Nelson-Shepherd cutoff: The point at which you realise someone is an idiot while trying to help them.
    \"Well as far as the spelling, I speak fluently both your native languages. Do you even can try spell mine ?\" -- Failed Insult
    Is your whole family retarded, or did they just catch it from you?

  7. #7
    PHP/PostgreSQL guy
    Join Date
    Dec 2001
    Posts
    1,164
    Yeah, there must be some weird way it's being called because symlinks pass all arguments to the actual binary being executed although I've never seen what rcgreen's going through on any other system like HP, Solaris, etc...maybe it's inherent to RH.
    We the willing, led by the unknowing, have been doing the impossible for the ungrateful. We have done so much with so little for so long that we are now qualified to do just about anything with almost nothing.

  8. #8
    Senior Member
    Join Date
    Nov 2001
    Posts
    1,255
    Originally posted by Vorlin
    Yeah, there must be some weird way it's being called because symlinks pass all arguments to the actual binary being executed although I've never seen what rcgreen's going through on any other system like HP, Solaris, etc...maybe it's inherent to RH.
    Sorry if I didn't make this clearer. It's the actual APPLICATION that's acting differently.

    It just contains a block of code that looks like (I know C != PHP, but the highlighting works well for both):

    PHP Code:
    int main(int argc,char **argv) {
         
    char *base_name 0;        /*command base name*/
         
         
    if ( ( base_name strrchr(argv[0],'/') ) != 0) {
              ++
    base_name;               /* Skip over */
         
    } else {
              
    base_name argv[0];    /* Command without path */
         
    }

         
    /* now we have the name of the command, so we check it against the list we have of 
             different commands to execute */
         
    if ( !strcmp(base_name"mcedit") ) {
              
    /* run Midnight Commander in non-edit mode */
         
    } else {
              
    /* run Midnight Commander in edit mode */
         
    }

         
    etc... 
    What that does is that when the application (in this case, mc) is executed, it first looks at the name by which it was called. If it sees mcedit it will run Midnight Commander in edit mode, if it doesn't, it just assumes it should run in normal mode. I've actually used this on a couple of apps, and it wouldn't surprise me to see if it's common.
    Another couple of utilities I know of that do this are unix_cvrt and dos_cvrt.
    Chris Shepherd
    The Nelson-Shepherd cutoff: The point at which you realise someone is an idiot while trying to help them.
    \"Well as far as the spelling, I speak fluently both your native languages. Do you even can try spell mine ?\" -- Failed Insult
    Is your whole family retarded, or did they just catch it from you?

  9. #9
    AO Curmudgeon rcgreen's Avatar
    Join Date
    Nov 2001
    Posts
    2,716

    Thumbs up

    Yes!
    I copied it to my home dir.
    cp /usr/bin mc /home/rcgreen/mcedit

    then

    ./mcedit
    (runs editor!)

    like you said, the program checks first arg (its own name,by which it was
    invoked on the command line.
    It has nothing to do with the link at all.
    I came in to the world with nothing. I still have most of it.

  10. #10
    PHP/PostgreSQL guy
    Join Date
    Dec 2001
    Posts
    1,164
    That's f'ing odd. Symbolic links aren't supposed to act that way and if they're modifying the way the binary is called and using the symlink to determine what happens, I can almost guarantee not many *nix boxes have that. It's a weird way of calling 'command line' options I guess. Good job though!
    We the willing, led by the unknowing, have been doing the impossible for the ungrateful. We have done so much with so little for so long that we are now qualified to do just about anything with almost nothing.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •