csh and tcsh work

Sources of csh/sh.sem.c

csh と tcsh のソース

Bill Joy

First published: October, 1978.

Copyright © 1979 Regents of the University of California.

  1. 1
    /* Copyright (c) 1979 Regents of the University of California */
  2. 2
    #include "sh.h"
  3. 3
  4. 4
    /*
  5. 5
     * C shell
  6. 6
     */
  7. 7
  8. 8
    execute(t, pipein, pipeout)
  9. 9
    	register struct command *t;
  10. 10
    	int *pipein, *pipeout;
  11. 11
    {
  12. 12
    	int pid, flags, pv[2];
  13. 13
    	register struct command *t1;
  14. 14
    	register char *cp;
  15. 15
    	bool forked = 0;
  16. 16
    	bool shudint;
  17. 17
  18. 18
    	if (t == 0)
  19. 19
    		return;
  20. 20
    	switch (t->t_dtyp) {
  21. 21
  22. 22
    	case TCOM:
  23. 23
    		cp = t->t_dcom[0];
  24. 24
    		if ((cp[0] & (QUOTE|TRIM)) == QUOTE)
  25. 25
    			strcpy(cp, cp + 1);
  26. 26
    		if ((t->t_dflg & FREDO) == 0)
  27. 27
    			Dfix(t);		/* $ " ' \ */
  28. 28
    		/* fall into... */
  29. 29
  30. 30
    	case TPAR:
  31. 31
    		flags = t->t_dflg;
  32. 32
    		if (flags & FPOU)
  33. 33
    			mypipe(pipeout);
  34. 34
    		/*
  35. 35
    		 * A child will be interruptible only under very
  36. 36
    		 * certain conditions:
  37. 37
    		 *	we must be monkeying with interrupts
  38. 38
    		 *	the child must not be &'ed
  39. 39
    		 *	we must not have had an "onintr -"
  40. 40
    		 */
  41. 41
    		shudint = setintr && (flags & FINT) == 0 && (!gointr || !eq(gointr, "-"));
  42. 42
  43. 43
    		/*
  44. 44
    		 * Must do << early so parent will know
  45. 45
    		 * where input pointer should be
  46. 46
    		 */
  47. 47
    		if (flags & FHERE)
  48. 48
    			close(0), heredoc(t->t_dlef);
  49. 49
  50. 50
    		/*
  51. 51
    		 * If not executing commands then
  52. 52
    		 * all we must do is read forward in the input to
  53. 53
    		 * account for << redirection if present.
  54. 54
    		 */
  55. 55
    		if (noexec) {
  56. 56
    			if (flags & FHERE)
  57. 57
    				close(0);
  58. 58
    			return;
  59. 59
    		}
  60. 60
  61. 61
    		set("status", "0");
  62. 62
    		pid = 0;
  63. 63
  64. 64
    		/*
  65. 65
    		 * Built-in functions
  66. 66
    		 */
  67. 67
    		if (t->t_dtyp == TCOM && isbfunc(t->t_dcom[0])) {
  68. 68
    			/*
  69. 69
    			 * If output is piped, or running & and we would
  70. 70
    			 * eventually fork for non-builtin commands,
  71. 71
    			 * then do it now, so we won't block.
  72. 72
    			 */
  73. 73
    			if ((flags & (FPOU|FAND)) && (flags & FPAR) == 0)
  74. 74
    				pid = dofork(shudint), forked++;
  75. 75
  76. 76
    			/*
  77. 77
    			 * If the builtin is actually executed (some, e.g.
  78. 78
    			 * time and nice may refuse to execute here)
  79. 79
    			 * then either exit (if we forked) or close i/o
  80. 80
    			 * and continue execution (if we didn't).
  81. 81
    			 */
  82. 82
    			if (pid == 0) {
  83. 83
    				doio(t, pipein, pipeout);
  84. 84
    				if (flags & FPOU) {
  85. 85
    					close(pipeout[0]), close(pipeout[1]);
  86. 86
    					pipeout[0] = pipeout[1] = -1;
  87. 87
    				}
  88. 88
    				if (setintr && forked) {
  89. 89
    					if (shudint)
  90. 90
    						signal(SIGINT, SIG_DFL), signal(SIGQUIT, SIG_DFL);
  91. 91
    					signal(SIGTERM, parterm);
  92. 92
    					if (flags & FINT)
  93. 93
    						setintr = 0;
  94. 94
    				}
  95. 95
    				if (func(t, pipein, pipeout)) {
  96. 96
    					if (forked)
  97. 97
    						exitstat();
  98. 98
    					if (didfds && !(t->t_dflg & FREDO))
  99. 99
    						donefds();
  100. 100
    					return;
  101. 101
    				}
  102. 102
    			}
  103. 103
    		}
  104. 104
  105. 105
    		/*
  106. 106
    		 * Now, we must make a new process since either the
  107. 107
    		 * command is non-builtin, a parenthesized list,
  108. 108
    		 * or builtin such as time or nice which really
  109. 109
    		 * requires a child.
  110. 110
    		 */
  111. 111
    		if (!forked && (flags & FPAR) == 0)
  112. 112
    			pid = dofork(shudint);
  113. 113
    		if (pid != 0) {
  114. 114
    			/*
  115. 115
    			 * The parent path (or nobody does this if
  116. 116
    			 * (flags & FPAR), i.e. date in (set;date))
  117. 117
    			 */
  118. 118
    			if (didfds == 0 && (flags & FPIN))
  119. 119
    				close(pipein[0]), close(pipein[1]);
  120. 120
    			if (didfds && !(t->t_dflg & FREDO))
  121. 121
    				donefds();
  122. 122
    			if (flags & FPRS)
  123. 123
    				printf("%d\n", pid), set("child", putn(pid));
  124. 124
    			/*
  125. 125
    			 * Unless output is piped or command is &
  126. 126
    			 * wait for it.
  127. 127
    			 */
  128. 128
    			if (t->t_dtyp == TCOM)
  129. 129
    				cadd(pid, t->t_dcom[0]);
  130. 130
    			else
  131. 131
    				cadd(pid, "()");
  132. 132
    			if ((flags & (FPOU|FAND)) == 0)
  133. 133
    				pwait(pid);
  134. 134
    			return;
  135. 135
    		}
  136. 136
  137. 137
    		/*
  138. 138
    		 * Insure that this (child) shell doesn't muck on
  139. 139
    		 */
  140. 140
    		child++;
  141. 141
  142. 142
    		/*
  143. 143
    		 * If havent yet, finally set up the file descriptors.
  144. 144
    		 */
  145. 145
    		doio(t, pipein, pipeout);
  146. 146
    		if (flags & FPOU)
  147. 147
    			close(pipeout[0]), close(pipeout[1]);
  148. 148
  149. 149
    		/*
  150. 150
    		 * If mucking with interrupts fix interrupt, quit,
  151. 151
    		 * and terminate handling ... in any case set setintr
  152. 152
    		 * to 0 if we are not interruptible so that no further
  153. 153
    		 * interrupt mucking occurs.
  154. 154
    		 */
  155. 155
    		if (setintr) {
  156. 156
    			if (shudint)
  157. 157
    				signal(SIGINT, SIG_DFL), signal(SIGQUIT, SIG_DFL);
  158. 158
    			signal(SIGTERM, parterm);
  159. 159
    			if (flags & FINT)
  160. 160
    				setintr = 0;
  161. 161
    		}
  162. 162
  163. 163
    		/*
  164. 164
    		 * For () commands must put new 0,1,2 in FSH* and recurse
  165. 165
    		 */
  166. 166
    		if (t->t_dtyp == TPAR) {
  167. 167
    			t1 = t->t_dspr;
  168. 168
    			t1->t_dflg |= flags & FINT;
  169. 169
    			OLDSTD = dcopy(0, FOLDSTD);
  170. 170
    			SHOUT = dcopy(1, FSHOUT);
  171. 171
    			SHDIAG = dcopy(2, FSHDIAG);
  172. 172
    			close(SHIN), SHIN = -1;
  173. 173
    			didcch = 0, didfds = 0;
  174. 174
    			execute(t1);
  175. 175
    			exitstat();
  176. 176
    		}
  177. 177
    		if (eq(t->t_dcom[0], "nice")) {
  178. 178
    /* sigh...
  179. 179
    			nice(20);
  180. 180
    			nice(-10);
  181. 181
    */
  182. 182
    			cp = t->t_dcom[1];
  183. 183
    			if (any(cp[0], "+-"))
  184. 184
    				nice(getn(cp)), lshift(t->t_dcom, 2);
  185. 185
    			else
  186. 186
    				nice(4), lshift(t->t_dcom, 1);
  187. 187
    			t->t_dflg = FPAR | FREDO;
  188. 188
    			execute(t);
  189. 189
    			exitstat();
  190. 190
    		}
  191. 191
    		if (eq(t->t_dcom[0], "nohup")) {
  192. 192
    			if (setintr == 0)
  193. 193
    				signal(SIGHUP, SIG_IGN);
  194. 194
    			lshift(t->t_dcom, 1);
  195. 195
    			t->t_dflg = FPAR | FREDO;
  196. 196
    			execute(t);
  197. 197
    			exitstat();
  198. 198
    		}
  199. 199
    		doexec(t);
  200. 200
    		/* no return */
  201. 201
  202. 202
    	case TFIL:
  203. 203
    		flags = t->t_dflg;
  204. 204
    		t1 = t->t_dcar;
  205. 205
    		t1->t_dflg |= FPOU | (flags & (FPIN|FINT|FPRS|FDIAG));
  206. 206
    		execute(t1, pipein, pv);
  207. 207
    		t1 = t->t_dcdr;
  208. 208
    		t1->t_dflg |= FPIN | (flags & (FPOU|FINT|FAND|FPRS|FPAR));
  209. 209
    		execute(t1, pv, pipeout);
  210. 210
    		return;
  211. 211
  212. 212
    	case TLST:
  213. 213
    		flags = t->t_dflg & FINT;
  214. 214
    		if (t1 = t->t_dcar)
  215. 215
    			t1->t_dflg |= flags, execute(t1);
  216. 216
    		if (t1 = t->t_dcdr)
  217. 217
    			t1->t_dflg |= t->t_dflg & (FINT|FPAR), execute(t1);
  218. 218
    		return;
  219. 219
  220. 220
    	case TOR:
  221. 221
    	case TAND:
  222. 222
    		flags = t->t_dflg & FINT;
  223. 223
    		if (t1 = t->t_dcar) {
  224. 224
    			t1->t_dflg |= flags, execute(t1);
  225. 225
    			if ((getn(value("status")) == 0) == (t->t_dtyp == TAND))
  226. 226
    				return;
  227. 227
    		}
  228. 228
    		if (t1 = t->t_dcdr)
  229. 229
    			t1->t_dflg |= t->t_dflg & (FINT|FPAR), execute(t1);
  230. 230
    		return;
  231. 231
    	}
  232. 232
    }
  233. 233
  234. 234
    doio(t, pipein, pipeout)
  235. 235
    	register struct command *t;
  236. 236
    	int *pipein, *pipeout;
  237. 237
    {
  238. 238
    	register char *cp;
  239. 239
    	register int flags = t->t_dflg;
  240. 240
  241. 241
    	if (didfds || (flags & FREDO))
  242. 242
    		return;
  243. 243
    	if (flags & FHERE)
  244. 244
    		goto skipin;
  245. 245
    	close(0);
  246. 246
    	if (cp = t->t_dlef) {
  247. 247
    		cp = globone(Dfix1(cp));
  248. 248
    		xfree(cp);
  249. 249
    		if (open(cp, 0) < 0)
  250. 250
    			Perror(cp);
  251. 251
    	} else if (flags & FPIN)
  252. 252
    		dup(pipein[0]), close(pipein[0]), close(pipein[1]);
  253. 253
    	else if (flags & FINT)
  254. 254
    		close(0), open("/dev/null", 0);
  255. 255
    	else
  256. 256
    		dup(OLDSTD);
  257. 257
  258. 258
    skipin:
  259. 259
    	close(1);
  260. 260
    	if (cp = t->t_drit) {
  261. 261
    		cp = globone(Dfix1(cp));
  262. 262
    		xfree(cp);
  263. 263
    		if ((flags & FCAT) && open(cp, 1) >= 0)
  264. 264
    			lseek(1, 0l, 2);
  265. 265
    		else {
  266. 266
    			if (!(flags & FANY) && adrof("noclobber")) {
  267. 267
    				if (flags & FCAT)
  268. 268
    					Perror(cp);
  269. 269
    				chkclob(cp);
  270. 270
    			}
  271. 271
    			if (creat(cp, 0644) < 0)
  272. 272
    				Perror(cp);
  273. 273
    		}
  274. 274
    	} else
  275. 275
    		dup((flags & FPOU) ? pipeout[1] : SHOUT);
  276. 276
  277. 277
    	close(2);
  278. 278
    	dup((flags & FDIAG) ? 1 : SHDIAG);
  279. 279
    	didfds = 1;
  280. 280
    }
  281. 281
  282. 282
    dofork(shudint)
  283. 283
    	bool shudint;
  284. 284
    {
  285. 285
    	register int pid, (*savint)();
  286. 286
  287. 287
    	savint = signal(SIGINT, SIG_IGN);
  288. 288
    	pid = fork();
  289. 289
    	if (pid < 0) {
  290. 290
    		signal(SIGINT, savint);
  291. 291
    		error("No more processes");
  292. 292
    	}
  293. 293
    	if (pid == 0) {
  294. 294
    		child++;
  295. 295
    		signal(SIGINT, shudint ? SIG_DFL : savint);
  296. 296
    	} else
  297. 297
    		signal(SIGINT, savint);
  298. 298
    	return (pid);
  299. 299
    }
  300. 300
  301. 301
    mypipe(pv)
  302. 302
    	register int *pv;
  303. 303
    {
  304. 304
  305. 305
    	if (pipe(pv) < 0)
  306. 306
    		goto oops;
  307. 307
    	pv[0] = dmove(pv[0], -1);
  308. 308
    	pv[1] = dmove(pv[1], -1);
  309. 309
    	if (pv[0] >= 0 && pv[1] >= 0)
  310. 310
    		return;
  311. 311
    oops:
  312. 312
    	error("Can't make pipe");
  313. 313
    }
  314. 314
  315. 315
    chkclob(cp)
  316. 316
    	register char *cp;
  317. 317
    {
  318. 318
    	struct stat stb;
  319. 319
  320. 320
    	if (stat(cp, &stb) < 0)
  321. 321
    		return;
  322. 322
    	if ((stb.st_mode & S_IFMT) == S_IFCHR)
  323. 323
    		return;
  324. 324
    	error("%s: File exists", cp);
  325. 325
    }

To the top of this page