May 12, 2003

Helmut Leitner wrote:
> 
> Walter wrote:
> 
>>"Helmut Leitner" <helmut.leitner@chello.at> wrote in message
>>news:3EBE0A90.F5EC470A@chello.at...
>>
>>>I think in the Linux version the configuration file dmd.conf should not go
>>>with the executable because this isn't the Unix way to do it (there seems
>>>to be no reliable way to get at the path of the executable) ...
>>>
>>>... but be searched at
>>>
>>>  /etc/dmd.conf
>>
>>Why /etc instead of, say, /usr/local/etc? (Pardon my ignorance of linux
>>conventions.0

On BSD systems (and Debian Linuxas far as I know), /etc is for system conf files. /usr/local/etc is for userland conf files. So that is where you would expect dmd.conf. Or when it is really big and has several config files in /usr/local/dm/dmd.conf.

As for the executable path. I once used a libc function or api-call on FreeBSD to get the full filepath of the current executable. But I can't remember the name of it. I don't know whether or not this function is available on Linux.

May 12, 2003
Helmut Leitner wrote:
> 
> Walter wrote:
> 
>>"Helmut Leitner" <helmut.leitner@chello.at> wrote in message
>>news:3EBE0A90.F5EC470A@chello.at...
>>
>>>I think in the Linux version the configuration file dmd.conf should not go
>>>with the executable because this isn't the Unix way to do it (there seems
>>>to be no reliable way to get at the path of the executable) ...
>>>
>>>... but be searched at
>>>
>>>  /etc/dmd.conf
>>
>>Why /etc instead of, say, /usr/local/etc? (Pardon my ignorance of linux
>>conventions.0
> 
> 
> Sorry, I can't answer the question. I'm still a 90% Windows developer.
> I only notice that all applications that I installed (apache, exim, ...)
> put their config files into /etc. It's the place where people look first.
> 
> --
> Helmut Leitner    leitner@hls.via.at   Graz, Austria   www.hls-software.com

Helmut's right.

It's just convention. That's why :-). /etc is used typically for system wide configuration files.  If this machine is a network server (gateway, firewall, or shared system to some other degree -- something Linux is often used for), than it likely is managing distributed machines on the network or serving software.  So programs designed to be shared or served network wide will likely use /etc for configuration. Examples: XFree86, NFS, consoles, web services, etc.  I imagine that's more the original reason. Now it's just the place to use when most software is installed.  It's nice, at least, to know where to look when you need to setup your software.

The system startup scripts (rc.d) also reside in /etc and will usually set the compiler environment variables (cc) = gcc and default compiler options.  Like someone else said, users usually have a specific config file in their home directory also that's created when they first run the program (something like .dmd-config).  This reflects their personalized setting for when they use the software.  It overrides the defaults system wide configuration in /etc so that they can control the software to their liking.

I don't think /usr/local/etc is very often used.  If it is, I imagine it would be more used for programs that are designed for trully local consumption only, ie NON-server/NON-shared software (eg. computer games like unreal tournament).  It may also be retained as a result of maintaining compatibility across various other UNIX conventions.

Of course, like windows, you really can do whatever you want... it's just often easier for the Linux crowd to understand/use software that follows the crazy system they're familiar with.  I think that's why dependency packaging systems like RPM and ebuilds (and BSD ports) surfaced.  They present a single package to the user that includes all the configuration files.  Everything is automatically moved to the standard locations behind the scenes during installation... Well just like windows, I guess :-).

I still maintain that the Gentoo Linux ebuild/emerge system is the all round best I've see yet... and it's fun too!

Later,

John

May 12, 2003
It's probably better for to actually refer to documents that explain it, just so that I don't trip over myself :-).

http://www.tuxfiles.org/linuxhelp/linuxdir.html

"< /etc >

The configuration files for the Linux system. Most of these files are text files and can be edited by hand. Some interesting stuff in this directory:

< /usr/local >

This is where you install apps and other files for use on the local machine. If your machine is a part of a network, the /usr directory may physically be on another machine and can be shared by many networked Linux workstations. On this kind of a network, the /usr/local directory contains only stuff that is not supposed to be used on many machines and is intended for use at the local machine only.

