home *** CD-ROM | disk | FTP | other *** search
- /*
- * tsh - "Troy's Shell" - a command line interface for Windows.
- *
- * Copyright (C) 1994 Troy Rollo <troy@cbme.unsw.EDU.AU>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
- #include <windows.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <fcntl.h>
- #include <dir.h>
- #include <dos.h>
- #include <sys/stat.h>
- #include <io.h>
- #include <time.h>
- #include <ctype.h>
- #include <errno.h>
- #include <toolhelp.h>
- #include <share.h>
- #include <sys/tkwin.h>
- #include <sys/tkern.h>
- #include <sys/tkexec.h>
- #include <sys/task.h>
- #include <sys/wait.h>
- #include <signal.h>
-
-
- char *Months[] =
- {
- "January",
- "February",
- "March",
- "April",
- "May",
- "June",
- "July",
- "August",
- "September",
- "October",
- "November",
- "December"
- };
-
- char *Days[] =
- {
- "Sunday",
- "Monday",
- "Tuesday",
- "Wednesday",
- "Thursday",
- "Friday",
- "Saturday"
- };
-
- struct redirection
- {
- int fd;
- int fdSource;
- int iMode;
- char *pchFile;
- };
-
- struct backend
- {
- int iTask;
- struct backend *pbeNext;
- };
-
- struct backend *pbeList = 0;
-
-
- int parse_command(char const *s);
- char *pwd(void);
-
- static char tmpbuf[2048];
- static char buf[2048] = {0};
- static char title[80] = "tsh";
- static unsigned instance = 0;
- static HWND hWnd = 0;
- static HWND hWndOA;
- static HINSTANCE hInstance;
- static HTASK hTask;
- static BOOL bBreak = FALSE;
-
-
- #pragma argsused
- BOOL CALLBACK _export EnumOldApp(HWND hThisWnd, LPARAM lParam)
- {
- hWndOA = hThisWnd;
- return TRUE;
- }
-
- HTASK GetTaskFromInstance(HINSTANCE hInst)
- {
- TASKENTRY te;
-
- te.dwSize = sizeof(TASKENTRY);
- TaskFirst(&te);
- do
- {
- if (te.hInst == hInst)
- return te.hTask;
- } while (TaskNext(&te));
- return 0;
- }
-
- HINSTANCE GetInstanceFromTask(HTASK hTask)
- {
- TASKENTRY te;
-
- te.dwSize = sizeof(TASKENTRY);
- TaskFirst(&te);
- do
- {
- if (te.hTask == hTask)
- return te.hInst;
- } while (TaskNext(&te));
- return 0;
- }
-
-
- char *BaseName(char *File)
- {
- char *c1;
- char *c2;
-
- c1 = strrchr(File, '\\');
- c2 = strrchr(File, '/');
- if (c1 || c2)
- {
- if (c1 > c2)
- return c1+1;
- else
- return c2+1;
- }
- return File;
- }
-
- #define MAXTASKS 20
-
- char WhiteSpace[] = " \t";
- char EmptyString[] = "";
-
- struct TaskInfo
- {
- HTASK hTask;
- WORD wStatus;
- };
-
- #define EF_BATCH 0x0001
-
- struct ExtTypes
- {
- char Ext[4];
- char Prog[13];
- int Exists;
- int Flags;
- } Extensions[80] =
- {
- "EXE", "", 0, 0,
- "COM", "", 0, 0,
- "TSH", "*", 0, EF_BATCH,
- "BAT", "", 0, 0,
- "PIF", "", 0, 0,
- "", "", 0, 0
- };
-
- BOOL NewDead = FALSE;
-
- struct TaskInfo Tasks[MAXTASKS];
-
- void FlushMessages(void)
- {
- MSG msg;
-
- while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
- {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- }
-
-
- int cmdnum = 0;
-
- char *prompt_names[3] = { "PS1", "PS2", "PS3" };
-
- void PutFormat(char *buffer, char const *format)
- {
- char *c;
- char const *tmp;
- char varname[20];
-
- c = buffer;
- for (;*format;format++)
- {
- switch(*format)
- {
- case '!':
- sprintf(c, "%d", cmdnum);
- c+=strlen(c);
- break;
- case '~':
- strcpy(c, pwd());
- c+=strlen(c);
- break;
- case '$':
- if (format[1]!='{')
- break;
- tmp = ++format;
- while (*format && *format != '}')
- format++;
- if (!*format)
- {
- format--;
- break;
- }
- strncpy(varname, tmp, format-tmp);
- varname[format-tmp] = '\0';
- if ((tmp = getenv(varname)) != 0)
- {
- strcpy(c, tmp);
- c+=strlen(c);
- }
- break;
- default:
- *c++ = *format;
- break;
- }
- }
- *c = '\0';
- }
- void
- add_backend(int iTask)
- {
- struct backend **ppbe;
-
- for (ppbe = &pbeList; *ppbe; ppbe = &(*ppbe)->pbeNext);
- *ppbe = (struct backend *) malloc(sizeof(struct backend));
- (*ppbe)->iTask = iTask;
- (*ppbe)->pbeNext = 0;
- }
-
- BOOL
- remove_backend(int iTask)
- {
- struct backend **ppbe, *pbeTemp;
-
- for (ppbe = &pbeList; *ppbe; ppbe = &(*ppbe)->pbeNext)
- {
- if ((*ppbe)->iTask == iTask)
- {
- pbeTemp = *ppbe;
- *ppbe = pbeTemp->pbeNext;
- free(pbeTemp);
- return TRUE;
- }
- }
- return FALSE;
- }
-
-
-
- void show_prompt(int number)
- {
- char *format;
- char buffer[160];
- char *c;
- char *tmp;
- char varname[20];
- struct time timeval;
- long dateval;
- struct tm *gmt;
-
- c = buffer;
- if ((format = getenv(prompt_names[number])) != 0)
- {
- PutFormat(buffer, format);
- }
- else
- {
- format = getenv("PROMPT");
- for (;*format;format++)
- {
- if (*format == '$')
- {
- switch(*++format)
- {
- case 'p':
- strcpy(c, pwd());
- c+=strlen(c);
- break;
- case 'q':
- *c++ = '=';
- break;
- case '$':
- *c++ = '$';
- break;
- case 't':
- gettime(&timeval);
- sprintf(c, "%02d:%02d:%02d.%02d",
- timeval.ti_hour,
- timeval.ti_min,
- timeval.ti_sec,
- timeval.ti_hund);
- c += strlen(c);
- break;
- case 'd':
- time(&dateval);
- gmt = gmtime(&dateval);
- sprintf(c, "%3.3s %02d-%02d-%04d",
- Days[gmt->tm_wday],
- gmt->tm_mon+1,
- gmt->tm_mday,
- gmt->tm_year+1900);
- c += strlen(c);
- break;
- case 'v':
- sprintf(c, "MS-DOS Version %d.%d", _osmajor, _osminor);
- c += strlen(c);
- break;
- case 'l':
- *c++ = '<';
- break;
- case 'g':
- *c++ = '>';
- break;
- case 's':
- *c++ = ';';
- break;
- case 'c':
- *c++ = ':';
- break;
- case 'r':
- *c++ = '\r';
- break;
- case '_':
- *c++ = '\n';
- break;
- case 'n':
- *c++ = 'A' + getdisk();
- break;
- case 'b':
- *c++ = '|';
- break;
- case 'e':
- *c++ = '\033';
- break;
- case 'h':
- *c++ = '\b';
- break;
- case '!':
- sprintf(c, "%d", cmdnum);
- c+=strlen(c);
- break;
- case '\0':
- format--;
- }
- }
- else
- (*c++ = *format);
- }
- *c = '\0';
- }
- printf("%s", buffer);
- if (hWnd && (format = getenv("WS1")) != 0)
- {
- PutFormat(buffer, format);
- SetWindowText(hWnd, buffer);
- }
- }
-
- #pragma argsused
- void
- IntCatcher(int nSig)
- {
- bBreak = TRUE;
- signal(SIGINT, IntCatcher);
- }
-
-
- #pragma argsused
- main(int argc, char **argv)
- {
- int i;
- FILE *fp;
- long wstatus;
- short pid;
-
- hTask = GetCurrentTask();
- hInstance = GetInstanceFromTask(hTask);
- for (i = 0; i<MAXTASKS; i++)
- Tasks[i].hTask = 0;
- if (tkern_is_device(0, "window"))
- hWnd = (HWND) ioctl(0, WIOCGETHANDLE);
- signal(SIGINT, IntCatcher);
-
- if ((fp = fopen("C:\\AUTOEXEC.TSH", "r")) != 0)
- {
- while (!bBreak && fgets(buf, 2048, fp))
- {
- buf[strlen(buf)-1] = '\0';
- parse_command(buf);
- }
- fclose(fp);
- }
- while(1)
- {
- ++cmdnum;
- while ((pid = waitpid(0, &wstatus , WNOHANG)) > 0)
- {
- if (remove_backend(pid))
- ;
- else if (WIFEXITED(wstatus))
- printf("%d - Exit %d\n",
- (int) pid,
- (int) WEXITSTATUS(wstatus));
- else if (WIFSTOPPED(wstatus))
- printf("%d - Stopped\n",
- (int) pid);
- else
- printf("%d - Terminated (Signal %d)\n",
- (int) pid,
- (int) WTERMSIG(wstatus));
- }
- if (bBreak)
- {
- printf("\nInterrupt\n");
- bBreak = FALSE;
- }
- show_prompt(0);
- if (bBreak)
- bBreak = FALSE;
- if (!gets(buf))
- break;
- if (bBreak)
- bBreak = FALSE;
- parse_command(buf);
- }
- return 0;
- }
-
- #pragma argsused
- char *pwd(void)
- {
- static char buf[256];
- char *s;
-
- return ((s = getcwd(buf, 255)) != 0) ? s : "invalid";
- }
-
- #pragma argsused
- int do_pwd(int argc, char **argv)
- {
- printf("Current directory is %s\n", pwd());
- return 0;
- }
-
- int do_chdrive(char *s)
- {
- if (islower(*s))
- *s=toupper(*s);
- if (s[1] == ':')
- {
- setdisk(s[0] - 'A');
- return 0;
- }
- else
- {
- return 1;
- }
- }
-
- int do_cd(int argc, char **argv)
- {
- if (argc != 1)
- {
- printf("Usage: cd directory\n");
- return 1;
- }
- if (argv[0][1] == ':')
- {
- // allow drives in here too
- if (do_chdrive(argv[0]))
- return 2;
- argv[0] += 2;
- }
- if (*argv[0] && chdir(argv[0]))
- {
- printf("File not found\n");
- return 3;
- }
- else
- return 0;
- }
-
- #define DF_LONG 1
- #define DF_SIZE 2
- #define DF_ALL 4
- #define DF_PC 8
- #define DF_DIRONLY 16
- #define DF_SPC 32
- #define DF_RECUR 64
- #define DF_DOS 128
-
- void show_filename(char *directory, struct find_t *pinfo, unsigned Flags, unsigned FileNo)
- {
- struct stat sbuf;
- char attributes[8];
- char *c, *c2;
- struct tm *modtime;
- char path[256];
- char specialc;
-
- strcpy(path, directory);
- if (path[0] && path[strlen(path) - 1] != '\\')
- strcat(path, "\\");
- strcat(path, pinfo->name);
- stat(path, &sbuf);
- c=attributes;
- specialc = ' ';
- switch(sbuf.st_mode&S_IFMT)
- {
- case S_IFDIR:
- *c++='d';
- specialc = '/';
- break;
- case S_IFIFO:
- *c++='p';
- break;
- case S_IFCHR:
- *c++='c';
- break;
- case S_IFBLK:
- *c++='b';
- break;
- default:
- *c++='-';
- break;
- }
- modtime = localtime(&sbuf.st_mtime);
- *c++=(sbuf.st_mode&S_IREAD)?'r':'-';
- if ((sbuf.st_mode&S_IFMT) == S_IFDIR)
- *c++ = 'w';
- else
- *c++=(sbuf.st_mode&S_IWRITE)?'w':'-';
- if ((c2 = strrchr(pinfo->name, '.')) != 0 &&
- !(strcmp(c2+1, "EXE") &&
- strcmp(c2+1, "COM") &&
- strcmp(c2+1, "BAT") &&
- strcmp(c2+1, "DIR") &&
- strcmp(c2+1, "TEX") &&
- strcmp(c2+1, "TCO") &&
- strcmp(c2+1, "TSH")))
- {
- specialc = '*';
- *c++ = 'x';
- }
- else
- *c++=(sbuf.st_mode&S_IEXEC)?'x':'-';
- *c++=(pinfo->attrib & _A_SYSTEM)?'s':'-';
- *c++=(pinfo->attrib & _A_HIDDEN)?'h':'-';
- *c++=(pinfo->attrib & _A_ARCH)?'a':'-';
- *c='\0';
- if (!(sbuf.st_mode&S_IFDIR))
- for (c=pinfo->name; *c; c++)
- if (isupper(*c))
- *c=tolower(*c);
- if (!(Flags & DF_PC))
- specialc = ' ';
- if (Flags & DF_DOS)
- {
- if (sbuf.st_mode&S_IFDIR)
- {
- printf("%-12s <DIR> %2d-%02d-%02d %02d:%02d%c\n",
- pinfo->name, modtime->tm_mon+1, modtime->tm_mday,
- modtime->tm_year,
- (modtime->tm_hour==0)?12:(
- (modtime->tm_hour<12)?modtime->tm_hour:(modtime->tm_hour-12)),
- modtime->tm_min, (modtime->tm_hour<12)?'a':'p');
- }
- else
- {
- printf("%-12s %9ld %2d-%02d-%02d %02d:%02d%c\n",
- pinfo->name, pinfo->size,
- modtime->tm_mon+1, modtime->tm_mday,
- modtime->tm_year,
- (modtime->tm_hour==0)?12:(
- (modtime->tm_hour<12)?modtime->tm_hour:(modtime->tm_hour-12)),
- modtime->tm_min, (modtime->tm_hour<12)?'a':'p');
- }
- }
- else if (Flags & DF_LONG)
- {
- printf(" %s %8ld %2d-%3.3s-%2.2d %02d:%02d %s%c\n",
- attributes, pinfo->size,
- modtime->tm_mday, Months[modtime->tm_mon], modtime->tm_year,
- modtime->tm_hour, modtime->tm_min, pinfo->name, specialc);
- }
- else
- {
- printf("%s%c%*.*s", pinfo->name, specialc,
- 14-strlen(pinfo->name), 14-strlen(pinfo->name), " ");
- if (FileNo%5 == 4)
- putchar('\n');
- }
- }
-
- void list_file(char *name, unsigned Flags)
- {
- char dirname[80];
- char wildcard[80];
- unsigned attrib;
- unsigned files;
- unsigned long bytes;
- struct find_t info;
- struct stat sbuf;
-
- strcpy(dirname, name);
- *BaseName(dirname) = '\0';
- strcpy(wildcard, name);
- if (strlen(wildcard) == 2 && wildcard[1] == ':')
- strcat(wildcard, ".");
- attrib = _A_NORMAL | _A_SUBDIR | _A_RDONLY;
- if (Flags & DF_ALL)
- attrib |= _A_SYSTEM | _A_HIDDEN;
- if (!(Flags&DF_DIRONLY) &&
- !strchr(wildcard, '?') &&
- !strchr(wildcard, '*') &&
- stat(wildcard, &sbuf) != -1 &&
- (sbuf.st_mode & S_IFMT) == S_IFDIR)
- {
- if (wildcard[strlen(wildcard)-1] != '\\')
- {
- strcat(wildcard, "\\");
- strcpy(dirname, wildcard);
- }
- strcat(wildcard, "*.*");
- }
- files = 0;
- if (_dos_findfirst(wildcard, attrib, &info) != 0)
- {
- printf("%s: File Not Found\n", wildcard);
- return;
- }
- files = 0;
- bytes = 0;
- do
- {
- if (*info.name == '.' && !(Flags&DF_SPC))
- continue;
- show_filename(dirname, &info, Flags, files);
- files++;
- bytes += info.size;
- } while (!bBreak && _dos_findnext(&info) == 0);
- if (!(Flags & (DF_DOS | DF_LONG)) && (files % 5))
- putchar('\n');
- printf("%5u File(s)\t%lu bytes\n", files, bytes);
- return;
- }
-
-
- int do_std_dir(int argc, char **argv, unsigned Flags)
- {
- struct find_t info;
- unsigned long bytes;
- unsigned attrib, files;
- char *arg;
- struct stat sbuf;
-
- while (argc && **argv == '-')
- {
- argc--;
- arg = *argv++;
- while (*++arg)
- {
- switch(*arg)
- {
- case 'l':
- Flags |= DF_LONG;
- break;
- case 'a':
- Flags |= DF_ALL | DF_SPC;
- break;
- case 'A':
- Flags |= DF_ALL;
- break;
- case 's':
- Flags |= DF_SIZE;
- break;
- case 'C':
- break; /* No op */
- case 'd':
- Flags |= DF_DIRONLY;
- break;
- case 'F':
- Flags |= DF_PC;
- break;
- case 'R':
- Flags |= DF_RECUR;
- break;
- case 'D':
- Flags |= DF_DOS;
- break;
- case 'W':
- case 'w':
- Flags &= ~DF_DOS;
- default:
- fprintf(stderr, "Usage: ls [-laAsCdFRDwW] [directories]\n");
- return 1;
- }
- }
- }
- if (argc)
- {
- while (argc--)
- list_file(*argv++, Flags);
- }
- else
- list_file(".", Flags);
- return 0;
- }
-
- int do_dir(int argc, char **argv)
- {
- return do_std_dir(argc, argv, 0);
- }
-
- int do_dos_dir(int argc, char **argv)
- {
- return do_std_dir(argc, argv, DF_DOS);
- }
-
- int do_df(int argc, char **argv)
- {
- struct diskfree_t dtable;
- char drive;
- long nKbytes;
-
- printf("Drive CSize Total Free KB Free %%Used\n");
- if (argc)
- {
- while (argc--)
- {
- if (!_dos_getdiskfree(toupper(*argv[0]) - '@', &dtable))
- {
- nKbytes = (long) dtable.avail_clusters *
- (long) dtable.sectors_per_cluster *
- (long) dtable.bytes_per_sector /
- 1024l;
- printf("%c: %7u %7u %7u %9lu %5.1f\n",
- toupper(*argv[0]),
- dtable.sectors_per_cluster * dtable.bytes_per_sector,
- dtable.total_clusters,
- dtable.avail_clusters,
- nKbytes,
- ((float) dtable.total_clusters - dtable.avail_clusters) /
- dtable.total_clusters * 100.0);
- }
- else
- {
- printf("Invalid drive specification\n");
- }
- argv++;
- }
- return 0;
- }
- for (drive = 3; drive < 26; drive++)
- {
- if (bBreak)
- break;
- if (_dos_getdiskfree(drive, &dtable))
- continue;
- nKbytes = (long) dtable.avail_clusters *
- (long) dtable.sectors_per_cluster *
- (long) dtable.bytes_per_sector /
- 1024l;
- printf("%c: %7u %7u %7u %9lu %5.1f\n",
- (char) ('@' + drive),
- dtable.sectors_per_cluster * dtable.bytes_per_sector,
- dtable.total_clusters,
- dtable.avail_clusters,
- nKbytes,
- (float) (((float) dtable.total_clusters - dtable.avail_clusters) /
- dtable.total_clusters * 100.0));
- }
- return 0;
- }
-
-
-
- char *expand_wildcards(char *s)
- {
- static struct find_t info;
- char wildcard[80];
- static char directory[256];
- static char filename[256];
- unsigned attrib;
- char *c1, *c2;
-
- if (s)
- {
- strcpy(wildcard, s);
- strcpy(directory, wildcard);
- if ((c1 = strrchr(directory, '/')) != 0 ||
- (c2 = strrchr(directory, '\\')) != 0)
- {
- if (c1 > c2)
- c1[1] = '\0';
- else
- c2[1] = '\0';
- }
- else
- directory[0] = '\0';
- if (! strchr(wildcard, '.'))
- strcat(wildcard, "*.*");
- attrib = _A_NORMAL | _A_SUBDIR | _A_RDONLY;
- if (_dos_findfirst(wildcard, attrib, &info) != 0)
- return NULL;
- while (!strcmp(info.name, ".") || !strcmp(info.name, ".."))
- if (_dos_findnext(&info))
- return NULL;
- }
- else
- {
- if (_dos_findnext(&info) != 0)
- return NULL;
- }
- strcpy(filename, directory);
- strcat(filename, info.name);
- return filename;
- }
-
-
- char *FindExe(char *Path, char *Name, int *batch)
- {
- static char ExecLine[256];
- struct find_t info;
- char wildcard[160];
- int i;
- unsigned attrib;
- char *Ext;
- int r;
- int HasExt = 0;
-
- *batch = 0;
- for (i=0; *Extensions[i].Ext; i++)
- Extensions[i].Exists = 0;
- if (Path)
- {
- strcpy(wildcard, Path);
- strcat(wildcard, "\\");
- }
- else
- *wildcard = '\0';
- strcat(wildcard, Name);
- if (! strchr(Name, '.'))
- strcat(wildcard, ".*");
- else
- HasExt = 1;
- attrib = _A_NORMAL | _A_SUBDIR | _A_RDONLY;
- for (r = _dos_findfirst(wildcard, attrib, &info); !r; r = _dos_findnext(&info))
- {
- if ((Ext = strchr(info.name, '.')) == 0)
- continue;
- Ext++;
- for (i = 0; *Extensions[i].Ext; i++)
- {
- if (!stricmp(Extensions[i].Ext, Ext))
- {
- Extensions[i].Exists = 1;
- break;
- }
- }
- }
- for (i = 0; *Extensions[i].Ext; i++)
- {
- if (Extensions[i].Exists)
- {
- if (*Extensions[i].Prog == '*')
- {
- *batch = 1;
- *ExecLine = '\0';
- }
- else if (*Extensions[i].Prog)
- {
- strcpy(ExecLine, Extensions[i].Prog);
- strcat(ExecLine, " ");
- }
- else
- *ExecLine = '\0';
- if (Path)
- strcat(ExecLine, Path);
- if (*ExecLine && ExecLine[strlen(ExecLine) - 1] != '\\')
- strcat(ExecLine, "\\");
- strcat(ExecLine, Name);
- if (!HasExt)
- {
- strcat(ExecLine, ".");
- strcat(ExecLine, Extensions[i].Ext);
- }
- return ExecLine;
- }
- }
- return NULL;
- }
-
- char *FindPath(char *s, int *IsBatch)
- {
- char PathList[256];
- char *ExeName;
- char *PathElement;
-
- if (strchr(s, '/') || strchr(s, '\\'))
- {
- return FindExe(NULL, s, IsBatch);
- }
- strcpy(PathList, ".;");
- strcat(PathList, getenv("PATH"));
- for (PathElement = strtok(PathList, ";"); PathElement; PathElement = strtok(NULL, ";"))
- if ((ExeName = FindExe(PathElement, s, IsBatch)) != 0)
- return ExeName;
- return NULL;
- }
-
-
- int do_activate(int argc, char **argv)
- {
- HWND hWnd;
-
- while (argc--)
- {
- hWnd = FindWindow(NULL, *argv);
- if (hWnd)
- {
- argv++;
- BringWindowToTop(hWnd);
- if (IsIconic(hWnd))
- ShowWindow(hWnd, SW_RESTORE);
- }
- else
- {
- fprintf(stderr, "%s: Window not found\n", argv);
- return 1;
- }
- }
- return 0;
- }
-
- struct alias
- {
- struct alias *next;
- char *name;
- char *text;
- int inuse;
- };
-
- struct alias *alias_list = NULL;
-
- int do_alias(int argc, char **argv)
- {
- char *c;
- struct alias *Alias;
- int i;
- int len;
-
- if (argc)
- {
- if (argc > 1)
- {
- for (len = 0, i = 1; i < argc; i++)
- len += strlen(argv[i]);
- len += argc - 1;
- Alias = malloc(sizeof(struct alias));
- Alias->name = malloc(strlen(argv[0])+1);
- Alias->text = malloc(len);
- strcpy(Alias->name, argv[0]);
- strcpy(Alias->text, argv[1]);
- for (i = 2; i < argc; i++)
- {
- strcat(Alias->text, " ");
- strcat(Alias->text, argv[i]);
- }
- Alias->inuse = 0;
- Alias->next = alias_list;
- alias_list = Alias;
- }
- else
- {
- for (Alias = alias_list; Alias!=NULL; Alias = Alias->next)
- {
- if (!strcmp(Alias->name, argv[0]))
- {
- printf("%-10s %s\n", argv[0], Alias->text);
- return 0;
- }
- }
- fprintf(stderr, "No such alias: %s\n", argv[0]);
- return 1;
- }
- }
- else
- {
- for (Alias = alias_list; Alias; Alias = Alias->next)
- printf("%-10s %s\n", Alias->name, Alias->text);
- }
- return 0;
- }
-
- int do_set(int argc, char **argv)
- {
- char *word;
- char *value, envvar[160];
- char *putable;
- int i;
- char **current;
-
- if (!argc)
- {
- for (current = environ; *current; current++)
- printf("%s\n", *current);
- return 0;
- }
- if (argc > 1)
- {
- sprintf(envvar, "%s=%s", argv[0], argv[1]);
- for (i = 2; i < argc; i++)
- {
- strcat(envvar, " ");
- strcat(envvar, argv[i]);
- }
- putable = malloc(strlen(envvar)+1);
- strcpy(putable, envvar);
- if (putenv(putable))
- {
- fprintf(stderr, "%s: %s\n", putable, sys_errlist[errno]);
- free(putable);
- }
- }
- else
- {
- if ((value = getenv(argv[0])) != 0)
- {
- printf("%s=%s\n", argv[0], value);
- }
- else
- {
- printf("No value for %s\n", argv[0]);
- return 1;
- }
- }
- return 0;
- }
-
- int do_mkdir(int argc, char **argv)
- {
- if (!argc)
- {
- fprintf(stderr, "Must specify a directory for mkdir\n");
- return 0;
- }
- while (!bBreak && argc--)
- {
- if (mkdir(*argv)==-1)
- {
- fprintf(stderr, "%s: %s\n", argv[0], sys_errlist[errno]);
- return 1;
- }
- argv++;
- }
- return 0;
- }
-
- int do_rmdir(int argc, char **argv)
- {
- if (!argc)
- {
- printf("Must specify a directory for rmdir\n");
- return 1;
- }
- while (!bBreak && argc--)
- {
- if (rmdir(*argv)==-1)
- {
- fprintf(stderr, "%s: %s\n", argv[0], sys_errlist[errno]);
- return 1;
- }
- argv++;
- }
- return 0;
- }
-
-
- int do_del(int argc, char **argv)
- {
- int files;
- char *sfile;
- int error;
-
- if (!argc)
- {
- printf("Must specify files for del\n");
- return 1;
- }
- while (!bBreak && argc--)
- {
- for (files = 0, sfile = expand_wildcards(argv[0]);
- !bBreak && sfile;
- files++, sfile = expand_wildcards(NULL))
- {
- if (unlink(sfile)==-1)
- {
- fprintf(stderr, "%s: %s\n", sfile, sys_errlist[errno]);
- error = 1;
- }
- }
- if (!files)
- {
- fprintf(stderr, "%s: file not found\n", argv[0]);
- error = 1;
- }
- argv++;
- }
- return error;
- }
-
- int do_type(int argc, char **argv)
- {
- int files;
- char *sfile;
- FILE *fp;
- char Buffer[512];
- int nread;
- int error = 0;
-
- if (!argc)
- {
- fprintf(stderr, "Must specify files for type\n");
- return 1;
- }
- while (!bBreak && argc--)
- {
- for (files = 0, sfile = expand_wildcards(argv[0]);
- !bBreak && sfile;
- files++, sfile = expand_wildcards(NULL))
- {
- if ((fp = fopen(sfile, "r")) == NULL)
- {
- fprintf(stderr, "%s: %s\n", sfile, sys_errlist[errno]);
- error = 1;
- continue;
- }
- while (!bBreak &&
- (nread = fread(Buffer, 1, 512, fp)) > 0)
- fwrite(Buffer, 1, nread, stdout);
- fclose(fp);
- }
- if (!files)
- {
- fprintf(stderr, "%s: file not found\n", argv[0]);
- error = 1;
- }
- argv++;
- }
- return error;
- }
-
- #pragma argsused
- int do_mem(int argc, char **argv)
- {
- printf("%ldK free %d%% System Resources free\n",
- GetFreeSpace(0) / 1024,
- GetFreeSystemResources(GFSR_SYSTEMRESOURCES));
- return 0;
- }
-
- #pragma argsused
- int do_sysinfo(int argc, char **argv)
- {
- DWORD sys_info;
-
- sys_info = GetWinFlags();
-
- if (sys_info & WF_80x87)
- printf("Maths Coprocessor Present\n");
- if (sys_info & WF_CPU286)
- printf("80286 Processor\n");
- if (sys_info & WF_CPU386)
- printf("80386 Processor\n");
- if (sys_info & WF_CPU486)
- printf("i486 Processor\n");
- if (sys_info & WF_ENHANCED)
- printf("Enhanced Mode\n");
- if (sys_info & WF_STANDARD)
- printf("Standard Mode\n");
- if (sys_info & WF_PAGING)
- printf("System has paging\n");
- return 0;
- }
-
- /*
- * ps - list all running tasks with useful info. Note that while we are printing,
- * we may process messages. Once this happens, the task list may be in a new order.
- * consequently, we must build the list without displaying, and then display the
- * results from the list.
- */
-
- extern int tkern_total_zombies(void);
- extern int tkern_list_zombies(struct tk_process *, int);
- extern int tkern_get_process(HTASK, struct tk_process *);
-
- #pragma argsused
- int do_ps(int argc, char **argv)
- {
- TASKENTRY te;
- FARPROC lpfnEnumWndProc;
- char TaskName[160];
- int nTasks = 0;
- int iTask = 0;
- TASKENTRY *teList;
- char **ppchTaskNames;
- struct tk_process *pZombies;
- struct tk_process *pProcesses;
- int nZombies;
- int i;
-
- te.dwSize = sizeof(TASKENTRY);
- printf(" PID PPID Task Parent Hinst Events StkSz Command\n");
- lpfnEnumWndProc = MakeProcInstance((FARPROC) EnumOldApp, hInstance);
- TaskFirst(&te);
- do
- {
- nTasks++;
- } while (TaskNext(&te));
- pProcesses = (struct tk_process *) malloc(sizeof(*pProcesses) * nTasks);
- nZombies = tkern_total_zombies();
- if (nZombies)
- {
- pZombies = (struct tk_process *) malloc(sizeof(*pZombies) * nZombies);
- tkern_list_zombies(pZombies, nZombies);
- }
- teList = (TASKENTRY *) malloc(sizeof(TASKENTRY) * nTasks);
- ppchTaskNames = malloc(sizeof(char *) * nTasks);
- memset(ppchTaskNames, 0, sizeof(char *) * nTasks);
- TaskFirst(&te);
- do
- {
- teList[iTask] = te;
- tkern_get_process(te.hTask, &pProcesses[iTask]);
- strcpy(TaskName, teList[iTask].szModule);
- if (!strcmp(TaskName, "WINOLDAP"))
- {
- hWndOA = 0;
- EnumTaskWindows(teList[iTask].hTask, (WNDENUMPROC) lpfnEnumWndProc, 0L);
- if (hWndOA)
- GetWindowText(hWndOA, TaskName, 160);
- ppchTaskNames[iTask] = malloc(strlen(TaskName) + 1);
- strcpy(ppchTaskNames[iTask], TaskName);
- }
- iTask++;
- } while (TaskNext(&te));
- for (iTask = 0; iTask < nTasks; iTask++)
- {
- printf("%5d %5d %5d %5d %5d %5d %4x %s\n",
- pProcesses[iTask].pid,
- pProcesses[iTask].pidParent,
- teList[iTask].hTask,
- teList[iTask].hTaskParent,
- teList[iTask].hInst,
- teList[iTask].wcEvents,
- teList[iTask].wStackBottom - teList[iTask].wStackTop,
- ppchTaskNames[iTask] ? ppchTaskNames[iTask] : teList[iTask].szModule);
- if (ppchTaskNames[iTask])
- free(ppchTaskNames[iTask]);
- }
- free(ppchTaskNames);
- free(teList);
- free(pProcesses);
- FreeProcInstance(lpfnEnumWndProc);
- if (nZombies)
- {
- for (i = 0; i < nZombies; i++)
- printf("%5d %5d <defunct>\n",
- (int) pZombies[i].pid,
- (int) pZombies[i].pidParent);
- free(pZombies);
- }
- return 0;
- }
-
- int do_kill(int argc, char **argv)
- {
- int signal;
- char *flags;
- int pid;
- BOOL bError = FALSE;
-
- if (argc && *argv[0] == '-')
- {
- signal = atoi(argv[0]+1);
- argc--;
- argv++;
- }
- else
- signal = 14;
-
- if (!argc)
- {
- printf("Usage: kill [-#] task\n");
- return 1;
- }
- do
- {
- pid = atoi(argv[0]);
- if (kill(pid, signal) == -1)
- fprintf(stderr, "%d: %s\n", pid, sys_errlist[errno]);
- argv++;
- } while (--argc);
- return bError;
- }
-
- #pragma argsused
- int do_date(int argc, char **argv)
- {
- long tm;
-
- time(&tm);
- printf("%s", ctime(&tm));
- return 0;
- }
-
- int do_mv(int argc, char **argv)
- {
- char *dest;
- struct stat sbuf;
- char TmpBuffer[160];
- char *FileStart;
- char *sfile;
- int files;
- int error = 0;
-
- if ((argc > 2 && (stat(argv[argc-1], &sbuf) == -1 ||
- !(sbuf.st_mode & S_IFDIR))) ||
- argc < 2)
- {
- fprintf(stderr, "Usage: mv file1 file2\n mv files directory\n");
- return 1;
- }
-
- dest = argv[argc-1];
- argc--;
- if (strlen(dest) == 2 && dest[1] == ':')
- {
- strcpy(TmpBuffer, dest);
- strcat(TmpBuffer, ".\\");
- dest = TmpBuffer;
- FileStart = TmpBuffer + strlen(TmpBuffer);
- }
- else if (stat(dest, &sbuf) != -1 && sbuf.st_mode & S_IFDIR)
- {
- strcpy(TmpBuffer, dest);
- if (TmpBuffer[strlen(TmpBuffer)-1] != '\\')
- strcat(TmpBuffer, "\\");
- FileStart = TmpBuffer + strlen(TmpBuffer);
- dest = TmpBuffer;
- }
- else
- FileStart = NULL;
- while (!bBreak && argc--)
- {
- for (files = 0, sfile = expand_wildcards(argv[0]);
- !bBreak && sfile;
- files++, sfile = expand_wildcards(NULL))
- {
- if (FileStart)
- strcpy(FileStart, BaseName(sfile));
- if (rename(sfile, dest) == -1)
- {
- fprintf(stderr, "%s: %s\n", sfile, sys_errlist[errno]);
- error = 1;
- }
- }
- if (!files)
- {
- fprintf(stderr, "%s: File not found\n", argv[0]);
- error = 1;
- }
- argv++;
- }
- return error;
- }
-
- int do_exit(int argc, char **argv)
- {
- if (argc)
- exit(atoi(argv[0]));
- else
- exit(0);
- return -1;
- }
-
-
-
- int do_copy(int argc, char **argv)
- {
- char *dest;
- struct stat sbuf;
- char TmpBuffer[160];
- char Buffer[512];
- char *FileStart;
- char *sfile;
- int files;
- int fdin, fdout;
- int nread;
- char far *lpchBuffer;
- HANDLE hMem;
- unsigned uDate, uTime;
- int error = 0;
-
- if ((argc > 2 && (stat(argv[argc-1], &sbuf) == -1 ||
- !(sbuf.st_mode & S_IFDIR))) ||
- argc < 2)
- {
- fprintf(stderr, "Usage: copy file1 file2\n copy files directory\n");
- return 1;
- }
-
- dest = argv[argc-1];
- argc--;
- if (strlen(dest) == 2 && dest[1] == ':')
- {
- strcpy(TmpBuffer, dest);
- strcat(TmpBuffer, ".\\");
- dest = TmpBuffer;
- FileStart = TmpBuffer + strlen(TmpBuffer);
- }
- else if (stat(dest, &sbuf) != -1 && sbuf.st_mode & S_IFDIR)
- {
- strcpy(TmpBuffer, dest);
- if (TmpBuffer[strlen(TmpBuffer)-1] != '\\')
- strcat(TmpBuffer, "\\");
- FileStart = TmpBuffer + strlen(TmpBuffer);
- dest = TmpBuffer;
- }
- else
- FileStart = NULL;
- hMem = GlobalAlloc(GMEM_FIXED, 32000);
- lpchBuffer = GlobalLock(hMem);
- while (!bBreak && argc--)
- {
- for (files = 0, sfile = expand_wildcards(argv[0]);
- !bBreak && sfile;
- files++, sfile = expand_wildcards(NULL))
- {
- if (FileStart)
- strcpy(FileStart, BaseName(sfile));
- if ((fdin = _lopen(sfile, READ)) == -1)
- {
- fprintf(stderr, "Cannot open %s: %s\n", sfile, sys_errlist[errno]);
- error = 1;
- continue;
- }
- if ((fdout = _lcreat(dest, 0)) == -1)
- {
- _lclose(fdin);
- fprintf(stderr, "Cannot create %s: %s\n", dest, sys_errlist[errno]);
- error = 1;
- continue;
- }
- while (!bBreak && (nread = _lread(fdin, lpchBuffer, 32000)) != 0)
- _lwrite(fdout, lpchBuffer, nread);
-
- _dos_getftime(fdin, &uDate, &uTime);
- _dos_setftime(fdout, uDate, uTime);
- _lclose(fdin);
- _lclose(fdout);
- if (bBreak)
- unlink(dest);
- }
- if (!files)
- {
- fprintf(stderr, "%s: File not found\n", argv[0]);
- error = 1;
- }
- argv++;
- }
- GlobalUnlock(hMem);
- GlobalFree(hMem);
- return error;
- }
-
- int do_echo(int argc, char **argv)
- {
- while (argc--)
- printf("%s ", *argv++);
- printf("\n");
- return 0;
- }
-
- #pragma argsused
- int
- do_true(int argc,
- char **argv)
- {
- return 0;
- }
-
- #pragma argsused
- int
- do_false(int argc,
- char **argv)
- {
- return 1;
- }
-
- struct
- {
- char *name;
- int (*func)(int argc, char **argv);
- } command_list[] = {
- ":", do_true,
- "ACTIVATE", do_activate,
- "ALIAS", do_alias,
- "CD", do_cd,
- "COPY", do_copy,
- "DATE", do_date,
- "DEL", do_del,
- "DF", do_df,
- "DIR", do_dos_dir,
- "ECHO", do_echo,
- "EXIT", do_exit,
- "FALSE", do_false,
- "KILL", do_kill,
- "LS", do_dir,
- "MEM", do_mem,
- "MKDIR", do_mkdir,
- "MV", do_mv,
- "PS", do_ps,
- "PWD", do_pwd,
- "RMDIR", do_rmdir,
- "SET", do_set,
- "SYSINFO", do_sysinfo,
- "TRUE", do_true,
- "TYPE", do_type,
- 0, 0
- };
-
-
- #pragma argsused
- int RunBatch(char *FileName, char **argv, int argc)
- {
- FILE *fp;
- char buf[2048];
-
- if ((fp = fopen(FileName, "r")) == 0)
- {
- while (!bBreak && fgets(buf, 2048, fp))
- {
- buf[strlen(buf)-1] = '\0';
- parse_command(buf);
- }
- fclose(fp);
- return 0;
- }
- else
- {
- printf("%s: %s\n", FileName, sys_errlist[errno]);
- return -1;
- }
-
- }
-
- int expand_alias(char const *cmd, char const *args, int *retval)
- {
- char *expanded;
- struct alias *Alias;
-
- for (Alias = alias_list; Alias; Alias=Alias->next)
- {
- if (!stricmp(Alias->name, cmd))
- {
- if (Alias->inuse)
- {
- /* Allow an alias to merely add arguments */
- return FALSE;
- }
- expanded = malloc(strlen(Alias->text)+
- strlen(args)+2);
- strcpy(expanded, Alias->text);
- if (args)
- {
- strcat(expanded, " ");
- strcat(expanded, args);
- }
- Alias->inuse = 1;
- *retval = parse_command(expanded);
- Alias->inuse = 0;
- free(expanded);
- return TRUE;
- }
- }
- return FALSE;
- }
-
- int do_command( char **orig_args,
- int nArgs,
- BOOL bWait,
- BOOL bPipe,
- struct redirection *ar,
- int nRedirections)
- {
- char **args, **alloc_args;
- int ret;
- int i;
- int iTask;
- char *PathElement;
- char *ExeName;
- char Command[256];
- HTASK hTask;
- int GotTask;
- int IsBatch;
- HWND focus;
- long wstatus;
- int fdSource[3];
-
- if (!nArgs)
- return 0; /* Null command always succeeds */
-
- args = alloc_args = malloc(sizeof(*args) * (nArgs + 1));
- memcpy(args, orig_args, sizeof(*args) * (nArgs + 1));
-
- /* Check for a drive change directive */
-
- if (nArgs == 1 &&
- (strlen(args[0]) == 2) &&
- (args[0][1] == ':')) // Change Drive:
- return do_chdrive(args[0]);
-
- /* Check for builtin commands */
-
- for (i = 0; command_list[i].name; i++)
- if (!stricmp(command_list[i].name, args[0]))
- return (*command_list[i].func)(nArgs-1, args+1);
-
-
- NewDead = 0;
- strcpy(tmpbuf, ".;");
- strcat(tmpbuf, getenv("PATH"));
- strupr(args[0]);
- if ((ExeName = FindPath(args[0], &IsBatch)) != 0)
- {
- if (IsBatch)
- {
- ret = RunBatch(ExeName, args+1, nArgs-1);
- }
- else
- {
- *Command = 0;
- while (--nArgs)
- {
- if (*Command)
- strcat(Command, " ");
- ++args;
- if (strchr(*args, ' ') ||
- strchr(*args, '\t'))
- {
- strcat(Command, "\"");
- strcat(Command, *args);
- strcat(Command, "\"");
- }
- else
- strcat(Command, *args);
- }
- for (i = 0; i < nRedirections; i++)
- {
- if (ar[i].fdSource != -1)
- {
- fdSource[i] = dup(ar[i].fdSource);
- if (fdSource[i] == -1)
- fprintf(stderr, "%d: %s\n",
- ar[i].fdSource,
- sys_errlist[errno]);
- }
- else
- {
- fdSource[i] = open( ar[i].pchFile,
- ar[i].iMode,
- 0666);
- if (fdSource[i] == -1)
- fprintf(stderr, "%s: %s\n",
- ar[i].pchFile,
- sys_errlist[errno]);
- }
- if (fdSource[i] == -1)
- {
- while (i > 0)
- close(fdSource[--i]);
- free(alloc_args);
- return -1;
- }
- }
- iTask = fork();
- switch(iTask)
- {
- case 0:
- for (i = 0; i < nRedirections; i++)
- {
- if (dup2(fdSource[i], ar[i].fd) == -1)
- {
- fprintf(stderr, "dup2: %s\n", sys_errlist[errno]);
- }
- close(fdSource[i]);
- }
- execv_ext(Command, ExeName, orig_args);
- break;
-
- case -1:
- fprintf(stderr, "%s: %s\n", ExeName, sys_errlist[errno]);
- ret = -1;
- break;
-
- default:
- if (bWait)
- {
- waitpid(iTask, &wstatus, 0);
- if (WIFEXITED(wstatus))
- ret = WEXITSTATUS(wstatus);
- else
- ret = -1;
- }
- else if (bPipe)
- {
- add_backend(iTask);
- ret = 0;
- }
- else
- {
- ret = 0;
- }
- break;
- }
- for (i = 0; i < nRedirections; i++)
- {
- close(fdSource[i]);
- }
- }
- }
- else
- {
- ret = -2;
- fprintf(stderr, "%s: File not found\n", args[0]);
- }
- free(alloc_args);
- return ret;
- }
-
- char const *FindMatch(char const *buffer, char match)
- {
- for (buffer++; *buffer; buffer++)
- {
- if (*buffer == match)
- return buffer;
- if (*buffer == '\\' && buffer[1])
- buffer++;
- }
- return 0;
- }
-
-
- BOOL IsEscapable(char c)
- {
- return (c == '\\' || c == '\'' || c == '"' ||
- c == ';' || c == ' ' || c == '\t');
- }
-
- #define ARG_CHUNK 64
-
- #define CALC_SIZE(x) (((x)-1)-((x)-1)%ARG_CHUNK+ARG_CHUNK)
-
- #pragma argsused
- void CopyTo(char **arg, char const *data, int chars, int dosubs)
- {
- int len;
- int size;
- int newlen;
- int newsize;
- char *newarg;
-
- if (!*arg)
- {
- size = 0;
- len = 1;
- }
- else
- {
- len = strlen(*arg) + 1;
- size = CALC_SIZE(len);
- }
- newlen = len + chars;
- newsize = CALC_SIZE(newlen);
- if (newsize != size)
- {
- newarg = malloc(newsize);
- if (*arg)
- {
- memcpy(newarg, arg, len);
- free(*arg);
- }
- *arg = newarg;
- }
- memcpy(*arg + len - 1, data, chars);
- (*arg)[newlen-1] = '\0';
- }
-
- void FreeArgs(char **args, int nArgs)
- {
- int i;
-
- for (i = 0; i < nArgs; i++)
- {
- free(args[i]);
- args[i] = 0;
- }
- }
-
- void FinishArg(char **arg)
- {
- int len;
- int size;
- char *newarg;
-
- len = strlen(*arg) + 1;
- size = CALC_SIZE(len);
- if (size == len)
- return;
- newarg = malloc(len);
- memcpy(newarg, *arg, len);
- free(*arg);
- *arg = newarg;
- }
-
- #define TOKEN_ENDCOMMAND ((unsigned) 0x8001)
- #define TOKEN_BGCOMMAND ((unsigned) 0x8002)
- #define TOKEN_REDIRFROM ((unsigned) 0x8003)
- #define TOKEN_REDIRTO ((unsigned) 0x8004)
- #define TOKEN_APPENDTO ((unsigned) 0x8005)
- #define TOKEN_FDFROM ((unsigned) 0x8006)
- #define TOKEN_FDTO ((unsigned) 0x8007)
- #define TOKEN_PIPE ((unsigned) 0x8008)
-
- #define TOKEN_SPECIAL ((unsigned) 0x8000)
- #define TOKEN_ERROR ((unsigned) 0xFFFF)
- #define TOKEN_NONE ((unsigned) 0x0000)
- #define TOKEN_OK ((unsigned) 0x0001)
-
- static char const achTokenChars[] =
- { ";&<>|" };
-
- struct token_information
- {
- char *pchToken;
- int nToken;
- };
-
- static struct token_information ati[] =
- {
- { ">&", TOKEN_FDTO },
- { "<&", TOKEN_FDFROM },
- { ">>", TOKEN_APPENDTO },
- { ">", TOKEN_REDIRTO },
- { "<", TOKEN_REDIRFROM },
- { "&", TOKEN_BGCOMMAND },
- { ";", TOKEN_ENDCOMMAND },
- { "|", TOKEN_PIPE },
- { 0, 0 }
- };
-
- unsigned GetArg(char const **pchString,
- char **arg,
- BOOL *bRunOn)
- {
- int i;
- int nLen;
- char const *c;
- char const *end;
-
- *bRunOn = FALSE;
- c = *pchString;
- while (isspace(*c))
- c++;
- if (!*c)
- {
- *bRunOn = FALSE;
- return TOKEN_NONE;
- }
- if (strchr(achTokenChars, *c))
- {
- *bRunOn = FALSE;
- for (i = 0; ati[i].nToken; i++)
- {
- nLen = strlen(ati[i].pchToken);
- if (!strncmp(ati[i].pchToken, c, nLen))
- {
- *pchString = c + nLen;
- return ati[i].nToken;
- }
- }
- /* It is impossible to get here */
- *(char *) 0 = 0;
- }
- for (; *c!='\0'; c++)
- {
- if (isspace(*c))
- {
- FinishArg(arg);
- *bRunOn = FALSE;
- *pchString = c;
- return TOKEN_OK;
- }
- if (strchr(achTokenChars, *c))
- {
- *bRunOn = TRUE;
- FinishArg(arg);
- *pchString = c;
- return TOKEN_OK;
- }
- switch(*c)
- {
- case '"':
- case '\'':
- end = FindMatch(c, *c);
- if (!end)
- {
- fprintf(stderr, "Unterminated %c\n", *c);
- if (*arg)
- {
- free(*arg);
- *arg = 0;
- }
- return TOKEN_ERROR;
- }
- CopyTo(arg, c+1, end - c - 1, (*c == '"'));
- c = end;
- break;
-
- case '\\':
- if (IsEscapable(c[1]))
- {
- CopyTo(arg, ++c, 1, 0);
- break;
- }
- default:
- CopyTo(arg, c, 1, 0);
- break;
- }
- }
- *bRunOn = FALSE;
- *pchString = c;
- FinishArg(arg);
- return TOKEN_OK;
- }
-
- void free_redirections( struct redirection *ar,
- int nRedirections)
- {
- int i;
-
- for (i = 0; i < nRedirections; i++)
- {
- if (ar[i].pchFile)
- free(ar[i].pchFile);
- }
- }
-
- void cleanup( char *pchArg,
- char **ppchArgs,
- int nUsed,
- struct redirection *ar,
- int nRedirections,
- int pfd[2])
- {
- if (pchArg)
- free(pchArg);
- FreeArgs(ppchArgs, nUsed);
- free(ppchArgs);
- free_redirections(ar, nRedirections);
- if (pfd[0] != -1)
- close(pfd[0]);
- }
-
- int parse_command( char const *pchCmd)
- {
- char *c, *c2, *end;
- char **args;
- char *pchArg;
- int nUsed;
- int fdNow;
- int i;
- int retval;
- struct redirection ar[3];
- int nRedirections = 0;
- unsigned nToken, nFileToken;
- BOOL bRunOn = FALSE;
- BOOL bLastRunOn;
- BOOL bNonDigit;
- int nFile;
- int pfd[2];
- int fdOldPipe;
-
- pfd[0] = pfd[1] = -1;
- args = malloc(50 * sizeof(char *));
- memset(args, 0, sizeof(*args) * 50);
- nUsed = 0;
- while(!bBreak)
- {
- bLastRunOn = bRunOn;
- pchArg = 0;
- nToken = GetArg(&pchCmd, &pchArg, &bRunOn);
- switch (nToken)
- {
- case TOKEN_NONE:
- case TOKEN_ENDCOMMAND:
- case TOKEN_BGCOMMAND:
- case TOKEN_PIPE:
- if (nUsed)
- {
- fdOldPipe = pfd[0];
- if (nToken == TOKEN_PIPE)
- {
- for (i = 0; i < nRedirections; i++)
- {
- if (ar[i].fd == 1)
- {
- fprintf(stderr, "Ambiguous redirection\n");
- cleanup(pchArg, args, nUsed, ar, nRedirections, pfd);
- return -1;
- }
- }
- if (pipe(pfd) == -1)
- {
- fprintf(stderr, "pipe: %s\n", sys_errlist[errno]);
- cleanup(pchArg, args, nUsed, ar, nRedirections, pfd);
- return -1;
- }
- ar[nRedirections].fd = 1;
- ar[nRedirections].fdSource = pfd[1];
- ar[nRedirections].pchFile = 0;
- nRedirections++;
- }
- else
- {
- pfd[0] = pfd[1] = -1;
- }
- retval = do_command(args, nUsed,
- (nToken == TOKEN_BGCOMMAND ||
- nToken == TOKEN_PIPE) ?
- FALSE : TRUE,
- (nToken == TOKEN_PIPE) ?
- TRUE : FALSE,
- ar, nRedirections);
- FreeArgs(args, nUsed);
- nUsed = 0;
- free_redirections(ar, nRedirections);
- nRedirections = 0;
- if (nToken == TOKEN_PIPE)
- {
- close(pfd[1]);
- ar[nRedirections].fd = 0;
- ar[nRedirections].fdSource = pfd[0];
- ar[nRedirections].pchFile = 0;
- nRedirections++;
- }
- if (fdOldPipe != -1)
- close(fdOldPipe);
- }
- else
- {
- FreeArgs(args, nUsed);
- free(args);
- free_redirections(ar, nRedirections);
- return retval;
- }
- break;
-
- case TOKEN_OK:
- args[nUsed++] = pchArg;
- if (nUsed == 1 &&
- expand_alias(args[0], pchCmd, &retval))
- {
- FreeArgs(args, nUsed);
- free(args);
- free_redirections(ar, nRedirections);
- return retval;
- }
- break;
-
- case TOKEN_FDTO:
- case TOKEN_APPENDTO:
- case TOKEN_REDIRTO:
- case TOKEN_REDIRFROM:
- case TOKEN_FDFROM:
- nFileToken = GetArg(&pchCmd, &pchArg, &bRunOn);
- if (nFileToken != TOKEN_OK)
- {
- fprintf(stderr, "Redirection syntax error\n");
- cleanup(pchArg, args, nUsed, ar, nRedirections, pfd);
- return -1;
- }
- bRunOn = FALSE;
- nFile = -1;
- if (bLastRunOn)
- {
- bNonDigit = FALSE;
- for (i = 0; args[nUsed - 1][i]; i++)
- {
- if (!isdigit(args[nUsed - 1][i]))
- {
- bNonDigit = TRUE;
- break;
- }
- }
- if (!bNonDigit && args[nUsed - 1][0])
- {
- nFile = atoi(args[nUsed - 1]);
- free(args[--nUsed]);
- args[nUsed] = 0;
- if (nFile > 2)
- {
- fprintf(stderr, "Silly redirection\n");
- cleanup(pchArg, args, nUsed, ar, nRedirections, pfd);
- return -1;
- }
- }
- }
- if (nFile == -1)
- {
- switch(nToken)
- {
- case TOKEN_FDTO:
- case TOKEN_APPENDTO:
- case TOKEN_REDIRTO:
- nFile = 1;
- break;
-
- case TOKEN_REDIRFROM:
- case TOKEN_FDFROM:
- nFile = 2;
- break;
- }
- }
- for (i = 0; i < nRedirections; i++)
- {
- if (ar[i].fd == nFile)
- {
- fprintf(stderr, "Ambiguous redirection\n");
- cleanup(pchArg, args, nUsed, ar, nRedirections, pfd);
- return -1;
- }
- }
- ar[nRedirections].fd = nFile;
- switch(nToken)
- {
- case TOKEN_FDFROM:
- case TOKEN_FDTO:
- ar[nRedirections].pchFile = 0;
- ar[nRedirections].fdSource = atoi(pchArg);
- free(pchArg);
- break;
-
- case TOKEN_APPENDTO:
- case TOKEN_REDIRTO:
- case TOKEN_REDIRFROM:
- ar[nRedirections].pchFile = pchArg;
- ar[nRedirections].fdSource = -1;
- break;
- }
- switch(nToken)
- {
- case TOKEN_REDIRFROM:
- case TOKEN_FDFROM:
- ar[nRedirections].iMode = O_RDONLY;
- break;
-
- case TOKEN_REDIRTO:
- case TOKEN_FDTO:
- ar[nRedirections].iMode = O_WRONLY | O_CREAT | O_TRUNC;
- break;
-
- case TOKEN_APPENDTO:
- ar[nRedirections].iMode = O_WRONLY | O_CREAT | O_APPEND;
- break;
- }
- nRedirections++;
- break;
-
- case TOKEN_ERROR:
- cleanup(pchArg, args, nUsed, ar, nRedirections, pfd);
- return -1;
- }
- }
- cleanup(pchArg, args, nUsed, ar, nRedirections, pfd);
- return -1;
- }
-
-