ftp.nice.ch/pub/next/unix/hack/WorkspaceHack.1.1.N.b.tar.gz#/WorkspaceHack1.1/my_main.c

This is my_main.c in view mode; [Download] [Up]

/* $Id: my_main.c,v 1.0 92/07/31 17:39:45 cap Exp $
 * This is the routine we jump to.
 *
 * The data for this module doesn't go into a zero-filled segment,
 * so you need to initialize everything.
 */

#include <stdlib.h>
#include <fcntl.h>
#include <sys/errno.h>
#include <defaults.h>
#include <objc/hashtable.h>

extern char ***_libsys_environ;
char **environ_from_command();

/* 
 * This function gets called at the point where Workspace's main
 * should have been called. Thus, we do our business, then call
 * Workspace's main, and then return from here.
 * Right now I'm not using the arguments, but maybe we could 
 * add some fancy command line processing.
 */

my_main(argc, argv, envp)
     int argc;
     char *argv[];
     char *envp[];
{
    int (*workspace_main)() = (int (*)()) RETURN;
    const char *environ_preference;
    extern const char *sound_file;

    environ_preference = NXGetDefaultValue("Workspace", "CustomEnvironmentCommand");
    sound_file = NXGetDefaultValue("Workspace", "CustomEmptyRecyclerSound");
    if (environ_preference) {
	char **environ = environ_from_command(environ_preference);
	
	if (environ)
	    *_libsys_environ = environ;	/* very necessary! */
    }
    if (sound_file)
	sound_file = NXUniqueString(sound_file);
    return (*workspace_main)(argc, argv, *_libsys_environ);
}

/* 
 * environ_from_command -
 *          Add things to the environment. The argument is a string 
 * 	    specifying a command to be executed by /bin/sh, through 
 * 	    the popen call. The command must print on stdout a list of 
 * 	    environment variables, complete with the = between the 
 * 	    variable name and the value. These commands are taken to be
 *	    the new environment of all programs that Workspace launches. 
 * 	    
 * 	    If the command prints nothing, you will get an empty 
 * 	    environment. An example command that retains the current 
 * 	    environment would be "printenv". A more useful thing would 
 * 	    be to have something like "cat ~/Library/environment", 
 * 	    where the environment file would contain strings like
 * 	    
 * 	        PATH=blah
 * 	        PAGER=less
 * 	        
 * 	    and so on. This doesn't allow you any shell substitutions, 
 * 	    which most people want. My final suggestion is to extract 
 * 	    the part of your .login file that establishes your 
 * 	    environment into a separate file, say, ~/.environment.
 * 	    Your .login file would then source this file. The command 
 * 	    you'd specify for here would then be, for csh users,
 * 	    
 * 	        csh -c "source ~/.environment; printenv"
 * 	    
 * 	    It's important that whatever command you choose, it prints 
 * 	    only environment information. That's why you wouldn't want 
 * 	    to use "source ~/.login", because many people like to 
 * 	    print things in their .login files.
 *
 *	    The exit status of the command must be 0, or you don't
 * 	    get the new environment, you retain the old.
 */

/* maximum length of a single environment variable string */
#define ENVIRON_STRING_SIZE 10240

char **environ_from_command(command)
     const char *command;
{
    FILE *stream;
    const char **environ = NULL;
    int index;			/* into environ */
    int environ_size;
    int status;			/* of command */
    char environ_string[ENVIRON_STRING_SIZE]; /* one line of environment */
    int console;

    /* 
     * I don't actually use this console descriptor, but popen fails unless 
     * we open some other file first. This is probably because 
     * Workspace is started by loginwindow, which probably doesn't 
     * supply open files on descriptors 0-2. I didn't check this though.
     */
    console = open("/dev/console", O_WRONLY);
    if ((stream = popen(command, "r")) == NULL)
	fprintf(stderr, "CustomWorkspace[%d]: could not open pipe to environment command: %s\n", getpid(), sys_errlist[errno]);
    else {
	environ_size = 16;
	index = 0;
	environ = malloc(environ_size * sizeof *environ);
	while (fgets(environ_string, ENVIRON_STRING_SIZE, stream)) {
	    environ_string[strlen(environ_string) - 1] = '\0';
	    environ[index++] = NXUniqueString(environ_string);
	    if (index == environ_size) {
		environ_size *= 2;
		environ = realloc(environ, environ_size * sizeof *environ);
	    }
	}
	environ[index] = NULL;
	if (status = pclose(stream)) {
	    printf("CustomWorkspace[%d]: environment command exited with status %d\n", getpid(), status);
	    free(environ);
	    environ = NULL;
	}
    }
    close(console);
    return environ;
}	

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.