Skip to content

Commit a253687

Browse files
authored
Use SHELL rather than /bin/csh when forking shells. Issue Interlisp/medley#384 (#400)
As long as $(SHELL) names an executable that appears in /etc/shells (as determined by the getusershell() function) use that. It used to always use /bin/csh, but some modern distros do not ship with csh installed. Using the user's preferred shell seems like a better choice, while allowing the choice from /etc/shells gives some additional flexibility.
1 parent 3cdbccd commit a253687

File tree

2 files changed

+52
-50
lines changed

2 files changed

+52
-50
lines changed

src/unixcomm.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ static int FindAvailablePty(char *Slave) {
351351
/* => byte count (<= 512), NIL (no data), or T (EOF) */
352352
/* 10 Set Window Size, Arg2 = rows, Arg3 = columns */
353353
/* 11 Fork PTY to Shell (obsoletes command 4) */
354-
/* Arg1 = termtype, Arg2 = csh command string */
354+
/* Arg1 = termtype, Arg2 = shell command string */
355355
/* => Job # or NIL */
356356
/* 12 Create Unix Socket */
357357
/* Arg1 = pathname to bind socket to (string) */

src/unixfork.c

Lines changed: 51 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -75,76 +75,78 @@ static inline ssize_t SAFEREAD(int f, char *b, int c)
7575
/* */
7676
/************************************************************************/
7777

78-
/* Creates a PTY connection to a csh */
78+
/* Creates a PTY connection to a shell */
7979

8080
static int ForkUnixShell(int slot, char *PtySlave, char *termtype, char *shellarg)
8181
{
8282
int PID, SlaveFD;
8383
struct termios tio;
84+
char *argvec[4] = {NULL, NULL, NULL, NULL};
85+
char *shell = NULL;
86+
char *userShell = NULL;
8487

8588
PID = fork();
8689

87-
if (PID == 0) {
88-
char *argvec[4];
90+
if (PID != 0) {
91+
if (shellarg != shcom) free(shellarg);
92+
return (PID);
93+
}
8994

90-
if (0 > setsid()) /* create us a new session for tty purposes */
91-
perror("setsid");
95+
if (0 > setsid()) /* create us a new session for tty purposes */
96+
perror("setsid");
9297

93-
/* Open the slave side */
94-
SlaveFD = open(PtySlave, O_RDWR);
95-
if (SlaveFD == -1) {
96-
perror("Slave Open");
97-
perror(PtySlave);
98-
exit(0);
99-
}
98+
/* Open the slave side */
99+
SlaveFD = open(PtySlave, O_RDWR);
100+
if (SlaveFD == -1) {
101+
perror("Slave Open");
102+
perror(PtySlave);
103+
exit(0);
104+
}
100105

101106
#ifdef OS5
102-
ioctl(SlaveFD, I_PUSH, "ptem");
103-
ioctl(SlaveFD, I_PUSH, "ldterm");
107+
ioctl(SlaveFD, I_PUSH, "ptem");
108+
ioctl(SlaveFD, I_PUSH, "ldterm");
104109
#endif /* OS5 */
105110

106-
/* Set up as basic display terminal: canonical erase,
107-
kill processing, echo, backspace to erase, echo ctrl
108-
chars as ^x, kill line by backspacing */
109-
tcgetattr(SlaveFD, &tio);
110-
tio.c_lflag |= ICANON | ECHO | ECHOE | ECHOCTL | ECHOKE;
111-
tcsetattr(SlaveFD, TCSANOW, &tio);
111+
/* Set up as basic display terminal: canonical erase,
112+
kill processing, echo, backspace to erase, echo ctrl
113+
chars as ^x, kill line by backspacing */
114+
tcgetattr(SlaveFD, &tio);
115+
tio.c_lflag |= ICANON | ECHO | ECHOE | ECHOCTL | ECHOKE;
116+
tcsetattr(SlaveFD, TCSANOW, &tio);
112117

113-
(void)dup2(SlaveFD, 0);
114-
(void)dup2(SlaveFD, 1);
115-
(void)dup2(SlaveFD, 2);
116-
(void)close(SlaveFD);
118+
(void)dup2(SlaveFD, 0);
119+
(void)dup2(SlaveFD, 1);
120+
(void)dup2(SlaveFD, 2);
121+
(void)close(SlaveFD);
117122

118-
/* set the LDESHELL variable so the underlying .cshrc can see it and
119-
configure the shell appropriately, though this may not be so important any more */
120-
setenv("LDESHELL", "YES", 1);
123+
/* set the LDESHELL variable so the underlying shell initialization can see it and
124+
configure the shell appropriately, though this may not be so important any more */
125+
setenv("LDESHELL", "YES", 1);
121126

122-
if (termtype[0] != 0) { /* set the TERM environment var */
123-
setenv("TERM", termtype, 1);
124-
}
125-
/* Start up csh */
126-
argvec[0] = "csh";
127-
if (shellarg[0] != 0) { /* setup to run command */
128-
argvec[1] = "-c"; /* read commands from next arg */
129-
argvec[2] = shellarg;
130-
argvec[3] = (char *)0;
131-
} else
132-
argvec[1] = (char *)0;
133-
134-
execv("/bin/csh", argvec);
135-
136-
/* Should never get here */
137-
perror("execv");
127+
if (termtype[0] != 0) { /* set the TERM environment var */
128+
setenv("TERM", termtype, 1);
129+
}
130+
/* Start up shell -- use SHELL environment variable as long as it's in /etc/shells */
131+
shell = getenv("SHELL");
132+
for (userShell = getusershell(); userShell != NULL && strcmp(shell, userShell) != 0; userShell = getusershell());
133+
if (userShell == NULL) {
134+
perror("$(SHELL) not found in /etc/shells");
138135
exit(0);
139-
} else { /* not the forked process. */
140-
if (shellarg != shcom) free(shellarg);
141136
}
142137

143-
/* Set the process group so all the kids get the bullet too
144-
if (setpgrp(PID, PID) != 0)
145-
perror("setpgrp"); */
138+
/* argvec entries initialized to NULL */
139+
argvec[0] = strrchr(userShell, '/') + 1;
140+
if (shellarg[0] != 0) { /* setup to run command */
141+
argvec[1] = "-c"; /* read commands from next arg */
142+
argvec[2] = shellarg;
143+
}
144+
145+
execv(userShell, argvec);
146146

147-
return (PID);
147+
/* Should never get here */
148+
perror("execv");
149+
exit(0);
148150
}
149151

150152
/* fork_Unix is the secondary process spawned right after LISP is

0 commit comments

Comments
 (0)