Unify process_alloc() and process_realloc() with PROCESS_ALLOC_MODE_REALLOC bit
[moveable_pool.git] / ucp.c
1 /**************************************************
2   UZI (Unix Z80 Implementation) Utilities:  ucp.c
3 Modifications:
4 14 June 1998 - Reformatted, restructured command
5 switch, sense Ctrl-Z in type.   HFB
6 21 Sept 1999 - Corrected the 'constant expression'
7 problem, added some missing breaks.
8 HP
9  ***************************************************/
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <time.h>
15 #include <unistd.h>
16 #include <libgen.h>
17 #define UCP 1
18 #include "fuzix_fs.h"
19 #include "util.h"
20
21 #define UCP_VERSION  "1.3ac"
22
23 static int16_t *syserror = (int16_t*)&udata.u_error;
24 static char cwd[100];
25 static char line[128];
26 static char *nextline = NULL;
27 static char *month[] =
28 { "Jan", "Feb", "Mar", "Apr",
29     "May", "Jun", "Jul", "Aug",
30     "Sep", "Oct", "Nov", "Dec" };
31
32 #define DEVIO
33
34 static int match(char *cmd);
35 static void usage(void);
36 static void prmode(int mode);
37 static int cmd_ls(char *path);
38 static int cmd_chmod(char *modes, char *path);
39 static int cmd_mknod( char *path, char *modes, char *devs);
40 static int cmd_mkdir(char *path);
41 static int cmd_link( char *src, char *dst );
42 static int cmd_get( char *src, char *dest, int binflag);
43 static int cmd_put( char *arg, int binflag);
44 static int cmd_type( char *arg);
45 static int cmd_fdump(char *arg);
46 static int cmd_rm( char *path);
47 static int cmd_rmdir(char *path);
48
49 static int interactive = 0;
50
51 int main(int argc, char *argval[])
52 {
53     int  rdev;
54     char cmd[30], arg1[1024], arg2[30], arg3[30];
55     int  count;
56     int  multiline;
57     int  pending_line = 0;
58     struct filesys fsys;
59     int  j, retc = 0;
60
61     if (argc == 2) {
62         fd_open(argval[1]);
63         multiline = 1;
64     } else if (argc == 3) {
65         fd_open(argval[1]);
66         strncpy(&line[0], argval[2], 127);
67         line[127] = '\0';
68         multiline = 0;
69     } else {
70         printf("Usage: ucp FILE [COMMAND]\n");
71         exit(1);
72     }
73
74     if (isatty(0))
75         interactive = 1;
76
77     rdev = 0;
78
79     xfs_init(rdev);
80     strcpy(cwd, "/");
81
82     printf("Fuzix UCP version " UCP_VERSION ".%s\n", interactive?" Type ? for help.":"");
83
84     do {
85         if (multiline && !pending_line) {
86             if (interactive)
87                 printf("unix: ");
88             if (fgets(line, 128, stdin) == NULL) {
89                 xfs_end();
90                 exit(retc);
91             }
92         }
93
94         if (!pending_line) {
95             nextline = strchr(&line[0], ';');
96             if (nextline != NULL) {
97                 nextline[0] = '\0';
98                 nextline++;
99             }
100         }
101
102         cmd[0] = '\0';
103         *arg1 = '\0';
104         arg2[0] = '\0';
105         arg3[0] = '\0';
106
107         if (pending_line) {
108             count = sscanf(nextline, "%s %s %s %s", cmd, arg1, arg2, arg3);
109             nextline = NULL;
110             pending_line = 0;
111             if (count == 0 || cmd[0] == '\0')
112                 continue;
113         } else {
114             count = sscanf(line, "%s %s %s %s", cmd, arg1, arg2, arg3);
115             if (nextline != NULL) {
116                 pending_line = 1;
117             }
118             if (count == 0 || cmd[0] == '\0')
119                 continue;
120         }
121
122         fuzix_sync();
123
124         if (strcmp(cmd, "\n") == 0)
125             continue;
126         if (cmd[0] == '#')
127             continue;
128         switch (match(cmd)) {
129             case 0:         /* exit */
130                 xfs_end();
131                 exit(retc);
132
133             case 1:         /* ls */
134                 if (*arg1)
135                     retc = cmd_ls(arg1);
136                 else
137                     retc = cmd_ls(".");
138                 break;
139
140             case 2:         /* cd */
141                 if (*arg1) {
142                     strcpy(cwd, arg1);
143                     if ((retc = fuzix_chdir(arg1)) != 0) {
144                         printf("cd: error number %d\n", *syserror);
145                     }
146                 }
147                 break;
148
149             case 3:         /* mkdir */
150                 if (*arg1)
151                     retc = cmd_mkdir(arg1);
152                 break;
153
154             case 4:         /* mknod */
155                 if (*arg1 && *arg2 && *arg3)
156                     retc = cmd_mknod(arg1, arg2, arg3);
157                 break;
158
159             case 5:         /* chmod */
160                 if (*arg1 && *arg2)
161                     retc = cmd_chmod(arg1, arg2);
162                 break;
163
164             case 6:         /* get */
165                 if (*arg1)
166                     retc = cmd_get(arg1, *arg2 ? arg2 : arg1, 0);
167                 break;
168
169             case 7:         /* bget */
170                 if (*arg1)
171                     retc = cmd_get(arg1, *arg2 ? arg2 : arg1, 1);
172                 break;
173
174             case 8:         /* put */
175                 if (*arg1)
176                     retc = cmd_put(arg1, 0);
177                 break;
178
179             case 9:         /* bput */
180                 if (*arg1)
181                     retc = cmd_put(arg1, 1);
182                 break;
183
184             case 10:        /* type */
185                 if (*arg1)
186                     retc = cmd_type(arg1);
187                 break;
188
189             case 11:        /* dump */
190                 if (*arg1)
191                     retc = cmd_fdump(arg1);
192                 break;
193
194             case 12:        /* rm */
195                 if (*arg1)
196                     retc = cmd_rm(arg1);
197                 break;
198
199             case 13:        /* df */
200                 for (j = 0; j < 4; ++j) {
201                     retc = fuzix_getfsys(j, (char*)&fsys);
202                     if (retc == 0 && fsys.s_mounted) {
203                         printf("%d:  %u blks used, %u free;  ", j,
204                                 (fsys.s_fsize - fsys.s_isize) - fsys.s_tfree,
205                                 fsys.s_tfree);
206                         printf("%u inodes used, %u free\n",
207                                 (8 * (fsys.s_isize - 2) - fsys.s_tinode),
208                                 fsys.s_tinode);
209                     }
210                 }
211                 break;
212
213             case 14:        /* rmdir */
214                 if (*arg1)
215                     retc = cmd_rmdir(arg1);
216                 break;
217
218             case 17:        /* ln */
219                 if (*arg1 && *arg2)
220                     retc = cmd_link(arg1, arg2);
221                 break;
222
223             case 50:        /* help */
224                 usage();
225                 retc = 0;
226                 break;
227
228             default:        /* ..else.. */
229                 printf("Unknown command, type ? for help.\n");
230                 retc = -1;
231                 break;
232         }           /* End Switch */
233     } while (multiline || pending_line);
234
235     fuzix_sync();
236
237     return retc;
238 }
239
240
241 static int match(char *cmd)
242 {
243     if (strcmp(cmd, "exit") == 0)
244         return (0);
245     else if (strcmp(cmd, "quit") == 0)
246         return (0);
247     else if (strcmp(cmd, "ls") == 0)
248         return (1);
249     else if (strcmp(cmd, "dir") == 0)
250         return (1);
251     else if (strcmp(cmd, "cd") == 0)
252         return (2);
253     else if (strcmp(cmd, "mkdir") == 0)
254         return (3);
255     else if (strcmp(cmd, "mknod") == 0)
256         return (4);
257     else if (strcmp(cmd, "chmod") == 0)
258         return (5);
259     else if (strcmp(cmd, "get") == 0)
260         return (6);
261     else if (strcmp(cmd, "bget") == 0)
262         return (7);
263     else if (strcmp(cmd, "put") == 0)
264         return (8);
265     else if (strcmp(cmd, "bput") == 0)
266         return (9);
267     else if (strcmp(cmd, "type") == 0)
268         return (10);
269     else if (strcmp(cmd, "cat") == 0)
270         return (10);
271     else if (strcmp(cmd, "dump") == 0)
272         return (11);
273     else if (strcmp(cmd, "rm") == 0)
274         return (12);
275     else if (strcmp(cmd, "df") == 0)
276         return (13);
277     else if (strcmp(cmd, "rmdir") == 0)
278         return (14);
279     else if (strcmp(cmd, "ln" ) == 0 )
280         return (17);
281     else if (strcmp(cmd, "help") == 0)
282         return (50);
283     else if (strcmp(cmd, "?") == 0)
284         return (50);
285     else
286         return (-1);
287 }
288
289
290 static void usage(void)
291 {
292     printf("UCP commands:\n");
293     printf("?|help\n");
294     printf("exit|quit\n");
295     printf("dir|ls [path]\n");
296     printf("cd path\n");
297     printf("mkdir dirname\n");
298     printf("mknod name mode dev#\n");
299     printf("chmod mode path\n");
300     printf("[b]get sourcefile [destfile]\n");
301     printf("[b]put uzifile\n");
302     printf("type|cat filename\n");
303     printf("dump filename\n");
304     printf("rm path\n");
305     printf("rmdir dirname\n");
306     printf("df\n");
307     printf("ln sourcefile destfile\n");
308 }
309
310 static void prmode(int mode)
311 {
312     if (mode & 4)
313         printf("r");
314     else
315         printf("-");
316
317     if (mode & 2)
318         printf("w");
319     else
320         printf("-");
321
322     if (mode & 1)
323         printf("x");
324     else
325         printf("-");
326 }
327
328 static int cmd_ls(char *path)
329 {
330     struct direct buf;
331     struct uzi_stat statbuf;
332     char dname[128];
333     int d, st;
334
335     /*
336        if (fuzix_stat(path, &statbuf) != 0 || (statbuf.st_mode & F_MASK) != F_DIR) {
337        printf("ls: can't stat %s\n", path);
338        return -1;
339        }
340        */
341
342     d = fuzix_open(path, 0);
343     if (d < 0) {
344         fprintf(stderr, "ls: can't open %s\n", path);
345         return -1;
346     }
347     while (fuzix_read(d, (char *) &buf, 16) == 16) {
348         if (buf.d_name[0] == '\0')
349             continue;
350
351         if (path[0] != '.' || path[1]) {
352             strcpy(dname, path);
353             strcat(dname, "/");
354         } else {
355             dname[0] = '\0';
356         }
357
358         strcat(dname, buf.d_name);
359
360         if (fuzix_stat(dname, &statbuf) != 0) {
361             fprintf(stderr, "ls: can't stat %s\n", dname);
362             break;
363         }
364         st = (statbuf.st_mode & F_MASK);
365
366         if ((st & F_MASK) == F_DIR) /* & F_MASK is redundant */
367             printf("d");
368         else if ((st & F_MASK) == F_CDEV)
369             printf("c");
370         else if ((st & F_MASK) == F_BDEV)
371             printf("b");
372         else if ((st & F_MASK) == F_PIPE)
373             printf("p");
374         else if ((st & F_REG) == 0)
375             printf("l");
376         else
377             printf("-");
378
379         prmode(statbuf.st_mode >> 6);
380         prmode(statbuf.st_mode >> 3);
381         prmode(statbuf.st_mode);
382
383         printf("%4d %5d", statbuf.st_nlink, statbuf.st_ino);
384
385         if ((statbuf.st_mode & F_MASK) == F_DIR)
386             strcat(dname, "/");
387
388         printf("%12u ",
389                 (statbuf.st_mode & F_CDEV) ?
390                 statbuf.st_rdev :
391                 statbuf.st_size);
392
393         if (statbuf.fst_mtime == 0) { /* st_mtime? */
394             /*printf("--- -- ----   --:--");*/
395             printf("                   ");
396         } else {
397             time_t t = statbuf.fst_mtime;
398             struct tm *tm = gmtime(&t);
399             printf("%s %02d %4d   ",
400                     month[tm->tm_mon],
401                     tm->tm_mday,
402                     tm->tm_year);
403
404             printf("%2d:%02d",
405                     tm->tm_hour,
406                     tm->tm_min);
407         }
408
409         printf("  %-15s\n", dname);
410     }
411     fuzix_close(d);
412     return 0;
413 }
414
415 static int cmd_chmod(char *modes, char *path)
416 {
417     unsigned int mode;
418
419     if (interactive)
420         printf("chmod %s to %s\n", path, modes);
421     if (sscanf(modes, "%o", &mode) != 1) {
422         fprintf(stderr, "chmod: bad mode\n");
423         return (-1);
424     }
425     /* Preserve the type if not specified */
426     if (mode < 10000) {
427         struct uzi_stat st;
428         if (fuzix_stat(path, &st) != 0) {
429             fprintf(stderr, "chmod: can't stat file '%s': %d\n", path, *syserror);
430             return -1;
431         }
432         mode = (st.st_mode & ~0x7777) | mode;
433     }
434     if (fuzix_chmod(path, mode)) {
435         fprintf(stderr, "chmod: error %d\n", *syserror);
436         return (-1);
437     }
438     return 0;
439 }
440
441
442 static int cmd_mknod( char *path, char *modes, char *devs)
443 {
444     unsigned int mode;
445     int dev;
446
447     if (sscanf(modes, "%o", &mode) != 1) {
448         fprintf(stderr, "mknod: bad mode\n");
449         return (-1);
450     }
451     if ((mode & F_MASK) != F_BDEV && (mode & F_MASK) != F_CDEV) {
452         fprintf(stderr, "mknod: mode is not device\n");
453         return (-1);
454     }
455     dev = -1;
456     sscanf(devs, "%d", &dev);
457     if (dev == -1) {
458         fprintf(stderr, "mknod: bad device\n");
459         return (-1);
460     }
461     if (fuzix_mknod(path, mode, dev) != 0) {
462         fprintf(stderr, "fuzix_mknod: error %d\n", *syserror);
463         return (-1);
464     }
465     return (0);
466 }
467
468
469
470 static int cmd_mkdir(char *path)
471 {
472     if (fuzix_mkdir(path, 0777) != 0) {
473         fprintf(stderr, "mkdir: mknod error %d\n", *syserror);
474         return (-1);
475     }
476     return (0);
477 }
478
479 static int cmd_link( char *src, char *dst )
480 {
481     if( fuzix_link( src, dst ) != 0 ){
482         fprintf(stderr, "link: error %d\n", *syserror );
483         return -1;
484     }
485     return 0;
486 }
487
488 static int cmd_get( char *src, char *dest, int binflag)
489 {
490     FILE *fp;
491     int d;
492     char cbuf[512];
493     int nread;
494
495     fp = fopen(src, binflag ? "rb" : "r");
496     if (fp == NULL) {
497         fprintf(stderr, "Source file '%s' not found\n", src);
498         return (-1);
499     }
500     d = fuzix_creat(basename(dest), 0666);
501     if (d < 0) {
502         fprintf(stderr, "Can't open destination file '%s'; error %d\n", dest, *syserror);
503         fclose(fp);
504         return (-1);
505     }
506     for (;;) {
507         nread = fread(cbuf, 1, 512, fp);
508         if (nread == 0)
509             break;
510         if (fuzix_write(d, cbuf, nread)) {
511             fprintf(stderr, "fuzix_write error %d\n", *syserror);
512             fclose(fp);
513             fuzix_close(d);
514             return (-1);
515         }
516     }
517     fclose(fp);
518     fuzix_close(d);
519     fuzix_sync();
520     return (0);
521 }
522
523
524 static int cmd_put( char *arg, int binflag)
525 {
526     FILE *fp;
527     int d;
528     char cbuf[512];
529     int nread;
530
531     fp = fopen(arg, binflag ? "wb" : "w");
532     if (fp == NULL) {
533         fprintf(stderr, "Can't open destination file.\n");
534         return (-1);
535     }
536     d = fuzix_open(arg, 0);
537     if (d < 0) {
538         fprintf(stderr, "Can't open unix file error %d\n", *syserror);
539         return (-1);
540     }
541     for (;;) {
542         if ((nread = fuzix_read(d, cbuf, 512)) == 0)
543             break;
544         if (fwrite(cbuf, 1, nread, fp) != nread) {
545             fprintf(stderr, "fwrite error");
546             fclose(fp);
547             fuzix_close(d);
548             return (-1);
549         }
550     }
551     fclose(fp);
552     fuzix_close(d);
553     return (0);
554 }
555
556
557 static int cmd_type( char *arg)
558 {
559     int d, i;
560     char cbuf[512];
561     int nread;
562
563     d = fuzix_open(arg, 0);
564     if (d < 0) {
565         fprintf(stderr, "Can't open unix file error %d\n", *syserror);
566         return (-1);
567     }
568     for (;;) {
569         if ((nread = fuzix_read(d, cbuf, 512)) == 0)
570             break;
571
572         for (i = 0; i < nread; i++) {
573             if (cbuf[i] == 0x1a)
574                 break;
575             fputc(cbuf[i], stdout);
576         }
577     }
578     fputc('\n', stdout);
579     fuzix_close(d);
580     return (0);
581 }
582
583
584 static int cmd_fdump(char *arg)
585 {
586     int d;
587     char cbuf[512];
588     int nread;
589
590     printf("Dump starting.\n");
591     d = fuzix_open(arg, 0);
592     if (d < 0) {
593         fprintf(stderr, "Can't open unix file error %d\n", *syserror);
594         return (-1);
595     }
596     for (;;) {
597         if ((nread = fuzix_read(d, cbuf, 512)) == 0)
598             break;
599     }
600     fuzix_close(d);
601     printf("Dump done.\n");
602     return (0);
603 }
604
605
606 static int cmd_rm( char *path)
607 {
608     struct uzi_stat statbuf;
609
610     if (fuzix_stat(path, &statbuf) != 0) {
611         fprintf(stderr, "unlink: can't stat %s\n", path);
612         return (-1);
613     }
614     if ((statbuf.st_mode & F_MASK) == F_DIR) {
615         fprintf(stderr, "unlink: %s is a directory\n", path);
616         return (-1);
617     }
618     if (fuzix_unlink(path) != 0) {
619         fprintf(stderr, "unlink: fuzix_unlink errn=or %d\n", *syserror);
620         return (-1);
621     }
622     return (0);
623 }
624
625
626 static int cmd_rmdir(char *path)
627 {
628     struct uzi_stat statbuf;
629     char newpath[100];
630     struct direct dir;
631     int fd;
632
633     if (fuzix_stat(path, &statbuf) != 0) {
634         fprintf(stderr, "rmdir: can't stat %s\n", path);
635         return (-1);
636     }
637     if ((statbuf.st_mode & F_DIR) == 0) {
638         /*-- Constant expression !!!  HFB --*/
639         fprintf(stderr, "rmdir: %s is not a directory\n", path);
640         return (-1);
641     }
642     if ((fd = fuzix_open(path, 0)) < 0) {
643         fprintf(stderr, "rmdir: %s is unreadable\n", path);
644         return (-1);
645     }
646     while (fuzix_read(fd, (char *) &dir, sizeof(dir)) == sizeof(dir)) {
647         if (dir.d_ino == 0)
648             continue;
649         if (!strcmp(dir.d_name, ".") || !strcmp(dir.d_name, ".."))
650             continue;
651         fprintf(stderr, "rmdir: %s is not empty\n", path);
652         fuzix_close(fd);
653         return (-1);
654     }
655     fuzix_close(fd);
656
657     strcpy(newpath, path);
658     strcat(newpath, "/.");
659     if (fuzix_unlink(newpath) != 0) {
660         fprintf(stderr, "rmdir: can't unlink \".\"  error %d\n", *syserror);
661         /*return (-1); */
662     }
663     strcat(newpath, ".");
664     if (fuzix_unlink(newpath) != 0) {
665         fprintf(stderr, "rmdir: can't unlink \"..\"  error %d\n", *syserror);
666         /*return (-1); */
667     }
668     if (fuzix_unlink(path) != 0) {
669         fprintf(stderr, "rmdir: fuzix_unlink error %d\n", *syserror);
670         return (-1);
671     }
672     return (0);
673 }