This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[patch] invoking user's preferred shell from cygwin.bat


Hi

As you will know, the default Cygwin shortcuts invoke "cygwin.bat" which in turn runs "bash --login".

On most of my Unix accounts, I have tcsh set as my login shell, and have also started to find zsh quite useful, therefore I would prefer to be able to set my preferred shell in Cygwin as well. Most Unix systems do this with the pw_shell field of the password database, /etc/passwd.

I have attached a simple C source file which tries to use the user's shell if it's specified in the password database. You might compile this and make it available with a name such as /bin/shell and change cygwin.bat to invoke "shell" instead of "bash --login".

Design decisions:
- falls back to the default shell rather than exiting if a user
  doesn't exist since Cygwin doesn't currently require a valid
  user account
- uses the default shell if the shell field in /etc/passwd is blank
  as many other Unixes do
- uses /bin/bash as the default shell since cygwin.bat uses that
  as the default

Features:
- sets argv[0] to the shell's basename prefixed by a hyphen/minus
  character which makes most common shells switch to "login" mode

I hope you find it useful.

--
Michael Wardle
/*
 * shell - start user's preferred shell
 */

#include <sys/types.h>
#include <errno.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define DEFAULT_SHELL "/bin/bash"
#define PATH_SEPARATOR '/'

int main(int argc, char **argv)
{
	const struct passwd *passwd;
	const char *shell;
	char *basename;
	char *arg0;
	char **args;

	/* Get the current user's shell */
	errno = 0;
	passwd = getpwuid(getuid());
	if (!passwd) {
		fprintf(stderr, "Cannot get password entry: %s\n",
			strerror(errno));
		shell = NULL;
	}
	else {
		shell = passwd->pw_shell;
	}

	/* Fall back to the default if the shell is unset or empty */
	if (!shell||!*shell) {
		fprintf(stderr, "Using default shell %s\n", DEFAULT_SHELL);
		shell = DEFAULT_SHELL;
	}

	/* Set the SHELL environment variable for make, etc. */
	setenv("SHELL", shell, 1);

	/* Set up the shell's argument vector - argv[0] */
	errno = 0;
	arg0 = (char *)malloc(strlen(shell)*sizeof(char)+1);
	if (!arg0) {
		perror("Cannot allocate memory for shell argument 0\n");
		exit(1);
	}
	basename = strrchr(shell, (int)PATH_SEPARATOR);
	if (basename) basename++;	/* move past '/' */
	if (basename) {
		/* Set arg0 to -basename to denote login shell */
		strcpy(arg0, "-");
		strcat(arg0, basename);
	}
	else {
		/* Leave arg0 as full path */
		strcpy(arg0, shell);
	}

	/* Set up the shell's argument vector - argv */
	errno = 0;
	args = (char **)malloc(2*sizeof(arg0));	/* {arg0, NULL} */
	if (!args) {
		perror("Cannot allocate memory for shell arguments\n");
		exit(1);
	}
	args[0] = arg0;
	args[1] = (char *)NULL;

	/* Start the shell */
	errno = 0;
	if (execv(shell, args) == -1) {
		fprintf(stderr, "Cannot execute shell %s: %s\n", shell,
			strerror(errno));
		exit(1);
	}

	exit(0);
}

--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]