rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 1 | #include <u.h> |
rsc | 3e61079 | 2004-10-22 17:05:24 +0000 | [diff] [blame] | 2 | #include <signal.h> |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 3 | #include <libc.h> |
rsc | 276bf4e | 2005-02-11 19:44:04 +0000 | [diff] [blame] | 4 | #include <bio.h> |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 5 | #include <fcall.h> |
rsc | eb423b5 | 2005-01-04 22:09:51 +0000 | [diff] [blame] | 6 | #include <9pclient.h> |
rsc | 0d4243f | 2005-02-11 16:53:27 +0000 | [diff] [blame] | 7 | #include <auth.h> |
rsc | f063dad | 2004-02-29 22:42:33 +0000 | [diff] [blame] | 8 | #include <thread.h> |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 9 | |
| 10 | char *addr; |
| 11 | |
| 12 | void |
| 13 | usage(void) |
| 14 | { |
rsc | 011090f | 2005-03-21 17:27:25 +0000 | [diff] [blame] | 15 | fprint(2, "usage: 9p [-a address] [-A aname] cmd args...\n"); |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 16 | fprint(2, "possible cmds:\n"); |
| 17 | fprint(2, " read name\n"); |
rsc | 32f69c3 | 2003-12-11 17:48:38 +0000 | [diff] [blame] | 18 | fprint(2, " readfd name\n"); |
rsc | 276bf4e | 2005-02-11 19:44:04 +0000 | [diff] [blame] | 19 | fprint(2, " write [-l] name\n"); |
rsc | 32f69c3 | 2003-12-11 17:48:38 +0000 | [diff] [blame] | 20 | fprint(2, " writefd name\n"); |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 21 | fprint(2, " stat name\n"); |
rsc | 05abefb | 2005-02-13 18:32:38 +0000 | [diff] [blame] | 22 | fprint(2, " rdwr name\n"); |
rsc | 1b404fe | 2006-02-05 15:34:46 +0000 | [diff] [blame] | 23 | fprint(2, " ls [-ldn] name\n"); |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 24 | fprint(2, "without -a, name elem/path means /path on server unix!$ns/elem\n"); |
rsc | 38c10d1 | 2005-01-17 21:29:00 +0000 | [diff] [blame] | 25 | threadexitsall("usage"); |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 26 | } |
| 27 | |
rsc | 011090f | 2005-03-21 17:27:25 +0000 | [diff] [blame] | 28 | char *aname; |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 29 | void xread(int, char**); |
| 30 | void xwrite(int, char**); |
rsc | 32f69c3 | 2003-12-11 17:48:38 +0000 | [diff] [blame] | 31 | void xreadfd(int, char**); |
| 32 | void xwritefd(int, char**); |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 33 | void xstat(int, char**); |
| 34 | void xls(int, char**); |
rsc | 05abefb | 2005-02-13 18:32:38 +0000 | [diff] [blame] | 35 | void xrdwr(int, char**); |
rsc | 1b404fe | 2006-02-05 15:34:46 +0000 | [diff] [blame] | 36 | void xrm(int, char**); |
| 37 | void xcreate(int, char**); |
rsc | e29d0c8 | 2006-01-06 18:00:42 +0000 | [diff] [blame] | 38 | void xcon(int, char**); |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 39 | |
| 40 | struct { |
| 41 | char *s; |
| 42 | void (*f)(int, char**); |
| 43 | } cmds[] = { |
rsc | e29d0c8 | 2006-01-06 18:00:42 +0000 | [diff] [blame] | 44 | "con", xcon, |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 45 | "read", xread, |
| 46 | "write", xwrite, |
rsc | 32f69c3 | 2003-12-11 17:48:38 +0000 | [diff] [blame] | 47 | "readfd", xreadfd, |
| 48 | "writefd", xwritefd, |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 49 | "stat", xstat, |
rsc | 05abefb | 2005-02-13 18:32:38 +0000 | [diff] [blame] | 50 | "rdwr", xrdwr, |
rsc | 1d2f561 | 2005-03-18 19:19:33 +0000 | [diff] [blame] | 51 | "ls", xls, |
rsc | 1b404fe | 2006-02-05 15:34:46 +0000 | [diff] [blame] | 52 | "rm", xrm, |
| 53 | "create", xcreate, |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 54 | }; |
| 55 | |
| 56 | void |
rsc | f063dad | 2004-02-29 22:42:33 +0000 | [diff] [blame] | 57 | threadmain(int argc, char **argv) |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 58 | { |
| 59 | char *cmd; |
| 60 | int i; |
| 61 | |
| 62 | ARGBEGIN{ |
rsc | 011090f | 2005-03-21 17:27:25 +0000 | [diff] [blame] | 63 | case 'A': |
| 64 | aname = EARGF(usage()); |
| 65 | break; |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 66 | case 'a': |
| 67 | addr = EARGF(usage()); |
rsc | 1d2f561 | 2005-03-18 19:19:33 +0000 | [diff] [blame] | 68 | if(strchr(addr, '!') == nil) |
| 69 | addr = netmkaddr(addr, "tcp", "9fs"); |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 70 | break; |
rsc | 17cdbb9 | 2004-12-27 01:22:48 +0000 | [diff] [blame] | 71 | case 'D': |
rsc | 0d4243f | 2005-02-11 16:53:27 +0000 | [diff] [blame] | 72 | chatty9pclient = 1; |
| 73 | break; |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 74 | default: |
| 75 | usage(); |
| 76 | }ARGEND |
| 77 | |
rsc | 3e61079 | 2004-10-22 17:05:24 +0000 | [diff] [blame] | 78 | signal(SIGINT, SIG_DFL); |
| 79 | |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 80 | if(argc < 1) |
| 81 | usage(); |
| 82 | |
| 83 | cmd = argv[0]; |
| 84 | for(i=0; i<nelem(cmds); i++){ |
| 85 | if(strcmp(cmds[i].s, cmd) == 0){ |
| 86 | cmds[i].f(argc, argv); |
rsc | f063dad | 2004-02-29 22:42:33 +0000 | [diff] [blame] | 87 | threadexitsall(0); |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 88 | } |
| 89 | } |
| 90 | usage(); |
| 91 | } |
| 92 | |
rsc | eb423b5 | 2005-01-04 22:09:51 +0000 | [diff] [blame] | 93 | CFsys* |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 94 | xparse(char *name, char **path) |
| 95 | { |
| 96 | int fd; |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 97 | char *p; |
rsc | eb423b5 | 2005-01-04 22:09:51 +0000 | [diff] [blame] | 98 | CFsys *fs; |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 99 | |
| 100 | if(addr == nil){ |
| 101 | p = strchr(name, '/'); |
| 102 | if(p == nil) |
| 103 | p = name+strlen(name); |
| 104 | else |
| 105 | *p++ = 0; |
| 106 | *path = p; |
rsc | 011090f | 2005-03-21 17:27:25 +0000 | [diff] [blame] | 107 | fs = nsamount(name, aname); |
rsc | 32f69c3 | 2003-12-11 17:48:38 +0000 | [diff] [blame] | 108 | if(fs == nil) |
| 109 | sysfatal("mount: %r"); |
| 110 | }else{ |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 111 | *path = name; |
rsc | 32f69c3 | 2003-12-11 17:48:38 +0000 | [diff] [blame] | 112 | if((fd = dial(addr, nil, nil, nil)) < 0) |
| 113 | sysfatal("dial: %r"); |
rsc | 011090f | 2005-03-21 17:27:25 +0000 | [diff] [blame] | 114 | if((fs = fsamount(fd, aname)) == nil) |
| 115 | sysfatal("fsamount: %r"); |
rsc | 32f69c3 | 2003-12-11 17:48:38 +0000 | [diff] [blame] | 116 | } |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 117 | return fs; |
| 118 | } |
| 119 | |
rsc | eb423b5 | 2005-01-04 22:09:51 +0000 | [diff] [blame] | 120 | CFid* |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 121 | xopen(char *name, int mode) |
| 122 | { |
rsc | eb423b5 | 2005-01-04 22:09:51 +0000 | [diff] [blame] | 123 | CFid *fid; |
| 124 | CFsys *fs; |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 125 | |
| 126 | fs = xparse(name, &name); |
| 127 | fid = fsopen(fs, name, mode); |
| 128 | if(fid == nil) |
| 129 | sysfatal("fsopen %s: %r", name); |
| 130 | return fid; |
| 131 | } |
| 132 | |
rsc | 32f69c3 | 2003-12-11 17:48:38 +0000 | [diff] [blame] | 133 | int |
| 134 | xopenfd(char *name, int mode) |
| 135 | { |
rsc | eb423b5 | 2005-01-04 22:09:51 +0000 | [diff] [blame] | 136 | CFsys *fs; |
rsc | 32f69c3 | 2003-12-11 17:48:38 +0000 | [diff] [blame] | 137 | |
| 138 | fs = xparse(name, &name); |
| 139 | return fsopenfd(fs, name, mode); |
| 140 | } |
| 141 | |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 142 | void |
| 143 | xread(int argc, char **argv) |
| 144 | { |
rsc | 05abefb | 2005-02-13 18:32:38 +0000 | [diff] [blame] | 145 | char buf[4096]; |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 146 | int n; |
rsc | eb423b5 | 2005-01-04 22:09:51 +0000 | [diff] [blame] | 147 | CFid *fid; |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 148 | |
| 149 | ARGBEGIN{ |
| 150 | default: |
| 151 | usage(); |
| 152 | }ARGEND |
| 153 | |
| 154 | if(argc != 1) |
| 155 | usage(); |
| 156 | |
| 157 | fid = xopen(argv[0], OREAD); |
| 158 | while((n = fsread(fid, buf, sizeof buf)) > 0) |
| 159 | write(1, buf, n); |
rsc | 286237e | 2005-10-29 17:37:10 +0000 | [diff] [blame] | 160 | fsclose(fid); |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 161 | if(n < 0) |
| 162 | sysfatal("read error: %r"); |
rsc | 38c10d1 | 2005-01-17 21:29:00 +0000 | [diff] [blame] | 163 | threadexitsall(0); |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 164 | } |
| 165 | |
| 166 | void |
rsc | 32f69c3 | 2003-12-11 17:48:38 +0000 | [diff] [blame] | 167 | xreadfd(int argc, char **argv) |
| 168 | { |
rsc | 05abefb | 2005-02-13 18:32:38 +0000 | [diff] [blame] | 169 | char buf[4096]; |
rsc | 32f69c3 | 2003-12-11 17:48:38 +0000 | [diff] [blame] | 170 | int n; |
| 171 | int fd; |
| 172 | |
| 173 | ARGBEGIN{ |
| 174 | default: |
| 175 | usage(); |
| 176 | }ARGEND |
| 177 | |
| 178 | if(argc != 1) |
| 179 | usage(); |
| 180 | |
| 181 | fd = xopenfd(argv[0], OREAD); |
| 182 | while((n = read(fd, buf, sizeof buf)) > 0) |
| 183 | write(1, buf, n); |
| 184 | if(n < 0) |
| 185 | sysfatal("read error: %r"); |
rsc | 38c10d1 | 2005-01-17 21:29:00 +0000 | [diff] [blame] | 186 | threadexitsall(0); |
rsc | 32f69c3 | 2003-12-11 17:48:38 +0000 | [diff] [blame] | 187 | } |
| 188 | |
| 189 | void |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 190 | xwrite(int argc, char **argv) |
| 191 | { |
rsc | 05abefb | 2005-02-13 18:32:38 +0000 | [diff] [blame] | 192 | char buf[4096]; |
rsc | 3e61079 | 2004-10-22 17:05:24 +0000 | [diff] [blame] | 193 | int n, did; |
rsc | eb423b5 | 2005-01-04 22:09:51 +0000 | [diff] [blame] | 194 | CFid *fid; |
rsc | 276bf4e | 2005-02-11 19:44:04 +0000 | [diff] [blame] | 195 | Biobuf *b; |
| 196 | char *p; |
| 197 | int byline; |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 198 | |
rsc | 276bf4e | 2005-02-11 19:44:04 +0000 | [diff] [blame] | 199 | byline = 0; |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 200 | ARGBEGIN{ |
rsc | 276bf4e | 2005-02-11 19:44:04 +0000 | [diff] [blame] | 201 | case 'l': |
| 202 | byline = 1; |
rsc | 05abefb | 2005-02-13 18:32:38 +0000 | [diff] [blame] | 203 | break; |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 204 | default: |
| 205 | usage(); |
| 206 | }ARGEND |
| 207 | |
| 208 | if(argc != 1) |
| 209 | usage(); |
| 210 | |
rsc | 3e61079 | 2004-10-22 17:05:24 +0000 | [diff] [blame] | 211 | did = 0; |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 212 | fid = xopen(argv[0], OWRITE|OTRUNC); |
rsc | 276bf4e | 2005-02-11 19:44:04 +0000 | [diff] [blame] | 213 | if(byline){ |
| 214 | n = 0; |
| 215 | b = malloc(sizeof *b); |
| 216 | if(b == nil) |
| 217 | sysfatal("out of memory"); |
| 218 | Binit(b, 0, OREAD); |
| 219 | while((p = Brdstr(b, '\n', 0)) != nil){ |
| 220 | n = strlen(p); |
| 221 | did = 1; |
| 222 | if(fswrite(fid, p, n) != n) |
rsc | 05abefb | 2005-02-13 18:32:38 +0000 | [diff] [blame] | 223 | fprint(2, "write: %r\n"); |
rsc | 276bf4e | 2005-02-11 19:44:04 +0000 | [diff] [blame] | 224 | } |
| 225 | free(b); |
| 226 | }else{ |
| 227 | while((n = read(0, buf, sizeof buf)) > 0){ |
| 228 | did = 1; |
| 229 | if(fswrite(fid, buf, n) != n) |
| 230 | sysfatal("write error: %r"); |
| 231 | } |
rsc | 3e61079 | 2004-10-22 17:05:24 +0000 | [diff] [blame] | 232 | } |
| 233 | if(n == 0 && !did){ |
| 234 | if(fswrite(fid, buf, 0) != 0) |
| 235 | sysfatal("write error: %r"); |
| 236 | } |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 237 | if(n < 0) |
| 238 | sysfatal("read error: %r"); |
rsc | 286237e | 2005-10-29 17:37:10 +0000 | [diff] [blame] | 239 | fsclose(fid); |
rsc | 38c10d1 | 2005-01-17 21:29:00 +0000 | [diff] [blame] | 240 | threadexitsall(0); |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 241 | } |
| 242 | |
| 243 | void |
rsc | 32f69c3 | 2003-12-11 17:48:38 +0000 | [diff] [blame] | 244 | xwritefd(int argc, char **argv) |
| 245 | { |
rsc | 05abefb | 2005-02-13 18:32:38 +0000 | [diff] [blame] | 246 | char buf[4096]; |
rsc | 32f69c3 | 2003-12-11 17:48:38 +0000 | [diff] [blame] | 247 | int n; |
| 248 | int fd; |
| 249 | |
| 250 | ARGBEGIN{ |
| 251 | default: |
| 252 | usage(); |
| 253 | }ARGEND |
| 254 | |
| 255 | if(argc != 1) |
| 256 | usage(); |
| 257 | |
| 258 | fd = xopenfd(argv[0], OWRITE|OTRUNC); |
| 259 | while((n = read(0, buf, sizeof buf)) > 0) |
| 260 | if(write(fd, buf, n) != n) |
| 261 | sysfatal("write error: %r"); |
| 262 | if(n < 0) |
| 263 | sysfatal("read error: %r"); |
rsc | 38c10d1 | 2005-01-17 21:29:00 +0000 | [diff] [blame] | 264 | threadexitsall(0); |
rsc | 32f69c3 | 2003-12-11 17:48:38 +0000 | [diff] [blame] | 265 | } |
| 266 | |
| 267 | void |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 268 | xstat(int argc, char **argv) |
| 269 | { |
| 270 | Dir *d; |
rsc | eb423b5 | 2005-01-04 22:09:51 +0000 | [diff] [blame] | 271 | CFsys *fs; |
| 272 | char *name; |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 273 | |
| 274 | ARGBEGIN{ |
| 275 | default: |
| 276 | usage(); |
| 277 | }ARGEND |
| 278 | |
| 279 | if(argc != 1) |
| 280 | usage(); |
| 281 | |
rsc | eb423b5 | 2005-01-04 22:09:51 +0000 | [diff] [blame] | 282 | name = argv[0]; |
| 283 | fs = xparse(name, &name); |
| 284 | if((d = fsdirstat(fs, name)) == 0) |
| 285 | sysfatal("dirstat: %r"); |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 286 | fmtinstall('D', dirfmt); |
| 287 | fmtinstall('M', dirmodefmt); |
| 288 | print("%D\n", d); |
rsc | 38c10d1 | 2005-01-17 21:29:00 +0000 | [diff] [blame] | 289 | threadexitsall(0); |
rsc | d3df308 | 2003-12-06 18:08:52 +0000 | [diff] [blame] | 290 | } |
rsc | 05abefb | 2005-02-13 18:32:38 +0000 | [diff] [blame] | 291 | |
| 292 | void |
| 293 | xrdwr(int argc, char **argv) |
| 294 | { |
| 295 | char buf[4096]; |
| 296 | int n; |
| 297 | CFid *fid; |
| 298 | |
| 299 | ARGBEGIN{ |
| 300 | default: |
| 301 | usage(); |
| 302 | }ARGEND |
| 303 | |
| 304 | if(argc != 1) |
| 305 | usage(); |
| 306 | |
| 307 | fid = xopen(argv[0], ORDWR); |
| 308 | for(;;){ |
rsc | 1bb8ccf | 2006-02-14 19:41:02 +0000 | [diff] [blame] | 309 | fsseek(fid, 0, 0); |
rsc | 05abefb | 2005-02-13 18:32:38 +0000 | [diff] [blame] | 310 | if((n = fsread(fid, buf, sizeof buf)) < 0) |
| 311 | fprint(2, "read: %r\n"); |
| 312 | else{ |
| 313 | write(1, buf, n); |
| 314 | write(1, "\n", 1); |
| 315 | } |
| 316 | n = read(0, buf, sizeof buf); |
| 317 | if(n <= 0) |
| 318 | break; |
| 319 | if(buf[n-1] == '\n') |
| 320 | n--; |
| 321 | if(fswrite(fid, buf, n) != n) |
| 322 | fprint(2, "write: %r\n"); |
| 323 | } |
rsc | 286237e | 2005-10-29 17:37:10 +0000 | [diff] [blame] | 324 | fsclose(fid); |
rsc | 05abefb | 2005-02-13 18:32:38 +0000 | [diff] [blame] | 325 | threadexitsall(0); |
| 326 | } |
rsc | 1d2f561 | 2005-03-18 19:19:33 +0000 | [diff] [blame] | 327 | |
rsc | e29d0c8 | 2006-01-06 18:00:42 +0000 | [diff] [blame] | 328 | void |
rsc | 1b404fe | 2006-02-05 15:34:46 +0000 | [diff] [blame] | 329 | xcreate(int argc, char **argv) |
| 330 | { |
| 331 | int i; |
| 332 | CFsys *fs; |
| 333 | CFid *fid; |
| 334 | char *p; |
| 335 | |
| 336 | ARGBEGIN{ |
| 337 | default: |
| 338 | usage(); |
| 339 | }ARGEND |
| 340 | |
| 341 | if(argc == 0) |
| 342 | usage(); |
| 343 | |
| 344 | for(i=0; i<argc; i++){ |
| 345 | fs = xparse(argv[i], &p); |
| 346 | if((fid=fscreate(fs, p, OREAD, 0666)) == nil) |
| 347 | fprint(2, "create %s: %r\n", argv[i]); |
| 348 | else |
| 349 | fsclose(fid); |
| 350 | fsunmount(fs); |
| 351 | } |
| 352 | } |
| 353 | |
| 354 | void |
| 355 | xrm(int argc, char **argv) |
| 356 | { |
| 357 | int i; |
| 358 | CFsys *fs; |
| 359 | char *p; |
| 360 | |
| 361 | ARGBEGIN{ |
| 362 | default: |
| 363 | usage(); |
| 364 | }ARGEND |
| 365 | |
| 366 | if(argc == 0) |
| 367 | usage(); |
| 368 | |
| 369 | for(i=0; i<argc; i++){ |
| 370 | fs = xparse(argv[i], &p); |
| 371 | if(fsremove(fs, p) < 0) |
| 372 | fprint(2, "remove %s: %r\n", argv[i]); |
| 373 | fsunmount(fs); |
| 374 | } |
| 375 | } |
| 376 | |
| 377 | void |
rsc | e29d0c8 | 2006-01-06 18:00:42 +0000 | [diff] [blame] | 378 | rdcon(void *v) |
| 379 | { |
rsc | ed0601e | 2006-01-06 18:03:09 +0000 | [diff] [blame] | 380 | int n; |
rsc | e29d0c8 | 2006-01-06 18:00:42 +0000 | [diff] [blame] | 381 | char buf[4096]; |
| 382 | CFid *fid; |
| 383 | |
| 384 | fid = v; |
| 385 | for(;;){ |
| 386 | n = read(0, buf, sizeof buf); |
| 387 | if(n <= 0) |
| 388 | threadexitsall(0); |
rsc | ed0601e | 2006-01-06 18:03:09 +0000 | [diff] [blame] | 389 | if(buf[0] == 'R'-'A'+1) |
| 390 | threadexitsall(0); |
rsc | e29d0c8 | 2006-01-06 18:00:42 +0000 | [diff] [blame] | 391 | if(fswrite(fid, buf, n) != n) |
| 392 | fprint(2, "write: %r\n"); |
| 393 | } |
| 394 | } |
| 395 | |
| 396 | void |
| 397 | xcon(int argc, char **argv) |
| 398 | { |
| 399 | char buf[4096], *r, *w, *e; |
| 400 | int n, nocr; |
| 401 | CFid *fid; |
| 402 | |
| 403 | nocr = 1; |
| 404 | |
| 405 | ARGBEGIN{ |
| 406 | case 'r': |
| 407 | nocr = 0; |
| 408 | break; |
| 409 | default: |
| 410 | usage(); |
| 411 | }ARGEND |
| 412 | |
| 413 | if(argc != 1) |
| 414 | usage(); |
| 415 | |
| 416 | fid = xopen(argv[0], ORDWR); |
rsc | ed0601e | 2006-01-06 18:03:09 +0000 | [diff] [blame] | 417 | proccreate(rdcon, fid, 32768); |
rsc | e29d0c8 | 2006-01-06 18:00:42 +0000 | [diff] [blame] | 418 | for(;;){ |
rsc | ed0601e | 2006-01-06 18:03:09 +0000 | [diff] [blame] | 419 | n = fsread(fid, buf, sizeof buf); |
rsc | e29d0c8 | 2006-01-06 18:00:42 +0000 | [diff] [blame] | 420 | if(n <= 0) |
| 421 | threadexitsall(0); |
| 422 | if(nocr){ |
| 423 | for(r=w=buf, e=buf+n; r<e; r++) |
| 424 | if(*r != '\r') |
| 425 | *w++ = *r; |
| 426 | n = w-buf; |
| 427 | } |
| 428 | if(write(1, buf, n) != n) |
| 429 | threadexitsall(0); |
| 430 | } |
| 431 | fsclose(fid); |
| 432 | threadexitsall(0); |
| 433 | } |
| 434 | |
rsc | 1d2f561 | 2005-03-18 19:19:33 +0000 | [diff] [blame] | 435 | static char *mon[] = |
| 436 | { |
| 437 | "Jan", "Feb", "Mar", "Apr", "May", "Jun", |
| 438 | "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" |
| 439 | }; |
| 440 | |
| 441 | |
| 442 | int |
| 443 | timefmt(Fmt *fmt) |
| 444 | { |
| 445 | ulong u; |
| 446 | static ulong time0; |
| 447 | Tm *tm; |
| 448 | |
| 449 | if(time0 == 0) |
| 450 | time0 = time(0); |
| 451 | u = va_arg(fmt->args, ulong); |
| 452 | tm = localtime(u); |
| 453 | if((long)(time0-u) < 6*30*86400) |
| 454 | return fmtprint(fmt, "%s %2d %02d:%02d", |
| 455 | mon[tm->mon], tm->mday, tm->hour, tm->min); |
rsc | bcac59d | 2005-08-11 17:33:43 +0000 | [diff] [blame] | 456 | return fmtprint(fmt, "%s %2d %5d", |
| 457 | mon[tm->mon], tm->mday, tm->year+1900); |
rsc | 1d2f561 | 2005-03-18 19:19:33 +0000 | [diff] [blame] | 458 | } |
| 459 | |
| 460 | static int |
| 461 | dircmp(const void *va, const void *vb) |
| 462 | { |
| 463 | Dir *a, *b; |
| 464 | |
| 465 | a = (Dir*)va; |
| 466 | b = (Dir*)vb; |
| 467 | return strcmp(a->name, b->name); |
| 468 | } |
| 469 | |
| 470 | void |
| 471 | xls(int argc, char **argv) |
| 472 | { |
rsc | a919ad8 | 2005-08-10 18:54:14 +0000 | [diff] [blame] | 473 | char *err, *name, *xname, *f[4], buf[4096]; |
rsc | 1b404fe | 2006-02-05 15:34:46 +0000 | [diff] [blame] | 474 | int nf, i, j, l, sort; |
rsc | 1d2f561 | 2005-03-18 19:19:33 +0000 | [diff] [blame] | 475 | int lflag, dflag, n, len[4]; |
| 476 | Dir *d; |
| 477 | CFid *fid; |
| 478 | CFsys *fs; |
rsc | a919ad8 | 2005-08-10 18:54:14 +0000 | [diff] [blame] | 479 | |
| 480 | err = nil; |
rsc | 1b404fe | 2006-02-05 15:34:46 +0000 | [diff] [blame] | 481 | sort = 0; |
rsc | 1d2f561 | 2005-03-18 19:19:33 +0000 | [diff] [blame] | 482 | lflag = dflag = 0; |
| 483 | ARGBEGIN{ |
rsc | 1b404fe | 2006-02-05 15:34:46 +0000 | [diff] [blame] | 484 | case 'n': |
| 485 | sort = 0; |
| 486 | break; |
rsc | 1d2f561 | 2005-03-18 19:19:33 +0000 | [diff] [blame] | 487 | case 'l': |
| 488 | lflag = 1; |
| 489 | break; |
| 490 | case 'd': |
| 491 | dflag = 1; |
| 492 | break; |
| 493 | }ARGEND |
| 494 | |
| 495 | fmtinstall('D', dirfmt); |
| 496 | fmtinstall('M', dirmodefmt); |
| 497 | quotefmtinstall(); |
| 498 | fmtinstall('T', timefmt); |
| 499 | |
| 500 | for(i=0; i<argc; i++){ |
| 501 | name = argv[i]; |
| 502 | fs = xparse(name, &xname); |
| 503 | if((d = fsdirstat(fs, xname)) == nil){ |
| 504 | fprint(2, "dirstat %s: %r\n", name); |
| 505 | fsunmount(fs); |
rsc | a919ad8 | 2005-08-10 18:54:14 +0000 | [diff] [blame] | 506 | err = "errors"; |
rsc | 1d2f561 | 2005-03-18 19:19:33 +0000 | [diff] [blame] | 507 | continue; |
| 508 | } |
| 509 | if((d->mode&DMDIR) && !dflag){ |
| 510 | if((fid = fsopen(fs, xname, OREAD)) == nil){ |
| 511 | fprint(2, "open %s: %r\n", name); |
| 512 | fsunmount(fs); |
| 513 | free(d); |
rsc | a919ad8 | 2005-08-10 18:54:14 +0000 | [diff] [blame] | 514 | err = "errors"; |
rsc | 1d2f561 | 2005-03-18 19:19:33 +0000 | [diff] [blame] | 515 | continue; |
| 516 | } |
| 517 | free(d); |
| 518 | n = fsdirreadall(fid, &d); |
| 519 | fsclose(fid); |
| 520 | if(n < 0){ |
| 521 | fprint(2, "dirreadall %s: %r\n", name); |
| 522 | fsunmount(fs); |
rsc | a919ad8 | 2005-08-10 18:54:14 +0000 | [diff] [blame] | 523 | err = "errors"; |
rsc | 1d2f561 | 2005-03-18 19:19:33 +0000 | [diff] [blame] | 524 | continue; |
| 525 | } |
rsc | 1b404fe | 2006-02-05 15:34:46 +0000 | [diff] [blame] | 526 | if(sort) |
| 527 | qsort(d, n, sizeof d[0], dircmp); |
rsc | 1d2f561 | 2005-03-18 19:19:33 +0000 | [diff] [blame] | 528 | for(j=0; j<5; j++) |
| 529 | len[j] = 0; |
| 530 | for(i=0; i<n; i++){ |
| 531 | d[i].type = 'M'; |
| 532 | d[i].dev = 0; |
| 533 | snprint(buf, sizeof buf, "%d %s %s %lld", |
| 534 | d[i].dev, d[i].uid, d[i].gid, d[i].length); |
| 535 | nf = getfields(buf, f, 4, 0, " "); |
| 536 | for(j=0; j<4; j++){ |
| 537 | l = strlen(f[j]); |
| 538 | if(l > len[j]) |
| 539 | len[j] = l; |
| 540 | } |
| 541 | } |
| 542 | for(i=0; i<n; i++) |
| 543 | print("%M %C %*d %*s %*s %*lld %T %q\n", |
| 544 | d[i].mode, d[i].type, len[0], d[i].dev, |
| 545 | -len[1], d[i].uid, -len[2], d[i].gid, |
| 546 | len[3], d[i].length, d[i].mtime, d[i].name); |
| 547 | |
| 548 | }else{ |
| 549 | d->type = 'M'; |
| 550 | d->dev = 0; |
| 551 | print("%M %C %d %s %s %lld %T %q\n", |
| 552 | d->mode, d->type, d->dev, |
| 553 | d->uid, d->gid, d->length, d->mtime, d->name); |
| 554 | } |
| 555 | free(d); |
| 556 | } |
rsc | a919ad8 | 2005-08-10 18:54:14 +0000 | [diff] [blame] | 557 | threadexitsall(err); |
rsc | 1d2f561 | 2005-03-18 19:19:33 +0000 | [diff] [blame] | 558 | } |
| 559 | |