1 /*
2 * Attempt at emulation of Unix tar by calling Plan 9 tar.
3 *
4 * The differences from Plan 9 tar are:
5 * In the absence of an "f" flag, the file /dev/tape is used.
6 * An "f" flag with argument "-" causes use of stdin/stdout
7 * by passing no "f" flag (nor argument) to Plan 9 tar.
8 * By default, the "T" flag is passed to Plan 9 tar.
9 * The "m" flag to this tar inhibits this behavior.
10 */
11
12 #include <u.h>
13 #include <libc.h>
14
15 void
usage(void)16 usage(void)
17 {
18 fprint(2, "usage: ape/tar [crtx][vfm] [args...] [file...]\n");
19 exits("usage");
20 }
21
22 void
main(int argc,char ** argv)23 main(int argc, char **argv)
24 {
25 int i, j, verb, vflag, fflag, Tflag, nargc;
26 char *p, *file, **nargv, *cpu, flagbuf[10], execbuf[128];
27 Waitmsg *w;
28
29 argv++, argc--;
30 if(argc < 1)
31 usage();
32
33 p = argv[0];
34 argv++, argc--;
35
36 if(*p == '-')
37 p++;
38
39 if(strchr("crtx", *p) == nil)
40 usage();
41 verb = *p++;
42
43 /* unix defaults */
44 fflag = 1;
45 file = "/dev/tape";
46 Tflag = 1;
47 vflag = 0;
48
49 for(; *p; p++) {
50 switch(*p) {
51 default:
52 usage();
53 case 'v':
54 vflag = 1;
55 break;
56 case 'f':
57 if(argc <= 0)
58 usage();
59
60 fflag = 1;
61 file = argv[0];
62 argv++, argc--;
63 if(strcmp(file, "-") == 0) {
64 /*
65 * plan9 doesn't know about "-" meaning stdin/stdout,
66 * but it's the default,
67 * so rewrite to not use f flag at all.
68 */
69 file = nil;
70 fflag = 0;
71 }
72 break;
73 case 'm':
74 Tflag = 0;
75 break;
76 case 'p': /* pretend nothing's wrong */
77 break;
78 }
79 }
80
81 nargc = 1 + 1 + fflag + argc + 1;
82 nargv = malloc(sizeof(char*) * nargc);
83 if(nargv == nil) {
84 fprint(2, "ape/tar: out of memory\n");
85 exits("memory");
86 }
87
88 cpu = getenv("cputype");
89 if(cpu == nil) {
90 fprint(2, "ape/tar: need cputype environment variable set\n");
91 exits("cputype");
92 }
93 snprint(execbuf, sizeof execbuf, "/%s/bin/tar", cpu);
94
95 nargv[0] = "tar";
96 sprint(flagbuf, "%c%s%s%s", verb, vflag ? "v" : "", Tflag ? "T" : "", fflag ? "f" : "");
97 nargv[1] = flagbuf;
98
99 i = 2;
100 if(fflag)
101 nargv[i++] = file;
102
103 for(j=0; j<argc; j++, i++)
104 nargv[i] = argv[j];
105
106 nargv[i++] = nil;
107 assert(i == nargc);
108
109 switch(fork()){
110 case -1:
111 fprint(2, "ape/tar: fork failed: %r\n");
112 exits("fork");
113 case 0:
114 exec(execbuf, nargv);
115 fprint(2, "exec %s fails: %r\n", execbuf);
116 _exits("exec");
117 default:
118 w = wait();
119 if(w == nil)
120 exits("wait failed");
121 if(w->msg[0] == '\0')
122 exits(nil);
123 else
124 exits(w->msg);
125 }
126 assert(0);
127 }
128