1/* 2 * clone.c - start a forked instance of the current shell on a new terminal 3 * 4 * This file is part of zsh, the Z shell. 5 * 6 * Copyright (c) 1997 Zolt�n Hidv�gi 7 * All rights reserved. 8 * 9 * Permission is hereby granted, without written agreement and without 10 * license or royalty fees, to use, copy, modify, and distribute this 11 * software and to distribute modified versions of this software for any 12 * purpose, provided that the above copyright notice and the following 13 * two paragraphs appear in all copies of this software. 14 * 15 * In no event shall Zolt�n Hidv�gi or the Zsh Development Group be liable 16 * to any party for direct, indirect, special, incidental, or consequential 17 * damages arising out of the use of this software and its documentation, 18 * even if Zolt�n Hidv�gi and the Zsh Development Group have been advised of 19 * the possibility of such damage. 20 * 21 * Zolt�n Hidv�gi and the Zsh Development Group specifically disclaim any 22 * warranties, including, but not limited to, the implied warranties of 23 * merchantability and fitness for a particular purpose. The software 24 * provided hereunder is on an "as is" basis, and Zolt�n Hidv�gi and the 25 * Zsh Development Group have no obligation to provide maintenance, 26 * support, updates, enhancements, or modifications. 27 * 28 */ 29 30/* 31 * The clone builtin can be used to start a forked instance of the current 32 * shell on a new terminal. The only argument to the builtin is the name 33 * of the new terminal. In the new shell the PID, PPID and TTY parameters 34 * are changed appropriately. $! is set to zero in the new instance of the 35 * shell and to the pid of the new instance in the original shell. 36 * 37 */ 38 39#include "clone.mdh" 40#include "clone.pro" 41 42/**/ 43static int 44bin_clone(char *nam, char **args, UNUSED(Options ops), UNUSED(int func)) 45{ 46 int ttyfd, pid, cttyfd; 47 48 unmetafy(*args, NULL); 49 ttyfd = open(*args, O_RDWR|O_NOCTTY); 50 if (ttyfd < 0) { 51 zwarnnam(nam, "%s: %e", *args, errno); 52 return 1; 53 } 54 pid = fork(); 55 if (!pid) { 56 clearjobtab(0); 57 ppid = getppid(); 58 mypid = getpid(); 59#ifdef HAVE_SETSID 60 if (setsid() != mypid) 61 zwarnnam(nam, "failed to create new session: %e", errno); 62#elif defined(TIOCNOTTY) 63 if (ioctl(SHTTY, TIOCNOTTY, 0)) 64 zwarnnam(*args, "%e", errno); 65 setpgrp(0L, mypid); 66#endif 67 dup2(ttyfd,0); 68 dup2(ttyfd,1); 69 dup2(ttyfd,2); 70 if (ttyfd > 2) 71 close(ttyfd); 72 closem(0); 73 close(coprocin); 74 close(coprocout); 75 /* Acquire a controlling terminal */ 76 cttyfd = open(*args, O_RDWR); 77 if (cttyfd == -1) 78 zwarnnam(nam, "%e", errno); 79 else { 80#ifdef TIOCSCTTY 81 ioctl(cttyfd, TIOCSCTTY, 0); 82#endif 83 close(cttyfd); 84 } 85 /* check if we acquired the tty successfully */ 86 cttyfd = open("/dev/tty", O_RDWR); 87 if (cttyfd == -1) 88 zwarnnam(nam, "could not make %s my controlling tty, job control " 89 "disabled", *args); 90 else 91 close(cttyfd); 92 93 /* Clear mygrp so that acquire_pgrp() gets the new process group. 94 * (acquire_pgrp() is called from init_io()) */ 95 mypgrp = 0; 96 init_io(); 97 setsparam("TTY", ztrdup(ttystrname)); 98 } 99 close(ttyfd); 100 if (pid < 0) { 101 zerrnam(nam, "fork failed: %e", errno); 102 return 1; 103 } 104 lastpid = pid; 105 return 0; 106} 107 108static struct builtin bintab[] = { 109 BUILTIN("clone", 0, bin_clone, 1, 1, 0, NULL, NULL), 110}; 111 112static struct features module_features = { 113 bintab, sizeof(bintab)/sizeof(*bintab), 114 NULL, 0, 115 NULL, 0, 116 NULL, 0, 117 0 118}; 119 120/**/ 121int 122setup_(UNUSED(Module m)) 123{ 124 return 0; 125} 126 127/**/ 128int 129features_(Module m, char ***features) 130{ 131 *features = featuresarray(m, &module_features); 132 return 0; 133} 134 135/**/ 136int 137enables_(Module m, int **enables) 138{ 139 return handlefeatures(m, &module_features, enables); 140} 141 142/**/ 143int 144boot_(UNUSED(Module m)) 145{ 146 return 0; 147} 148 149/**/ 150int 151cleanup_(Module m) 152{ 153 return setfeatureenables(m, &module_features, NULL); 154} 155 156/**/ 157int 158finish_(UNUSED(Module m)) 159{ 160 return 0; 161} 162