Most likely your machine isn't a part of a network like this, but it doesn't mean that /usr/local is useless. If you find interesting apps that aren't officially a part of your distro, you should install them in /usr/local. For example, if the app would normally go to /usr/bin but it isn't a part of your distro, you should install it in /usr/local/bin instead. When you keep your own programs away from the programs that are included in your distro, you'll avoid confusion and keep things nice and clean."

< back to me >

So I guess you could say /etc should be used for config files that are more linux distro oriented.  To tell you the truth, I don't think people follow these rules perfectly.  In the case of DMD, it probably would do fine in the /usr/local path, as Arjan said.  But, you never know, it may become part of a distro someday, like gcc, and then would be just as at home with config files in /etc!

Later,

John


May 12, 2003
"Helmut Leitner" <helmut.leitner@chello.at> wrote in message news:3EBF325B.792E5A5E@chello.at...
> Sorry, I can't answer the question. I'm still a 90% Windows developer.
> I only notice that all applications that I installed (apache, exim, ...)
> put their config files into /etc. It's the place where people look first.

Sounds ok. I'll put it there.


May 12, 2003
I hate stuffing files in places like /usr/etc.  For one thing, not everyone has write permission to that directory.

We put our conf files in a directory relative to the executable, with user configurations in their home directory.  This also works well on Windows.  The Windows version was easy to write, the Linux one harder.

The problem with the Linux version was that there is no good function to find the path of the executable that I know of, so we had to write one.

This code is still fairly untested... It works on our systems, but we haven't had a Linux release of our software yet.

Bill

/*--------------------------------------------------------------------------------------------------
  Return the path name which an executable resides.
--------------------------------------------------------------------------------------------------*/
char *utExecPath(
    const char *program)
{
    char *path, *p;
    char *fullPath;

    if(strchr(program, UTDIRSEP) != NULL) {
        return utFullPath(program);
    } else {
        path = getenv ("PATH");
        if(path != NULL) {
            p = path;
            do {
                path = p;
                p = strchr(path, UTPATHSEP);
                if(p == NULL) {
                    p = strchr(path, '\0');
                }
                if(p == path) {
                    fullPath = utCopyString(program);
                } else {
                    fullPath = utMakeString((p - path) + 1);
                    utStrncpy(fullPath, path, p - path);
                    fullPath = utSprintf("%s%c%s", fullPath, UTDIRSEP,
                        program);
                }
                fullPath = utGlob(fullPath);
                if(fullPath != NULL) {
                    return fullPath;
                }
                fullPath = utGlob(utSprintf("%s.exe", fullPath));
                if(fullPath != NULL) {
                    return fullPath;
                }
            } while(*p++ != '\0');
        }
    }
    utError("could not find executable %s", program);
    return NULL;
}

/*--------------------------------------------------------------------------------------------------
  Set directories used in the system.  Take the name passed to main as argv[0].
--------------------------------------------------------------------------------------------------*/
static bool setDirectories(
    const char *executableName)
{
    char *execDirectory, *configDirectory;

    execDirectory = utDirName(utExecPath(executableName));
    if(execDirectory == NULL) {
        fprintf(stderr, "cannot find executable path");
        return true;
    }
    utSetExeDirectory(execDirectory);
    configDirectory = utSprintf("%s%c..%cconfig", execDirectory, UTDIRSEP, UTDIRSEP);
    configDirectory = utFullPath(configDirectory);
    utSetConfigDirectory(configDirectory);
    return false;
}

================================  Unix versions of subroutines...

/*--------------------------------------------------------------------------------------------------
  Take the relative path, and return the full path.
--------------------------------------------------------------------------------------------------*/
char *utFullPath(
    const char *relativePath)
{
    char *fileName = utGlob(relativePath);
    char *dirName = utGetcwd();

    if(*relativePath == UTDIRSEP) {
        return utCopyString(relativePath);
    }
    if(fileName == NULL) {
        return utSprintf("%s%c%s", dirName, UTDIRSEP, relativePath);
    }
    while(!strncmp(fileName, ".." szUTDIRSEP, 3)) {
        fileName = fileName + 3;
        dirName = utDirName(dirName);
        if(dirName == NULL) {
            return utSprintf("%s%c%s", dirName, UTDIRSEP, relativePath);
        }
    }
    return utSprintf("%s%c%s", dirName, UTDIRSEP, fileName);
}


