1/* execdos.c */ 2/***************************************************************************** 3 �s�������@�o�����������������@�w�s�q 4 5 �mDOS�R�}���h���s�n 6*****************************************************************************/ 7 8#include "xtr.h" 9 10#if defined(__TURBOC__) && __TURBOC__ > 0x0200 11 /* Turbo C++ 1.0, Borland C++ 2.0 �� putenv �́A���̃}�j���A���̋L�q�ɂ� 12 �����āAputenv ������ strdup �ɂ���Ĉ�����������R�s�[���������� 13 environ �ɓo�^���Ă���̂� */ 14 #define PutEnv(env) putenv(env) 15#else 16 #define PutEnv(env) putenv(DupStr(env)) 17#endif 18 19 20static uchar * 21MakeTemp(uchar *buf) 22{ 23#if MSDOS || WINNT 24#define TEMPLATE "X$XXXXXX" 25#else 26#define TEMPLATE "xtrXXXXXX" 27#endif 28 29 static const uchar templet[] = TEMPLATE; 30 if (tmppath) { /* ���ϐ� TMP ������� */ 31 strcpy((char *)buf, (char *)tmppath); 32 PathCat(buf, templet); 33 } else { 34 strcpy((char *)buf, (const char *)templet); 35 } 36#if __human68k__ 37 { 38#if DIRECT_SH 39 extern char *_toslash(); 40 _toslash(buf); 41#else /* !DIRECT_SH */ 42 extern char *_toslash(), *_tobslash(); 43 uchar *shell, *shelltype; 44 enum { 45 SHTYPE_COMMAND, 46 SHTYPE_UNIX, 47 SHTYPE_UNKNOWN 48 } shtype; 49 50 if ((shell = getenv("SYSTEM_SHELL")) != NULL) { 51 shelltype = getenv("SYSTEM_SHELLTYPE"); 52 } else { 53 shell = getenv("SHELL"); 54 shelltype = getenv("SHELLTYPE"); 55 } 56 57 if (shelltype) { 58 if (stricmp(shelltype, "COMMAND") == 0) 59 shtype = SHTYPE_COMMAND; 60 else if (stricmp(shelltype, "UNIX") == 0) 61 shtype = SHTYPE_UNIX; 62 else 63 shtype = SHTYPE_UNKNOWN; 64 } else { 65 if (shell) { 66 int len = strlen(shell); 67 if ((len >= 7 && stricmp(shell + len - 7, "command") == 0) || 68 (len >= 9 && stricmp(shell + len - 9, "command.x") == 0)) 69 shtype = SHTYPE_COMMAND; 70 else 71 shtype = SHTYPE_UNIX; 72 } else { 73 shtype = SHTYPE_COMMAND; 74 } 75 } 76 77 switch (shtype) { 78 case SHTYPE_COMMAND: 79 _tobslash(buf); 80 break; 81 case SHTYPE_UNIX: 82 case SHTYPE_UNKNOWN: 83 default: 84 _toslash(buf); 85 break; 86 } 87#endif /* !DIRECT_SH */ 88 } 89#endif /* __human68k__ */ 90 return (uchar *)mktemp((char *)buf); 91} 92 93#if DIRECT_SH 94#if UNIX 95 96#ifndef FILENAME_MAX 97#define FILENAME_MAX 1024 98#endif 99 100#if !HAVE_PUTENV 101extern int putenv ARGS((const char *)); 102#endif 103extern void include_fd ARGS((int)); 104static int open_file ARGS((const uchar *, int)); 105static int exec_and_include ARGS((int, const uchar *cmd)); 106static void write_here_doc ARGS((int)); 107static const uchar *copy_filename ARGS((uchar *, const uchar *)); 108static int simple_output ARGS((const uchar *, int, int)); 109static int simple_include ARGS((const uchar *, int, int)); 110static int cmd_exec ARGS((const uchar *, int)); 111 112#if !HAVE_DUP2 113int 114dup2(int old_fd, int new_fd) 115{ 116 close(new_fd); 117 return dup(old_fd) != new_fd ? -1 : 0 ; 118} 119#endif 120 121#define READ_MODE 0 122#define CREATE_MODE 1 123#define APPEND_MODE 2 124 125static int 126open_file(const uchar *fname, int mode) 127{ 128 uchar *fn, *errmsg; 129 int open_mode; 130 int fd; 131 132 if (fname == NULL || fname[0] == '\0') { 133 errmsg = "Can't create temporary file."; 134 fn = (uchar *)alloca(FILENAME_MAX); 135 if (!MakeTemp(fn)) 136 Error(errmsg); 137 } else { 138 errmsg = "Can't create file: %s"; 139 fn = (uchar *)fname; 140 } 141 142 if (mode == 0) 143 open_mode = O_RDONLY; 144 else if (mode == 1) 145 open_mode = O_RDWR | O_CREAT | O_TRUNC; 146 else 147 open_mode = O_WRONLY | O_CREAT | O_APPEND; 148 149 if ((fd = open((char *)fn, open_mode, 0644)) < 0) 150 Error(errmsg, fn); 151 152 if (fname == NULL || fname[0] == '\0') 153 unlink((char *)fn); 154 155 return fd; 156} 157 158#ifdef SIGCHLD 159static RETSIGTYPE reap_children ARGS((int)); 160static RETSIGTYPE 161reap_children(int sig) 162{ 163 int status; 164 wait(&status); 165} 166#endif 167 168static int 169exec_and_include(int fd, const uchar *cmd) 170{ 171 if (cmd[0] != '\0') { 172#ifdef __human68k__ 173 uchar fname[FILENAME_MAX]; 174 int save_fds[2]; 175 int pipe_fd; 176 177 if (fd != 0) { 178 save_fds[0] = dup(0); 179 dup2(fd, 0); 180 } 181 182 MakeTemp(fname); 183 save_fds[1] = dup(1); 184 pipe_fd = open_file(fname, CREATE_MODE); 185 dup2(pipe_fd, 1); 186 close(pipe_fd); 187 188 spawnl(P_WAIT, "/bin/sh", "sh", "-c", cmd, (char *)NULL); 189 190 if (fd != 0) { 191 dup2(save_fds[0], 0); 192 close(save_fds[0]); 193 close(fd); 194 } 195 196 dup2(save_fds[1], 1); 197 close(save_fds[1]); 198 199 fd = open_file(fname, READ_MODE); 200 unlink(fname); 201#else /* !__human68k__ */ 202 int pipefds[2]; 203 pid_t child; 204 205 if (pipe(pipefds) < 0) 206 return 1; 207#ifdef SIGCHLD 208 signal(SIGCHLD, reap_children); 209#endif 210 if ((child = fork()) < 0) 211 return 1; 212 213 if (child == 0) { 214 if (fd != 0) { 215 dup2(fd, 0); 216 close(fd); 217 } 218 dup2(pipefds[1], 1); 219 close(pipefds[0]); 220 close(pipefds[1]); 221 222 execl("/bin/sh", "sh", "-c", cmd, (char *)NULL); 223 224 _exit(127); 225 } 226 227 if (fd != 0) 228 close(fd); 229 close(pipefds[1]); 230 231 fd = pipefds[0]; 232#endif /* !__human68k__ */ 233 } 234 235 if (fd != 0) { 236 int save_tmpincludeflag = tmpincludeflag; 237 tmpincludeflag = 1; 238 include_fd(fd); 239 tmpincludeflag = save_tmpincludeflag; 240 } 241 242 return 0; 243} 244 245static void 246write_here_doc(int fd) 247{ 248 int len, n, buflen; 249 uchar *buf, *mbbuf; 250 int contlnflag; 251 252 contlnflag = 0; 253 while ((len = GetLine()) != 0) { 254 ILineNoCount(); 255 if (contlnflag || 256 *ibuf == cmddot_mchar || 257 cmddot_char && *ibuf == cmddot_char) { 258 n = CommandLineEnd(ibuf + 1, contlnflag) - ibuf; 259 if (!contlnflag && 260 CheckBlockEnd(ibuf + 1, n - 1, contlnflag, (const uchar **)NULL)) 261 break; 262 contlnflag = ibuf[n] == '\\'; 263 } 264 buf = AEvalStringN(&buflen, ibuf, len); 265 mbbuf = (uchar *)alloca(buflen * 2 + 1); 266 sjis2mbstring((char *)mbbuf, (char *)buf); 267 write(fd, (char *)mbbuf, strlen((char *)mbbuf)); 268 XFree((voidstar)buf); 269 } 270} 271 272static const uchar * 273copy_filename(uchar *dst, const uchar *src) 274{ 275 int c; 276 277 while ((c = *src) != '\0' && !isspace(c)) { 278 *dst++ = c; 279 src++; 280 } 281 *dst = '\0'; 282 283 return src; 284} 285 286/* !>ofile */ 287/* !>ofile { */ 288static int 289simple_output(const uchar *cmd, int block_mode, int open_mode) 290{ 291 uchar fname[FILENAME_MAX]; 292 int fd; 293 294 copy_filename(fname, SkipSpace(cmd + open_mode)); 295 fd = open_file(fname, open_mode); 296 if (block_mode) 297 write_here_doc(fd); 298 close(fd); 299 300 return 0; 301} 302 303/* !<ifile >ofile */ 304/* !<ifile */ 305static int 306simple_include(const uchar *cmd, int block_mode, int open_mode) 307{ 308 uchar src_fname[FILENAME_MAX]; 309 const uchar *p; 310 311 p = copy_filename(src_fname, SkipSpace(cmd + open_mode)); 312 p = SkipSpace(p); 313 if (*p == '>') { 314 uchar dst_fname[FILENAME_MAX]; 315 char buffer[4096]; 316 int read_fd, write_fd; 317 int n; 318 319 n = 0; 320 while (*p == '>') { 321 p++; 322 n++; 323 } 324 p = SkipSpace(p); 325 if (*p == '\0') 326 return 1; 327 328 copy_filename(dst_fname, p); 329 330 read_fd = open_file(src_fname, READ_MODE); 331 write_fd = open_file(dst_fname, n); 332#ifdef __human68k__ 333 setmode(read_fd, O_BINARY); 334 setmode(write_fd, O_BINARY); 335#endif 336 while ((n = read(read_fd, buffer, sizeof(buffer))) > 0) 337 write(write_fd, buffer, n); 338 close(write_fd); 339 close(read_fd); 340 } else { 341 int save_tmpincludeflag = tmpincludeflag; 342 tmpincludeflag = 0; 343 Include(src_fname, 1); 344 tmpincludeflag = save_tmpincludeflag; 345 } 346 347 return 0; 348} 349 350/* !{ */ 351/* ! cmd { */ 352/* ! cmd >ofile { */ 353/* ! */ 354/* ! cmd */ 355/* ! cmd >ofile */ 356static int 357cmd_exec(const uchar *cmd, int block_mode) 358{ 359 int ret = 0; 360 int fd = 0; 361 const uchar *p; 362 int c; 363 364 if (block_mode) { 365 fd = open_file((uchar *)NULL, CREATE_MODE); 366 write_here_doc(fd); 367 lseek(fd, (off_t)0, 0); 368 } 369 370 p = cmd; 371 while ((c = *p) != '\0' && c != '=' && !isspace(c)) 372 p++; 373 if (c == '=') { 374 putenv((char *)cmd); 375 } else if (c != '\0' && 376 strnicmp("SET", (const char *)cmd, p - cmd) == 0 && 377 (p = SkipSpace(p)) != NULL && 378 *p != '\0') { 379 uchar *buf, *bp; 380 381 bp = buf = (uchar *)alloca(strlen((const char *)p) + 1); 382 while ((c = *p) != '\0' && c != '=' && !isspace(c)) 383 *bp++ = c; 384 *bp++ = '='; 385 strcpy((char *)bp, (char *)(*p == '=' ? p + 1 : p)); 386 putenv((char *)buf); 387 } else 388 ret = exec_and_include(fd, cmd); 389 390 return ret; 391} 392 393static void 394exec_sh_command(const uchar *src) 395{ 396 int block_mode = 0; 397 int ret = 0; 398 int len, buflen, n; 399 uchar *buf, *cmd; 400 401 src = CutSpace(src); 402 len = strlen((const char *)src); 403 if (StrNthE(src, len - 1) == '{') { 404 block_mode = 1; 405 len--; 406 } 407 408 buf = AEvalStringN(&buflen, src, len); 409 cmd = SkipSpace(buf); 410 411 if ((n = strspn((char *)cmd, ">")) > 0) { 412 ret = simple_output(cmd, block_mode, n); 413 } else if ((n = strspn((char *)cmd, "<")) > 0) { 414 ret = simple_include(cmd, block_mode, n); 415 } else { 416 ret = cmd_exec(cmd, block_mode); 417 } 418 419 XFree((voidstar)buf); 420 421 buf = (uchar *)alloca(32); 422 WtNum(buf, ret); 423 SetRetValue(DupStr(buf), strlen((char *)buf)); 424} 425#endif /* UNIX */ 426#endif /* DIRECT_SH */ 427 428void 429ExecDosCommand(const uchar *src) 430/* src: <dos-command-line> ['{']*/ 431{ 432#if UNIX && DIRECT_SH 433 exec_sh_command(src); 434#else /* !(UNIX && DIRECT_SH) */ 435 436#ifndef FILENAME_MAX 437#if MSDOS || WINNT 438#define FILENAME_MAX 80 439#else 440#define FILENAME_MAX 1024 441#endif 442#endif 443 const uchar *srcp = CutSpace(src); 444 uchar fname1[FILENAME_MAX]; 445 uchar fname2[FILENAME_MAX]; 446 FILE *fp = NULL; 447#if UNIX 448 uchar *cmdbuf; 449#else 450 uchar cmdbuf[160]; 451#endif 452 uchar *vbuf = NULL; 453 uchar *cmdp; 454 uchar *p; 455 uchar *argp; 456 int len; 457 int ret = 0; 458 int block_mode = 0; 459 int output_include = 0; 460 int simple_output = 0; 461 int simple_include = 0; 462 int void_cmd = 0; 463 464#if UNIX 465#define ALLOCA(p,n) p = (uchar *)alloca((n)) 466 fname1[0] = fname2[0] = '\0'; 467 cmdbuf = ""; 468#else 469#define ALLOCA(p,n) 470 fname1[0] = fname2[0] = cmdbuf[0] = '\0'; 471#endif 472 473 len = strlen((const char *)srcp); 474 if (StrNthE(srcp, len-1) == '{') { 475 block_mode = 1; 476 --len; 477 } 478 vbuf = AEvalStringN(&len, srcp, len); 479 cmdp = SkipSpace(vbuf); 480 481 if (!*cmdp) { 482 void_cmd = 1; 483 } else if (simple_output = strspn(cmdp, ">")) { 484 strcpy(fname1, SkipSpace(cmdp + simple_output)); 485 if ((fp = fopen(fname1, simple_output == 1 ? WRITE_TEXT : APPEND_TEXT)) == NULL) 486 Error("Can't create file: %s", fname1); 487 } else if (simple_include = strspn(cmdp, "<")) { 488 strcpy(fname2, SkipSpace(cmdp + simple_include)); 489 } 490 if (!simple_output && !(p = strrchr(cmdp, '>')) || strchr(p, '\"')) { 491 /* �o�̓��_�C���N�g�w��i>...�j������������o�͂���荞�ރ��[�h */ 492 output_include = 1; 493 } 494 495 if (block_mode) { 496 /* �u���b�N���� */ 497 int contlnflag = 0; 498 499 if (!simple_output) { 500 if (!MakeTemp(fname1) || 501 (fp = fopen(fname1, WRITE_TEXT)) == NULL || 502 (output_include && !MakeTemp(fname2))) 503 Error("Can't create temporary file."); 504 } 505 if (output_include) { 506 if (void_cmd) { 507 /* !{ */ 508 strcpy(fname2, fname1); 509 } else { 510 /* ! cmd { */ 511 ALLOCA(cmdbuf, 512 strlen(cmdp) + strlen(fname1) + strlen(fname2) + 5); 513 sprintf(cmdbuf, "%s <%s >%s", cmdp, fname1, fname2); 514 } 515 } else if (simple_output) { 516 /* !>ofile { */ 517 ; 518 } else { 519 /* ! cmd >ofile { */ 520 ALLOCA(cmdbuf, strlen(cmdp) + strlen(fname1) + 3); 521 sprintf(cmdbuf, "%s <%s", cmdp, fname1); 522 } 523 for ( ; ; ) { 524 uchar *buf; 525 526 if (!(len = GetLine())) /* �P�s�ǂ�� ibuf �Ɋi�[ */ 527 break; /* EOF �Ȃ�I�� */ 528 ILineNoCount(); 529 if (contlnflag || *ibuf==cmddot_mchar || 530 cmddot_char && *ibuf==cmddot_char) { 531 int n = CommandLineEnd(ibuf+1, contlnflag) - ibuf; 532 if (!contlnflag && 533 CheckBlockEnd(ibuf+1, n-1, contlnflag, (uchar **)NULL)) 534 break; /* ".}" �ŏI�� */ 535 contlnflag = ibuf[n] == '\\'; 536 } 537 buf = AEvalStringN(&len, ibuf, len); 538 fwrite(buf, 1, len, fp); /* �ǂs���t�@�C���ɏ��� */ 539 XFree((voidstar)buf); 540 } 541 542 } else { 543 /* �u���b�N�Ȃ� */ 544 if (output_include) { 545 if (void_cmd) { 546 /* ! */ 547 } else if (simple_include) { 548 /* !<ifile */ 549 ; 550 } else { 551 /* ! cmd */ 552 if (!MakeTemp(fname2)) 553 Error("Can't create temporary file."); 554 ALLOCA(cmdbuf, strlen(cmdp) + strlen(fname2) + 3); 555 sprintf(cmdbuf, "%s >%s", cmdp, fname2); 556 } 557 } else if (simple_output) { 558 /* !>ofile */ 559 ; 560 } else if (simple_include) { 561 /* !<ifile >ofile */ 562#if UNIX 563# if __human68k__ 564# define BINCAT "cat %s" 565# else 566# define BINCAT "/bin/cat %s" 567# endif 568#else 569# define BINCAT "TYPE %s" 570#endif 571 ALLOCA(cmdbuf, strlen(cmdp + 1) + 10); 572 sprintf(cmdbuf, BINCAT, cmdp + 1); 573 } else { 574 /* ! cmd >ofile */ 575 ALLOCA(cmdbuf, strlen(cmdp) + 1); 576 strcpy(cmdbuf, cmdp); 577 } 578 } 579 if (fp) 580 fclose(fp); 581 582 if (!simple_output) { 583 for (argp = cmdp; *argp && *argp != '=' && !isspace(*argp); argp++) ; 584 p = NULL; 585 if (*argp) { 586 if (*argp == '=') { /* ���ϐ��ݒ� */ 587 p = argp; 588 argp = cmdp; 589 } else { 590 *argp++ = '\0'; 591 CutSpace(argp); 592 } 593 } 594 if (!cmdbuf[0]) { 595 ; 596 } else if (p || !stricmp(cmdp, "SET") && (p = strchr(argp, '='))) { 597 /* 598 * ���ϐ��̃Z�b�g 599 * envvar=value 600 * SET envvar=value 601 */ 602#ifndef UNIX 603 *p = '\0'; 604 StrUpper(argp, argp); 605#endif 606 *p = '='; 607 PutEnv(argp); /* SET�R�}���h�́A����ɕϊ� */ 608 output_include = 0; 609 } else { 610 ret = system(cmdbuf); /* DOS �R�}���h���s */ 611 } 612 if (output_include && 613 (simple_include || FileExists(fname2))) { 614 int tmpincludeflag0 = tmpincludeflag; 615 tmpincludeflag = !simple_include; 616 Include(fname2, 1); /* �o�͂���荞�� */ 617 if (!simple_include) 618 remove(fname2); /* �e���|�����t�@�C�������� */ 619 tmpincludeflag = tmpincludeflag0; 620 } 621 if (block_mode) 622 remove(fname1); 623 } 624 XFree((voidstar)vbuf); 625 626 /* ���^�[���R�[�h���Z�b�g */ 627 ALLOCA(cmdbuf, 32); 628 WtNum(cmdbuf, ret); 629 vbuf = DupStr(cmdbuf); 630 SetRetValue(vbuf, strlen(vbuf)); 631#endif /* !(UNIX && DIRECT_SH) */ 632} 633 634/* 635 * Local variables: 636 * mode: c 637 * c-indent-level: 4 638 * c-continued-statement-offset: 4 639 * c-brace-offset: -4 640 * c-argdecl-indent: 4 641 * c-label-offset: -4 642 * tab-width: 4 643 * tab-stop-list: (4 8 12 16 20 24 28 32 36 40 44 48 52 56 60 64 68 72 76 80) 644 * End: 645 */ 646