Problems are occurring downloading from downloads.sourceforge.net, so use
[tangerine.git] / workbench / c / Type.c
blob9846333a5730c1e9cc3c3ec6f43dd2f8a1806dcb
1 /*
2 Copyright © 1995-2008, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Type CLI command
6 Lang: English
7 */
9 /******************************************************************************
11 NAME
13 Type {<file | pattern>} [TO <name>] [OPT H | N] [HEX | NUMBER]
15 SYNOPSIS
17 FROM/A/M,TO/K,OPT/K,HEX/S,NUMBER/S
19 LOCATION
23 FUNCTION
25 Displays content of a file
27 INPUTS
29 FROM -- one or more files to display
30 TO -- print output to file
31 OPT -- H or N (see HEX or NUMBER)
32 HEX -- displays output in hexadecimal format
33 NUMBER -- the lines are numbered
34 HEX and NUMBER are mutually exclusive
36 RESULT
38 NOTES
40 EXAMPLE
42 Type abc.txt
43 Type xyz.dat HEX
45 BUGS
47 SEE ALSO
49 INTERNALS
51 ******************************************************************************/
53 #include <exec/memory.h>
54 #include <exec/execbase.h>
55 #include <proto/exec.h>
56 #include <proto/dos.h>
57 #include <dos/dos.h>
59 #include <string.h>
61 const TEXT version[] = "$VER: Type 42.1 (20.10.2005)\n";
63 #define BUFSIZE 8192
64 #define MAX_PATH_LEN 512
66 enum
68 ARG_FROM,
69 ARG_TO,
70 ARG_OPT,
71 ARG_HEX,
72 ARG_NUMBER,
73 NUMARGS
76 struct file
78 BPTR fd;
79 UBYTE *cur;
80 ULONG cnt;
81 LONG error;
82 UBYTE buf[BUFSIZE];
85 const UBYTE hs[16]="0123456789abcdef";
87 #define putc(f,c) (*(f)->cur++=(c),--(f)->cnt?0:put(f))
88 static int put(struct file *f)
90 LONG size,subsize;
91 STRPTR buf;
92 size=f->cur-f->buf;
93 buf=f->buf;
94 while(size)
96 subsize=Write(f->fd,buf,size);
97 if(subsize<=0)
99 f->error=IoErr();
100 return 1;
102 buf+=subsize;
103 size-=subsize;
105 f->cur=f->buf;
106 f->cnt=BUFSIZE;
107 return 0;
110 #define getc(f) ((f)->cnt--?*(f)->cur++:get(f))
111 static int get(struct file *f)
113 LONG size;
114 size=Read(f->fd,f->buf,BUFSIZE);
115 if(size<0)
116 f->error=IoErr();
117 if(size<=0)
118 return -1;
119 f->cnt=size-1;
120 f->cur=f->buf;
121 return *f->cur++;
124 static void putlinequick(struct file *f, ULONG offset, UBYTE *buf)
126 int c, i, k;
127 UBYTE *b, *o;
128 o=f->cur;
129 if(offset>=0x10000)
131 if(offset>=0x100000)
133 if(offset>=0x1000000)
135 if(offset>=0x10000000)
137 *o++=hs[(offset>>28)&0xf];
138 f->cnt--;
140 *o++=hs[(offset>>24)&0xf];
141 f->cnt--;
143 *o++=hs[(offset>>20)&0xf];
144 f->cnt--;
146 *o++=hs[(offset>>16)&0xf];
147 f->cnt--;
149 *o++=hs[(offset>>12)&0xf];
150 *o++=hs[(offset>>8)&0xf];
151 *o++=hs[(offset>>4)&0xf];
152 *o++=hs[offset&0xf];
153 *o++=':';
154 *o++=' ';
155 b=buf;
156 for(i=0;i<4;i++)
158 for(k=0;k<4;k++)
160 c=*b++;
161 *o++=hs[c>>4];
162 *o++=hs[c&0xf];
164 *o++=' ';
166 b=buf;
167 for(i=0;i<16;i++)
169 c=*b++;
170 *o++=(c&0x7f)>=0x20&&c!=0x7f?c:'.';
172 *o++='\n';
173 f->cur=o;
174 f->cnt-=59;
177 static int putline(struct file *f, ULONG offset, UBYTE *buf, ULONG num)
179 int c, i;
180 UBYTE *b;
181 if(offset>=0x10000)
183 if(offset>=0x10000000&&putc(f,hs[(offset>>28)&0xf]))
184 return 1;
185 if(offset>=0x1000000&&putc(f,hs[(offset>>24)&0xf]))
186 return 1;
187 if(offset>=0x100000&&putc(f,hs[(offset>>20)&0xf]))
188 return 1;
189 if(offset>=0x10000&&putc(f,hs[(offset>>16)&0xf]))
190 return 1;
192 if(putc(f,hs[(offset>>12)&0xf]))
193 return 1;
194 if(putc(f,hs[(offset>>8)&0xf]))
195 return 1;
196 if(putc(f,hs[(offset>>4)&0xf]))
197 return 1;
198 if(putc(f,hs[offset&0xf]))
199 return 1;
200 if(putc(f,':'))
201 return 1;
202 if(putc(f,' '))
203 return 1;
204 b=buf;
205 for(i=0;i<16;i++)
207 if(i<num)
209 c=*b++;
210 if(putc(f,hs[c>>4]))
211 return 1;
212 if(putc(f,hs[c&0xf]))
213 return 1;
214 }else
216 if(putc(f,' '))
217 return 1;
218 if(putc(f,' '))
219 return 1;
221 if((i&3)==3)
222 if(putc(f,' '))
223 return 1;
225 b=buf;
226 for(i=0;i<num;i++)
228 c=*b++;
229 if(putc(f,(c&0x7f)>=0x20&&c!=0x7f?c:'.'))
230 return 1;
232 if(putc(f,'\n'))
233 return 1;
234 return 0;
237 LONG hexdumpfile(struct file *in, struct file *out)
239 UBYTE buf[16];
240 UBYTE *b;
241 LONG offset=0, n, c, tty;
242 LONG retval = RETURN_OK;
244 tty=IsInteractive(out->fd);
245 for(;;)
247 if(in->cnt>16)
249 b=in->cur;
250 n=16;
251 in->cur+=16;
252 in->cnt-=16;
253 }else
255 b=buf;
256 for(n=0;n<16;n++)
258 c=getc(in);
259 if(c<0)
261 break;
263 b[n]=c;
266 if(n==16)
268 if(out->cnt>=63)
269 putlinequick(out,offset,b);
270 else
271 if(putline(out,offset,b,n))
273 retval = RETURN_ERROR;
274 break;
276 }else
278 if(n)
279 putline(out,offset,b,n);
280 if(out->cur!=out->buf)
281 put(out);
282 break;
284 if(tty)
285 if(put(out))
287 retval = RETURN_ERROR;
288 break;
290 offset+=n;
292 if (CheckSignal(SIGBREAKF_CTRL_C))
294 retval = RETURN_WARN;
295 break;
299 return retval;
303 void putlinenumber(struct file * out, unsigned short line)
305 int x = 10000;
306 BOOL s = FALSE;
308 while (x)
310 if (line / x || s)
312 putc(out, line/x+'0');
313 line %= x;
314 s = TRUE;
316 else
317 putc(out, ' ');
319 x/=10;
322 putc(out, ' ');
325 LONG dumpfile(struct file *in, struct file *out, BOOL showline)
327 LONG c, lastc = 0;
328 unsigned short line = 0;
329 LONG retval = RETURN_OK;
331 if (showline)
332 putlinenumber(out, ++line);
334 if(1/*IsInteractive(out->fd)*/)
335 for(;;)
337 c=getc(in);
339 if(c<0)
341 if (lastc!='\n')
342 putc(out, '\n');
344 put(out);
345 break;
348 if (lastc==0x0a && showline)
349 putlinenumber(out, ++line);
351 if(putc(out,c)||(c=='\n' && put(out)))
353 if (c!='\n')
354 putc(out, '\n');
356 put(out);
357 retval = RETURN_ERROR;
358 break;
361 if ((c == '\n') && CheckSignal(SIGBREAKF_CTRL_C))
363 retval = RETURN_WARN;
364 break;
366 lastc = c;
369 return retval;
372 static LONG processfile(CONST_STRPTR name, struct file *in, struct file *out, IPTR *args, LONG *numfiles)
374 LONG error = 0;
376 in->fd = Open(name, MODE_OLDFILE);
377 if (in->fd)
379 (*numfiles)++;
380 in->cnt = 0;
382 if (args[ARG_HEX])
383 error = hexdumpfile(in, out);
384 else
385 error = dumpfile(in, out, args[ARG_NUMBER]);
387 Close(in->fd);
389 else
390 error = IoErr();
392 return error;
395 int __nocommandline;
397 struct MyAnchorPath
399 struct AnchorPath apath;
400 UBYTE buf[MAX_PATH_LEN - 1];
403 int main (void)
405 IPTR args[5]={ 0, 0, 0, 0, 0 };
406 struct RDArgs *rda;
407 struct file *in, *out;
408 STRPTR *names;
409 int retval = RETURN_OK;
410 struct MyAnchorPath apath;
412 rda=ReadArgs("FROM/A/M,TO/K,OPT/K,HEX/S,NUMBER/S",args,NULL);
413 if(rda==NULL)
415 PrintFault(IoErr(),"Type");
416 return RETURN_FAIL;
418 names=(STRPTR *)args[0];
420 in =AllocMem(sizeof(struct file),MEMF_ANY);
421 out=AllocMem(sizeof(struct file),MEMF_ANY);
423 if(in!=NULL&&out!=NULL)
425 out->cur=out->buf;
426 out->cnt=BUFSIZE;
427 apath.apath.ap_BreakBits = SIGBREAKF_CTRL_C;
428 apath.apath.ap_FoundBreak = 0;
429 apath.apath.ap_Flags = 0;
430 apath.apath.ap_Strlen = MAX_PATH_LEN;
431 if (args[ARG_TO])
432 out->fd = Open((STRPTR) args[ARG_TO], MODE_NEWFILE);
433 else
434 out->fd=Output();
435 if (out->fd)
437 while(*names!=NULL)
439 ULONG numfiles = 0;
440 LONG error;
442 for (error = MatchFirst(*names, &apath.apath);
443 !error;
444 error = MatchNext(&apath.apath))
446 error = processfile(apath.apath.ap_Buf, in, out, args, &numfiles);
447 if (error)
448 break;
450 MatchEnd(&apath.apath);
452 if (numfiles == 0 && error == ERROR_NO_MORE_ENTRIES)
454 error = -1;
457 if (error && error != ERROR_NO_MORE_ENTRIES)
459 if (*names && error != ERROR_BREAK)
461 Printf("TYPE: can't open %s\n", (LONG) *names);
464 if (error != -1)
466 PrintFault(error, NULL);
467 SetIoErr(error);
470 break;
472 names++;
475 if (args[ARG_TO])
476 Close(out->fd);
478 /* If all files got dumped, return ok, else error.
480 retval = *names ? RETURN_ERROR : RETURN_OK;
481 } else
483 PrintFault(IoErr(), NULL);
485 }else
487 PrintFault(ERROR_NO_FREE_STORE,"Type");
488 retval = RETURN_ERROR;
491 if(in!=NULL)
492 FreeMem(in,sizeof(struct file));
493 if(out!=NULL)
494 FreeMem(out,sizeof(struct file));
495 if(rda!=NULL)
496 FreeArgs(rda);
498 return retval;