/*--------------------------------------------------------------------------------------------------
  Match the string to a file and return the matched file name.
--------------------------------------------------------------------------------------------------*/
char *utGlob(
    const char *fileName)
{
    glob_t globbuf;
    char *buffer = NULL;

    globbuf.gl_offs = 0;
    glob(fileName, 0, NULL, &globbuf);
    if(globbuf.gl_pathc >= 1) {
        buffer = utCopyString(*globbuf.gl_pathv);
    }
    globfree(&globbuf);
    return buffer;
}

================================  Windows versions of subroutines...

/*--------------------------------------------------------------------------------------------------
  Take the relative path, and return the full path.
--------------------------------------------------------------------------------------------------*/
char *utFullPath(
    const char *relativePath)
{
    char fullPath[UTSTRLEN];

    _fullpath(fullPath, relativePath, UTSTRLEN);
    return utCopyString(fullPath);
}

/*--------------------------------------------------------------------------------------------------
  Match the string to a file and return the matched file name.
--------------------------------------------------------------------------------------------------*/
char *utGlob(
    const char *fileName)
{
    if(utAccess(fileName, 0) == 0) {
        return utCopyString(fileName);
    }
    return NULL;
}



Helmut Leitner wrote:
> I think in the Linux version the configuration file dmd.conf should not go with the executable because this isn't the Unix way to do it (there seems to be no reliable way to get at the path of the executable) ...
> 
> ... but be searched at
> 
>   /etc/dmd.conf
> 
> You can always have the original in the installation directory and put a
> symbolic link at /etc, for example:
> 
>   cd /etc
>   ln -s /home/leitner/d/dmd/bin/dmd.conf
> 
> --
> Helmut Leitner    leitner@hls.via.at   Graz, Austria   www.hls-software.com

May 12, 2003
In article <3EBF8FC4.3050700@viasic.com>, Bill Cox says...
>
>I hate stuffing files in places like /usr/etc.  For one thing, not everyone has write permission to that directory.

There's a difference between installing as a user and installing as root. A user installs for his own usage, root installs only for "all users" or for "the system itself".

(Oh, and incidentally, ROOT NEVER COMPILES software.)

A personal install and a system-wide install should be considered two entirely separate cases. Root only installs known-good software for "all" users to use, and individuals for themselves only. (Ok, I know this isn't as clear cut as I state here, but this is a reasonable starting point here.)

..
>The problem with the Linux version was that there is no good function to find the path of the executable that I know of, so we had to write one.

Things like this bothered me for many years. Why is this or that done in an idiotic way in Unix, and later in Linux. This lead to work-arounds, kludges, and generally solutions that I regretted later. Finally I became enlightened:

- The Unix system is older than many who write comments here.
- The Unix system has always been primarily a Development system.
- The Unix system has been used by legions of top talents in programming.

This leads to a surprising conclusion: ANY problem at all one might encounter has already been encountered by people more experienced, more talented, or more industrious than we.

Therefore, if "something is missing" in Unix, or especially Linux, then there is a good reason for it not to be there!

And if something is done in a particular way, there is bound to be a good reason for it, too. One can either do the same, or search for the reason -- and then still do the same, this time with conviction.



May 12, 2003
Walter wrote:
> "Helmut Leitner" <helmut.leitner@chello.at> wrote in message
> news:3EBEA3FA.CAD63F57@chello.at...
> 
>>Walter wrote:
>>
>>>"Helmut Leitner" <helmut.leitner@chello.at> wrote in message
>>>news:3EBE0A90.F5EC470A@chello.at...
>>>
>>>>I think in the Linux version the configuration file dmd.conf should
> 
> not go
> 
>>>>with the executable because this isn't the Unix way to do it (there
> 
> seems
> 
>>>>to be no reliable way to get at the path of the executable) ...
>>>
>>>argv[0] doesn't do it?
>>
>>I don't think so:
>>    leitner@linux:~/d/dmd/samples/d> hello
>>    hello world
>>    args.length = 1
>>    args[0] = 'hello'
>>This is even the case, when the program is called from a script
>>and the directory is looked up from the PATH.
>>While you can usually rely on args[0] in the DOS/Windows world,
>>I think you usually can't in the Unix world.
> 
> 
> <rant>
> I occaisionally run into these frustrating lacks in linux - frustrating
> because they'd be so easy to add to the kernel, and are so unreliable to try
> and work around. One thing I wanted to avoid with linux is having a dmd
> installation spew files all over the system. It looks like it's going to be
> very hard avoiding this.
> </rant>
> 
> There, I feel better now <g>.

