home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 488.lha / csh_v5.0 / src / csh500src.lzh / comm1.c next >
C/C++ Source or Header  |  1991-02-23  |  30KB  |  1,340 lines

  1. /*
  2.  * COMM1.C
  3.  *
  4.  * Matthew Dillon, August 1986
  5.  *
  6.  * Version 2.07M by Steve Drew 10-Sep-87
  7.  * Version 4.01A by Carlo Borreo & Cesare Dieni 17-Feb-90
  8.  * Version 5.00L by Urban Mueller 17-Feb-91
  9.  *
  10.  */
  11.  
  12. #include "shell.h"
  13.  
  14. /* comm1.c */
  15. static void display_file(char *filestr);
  16. static char *myfgets(char *buf, int buflen, struct __stdio *file);
  17. static int search_file(char *s);
  18. static int quicksearch(char *name, int nocasedep, char *pattern);
  19. static int rm_file(char *file);
  20. static void setsystemtime(struct DateStamp *ds);
  21. static int found( char *lstart, int lnum, int loffs, char *name, char left );
  22. static void recurse(char *name, int (*action)(char *));
  23. static void recurse2( char *name, void (*action)(FIB *));
  24.  
  25. extern int has_wild;
  26.  
  27. int
  28. do_sleep( void )
  29. {
  30.     int i;
  31.  
  32.     if (ac == 2) for (i=atoi(av[1]); i>0 && !CHECKBREAK(); i--) Delay(50);
  33.     return 0;
  34. }
  35.  
  36. int
  37. do_protect( void )
  38. {
  39.     static char flags[]="DEWRAPSH";
  40.     char *s, *p;
  41.     long setmask=0, clrmask=0xFF, mask;
  42.     int  i, mode=0, stat;
  43.     struct DPTR *dp;
  44.  
  45.     for (s=strupr(av[--ac]); *s; s++) {
  46.         if (*s=='=') { mode=0; continue; }
  47.         if (*s=='+') { mode=1; clrmask=FIBF_ARCHIVE; continue; }
  48.         if (*s=='-') { mode=2; clrmask=FIBF_ARCHIVE; continue; }
  49.  
  50.         if (p=index(flags, *s)) {
  51.             if( mode==0 ) setmask|= 1<<(p-flags), clrmask=0xFF;
  52.             if( mode==1 ) setmask|= 1<<(p-flags);
  53.             if( mode==2 ) clrmask|= 1<<(p-flags);
  54.         } else
  55.             ierror(av[ac],500);
  56.     }
  57.  
  58.     for (i=1; i<ac; i++) {
  59.         if( (dp=dopen(av[i],&stat))) {
  60.             mask = dp->fib->fib_Protection ^ 0x0F;
  61.             mask&=~clrmask;
  62.             mask|= setmask;
  63.             dclose(dp);
  64.             if( !SetProtection( av[i], mask ^ 0x0F))
  65.                 pError(av[i]);
  66.         } else
  67.             pError(av[i]);
  68.     }
  69.     return 0;
  70. }
  71.  
  72. int
  73. do_filenote( void )
  74. {
  75.     struct DPTR *dp;
  76.     char *note;
  77.     int i, stat;
  78.  
  79.     if( options&1 ) {
  80.         for( i=1; i<ac && !dobreak(); i++ )
  81.             if( dp=dopen( av[i], &stat )) {
  82.                 printf( "%-12s %s\n", av[i],dp->fib->fib_Comment );
  83.                 dclose( dp );
  84.             }
  85.     } else {
  86.         note=av[--ac];
  87.         for (i=1; i<ac; i++) if (!SetComment(av[i], note)) pError(av[i]);
  88.     }
  89.     return 0;
  90. }
  91.  
  92. int
  93. do_cat( void )
  94. {
  95.     FILE *fi;
  96.     int lctr, i;
  97.     char buf[256];
  98.  
  99.     prepscroll(0);
  100.     if (ac<=1) {
  101.         if (has_wild) { printf("No files matching\n"); return 20; }
  102.         lctr=0;
  103.         while (fgets(buf,256,stdin) &&
  104.                !dobreak()) {
  105.             if (options) printf("%4d ",++lctr);
  106.             quickscroll();
  107.             fputs(buf,stdout);
  108.         }
  109.     } else {
  110.         for (i=1; i<ac; i++)
  111.             if (fi = fopen (av[i], "r")) {
  112.                 lctr=0;
  113.                 while (fgets(buf,256,fi) && !dobreak()) {
  114.                     if (options&1) printf("%4d ",++lctr);
  115.                     quickscroll();
  116.                     printf("%s",buf);
  117.                 }
  118.                 fclose (fi);
  119.             } else
  120.                 pError(av[i]);
  121.     }
  122.     return 0;
  123. }
  124.  
  125.  
  126. void
  127. get_drives(char *buf)
  128. {
  129.     struct DirectoryEntry *de_head=NULL, *de;
  130.  
  131.     buf[0]=0;
  132.     AddDADevs(&de_head, DLF_DEVICES | DLF_DISKONLY );
  133.     for(de=de_head; de; de=de->de_Next) {
  134.         if( buf[0] )
  135.             strcat( buf, "\240" );
  136.         strcat( buf, de->de_Name );
  137.     }
  138.     FreeDAList(de_head);
  139. }
  140.  
  141. static char infobuf[100];
  142. static char namebuf[12];
  143.  
  144. char *
  145. drive_name( char *name )
  146. {
  147.     struct DirectoryEntry *de_head=NULL, *de;
  148.     struct MsgPort *proc=DeviceProc( name );
  149.  
  150.     strcpy( namebuf, name );
  151.     AddDADevs(&de_head, DLF_DEVICES | DLF_DISKONLY );
  152.     for(de=de_head; de; de=de->de_Next)
  153.         if( DeviceProc( de->de_Name) == proc ) 
  154.             strcpy( namebuf, de->de_Name );
  155.     FreeDAList(de_head);
  156.  
  157.     return namebuf;
  158. }
  159.  
  160. int
  161. do_info( void )
  162. {
  163.     struct DirectoryEntry *de_head=NULL, *de;
  164.     int i;
  165.  
  166.     puts("Unit    Size  Bytes  Used Blk/Byt-Free Full Errs  Status    Name");
  167.     Myprocess->pr_WindowPtr = (APTR)(-1);
  168.  
  169.     if( ac==1 ) {
  170.         AddDADevs(&de_head, DLF_DEVICES | DLF_DISKONLY );
  171.         for(de=de_head; de; de=de->de_Next)
  172.             oneinfo( de->de_Name, 0);
  173.         FreeDAList(de_head);
  174.     } else {
  175.         for( i=1; i<ac; i++ )
  176.             oneinfo( drive_name( av[i] ), 0 );
  177.     }
  178.  
  179.     Myprocess->pr_WindowPtr = (APTR) o_noreq;
  180.     return 0;
  181. }
  182.  
  183. char *
  184. oneinfo( char *name, int mode )
  185. {
  186.     BPTR lock;
  187.     struct InfoData *info;
  188.     long size, free, freebl, blocks;
  189.     char *p, buf[130], *state="          ";
  190.     char *fmt="%s\240%s\240%d\240%d\240%d\240%s\240%d%%\240%d\240%s\240%s";
  191.  
  192.     infobuf[0]=0;
  193.     if( !name ) name="";
  194.     strcpy(infobuf,"0");
  195.     info=(struct InfoData *)AllocMem((long)sizeof(struct InfoData),MEMF_PUBLIC);
  196.     if (lock=Lock(name,ACCESS_READ)) {
  197.         if (Info(lock, info)) {
  198.             PathName(lock, buf, 128L);
  199.             if (p=index(buf,':')) *p = '\0';
  200.             size  = ((info->id_NumBlocks + 2)* info->id_BytesPerBlock);
  201.             freebl= (info->id_NumBlocks-info->id_NumBlocksUsed);
  202.             free  = freebl * info->id_BytesPerBlock;
  203.             switch(info->id_DiskState) {
  204.                 case ID_WRITE_PROTECTED: state="Read Only "; break;
  205.                 case ID_VALIDATED:       state="Read/Write"; break;
  206.                 case ID_VALIDATING:      state="Validating"; break;
  207.             }
  208.             blocks=info->id_NumBlocks;
  209.             if( mode==0 ) fmt="%-7s%5s%6d%7d%7d %5s%4d%%%4d  %s %s\n";
  210.             sprintf(infobuf,fmt,
  211.                 name,
  212.                 itok( size ),
  213.                 info->id_BytesPerBlock,
  214.                 info->id_NumBlocksUsed,
  215.                 freebl,
  216.                 itok( free ),
  217.                 (blocks) ? (info->id_NumBlocksUsed * 100)/blocks : 0,
  218.                 info->id_NumSoftErrors,
  219.                 state,
  220.                 buf);
  221.             if( mode==2 ) sprintf( infobuf, "%d", free );
  222.             if( mode==3 ) sprintf( infobuf, "%d", freebl );
  223.             if( mode==4 ) sprintf( infobuf, "%s", itok( free ));
  224.             if( mode==5 ) sprintf( infobuf, "%s:", buf );
  225.         } else
  226.             pError (name);
  227.         UnLock(lock);
  228.     } else {
  229.         if     ( mode==1 ) sprintf( infobuf, "%s\240No disk present", name );
  230.         else if( mode==0 ) sprintf( infobuf, "%-7s No disk present\n",name);
  231.         else if( mode==5 ) sprintf( infobuf, ""  );
  232.         else               sprintf( infobuf, "0" );
  233.     }
  234.     if( mode==0 ) printf( "%s",infobuf);
  235.     FreeMem(info,sizeof(struct InfoData));
  236.     return infobuf;
  237. }
  238.  
  239.  
  240. /* things shared with display_file */
  241.  
  242. #define DIR_SHORT 0x1
  243. #define DIR_FILES 0x2
  244. #define DIR_DIRS  0x4
  245. #define DIR_NOCOL 0x8
  246. #define DIR_NAMES 0x10
  247. #define DIR_HIDE  0x20
  248. #define DIR_LEN   0x40
  249. #define DIR_TIME  0x80
  250. #define DIR_BACK  0x100
  251. #define DIR_UNIQ  0x200
  252. #define DIR_IDENT 0x400
  253. #define DIR_CLASS 0x800
  254. #define DIR_QUIET 0x1000
  255. #define DIR_AGE   0x2000
  256. #define DIR_VIEW  0x4000
  257. #define DIR_NOTE  0x8000
  258.  
  259. static BPTR lastlock;
  260. static int filecount, col, wwidth;
  261. static long bytes, blocks;
  262.  
  263. /* the args passed to do_dir will never be expanded */
  264.  
  265. extern expand_err;
  266. extern int w_width;
  267.  
  268.  
  269. static struct DateStamp Stamp;
  270.  
  271. int
  272. do_dir( void )
  273. {
  274.     int i=1, c, eac, reverse, nump=ac, retcode=0;
  275.     char **eav, **av1, **av2, inter=interactive();
  276.     int (*func)(), ac1, ac2;
  277.  
  278.     if( options&DIR_CLASS ) options|=DIR_IDENT;
  279.     if( ac == i) ++nump, av[i]="";
  280.     if( !(options & (DIR_FILES | DIR_DIRS))) options|=(DIR_FILES | DIR_DIRS);
  281.     if( options&DIR_UNIQ) {
  282.         if( ac-i!=2 )  { show_usage(NULL); return 20; }
  283.         i=0, nump=3;
  284.     }
  285.  
  286.     if( options&DIR_AGE )
  287.         DateStamp( &Stamp );
  288.  
  289.     col = filecount = bytes = blocks = 0L;
  290.     lastlock=NULL;
  291.  
  292.     wwidth=77;
  293.     if( inter ) printf( "\033[?7l" ), wwidth=w_width; /* end of line wrap off */
  294.  
  295.     prepscroll(0);
  296.     for( ; i<nump && !CHECKBREAK(); ++i ) {
  297.         if( options&DIR_UNIQ ) {
  298.             switch( i ) {
  299.                 case 0: av1=expand( av[ac-2], &ac1 );
  300.                         av2=expand( av[ac-1], &ac2 );
  301.                         eav=without( av1, ac1, av2, ac2, &eac, 1 );
  302.                         break;
  303.                 case 1: printf("\nCommon files\n");
  304.                         eav=and( av1, ac1, av2, ac2, &eac, 1 );
  305.                         break;
  306.                 case 2: printf("\n");
  307.                         eav=without( av2, ac2, av1, ac1, &eac, 1 );
  308.                         break;
  309.             }
  310.             col = filecount = bytes = blocks = 0L;
  311.             lastlock=NULL;
  312.         } else if (!(eav = expand(av[i], &eac)) && expand_err) {
  313.             pError(av[i]);
  314.             retcode=5;
  315.             continue;
  316.         }
  317.  
  318.         reverse= ( options&DIR_BACK ) ? 1 : 0;
  319.         func=cmp;
  320.         if( options & DIR_TIME) func=datecmp;
  321.         if( options & DIR_LEN ) func=sizecmp;
  322.         if( options & DIR_CLASS)func=classcmp;
  323.         DirQuickSort(eav, eac, func, reverse);
  324.         for(c=0; c<eac && !CHECKBREAK(); ++c) {
  325.             if( options & DIR_HIDE ) {
  326.                 char *b=BaseName(eav[c]);
  327.                 int  l=strlen(b)-5;
  328.                 struct file_info *info =
  329.                     (struct file_info *)(eav[c]-sizeof(struct file_info));
  330.                 if(*b=='.'|| (l>=0 && !strcmp(b+l,".info"))||(info->flags&128))
  331.                     continue;
  332.             }
  333.             if (options & DIR_NAMES)
  334.                 puts(eav[c]);
  335.             else
  336.                 display_file(eav[c]);
  337.         }
  338.  
  339.         if (col) { quickscroll(); printf("\n"); col=0; }
  340.         if (options&DIR_UNIQ || (filecount>1 && i==nump-1)) {
  341.             blocks += filecount; /* account for dir blocks */
  342.             quickscroll();
  343.             printf(" %ld Blocks, %s Bytes used in %d files\n",
  344.                 blocks, itoa(bytes), filecount);
  345.         }
  346.         if( options&DIR_UNIQ )
  347.             free(eav);
  348.         else 
  349.             free_expand (eav);
  350.         if (lastlock) UnLock(lastlock), lastlock=0;
  351.     }
  352.     if (lastlock) UnLock(lastlock), lastlock=0;
  353.  
  354.     if( options&DIR_UNIQ )
  355.         free_expand( av1 ), free_expand( av2 );
  356.  
  357.     if( inter ) printf( "\033[?7h" );                /* end of line wrap off */
  358.  
  359.     return retcode;
  360. }
  361.  
  362.  
  363. static void
  364. display_file( char *filestr )
  365. {
  366.     int isadir,slen;
  367.     char sc, *base, buf[130];
  368.     struct file_info *info;
  369.     BPTR thislock;
  370.  
  371.     base=BaseName(filestr);
  372.     sc = *base;
  373.     *base = '\0';
  374.     thislock=Lock(filestr,SHARED_LOCK);
  375.     /* if (thislock==NULL) return; */
  376.     if (lastlock==NULL || CompareLock(thislock,lastlock)) {
  377.         /* struct InfoData *id=AllocMem( sizeof(struct InfoData), 0); */
  378.         if (col) { quickscroll(); printf("\n"); col=0; }
  379.         quickscroll();
  380.         PathName(thislock, buf, 128L);
  381.         /* Info( thislock, id ); */
  382.         printf("Directory of %s\n", buf );
  383.         /*itok((id->id_NumBlocks-id->id_NumBlocksUsed)*id->id_BytesPerBlock));*/
  384.         /* FreeMem( id, sizeof(struct InfoData)); */
  385.         if (lastlock) UnLock(lastlock);
  386.         lastlock=thislock;
  387.     } else
  388.         UnLock(thislock);
  389.  
  390.     *base    = sc;
  391.     if((slen = strlen(base)+1) & 1 ) ++slen;
  392.     info     = (struct file_info *)(filestr - sizeof(struct file_info));
  393.     isadir   = info->size<0;
  394.  
  395.     if (!(((options & DIR_FILES) && !isadir) ||
  396.                      ((options & DIR_DIRS) &&  isadir)))
  397.         return;
  398.     if (isadir && !(options & DIR_NOCOL)) printf (o_hilite);
  399.     if (options & DIR_SHORT) {
  400.         slen= (slen>18) ? 37 : 18;
  401.         if (col && col+slen>=wwidth )
  402.             { quickscroll(); printf("\n"); col = 0; }
  403.         printf(" %-*s",slen,base);
  404.         col+= ++slen;
  405.     } else {
  406.         quickscroll();
  407.         printf("   %-24s %s \n",base,formatfile(info));
  408.     }
  409.     if (isadir && !(options & DIR_NOCOL))
  410.         printf(o_lolite);
  411.     if(info->size>0)
  412.         bytes  += info->size;
  413.     blocks += info->blocks;
  414.     filecount++;
  415. }
  416.  
  417. /* will have either of these formats:
  418.  *
  419.  *    fullfilename'\0'hsparwed   <Dir>       DD-MMM-YY HH:MM:SS\n'\0'
  420.  *    fullfilename'\0'hsparwed NNNNNNN NNNN  DD-MMM-YY HH:MM:SS\n'\0'
  421.  *                              1111111111222222222233333333334 4  4
  422.  *                    01234567890123456789012345678901234567890 1  2
  423.  */
  424.  
  425. static char linebuf[140];
  426. static long dlen, dblocks;
  427.  
  428. static void
  429. count( FIB *fib )
  430. {
  431.     dlen+=fib->fib_Size;
  432.     dblocks+=fib->fib_NumBlocks+1;
  433. }
  434.  
  435. char *
  436. formatfile( struct file_info *info)
  437. {
  438.     char *str=linebuf, *class, *t;
  439.     int i, stat;
  440.  
  441.     if( options & DIR_NOTE ) {
  442.         struct DPTR *dp;
  443.         if( dp=dopen( (char *)(info+1), &stat )) {
  444.             strcpy( str, dp->fib->fib_Comment );
  445.             dclose( dp );
  446.         }
  447.         return linebuf;
  448.     }
  449.  
  450.     *str++= info->flags & 1<<30 ? 'c' : '-';
  451.     for (i=7; i>=0; i--)
  452.         *str++ = ((info->flags & (1L<<i)) ? "hspa----" : "----rwed")[7-i];
  453.     if (info->size >= 0)
  454.         sprintf(str,options&DIR_QUIET?" %7ld ":" %7ld %4ld  ",
  455.                     info->size, info->blocks);
  456.     else
  457.         strcpy(str,options&DIR_QUIET?"   <Dir> ":"   <Dir>       ");
  458.     str+=strlen(str);
  459.     if( options&DIR_VIEW && info->size<0 ) {
  460.         dlen=dblocks=0;
  461.         recurse2( (char *)(info+1),count);
  462.         sprintf( str, "%10s",itoa(dlen));
  463.         info->size=dlen; info->blocks=dblocks;
  464.     } else if( options&DIR_IDENT ) {
  465.         if( *info->class!=1 )
  466.             strcpy(str,info->class);
  467.         else if( class=getclass((char *)(info+1)))
  468.             if( t=index(strncpy(str,class,40),0xA0) )
  469.                 *t=0;
  470.     } else if( options&DIR_AGE) {
  471.         long mins=0;
  472.         if( Stamp.ds_Days!=0 ) {
  473.             mins =Stamp.ds_Days*1440 + Stamp.ds_Minute;
  474.             mins-=info->date.ds_Days*1440 + info->date.ds_Minute;
  475.         }
  476.         if( mins>=0 )
  477.             sprintf(str,"%4d %02d:%02d",mins/1440,mins/60%60,mins%40);
  478.         else 
  479.             sprintf(str,"Future");
  480.     } else if( !(options&DIR_VIEW) )
  481.         strcat(str,dates(&info->date));
  482.     return linebuf;
  483. }
  484.  
  485.  
  486. int
  487. do_quit( void )
  488. {
  489.     if (Src_stack) {
  490.         Quit = 1;
  491.         return(do_return());
  492.     }
  493.     main_exit(0);
  494.     return 0;
  495. }
  496.  
  497. int
  498. do_echo( void )
  499. {
  500.     char *args=compile_av(av,1,ac,' ',0);
  501.     fprintf( (options&2)?stderr:stdout, (options&1)?"%s":"%s\n",args );
  502.     free(args);
  503.     return 0;
  504. }
  505.  
  506.  
  507. static int
  508. breakcheckd(void)
  509. {
  510.     int ret=!o_nobreak && SetSignal(0L,0L) & SIGBREAKF_CTRL_D;
  511.     SetSignal(0L, SIGBREAKF_CTRL_D);
  512.     if( ret )
  513.         fprintf(stderr,"^D\n");
  514.     return ret;
  515. }
  516.  
  517. /* gets a line from file, joining two lines if the first ends in '\' */
  518.  
  519. static char *
  520. myfgets(char *buf, int buflen, FILE *file)
  521. {
  522.     char *bufptr=buf, *limit=buf+buflen;
  523.  
  524.     do {
  525.         if (fgets(bufptr, limit-bufptr, file)==NULL) {
  526.             if (bufptr != buf)
  527.                 fprintf(stderr,"Source: file ends in '\\'\n");
  528.             return NULL;
  529.         }
  530.         bufptr = bufptr+strlen(bufptr)-2;
  531.     } while (*bufptr=='\\');
  532.     return buf;
  533. }
  534.  
  535. int
  536. do_source( char *str )
  537. {
  538.     FILE *fi;
  539.     char *buf;
  540.     int len;
  541.  
  542.     if (Src_stack == MAXSRC) {
  543.         ierror(NULL,217);
  544.         return -1;
  545.     }
  546.     if ((fi = fopen (av[1], "r")) == 0)
  547.         { pError(av[1]); return -1;    }
  548.     buf=malloc(512);
  549.     set_var(LEVEL_SET, v_passed, next_word(next_word(str)));
  550.     ++H_stack;
  551.     Src_pos[Src_stack] = 0;
  552.     Src_base[Src_stack] = fi;
  553.     Src_if[Src_stack]=If_stack;
  554.     ++Src_stack;
  555.     while (myfgets (buf, 512, fi) && !dobreak() && !breakcheckd()) {
  556.         len = strlen(buf);
  557.         if(buf[len-1]=='\n')
  558.             buf[len-1] = '\0';
  559.         Src_pos[Src_stack - 1] += len;
  560.         if (Verbose && !forward_goto) fprintf(stderr,"%s\n",buf);
  561.         exec_command (buf);
  562.     }
  563.     --H_stack;
  564.     --Src_stack;
  565.     if( If_stack>Src_if[Src_stack] )
  566.         If_stack=Src_if[Src_stack], disable=If_stack && If_base[If_stack-1];
  567.  
  568.     if (forward_goto) ierror(NULL,501);
  569.     forward_goto = 0;
  570.     unset_level(LEVEL_SOURCE + Src_stack);
  571.     unset_var(LEVEL_SET, v_gotofwd);
  572.     unset_var(LEVEL_SET, v_passed);
  573.     free(buf);
  574.     fclose (fi);
  575.     return 0;
  576. }
  577.  
  578. /* set process cwd name and $_cwd, if str != NULL also print it. */
  579.  
  580. int
  581. do_pwd( char *str )
  582. {
  583.     char pwd[130];
  584.  
  585.     PathName(Myprocess->pr_CurrentDir, pwd, 128L);
  586.     if (str) puts(pwd);
  587.     set_var(LEVEL_SET, v_cwd, pwd);
  588.     /* put the current dir name in our CLI task structure */
  589.     CtoBStr(pwd, Mycli->cli_SetName, 128L);
  590.     return 0;
  591. }
  592.  
  593. /*
  594.  * CD
  595.  *
  596.  * CD(str, 0)      -do CD operation.
  597.  *
  598.  */
  599.  
  600. extern int qcd_flag;
  601.  
  602. static char lastqcd[80];
  603. static lastoffs;
  604.  
  605. int
  606. do_cd( char *str )
  607. {
  608.     BPTR oldlock, filelock;
  609.     FILE *file;
  610.     char buf[100], *old;
  611.     int  i=1, repeat;
  612.  
  613.     if( options & 1 ) {
  614.         if( !(file=fopen( o_csh_qcd, "w" )))
  615.             { fprintf(stderr,"Can't open output\n"); return 20; }
  616.         for( ; i<ac && !breakcheck(); i++ ) {
  617.             fprintf(file,"%s\n",av[i]);
  618.             strcpy(buf,av[i]);
  619.             appendslash( buf );
  620.             expand_all( buf, file );
  621.         }
  622.         fclose(file);
  623.         return 0;
  624.     }
  625.  
  626.     str= ( has_wild && ac>=2 ) ? av[1] : next_word(str);
  627.     if (!strcmp("..",str)) str="/";
  628.  
  629.     if( !*str ) {
  630.         printf("%s\n", get_var( LEVEL_SET, v_cwd ));
  631.         return 0;
  632.     }
  633.  
  634.     if (filelock=Lock(str,ACCESS_READ)) {
  635.         lastqcd[0]=0;
  636.         if (!isdir(str)) { UnLock(filelock); ierror(str,212); return 20; }
  637.     } else {
  638.         repeat= !strncmp( lastqcd, str, 79 );
  639.         strncpy( lastqcd, str, 79);
  640.  
  641.         if( !quick_cd( buf, av[i], repeat) )
  642.             { fprintf(stderr,"Object not found %s\n",str); return 20; }
  643.         if (!(filelock=Lock(buf,ACCESS_READ))) 
  644.             { pError(buf); return 20; }
  645.     }
  646.     if (oldlock=CurrentDir(filelock)) UnLock(oldlock);
  647.     if( !(old=get_var(LEVEL_SET, v_cwd)) )
  648.         old="";
  649.     set_var(LEVEL_SET, v_lcd, old);
  650.     do_pwd(NULL);
  651.  
  652.     return 0;
  653. }
  654.  
  655. char *
  656. quick_cd( char *buf, char *name, int repeat )
  657. {
  658.     qcd_flag=repeat ? 2 : 1;
  659.     strcpy(buf,name);
  660.     if( quicksearch( o_csh_qcd, 1, buf)!=2 )
  661.         return NULL;
  662.     return buf;
  663. }
  664.  
  665.  
  666. int
  667. do_mkdir( void )
  668. {
  669.     int i;
  670.     BPTR lock;
  671.     
  672.     for (i=1; i<ac; ++i) {
  673.         if (exists(av[i]))
  674.             ierror(av[i],203);
  675.         else if (lock=CreateDir(av[i]))
  676.             UnLock (lock);
  677.         else
  678.             pError(av[i]);
  679.     }
  680.     return 0;
  681. }
  682.  
  683. int
  684. do_mv( void )
  685. {
  686.     char *dest, buf[256];
  687.     int dirflag, i;
  688.  
  689.     dirflag=isdir(dest=av[--ac]);
  690.     if (ac>3 && !dirflag) { ierror(dest, 507); return (-1); }
  691.     for (i=1; i<ac; ++i) {
  692.         strcpy(buf, dest);
  693.         if (dirflag) TackOn(buf, BaseName(av[i]));
  694.         if (Rename(av[i], buf)==0)
  695.             { pError(av[i]); return -1; }
  696.         else 
  697.             clear_archive_bit( buf );
  698.     }
  699.     return 0;
  700. }
  701.  
  702. static int dirstoo;
  703.  
  704. int
  705. all_args( int (*action)(char *str), int dirsflag )
  706. {
  707.     int i;
  708.  
  709.     dirstoo=dirsflag;
  710.     for ( i=1; i<ac && !dobreak(); ++i)
  711.         if (isdir(av[i])) {
  712.             if (options & 1) recurse(av[i], action);
  713.             else if (dirstoo) (*action)(av[i]);
  714.         } else
  715.             (*action)(av[i]);
  716.     return 0;
  717. }
  718.  
  719. char *searchstring;
  720. char docr;
  721.  
  722. #define SEARCH_REC   1
  723. #define SEARCH_CASE  2
  724. #define SEARCH_WILD  4
  725. #define SEARCH_NUM   8
  726. #define SEARCH_EXCL  16
  727. #define SEARCH_QUIET 32
  728. #define SEARCH_VERB  64
  729. #define SEARCH_BIN   128
  730. #define SEARCH_FILE  256
  731. #define SEARCH_ABORT 512
  732. #define SEARCH_LEFT  1024
  733. #define SEARCH_ONLY  2048
  734.  
  735. static int abort_search;
  736. static char lowbuf[256], file_name, file_cr;
  737.  
  738. static int
  739. search_file( char *s )
  740. {
  741.     FILE *fopen(), *fi;
  742.     char *p, *q;
  743.     int nocasedep, lctr, len, excl=((options & 16) !=0 ), yesno;
  744.     char buf[256], searchit[120], first, left;
  745.  
  746.     if( abort_search )
  747.         return 0;
  748.  
  749.     nocasedep=!(options & SEARCH_CASE);
  750.     lctr= docr= file_name= file_cr= 0;
  751.     if (!(options & (SEARCH_QUIET|SEARCH_FILE)))
  752.         if( options & SEARCH_VERB )
  753.             printf("Examining %s...\n",s);
  754.         else 
  755.             printf("\015Examining %s...                  ",s), docr=1;
  756.  
  757.     strcpy(searchit,searchstring);
  758.     if (options & SEARCH_WILD) strcat(searchit,"\n");
  759.     len=strlen(searchit);
  760.     if (nocasedep) strupr(searchit);
  761.     first=*searchit;
  762.  
  763.     if( strcmp("STDIN",s) && !(options&SEARCH_WILD) && !excl ||
  764.                  options&SEARCH_BIN )
  765.         if( quicksearch(s,nocasedep,searchit) )
  766.             return 0;
  767.  
  768.     if( options&SEARCH_BIN )
  769.         { fprintf(stderr,"Out of memory\n"); return 20; }
  770.  
  771.     fi = strcmp("STDIN",s) ?  fopen(s,"r") : stdin;
  772.     if (fi==NULL) { pError(s); return 20; }
  773.  
  774.     prepscroll(0);
  775.  
  776.     while (fgets(buf,256,fi) && !dobreak()) {
  777.         lctr++; left=1;
  778.         if (options & SEARCH_WILD)
  779.             yesno=compare_ok(searchit, buf, options&SEARCH_CASE);
  780.         else {
  781.             if (nocasedep) {
  782.                 strcpy(lowbuf,buf);
  783.                 strupr(lowbuf);
  784.                 p=lowbuf;
  785.             } else
  786.                 p=buf;
  787.             q=p;
  788.             while ((p=index(p,first)) && strncmp(p++,searchit,len)) ;
  789.             yesno= (p!=NULL);
  790.             left = --p - q;
  791.         }
  792.         if( yesno ^ excl )
  793.             if(!(options&SEARCH_ONLY)|| !isalphanum(p[-1])&&!isalphanum(p[len]))
  794.                 if( found(buf, lctr, 0, s, left ) )
  795.                     break;
  796.     }
  797.     if (fi!=stdin) fclose (fi);
  798.     if( file_cr ) printf("\n");
  799.     return 0;
  800. }
  801.  
  802. int qcd_flag, qcd_offs;
  803.  
  804. static int
  805. quicksearch( char *name, int nocasedep, char *pattern )
  806. {
  807.     int i, ptrn=strlen(pattern);
  808.     char ut[256], *buffer, *lend;
  809.     char *uptab=ut, *get, c, *lpos, *lstart;
  810.     int len, lnum, qcd=qcd_flag, repeat=(qcd==2 && qcd_offs!=0);
  811.     int sofar, got;
  812.     BPTR fh;
  813.  
  814. #ifdef AZTEC_C
  815.     while(0) while(0) c=c=0, uptab=uptab=ut, get=get=NULL;
  816. #endif
  817.  
  818.     qcd_flag=0;
  819.     if( !(fh=Open(name,MODE_OLDFILE))) { 
  820.         i=(long)IoErr(), docr=0;
  821.         printf("\n");
  822.         ierror(name,i);
  823.         return 1;
  824.     }
  825.     len=filesize( name );
  826.     if( !(buffer=(void *)malloc(len+2))) { Close(fh); return 0; }
  827.     sofar=0;
  828.     do {
  829.         got=Read( fh, (char *)buffer+sofar, 60000);
  830.         sofar+=got;
  831.     } while( got==60000 );
  832.     Close( fh);
  833.     if( sofar != len ) { pError(pattern); return 1; }
  834.  
  835.     if( nocasedep )
  836.         strupr( pattern );
  837.  
  838.     if( !qcd )
  839.         prepscroll(0);
  840.  
  841.     for( i=0; i<256; i++ ) uptab[i]=i;
  842.     if( nocasedep ) for( i='a'; i<='z'; i++ ) uptab[i]=i-'a'+'A';
  843. retry:
  844.     c=*pattern, buffer[len]=c, buffer[len+1]=c;
  845.     get= (qcd==2) ? buffer+qcd_offs : buffer;
  846.     if( qcd==1 ) qcd_offs=0;
  847.  
  848.     lpos=lstart=buffer, lnum=1;
  849.     for( ;; ) {
  850.         do ; while( uptab[*get++]!=c );
  851.         if( --get>=buffer + len )
  852.             break;
  853.         for( i=1; i<ptrn; i++ )
  854.             if( uptab[get[i]]!=pattern[i] )
  855.                 break;
  856.         if( i==ptrn ) {
  857.             for( ;lpos<get; lpos++ )
  858.                 if( *lpos=='\n' )
  859.                     lstart=lpos+1, lnum++;
  860.             for( lend=lstart+1; *lend!='\n'; lend++ ) ;
  861.             if( qcd ) {
  862.                 if( get[-1]==':' || get[-1]=='/' ||
  863.                       lpos==lstart && lend[-1]==':' ) {
  864.                     char *tmp;
  865.                     for( tmp=get+ptrn; *tmp&& *tmp!='\n'&& *tmp!='/'; tmp++ );
  866.                     if( *tmp!='/' ) {
  867.                         *lend=0;
  868.                         strncpy(pattern,lstart,79);
  869.                         qcd_offs=lend-buffer;
  870.                         free( buffer );
  871.                         return 2;
  872.                     }
  873.                 } else 
  874.                     lend=lpos+1;
  875.             } else {
  876.                 *lend=0;
  877.                 if(!(options&SEARCH_ONLY) ||
  878.                      !isalphanum(lpos[-1])&&!isalphanum(lpos[ptrn]))
  879.                     if(found(lstart, lnum, get-buffer, name, lpos==lstart ))
  880.                         break;
  881.                 *lend='\n';
  882.             }
  883.             get=lend+1;
  884.         } else
  885.             get++;
  886.     }
  887.     if( repeat )  { repeat=0; qcd_offs=0; goto retry; }
  888.     if( file_cr ) { printf("\n"); quickscroll(); }
  889.     free( buffer );
  890.     return 1;
  891. }
  892.  
  893. static int
  894. found( char *lstart, int lnum, int loffs, char *name, char left )
  895. {
  896.     int fileabort=0;
  897.  
  898.     if ( docr )
  899.         { quickscroll(); printf("\n"); docr=0; }
  900.  
  901.     if( (options&SEARCH_LEFT) && !left)
  902.         return 0;
  903.  
  904.     if( options&SEARCH_FILE ) {
  905.         file_cr=1;
  906.         if( !file_name )
  907.             printf("%s",name), file_name=1;
  908.         if( options&SEARCH_NUM )
  909.             fileabort=1;
  910.         else 
  911.             printf(" %d",lnum);
  912.     } else if( options & SEARCH_BIN ) {
  913.         if (!(options & SEARCH_NUM))
  914.             printf("Byte offset %d\n",loffs);
  915.         else 
  916.             printf("%d\n",loffs);
  917.         quickscroll();
  918.     } else {
  919.         if (!(options & SEARCH_NUM))
  920.             printf("%4d ",lnum);
  921.         printf((lstart[strlen(lstart)-1]=='\n')?"%s":"%s\n",lstart);
  922.         quickscroll();
  923.     }
  924.     abort_search= options&SEARCH_ABORT;
  925.     return dobreak() || fileabort || abort_search;
  926. }
  927.  
  928.  
  929. int
  930. do_search( void )
  931. {
  932.     if( Cout_name ) options |= SEARCH_VERB;
  933.     abort_search=0;
  934.     searchstring=av[--ac];
  935.     all_args(search_file, 0);
  936.     if(docr) printf("\n"),docr=0;
  937.     return 0;
  938. }
  939.  
  940. static int
  941. rm_file(char *file)
  942. {
  943.     if ( file[strlen(file)-1]=='/' ) file[strlen(file)-1]=0;
  944.     if (has_wild) printf(" %s...",file);
  945.     if (options & 2) SetProtection(file,0L);
  946.     if (!DeleteFile(file)) 
  947.         { pError (file); return 20; }
  948.     else if (has_wild)
  949.         printf("Deleted\n");
  950.     return 0;
  951. }
  952.  
  953. int
  954. do_rm( void )
  955. {
  956.     all_args( rm_file, 1);
  957.     return 0;
  958. }
  959.  
  960. static void
  961. recurse(char *name, int (*action)(char *))
  962. {
  963.     BPTR lock, cwd;
  964.     FIB *fib=(FIB *)AllocMem((long)sizeof(FIB),MEMF_PUBLIC);
  965.     char *namecopy=malloc(256);
  966.  
  967.     if (name[0] =='\0') return;
  968.     namecopy[0]=0;
  969.     if (lock=Lock(name,ACCESS_READ)) {
  970.         cwd =CurrentDir(lock);
  971.         if (Examine(lock, fib))
  972.             while (ExNext(lock, fib) && !CHECKBREAK()) {
  973.                 if (*namecopy)
  974.                     { (*action)(namecopy); namecopy[0]=0; }
  975.                 if (fib->fib_DirEntryType>=0) recurse(fib->fib_FileName,action);
  976.                 else strcpy(namecopy,fib->fib_FileName);
  977.             }
  978.         if (*namecopy) (*action)(namecopy);
  979.         UnLock(CurrentDir(cwd));
  980.         if (dirstoo) (*action)(name);
  981.     } else
  982.         pError(name);
  983.     free(namecopy);
  984.     FreeMem(fib, (long)sizeof(FIB));
  985. }
  986.  
  987. static void
  988. recurse2( char *name, void (*action)(FIB *))
  989. {
  990.     BPTR lock, cwd;
  991.     FIB  *fib=(FIB *)AllocMem(sizeof(FIB),MEMF_PUBLIC);
  992.  
  993.     if (lock=Lock(name,ACCESS_READ)) {
  994.         cwd =CurrentDir(lock);
  995.         if (Examine(lock, fib))
  996.             while (ExNext(lock, fib) && !CHECKBREAK()) {
  997.                 (*action)(fib);
  998.                 if (fib->fib_DirEntryType>=0)
  999.                     recurse2(fib->fib_FileName,action);
  1000.             }
  1001.         UnLock(CurrentDir(cwd));
  1002.     }
  1003.  
  1004.     FreeMem(fib, sizeof(FIB));
  1005. }
  1006.  
  1007.  
  1008. int
  1009. do_history( void )
  1010. {
  1011.     struct HIST *hist;
  1012.     int i = H_tail_base;
  1013.     int len = (av[1]) ? strlen(av[1]) : 0;
  1014.  
  1015.     for (hist = H_tail; hist && !dobreak(); hist = hist->prev, i++)
  1016.         if (len == 0 || !strncmp(av[1], hist->line, len))
  1017.             printf("%3d %s\n", i, hist->line);
  1018.     return 0;
  1019. }
  1020.  
  1021. int
  1022. do_mem( void )
  1023. {
  1024.     static long clast, flast;
  1025.     long cfree, ffree;
  1026.     char *desc="Free";
  1027.  
  1028.     Forbid();
  1029.     cfree = AvailMem (MEMF_CHIP);
  1030.     ffree = AvailMem (MEMF_FAST);
  1031.     Permit();
  1032.     if( options&8 ) {
  1033.         clast=cfree, flast=ffree;
  1034.         return 0;
  1035.     }
  1036.     if( options&16 )
  1037.         cfree=clast-cfree, ffree=flast-ffree, desc="Used";
  1038.     if( options&4 ) {
  1039.         if     ( options & 1 ) printf("%ld\n",cfree);
  1040.         else if( options & 2 ) printf("%ld\n",ffree);
  1041.         else                   printf("%ld\n",cfree+ffree);
  1042.     } else {
  1043.         if     ( options & 1 ) printf("Free CHIP memory %s\n",itoa(cfree));
  1044.         else if( options & 2 ) printf("Free FAST memory %s\n",itoa(ffree));
  1045.         else {
  1046.             if(ffree) {
  1047.                 printf("FAST memory: %s\n",itoa(ffree));
  1048.                 printf("CHIP memory: %s\n",itoa(cfree));
  1049.             }
  1050.             printf("Total  %s: %s\n",desc,itoa(cfree+ffree));
  1051.         }
  1052.     }
  1053.     return 0;
  1054. }
  1055.  
  1056. int
  1057. do_forline( void )
  1058. {
  1059.     char vname[33], buf[256], *cstr;
  1060.     int lctr;
  1061.     FILE *f;
  1062.  
  1063.     strcpy(vname,av[1]);
  1064.     f=fopen(av[2],"r");
  1065.     if (f==NULL) pError(av[2]);
  1066.     lctr=0;
  1067.     ++H_stack;
  1068.     cstr = compile_av (av, 3, ac, ' ', 0);
  1069.     while (fgets(buf,256,f) && !dobreak()) {
  1070.         buf[strlen(buf)-1]='\0';    /* remove CR */
  1071.         lctr++;
  1072.         set_var(LEVEL_SET, vname, buf);
  1073.         sprintf(buf,"%d",lctr);
  1074.         set_var(LEVEL_SET, v_linenum, buf);
  1075.         exec_command(cstr);
  1076.     }
  1077.     fclose(f);
  1078.     --H_stack;
  1079.     free (cstr);
  1080.     unset_var (LEVEL_SET, vname);
  1081.     unset_var (LEVEL_SET, v_linenum);
  1082.     return 0;
  1083. }
  1084.  
  1085. int
  1086. do_fornum( void )
  1087. {
  1088.     char vname[33], buf[16];
  1089.     int n1, n2, step, i=1, verbose;
  1090.     char *cstr;
  1091.  
  1092.     verbose=(options & 1);
  1093.     strcpy(vname,av[i++]);
  1094.     n1=myatoi(av[i++],-32767,32767); if (atoierr) return 20;
  1095.     n2=myatoi(av[i++],-32767,32767); if (atoierr) return 20;
  1096.     if (options & 2) {
  1097.         step=myatoi(av[i++],-32767,32767); if (atoierr) return 20;
  1098.     } else
  1099.         step=1;
  1100.     ++H_stack;
  1101.     cstr = compile_av (av, i, ac, ' ', 0);
  1102.     for (i=n1; (step>=0 ? i<=n2 : i>=n2) && !CHECKBREAK(); i+=step) {
  1103.         if (verbose) fprintf(stderr, "fornum: %d\n", i);
  1104.         sprintf(buf,"%d",i);
  1105.         set_var (LEVEL_SET, vname, buf);
  1106.         exec_command(cstr);
  1107.     }
  1108.     --H_stack;
  1109.     free (cstr);
  1110.     unset_var (LEVEL_SET, vname);
  1111.     return 0;
  1112. }
  1113.  
  1114. /*
  1115.  * foreach var_name  ( str str str str... str ) commands
  1116.  * spacing is important (unfortunately)
  1117.  *
  1118.  * ac=0    1 2 3 4 5 6 7
  1119.  * foreach i ( a b c ) echo $i
  1120.  * foreach i ( *.c ) "echo -n "file ->";echo $i"
  1121.  */
  1122.  
  1123. int
  1124. do_foreach( void )
  1125. {
  1126.     int cstart, cend;
  1127.     char *cstr, **fav, vname[33];
  1128.     int i=1, verbose;
  1129.  
  1130.     verbose=(options & 1);
  1131.     strcpy(vname, av[i++]);
  1132.     if (*av[i] == '(') i++;
  1133.     cstart = i;
  1134.     while (i<ac && *av[i] != ')') i++;
  1135.     if (i > ac) { fprintf(stderr,"')' expected\n"); return 20; }
  1136.     ++H_stack;
  1137.     cend = i;
  1138.  
  1139.     fav = (char **)malloc(sizeof(char *) * (ac));
  1140.     cstr = compile_av (av, cend + 1, ac, ' ', 0);
  1141.  
  1142.     for (i = cstart; i < cend; ++i) fav[i] = av[i];
  1143.  
  1144.     for (i = cstart; i<cend && !CHECKBREAK(); ++i) {
  1145.         set_var (LEVEL_SET, vname, fav[i]);
  1146.         if (verbose) fprintf(stderr, "foreach: %s\n", fav[i]);
  1147.         exec_command(cstr);
  1148.     }
  1149.     --H_stack;
  1150.     free (fav);
  1151.     free (cstr);
  1152.     unset_var (LEVEL_SET, vname);
  1153.     return 0;
  1154. }
  1155.  
  1156. int
  1157. do_forever( char *str )
  1158. {
  1159.     int rcode = 0;
  1160.     char *ptr = next_word( str );
  1161.  
  1162.     ++H_stack;
  1163.     for (;;) {
  1164.         if (CHECKBREAK()) { rcode = 20; break; }
  1165.         if (exec_command (ptr) < 0) {
  1166.             str = get_var(LEVEL_SET, v_lasterr);
  1167.             rcode = (str) ? atoi(str) : 20;
  1168.             break;
  1169.         }
  1170.     }
  1171.     --H_stack;
  1172.     return rcode;
  1173. }
  1174.  
  1175. extern struct IntuitionBase *IntuitionBase;
  1176.  
  1177. int
  1178. do_window( void )
  1179. {
  1180.     long x=-1, y=-1, w=-1, h=-1, maxwidth, maxheight, arg[5];
  1181.     int i;
  1182.  
  1183.     if(options & 32) {
  1184.         struct Screen *scrn;
  1185.         struct Window *window;
  1186.         char buf[80];
  1187.         buf[40]=0;
  1188.         for (scrn=IntuitionBase->FirstScreen; scrn; scrn=scrn->NextScreen) {
  1189.             buf[0]=0;
  1190.             if( scrn->Title )
  1191.                 strncpy(buf,scrn->Title,40);
  1192.             printf("\nScreen \"%s\" (%d,%d,%dx%d):\n",
  1193.                 buf,
  1194.                 scrn->LeftEdge,
  1195.                 scrn->TopEdge,
  1196.                 scrn->Width,
  1197.                 scrn->Height
  1198.             );
  1199.             for (window=scrn->FirstWindow; window; window=window->NextWindow) {
  1200.                 buf[0]=0;
  1201.                 if( window->Title )
  1202.                     strncpy(buf,window->Title,40);
  1203.                 printf("\tWindow\t\"%s\" (%d,%d,%dx%d)\n",
  1204.                     buf,
  1205.                     window->LeftEdge,
  1206.                     window->TopEdge,
  1207.                     window->Width,
  1208.                     window->Height
  1209.                 );
  1210.             }
  1211.         }
  1212.         return 0;
  1213.     }
  1214.  
  1215.     if( o_nowindow || !Win )
  1216.         return 20;
  1217.  
  1218.     maxwidth = Win->WScreen->Width;
  1219.     maxheight= Win->WScreen->Height;
  1220.     if( options&1 )
  1221.         x=Win->LeftEdge,y=Win->TopEdge,w=Win->MinWidth,h=Win->MinHeight;
  1222.     if( options&2 ) x=y=0, w=maxwidth, h=maxheight;
  1223.     if( options&4 ) WindowToFront(Win);
  1224.     if( options&8 ) WindowToBack(Win);
  1225.     if( options&16) ActivateWindow(Win);
  1226.     if( ac >= 5) {
  1227.         for(i=1; i<5; i++) {
  1228.             arg[i] = myatoi(av[i],0,1023); if (atoierr) return 20;
  1229.         }
  1230.         x=arg[1]; y=arg[2]; w=arg[3]; h=arg[4];
  1231.     }
  1232.     if( w!=-1 ) {
  1233.         int i;
  1234.         if ( x+w>maxwidth || y+h>maxheight ) {
  1235.             ierror(NULL, 500);
  1236.             return 20;
  1237.         }
  1238.         if( w<Win->MinWidth  ) w=Win->MinWidth;
  1239.         if( h<Win->MinHeight ) h=Win->MinHeight;
  1240.         if( Win->LeftEdge!=0 || Win->TopEdge!=0 )
  1241.             MoveWindow(Win, -Win->LeftEdge, -Win->TopEdge );
  1242.         if( Win->Width!=w || Win->Height!=h )
  1243.             SizeWindow(Win, w-Win->Width   , h-Win->Height  );
  1244.         if( x || y )
  1245.             MoveWindow(Win, x, y );
  1246.         for( i=0; i<7; i++ ) {
  1247.             if(  Win->LeftEdge==x && Win->TopEdge==y && 
  1248.                  Win->Width   ==w && Win->Height ==h )
  1249.                 break;
  1250.             Delay(5);
  1251.         }
  1252.     } else 
  1253.         Delay(30); /* pause 1/2 sec. before trying to print */
  1254.  
  1255.     printf("\014");
  1256.     return 0;
  1257. }
  1258.  
  1259.  
  1260. static void
  1261. setsystemtime(struct DateStamp *ds)
  1262. {
  1263.     struct timerequest tr;
  1264.     long secs= ds->ds_Days*86400+ds->ds_Minute*60+ds->ds_Tick/TICKS_PER_SECOND;
  1265.  
  1266.     if (OpenDevice(TIMERNAME, UNIT_VBLANK,(struct IORequest *)&tr, 0L)) {
  1267.         fprintf(stderr,"Clock error: can't open timer device\n");
  1268.         return;
  1269.     }
  1270.  
  1271.     tr.tr_node.io_Message.mn_Node.ln_Type = NT_MESSAGE;
  1272.     tr.tr_node.io_Message.mn_Node.ln_Pri = 0L;
  1273.     tr.tr_node.io_Message.mn_Node.ln_Name = NULL;
  1274.     tr.tr_node.io_Message.mn_ReplyPort = NULL;
  1275.     tr.tr_node.io_Command = TR_SETSYSTIME;
  1276.     tr.tr_time.tv_secs = secs;
  1277.     tr.tr_time.tv_micro = 0L;
  1278.     if (DoIO ((struct IORequest *)&tr))
  1279.         fprintf(stderr,"Clock error: can't talk to timer device\n");
  1280.     CloseDevice ((struct IORequest *)&tr);
  1281. }
  1282.  
  1283. char tday[10];
  1284.  
  1285. char *
  1286. dates( struct DateStamp *dss )
  1287. {
  1288.     static char timestr[40];
  1289.     char tdate[10], ttime[10];
  1290.     struct DateTime dt;
  1291.     struct DateStamp *myds=&(dt.dat_Stamp);
  1292.  
  1293.     dt.dat_Format=FORMAT_DOS;
  1294.     dt.dat_StrDay=tday;
  1295.     dt.dat_StrDate=tdate;
  1296.     dt.dat_StrTime=ttime;
  1297.     dt.dat_Flags=NULL;
  1298.     myds->ds_Days=dss->ds_Days;
  1299.     myds->ds_Minute=dss->ds_Minute;
  1300.     myds->ds_Tick=dss->ds_Tick;
  1301.     StamptoStr(&dt);
  1302.     sprintf(timestr,"%s %s\n",tdate,ttime);
  1303.     timestr[18]=0;    /* protection against bad timestamped files */
  1304.     return timestr;
  1305. }
  1306.  
  1307. int
  1308. do_date( void )
  1309. {
  1310.     static long stopwatch;
  1311.     struct DateStamp dss;
  1312.     struct DateTime dt;
  1313.     long time;
  1314.     int i=1;
  1315.  
  1316.     dt.dat_Format=FORMAT_DOS;
  1317.     if (ac==1) {
  1318.         DateStamp(&dss);
  1319.         time=dss.ds_Minute*6000+2*dss.ds_Tick;   /* 2 = 100/TickPerSec   */
  1320.         if( options & 1 )
  1321.             stopwatch=time;
  1322.         else if( options&2 )
  1323.             printf( "%d.%02d\n",(time-stopwatch)/100,(time-stopwatch)%100);
  1324.         else 
  1325.             printf("%s %s\n",tday,dates(&dss));
  1326.     } else {
  1327.         DateStamp(&dt.dat_Stamp);
  1328.         for ( ; i<ac; i++) {
  1329.             dt.dat_StrDate=NULL;
  1330.             dt.dat_StrTime=NULL;
  1331.             dt.dat_Flags=DTF_FUTURE;
  1332.             if (index(av[i],':')) dt.dat_StrTime=av[i];
  1333.                 else dt.dat_StrDate=av[i];
  1334.             if (StrtoStamp(&dt)) ierror(av[i],500);
  1335.         }
  1336.         setsystemtime( & (dt.dat_Stamp) );
  1337.     }
  1338.     return 0;
  1339. }
  1340.