home *** CD-ROM | disk | FTP | other *** search
/ Dream 45 / Amiga_Dream_45.iso / Atari / Magazine / Dossier / texutils / ms.arc / MS.C < prev    next >
C/C++ Source or Header  |  1988-10-17  |  12KB  |  677 lines

  1. /*
  2.  * minimal shell for memory hogs on the atariST
  3.  *    - MWC required (sort of)
  4.  *
  5.  * to configure:
  6.  *    edit config.h
  7.  * to compile: (MWC)
  8.  *    cc -O -o ms.tos -VSMALL -VPEEP -VGEM -DMWC ms.c -s -x
  9.  *
  10.  * note use of -VGEM to keep the size to a min. Stderr init. is
  11.  * done at the begining of main().
  12.  *
  13.  * Builtins:
  14.  *    rm <list of files>
  15.  *    cp <src> <dst>    both <src> <dest> must be files
  16.  *            WARNING: no checks for <src> <dst> being to same
  17.  *    ls {<regular exp>} with no arg ls *.*
  18.  *    cd {<dir>} with no arg cd $HOME
  19.  *    md <dir>
  20.  *    rd <dir>
  21.  *    lo logout
  22.  *    @ file    read commands from file, then revert back to stdin.
  23.  *          NO nested @'s allowed.
  24.  *
  25.  * Aliases, Path, Environment:
  26.  *    see config.h
  27.  *
  28.  *    ++jrb    bammi@dsrgsun.ces.cwru.edu
  29.  */
  30.  
  31. #include <osbind.h>
  32.  
  33. #ifdef __GNUC__
  34.  
  35. /* quick fix, this should be fixed in osbind.h and the library */
  36.  
  37. #undef Fforce
  38. #define    Fforce(Hstd,Hnew)        trap_1_www(0x46,Hstd,Hnew)
  39.  
  40. int trap_1_www(args)
  41. long args;
  42. {
  43.   asm("movel a6@(16),d0");        /* copy w3 */
  44.   asm("movew d0,sp@-");
  45.   asm("movel a6@(12),d0");        /* copy w2 */
  46.   asm("movew d0,sp@-");
  47.   asm("movel a6@(8),d0");        /* copy w1 */
  48.   asm("movew d0,sp@-");
  49.   asm("trap #1");            /* do the trap */
  50.   asm("addl #6,sp");            /* pop junk off stack */
  51. }
  52.  
  53. #endif
  54.  
  55. #ifdef NULL
  56. #undef NULL
  57. #endif
  58.  
  59. #define NULL 0L        /* avoid stdio like the plague */
  60. #define BSIZE 256    /* size of all purpose buffer  */
  61.  
  62. #define PROMPT Bconws(cwd),Bconws("> ")
  63. #define PRINTI(i) printi((short)i)
  64. #define CRLF Bconws(_crlf)
  65. #define REG
  66.  
  67. typedef struct
  68. {
  69.     char    st_sp1[21];    /* Junk        */
  70.     char    st_mode;       /* File attributes */
  71.     short    st_time;       /* Mod Time      */
  72.     short   st_date;       /* Mod date      */
  73.     long    st_size;       /* File size       */
  74.     char    st_name[14];   /* File name       */
  75. } STAT;
  76.  
  77. #ifdef MWC
  78. long _stksize = 128;    /* don't trim this any further!! */
  79. #else
  80. #ifdef __GNUC__
  81. long _stksize = 128;    /* don't trim this any further!! */
  82. #else  /* alcyon */
  83. long _STKSIZ = 128;    /* don't trim this any further!! */
  84. #endif
  85. #endif
  86.  
  87. char *_crlf = "\r\n";
  88. int rhandle = -10;    /* some val < -5 */
  89. char buf[BSIZE];
  90. char cwd[64];        /* can tune this to your env */
  91. STAT *stat;
  92.  
  93. #include "config.h"    /* all the user configurable stuff in there */
  94.  
  95. /*
  96.  * Builtin commands
  97.  *
  98.  */
  99. #if __STDC__ || __GNUC__
  100. void Bconws(char *);
  101. void printi(int);
  102. void setcwd();
  103. char *nextarg(char **);
  104. char *alltolower(char *);
  105. int cd(char *);
  106. int ls(char *);
  107. void putls(STAT *, int);
  108. int rm(char *);
  109. int cp(char *);
  110. int md(char *);
  111. int rd(char *);
  112. int lo();
  113. int at(char *);
  114. void read_at(char *);
  115. int find_builtin(char *);
  116. int find_alias(char *);
  117. char *existf(char *, char *, char *);
  118. char *find_ext(char *);
  119. int do_command(char *, char *, char *);
  120. int main();
  121. extern char *strcpy(char *, char *);
  122. extern char *strcat(char *, char *);
  123. extern char *index(char *, char);
  124. extern int strlen(char *);
  125.  
  126. #else
  127.  
  128. int ls(), rm(), cp(), cd(), md(), rd(), lo(), at();
  129. extern char *strcpy();
  130. extern char *strcat();
  131. extern char *index();
  132. extern int strlen();
  133.  
  134. #endif
  135.  
  136. typedef struct {
  137.     char    *command;    /* command string    */
  138.     int     (*routine)();    /* routine to invoke    */
  139. } BUILTIN;
  140.  
  141. BUILTIN builtin[] = {
  142.     { "rm", rm },
  143.     { "cp", cp },
  144.     { "ls", ls },
  145.     { "cd", cd },
  146.     { "md", md },
  147.     { "rd", rd },
  148.     { "lo", lo },
  149.     { "@",  at },
  150.     { (char *)NULL, (int (*)())NULL }
  151.     };
  152.  
  153.  
  154. void Bconws(s)
  155. REG char *s;
  156. {
  157.     while(*s) Bconout(2, *s++);
  158. }
  159.  
  160. void printi(val)
  161. REG int val;
  162. {
  163.         static short divisors[] = { 10000, 1000, 100, 10, 1 };
  164.     register short first = 0, div_idx = 0;
  165.     register short j;
  166.     
  167.     /* Special Cases */
  168.         if (val == 0)
  169.     {
  170.         Bconout(2, '0');
  171.     }
  172.         else if (val == -32768)
  173.     {
  174.                 Bconws("-32768");
  175.     }
  176.     else
  177.     {    
  178.         /* Get digit for each power of 10 and print them, skip leading 0's */
  179.             if (val < 0)
  180.         {
  181.                     Bconout(2, '-');
  182.                     val = -val;
  183.         }
  184.  
  185.             while( div_idx < 5 )
  186.         {
  187.                     if(((j = val / divisors[div_idx]) != 0) || first != 0)
  188.             {
  189.                             Bconout(2, j + '0');
  190.                             first = 1;
  191.             }
  192.                     val %= divisors[div_idx++];
  193.         }
  194.     }
  195. }
  196.  
  197. void setcwd()
  198. {
  199.     register short drive;
  200.     extern char *alltolower();
  201.     
  202.     drive = Dgetdrv();
  203.     Dgetpath(&cwd[2],0);
  204.     cwd[0] = (char)(drive + 'a');
  205.     if(cwd[2] == '\0')
  206.     {
  207.         cwd[2] =  '\\';
  208.         cwd[3] = '\0';
  209.     }
  210.     else (void) alltolower(&cwd[2]);
  211. }
  212.  
  213. #define iswhite(c) ((c == ' ') || (c == '\t'))
  214.  
  215. /*
  216.  * return pointer to next arg, and advance q to char following next arg
  217.  */
  218. char *nextarg(q)
  219. REG char **q;
  220. {
  221.     register char *s = *q;
  222.     register char *p;
  223.  
  224.     if(*s == '\0')
  225.         return (char *)NULL;
  226.     while(iswhite(*s)) s++;
  227.     p = s; s++;
  228.     while((!iswhite(*s)) && (*s != '\0')) s++;
  229.     if(*s != '\0')
  230.     {
  231.         *s = '\0';
  232.         *q = ++s;
  233.     }
  234.     else
  235.         *q = s;
  236.  
  237.     return p;
  238. }
  239.  
  240.     
  241. #define isupper(c) ((c >= 'A') && (c <= 'Z'))
  242. #define tolower(c)  (c - 'A' + 'a')
  243.  
  244. char *alltolower(s)
  245. REG char *s;
  246. {
  247.     register char *p = s;
  248.  
  249.     while(*p != '\0')
  250.     {
  251.         if(isupper(*p)) *p = tolower(*p);
  252.         p++;
  253.     }
  254.     return s;
  255. }
  256.  
  257. int cd(s)
  258. REG char *s;
  259. {
  260.     register char *d, *path;
  261.     register int drive;
  262.  
  263.     if(*s == '\0')
  264.         return cd(HOME);
  265.  
  266.     if((d = index(s,':')) == (char *)NULL)
  267.     {
  268.         /* Drive was not specified, must mean the current drive */
  269.         path = s;
  270.     }
  271.     else
  272.     {
  273.         d--;
  274.         if(isupper(*d))
  275.         {
  276.             *d = tolower(*d);
  277.         }
  278.         drive = *d - 'a';
  279.         if(d[2] != '\\')    /* just gave D: */
  280.         {
  281.             /* we will shove in the '\' */
  282.             d[1] = '\\';
  283.             path = &d[1];
  284.         }
  285.         else
  286.             path = &d[2];
  287.  
  288.         /* Set the Drive */
  289.         if(Dsetdrv(drive) < 0)
  290.         {
  291.             Bconws("?drive: "); Bconout(2, *d); CRLF;
  292.             return 2;
  293.         }
  294.  
  295.     }
  296.  
  297.  
  298.     /* Set the Path */
  299.     if(Dsetpath(path) != 0)
  300.     {
  301.         Bconws("?dir: "); Bconws(path); CRLF;
  302.         return 3;
  303.     }
  304.     
  305.     setcwd();
  306.     return 0;
  307. }
  308.  
  309.  
  310. #define HASWILD(S) \
  311.   ((index(S, '*') != (char *)NULL) || (index(S, '?') != (char *)NULL))
  312.  
  313. void putls(statbuf, count)
  314. REG STAT *statbuf;
  315. REG int count;
  316. {
  317.     register int len = strlen(statbuf->st_name);
  318.     extern char *alltolower();
  319.  
  320.     if((statbuf->st_mode) & 0x0010)
  321.     {
  322.         /* subtree */
  323.         Bconws(alltolower(statbuf->st_name));
  324.         Bconout(2, '/');
  325.         len++;
  326.     }
  327.     else
  328.         /* file */
  329.         Bconws(alltolower(statbuf->st_name));
  330.  
  331.     if(!(count % 4))
  332.         CRLF;
  333.     else
  334.     {
  335.         len = 14 - len;
  336.         while(len--)
  337.             Bconout(2, ' ');
  338.     }
  339. }
  340.  
  341. int ls(s)
  342. REG char *s;
  343. {
  344.     register short count;
  345.  
  346.     if(*s == '\0')
  347.         return ls("*.*");
  348.  
  349.     if(HASWILD(s))
  350.         (void) strcpy(buf, s);
  351.     else
  352.     {
  353.         if(s[(strlen(s)    - 1)] != '\\')
  354.         {
  355.             (void) strcpy(buf, s);
  356.             (void) strcat(buf, "\\");
  357.         }
  358.         else
  359.             (void) strcpy(buf, s);
  360.         (void) strcat(buf, "*.*");
  361.     }
  362.     if(Fsfirst(buf, 0x0020 | 0x0010) != 0)
  363.     {
  364.         Bconws("?match: "); Bconws(buf); CRLF;
  365.         return 1;
  366.     }
  367.  
  368.     count = 0;
  369.     if(!((strcmp(stat->st_name,".") == 0) || 
  370.        (strcmp(stat->st_name, "..") == 0)))
  371.         putls(stat, ++count);
  372.  
  373.     while(Fsnext() == 0)
  374.     {
  375.         if(!((strcmp(stat->st_name,".") == 0) || 
  376.            (strcmp(stat->st_name, "..") == 0)))
  377.             putls(stat, ++count);
  378.     }
  379.  
  380.     if((count % 4))
  381.         CRLF;
  382.  
  383.     return 0;
  384. }
  385.  
  386. int rm(s)
  387. char *s;
  388. {
  389.     register char *p;
  390.     register int status = 0;
  391.     extern char *nextarg();
  392.  
  393.     while((p = nextarg(&s)) != (char *)NULL)
  394.     {
  395.         if(Fdelete(p) != 0)
  396.         {
  397.             Bconws("?file: "); Bconws(s); CRLF;
  398.             status = 1;
  399.         }
  400.     }
  401.     return status;
  402. }
  403.  
  404. int cp(s)
  405. char *s;
  406. {
  407.     register char *p;
  408.     register int src, dst;
  409.     register long l, k;
  410.     extern char *nextarg();
  411.  
  412.     if((p = nextarg(&s)) == (char *)NULL)
  413.     {
  414.         Bconws("?cp src dst"); CRLF;
  415.         return 1;
  416.     }
  417.     if((src = Fopen(p, 0)) < (-3))
  418.     {
  419.         Bconws("?src: "); Bconws(p); CRLF;
  420.         return src;
  421.     }
  422.     if((p = nextarg(&s)) == (char *)NULL)
  423.     {
  424.         Bconws("?cp src dst"); CRLF;
  425.         Fclose(src);
  426.         return 2;
  427.     }
  428.     if((dst = Fcreate(p, 0)) < (-3))
  429.     {
  430.         if((dst = Fopen(p, 1)) < (-3))
  431.         {
  432.             Bconws("?dst: "); Bconws(p); CRLF;
  433.             Fclose(src);
  434.             return dst;
  435.         }
  436.     }
  437.     while( (l = Fread(src, (long)BSIZE, buf)) > 0L)
  438.     {
  439.         if((k = Fwrite(dst, l, buf)) != l)
  440.         {
  441.             Bconws("?Write Fail\r\n");
  442.             Fclose(src);
  443.             Fclose(dst);
  444.             return (int)k;
  445.         }
  446.     }
  447.     Fclose(src);
  448.     Fclose(dst);
  449.     return 0;
  450.     
  451. }
  452.  
  453. int md(s)
  454. char *s;
  455. {
  456.     extern char *nextarg();
  457.     register char *p;
  458.  
  459.     if((p = nextarg(&s)) == (char *)NULL)
  460.     {
  461.         Bconws("?md\r\n");
  462.         return 1;
  463.     }
  464.     return(Dcreate(p));
  465. }
  466.  
  467. int rd(s)
  468. char *s;
  469. {
  470.     extern char *nextarg();
  471.     register char *p;
  472.  
  473.     if((p = nextarg(&s)) == (char *)NULL)
  474.     {
  475.         Bconws("?rd\r\n");
  476.         return 1;
  477.     }
  478.     return(Ddelete(p));
  479. }
  480.  
  481. int lo()
  482. {
  483.     Pterm(0);
  484. }
  485.  
  486. int at(s)
  487. REG char *s;
  488. {
  489.     if((s == (char *)NULL) || (*s == '\0'))    /* dependency !! */
  490.     {
  491.         if(rhandle > (-3))
  492.         {
  493.             Fclose(rhandle);
  494.             rhandle = -10;
  495.         }
  496.         return 0;
  497.     }
  498.  
  499.     if((rhandle = Fopen(s, 0)) < (-3))
  500.     {
  501.         Bconws("?file: "); Bconws(s); CRLF;
  502.         return 1;
  503.     }
  504.     return 0;
  505. }
  506.  
  507. void read_at(buf)
  508. char *buf;
  509. {
  510.     char c;
  511.     register char *p;
  512.  
  513.     p = &buf[2];
  514.     buf[1] = 0;
  515.     while(Fread(rhandle, 1L, &c) == 1L)
  516.     {
  517.         Bconout(2, c);
  518.         if(c == '\r')
  519.         {
  520.             Bconout(2, '\n');
  521.             *p = '\0';
  522.             buf[1] = strlen(&buf[2]);
  523.             Fread(rhandle, 1L, &c);
  524.             return;
  525.         }
  526.         *p++ = c;
  527.     }
  528.     Fclose(rhandle);
  529.     rhandle = -10;
  530.     CRLF;
  531. }
  532.         
  533.         
  534. int find_builtin(s)
  535. REG char *s;
  536. {
  537.     register short i;
  538.     for(i = 0; builtin[i].command != (char *)NULL; i++)
  539.         if(strcmp(s, builtin[i].command) == 0)
  540.             return i;
  541.     return -1;
  542. }
  543.  
  544. int find_alias(s)
  545. REG char *s;
  546. {
  547.     register short i;
  548.     for(i = 0; alias[i].aname != (char *)NULL; i++)
  549.         if(strcmp(s, alias[i].aname) == 0)
  550.             return i;
  551.     return -1;
  552. }
  553.  
  554. char *existf(name, pth, ex)
  555. REG char *name, *pth, *ex;
  556. {
  557.     register char *b = &buf[(BSIZE/2)];
  558.     
  559.     if(*pth != '\0')
  560.     {
  561.         (void) strcpy(b, pth);
  562.         (void) strcat(b, name);
  563.     }
  564.     else
  565.         (void) strcpy(b, name);
  566.     if(*ex != '\0')
  567.         (void) strcat(b, ex);
  568.     if(Fsfirst(b, 0) == 0)
  569.         return b;
  570.     return (char *)NULL;
  571. }
  572.     
  573.     
  574. char *find_ext(s)
  575. REG char *s;
  576. {
  577.     register char *p;
  578.     register short i, j;
  579.     extern char *existf();
  580.  
  581.     for(i = 0; path[i] != (char *)NULL; i++)
  582.         for(j = 0; ext[j] != (char *)NULL; j++)
  583.             if(( p = existf(s, path[i], ext[j])) != (char *)NULL)
  584.                 return p;
  585.     return (char *)NULL;
  586. }
  587.  
  588. int do_command(com, optarg, args)
  589. char *com, *optarg, *args;
  590. {
  591.  
  592.     Bconws(com);
  593.     Bconout(2, ' ');
  594.     if(optarg != (char *)NULL)
  595.     {
  596.         Bconws(optarg);
  597.         Bconout(2, ' ');
  598.     }
  599.     Bconws(args); CRLF;
  600.     if(optarg != (char *)NULL)
  601.     {
  602.         buf[(BSIZE/2)] = strlen(optarg) + strlen(args) + 1;
  603.         (void)strcat(strcat(strcpy(&buf[(BSIZE/2+1)], optarg), " "),
  604.                  args);
  605.         return (int)Pexec(0, com, &buf[(BSIZE/2)], env);
  606.     }
  607.     else        
  608.     {
  609.         buf[0] = strlen(args);
  610.         (void) strcpy(&buf[1], args);
  611.         return (int)Pexec(0, com, buf, env);
  612.     }
  613. }
  614.  
  615. int main()
  616. {
  617.     register char *com, *args, *line;
  618.     register int i, status;
  619.  
  620.     /* Set Up Stderr */
  621.     Fforce(2,(int)Fdup(1));
  622.  
  623.     stat = (STAT *)Fgetdta();
  624.     cwd[1] = ':';
  625.     cd(HOME);
  626.     while(1)
  627.     {
  628.         PROMPT;
  629.         buf[0] = 127;
  630.         if(rhandle > (-3))
  631.             read_at(buf);
  632.         else
  633.         {
  634.             Cconrs(buf);
  635.             Bconout(2, '\n');
  636.         }
  637.         if(buf[1] == 0)
  638.             continue;
  639.         
  640.         buf[(buf[1]+2)] = '\0';
  641.         line = &buf[2];
  642.         com = line;
  643.     
  644.         /* pick up argv[0] */
  645.         while((*line != '\0') && (!iswhite(*line)))
  646.             line++;
  647.  
  648.         if(*line != '\0')
  649.         {
  650.             *line++ = '\0';
  651.         }
  652.         args = line;
  653.  
  654.         status = 0;
  655.         if((i = find_builtin(com)) >= 0)
  656.             status = (*(builtin[i].routine))(args);
  657.         else if ((i = find_alias(com)) >= 0)
  658.             status = do_command(alias[i].adef, alias[i].optarg,
  659.                                       args);
  660.         else if ((line = find_ext(com)) != (char *)NULL)
  661.             status = do_command(line, (char *)NULL, args);
  662.         else
  663.         {
  664.             Bconws(com);Bconws(" not found\r\n");
  665.             continue;
  666.         }
  667.         if(status != 0)
  668.         {
  669.             PRINTI(status); CRLF;
  670.         }
  671.         
  672.     }
  673.     return 0;
  674. }
  675.  
  676. /* -eof- */
  677.