There's a semantic disconnect in Unix systems (which Linux is like) and the concept of "the path to the executable."  The file system makes a distinction between the data, and some "path name" by which the data can be found.  The data is uniquely identified by it's "inode", which is just an integer value, but there can be many file names that refer that inode (hard links).

When a program exec's some other program, it's free to put whatever it wishes into all the argv[] variables, argv[0] included.  The argv[0] thing has been just a convention begun by the Unix shell.  These shells simply put the exec'ed name there because it's a way to give the same executable different functions, distinguished by the command line verb.  For instance, in Unix "gzip" and "gunzip" are both links to the very same data set.  This was important back when Unix systems didn't have dynamic linking or command line aliases.

Now, I'm not trying to defend the system; I'm just explaining that it's there for historical reasons.

May 12, 2003
Bill Cox wrote:
The problem with your approach is, that argv[0] may be totally unrelated
to the executable filename, try:
> exec -a foo bash           # starts a new bash with argv[0]=foo ps -u


If you have the proc filesystem, you can get the path with:

char buf[30], execpath[2048];
sprintf(buf,"/proc/%d/exe", getpid());
memset(execpath, 0, sizeof(execpath))
readlink(buf, execpath);

Unfortunately, in UNIX there is no reliable and protable way to get the execpath.

-- 
+----------------------------------------------------------------------+ I Dr. Olaf Rogalsky                         Institut f. Theo. Physik I I I Tel.: 09131 8528440                       Univ. Erlangen-Nuernberg   I I Fax.: 09131 8528444                       Staudtstrasse 7 B3         I I rogalsky@theorie1.physik.uni-erlangen.de  D-91058 Erlangen           I +----------------------------------------------------------------------+
May 12, 2003
Ok, I hate to reply to myself, but I disobeyed the rule never to post untested code ... here is a working snipped:

char buf[30], execpath[2048];
sprintf(buf,"/proc/%d/exe", getpid());
memset(execpath, 0, sizeof(execpath));
readlink(buf, execpath, sizeof(execpath));

Further, I like to comment on Georg Wrede:
> Therefore, if "something is missing" in Unix, or especially Linux, then there is a good reason for it not to be there!
There is truth in this statement, but I don't wholeheartedly agree. Often enough the UNIX API is bad designed (e.g. job control). But in this particular example there IS a good reason, that there is no function to get the path to the executable: Not every process has a member in the directory hierarchy:

#include <stdio.h>
#include <unistd.h>

char* getexecpath() {
  static char buf[30], execpath[2048];

  sprintf(buf,"/proc/%d/exe", getpid());
  memset(execpath, 0, sizeof(execpath));
  readlink(buf, execpath, sizeof(execpath));
  return execpath;
}

int main(int argc, char *argv[]) {
  printf("execpath: %s\n", getexecpath());
  remove(getexecpath());
  printf("execpath: %s\n", getexecpath());
  return 0;
}

Pathological? Yes! But remember Murphy's law.

Olaf
May 12, 2003
"Olaf Rogalsky" <olaf.rogalsky@theorie1.physik.uni-erlangen.de> wrote in message news:3EBFABD4.D95BA618@theorie1.physik.uni-erlangen.de...
> Pathological? Yes! But remember Murphy's law.

On windows, you cannot delete an exe file that is currently running. One of the reasons for that is the exe file is loaded as a memory mapped file.