Codebase list 9base / 6401fe0
Merging upstream version 2. Daniel Baumann 14 years ago
18 changed file(s) with 764 addition(s) and 777 deletion(s). Raw diff Collapse all Expand all
22
33 include config.mk
44
5 SUBDIRS = lib9 yacc awk basename bc dc cat cleanname date echo grep ls \
6 mk rc read sed seq sleep sort tee test touch tr uniq
5 SUBDIRS = lib9 yacc awk basename bc dc cat cleanname date echo grep mk \
6 rc sed seq sleep sort tee test touch tr uniq
77
88 all:
99 @echo 9base build options:
33 PREFIX = /usr/local/9
44 MANPREFIX = ${PREFIX}/share/man
55
6 VERSION = 20060209
6 VERSION = 2
77
88 # Linux/BSD
99 CFLAGS = -Wall -Wno-missing-braces -Wno-parentheses -Wno-switch -c -I. -DPREFIX="\"${PREFIX}\""
1818 # following objects are not compiled for several reasons
1919 # crypt.o
2020 # netcrypt.o
21 # getcallerpc-$(OBJTYPE).o
2122 # convD2M.o
2223 # convM2D.o
2324 # convM2S.o
132133 exec.o\
133134 execl.o\
134135 fcallfmt.o\
135 getcallerpc-$(OBJTYPE).o\
136136 get9root.o\
137137 getenv.o\
138138 getfields.o\
Binary diff not shown
Binary diff not shown
Binary diff not shown
Binary diff not shown
Binary diff not shown
77 #if defined(__cplusplus)
88 extern "C" {
99 #endif
10
11 #include <utf.h>
12 #include <fmt.h>
1310
1411 /*
1512 * Begin usual libc.h
377374 extern int dirmodefmt(Fmt*);
378375 extern void exits(char*);
379376 extern double frexp(double, int*);
380 extern ulong getcallerpc(void*);
377 /*extern ulong getcallerpc(void*);*/
381378 extern char* p9getenv(char*);
382379 extern int p9putenv(char*, char*);
383380 extern int getfields(char*, char**, int, int, char*);
597594 #define OCEXEC 32 /* or'ed in, close on exec */
598595 #define ORCLOSE 64 /* or'ed in, remove on close */
599596 #define ODIRECT 128 /* or'ed in, direct access */
600 #define ONONBLOCK 256 /* or'ed in, non-blocking call */
597 #define ONONBLOCK 256 /* or'ed in, non-blocking call */
601598 #define OEXCL 0x1000 /* or'ed in, exclusive use (create only) */
602599 #define OLOCK 0x2000 /* or'ed in, lock after opening */
603600 #define OAPPEND 0x4000 /* or'ed in, append only */
622619 #define QTEXCL 0x20 /* type bit for exclusive use files */
623620 #define QTMOUNT 0x10 /* type bit for mounted channel */
624621 #define QTAUTH 0x08 /* type bit for authentication file */
625 #define QTTMP 0x04 /* type bit for non-backed-up file */
626 #define QTSYMLINK 0x02 /* type bit for symbolic link */
627 #define QTFILE 0x00 /* type bits for plain file */
622 #define QTLINK 0x04 /* symbolic link */
623 #define QTFILE 0x00 /* plain file */
628624
629625 /* bits in Dir.mode */
630626 #define DMDIR 0x80000000 /* mode bit for directories */
632628 #define DMEXCL 0x20000000 /* mode bit for exclusive use files */
633629 #define DMMOUNT 0x10000000 /* mode bit for mounted channel */
634630 #define DMAUTH 0x08000000 /* mode bit for authentication file */
635 #define DMTMP 0x04000000 /* mode bit for non-backed-up file */
636 #define DMSYMLINK 0x02000000 /* mode bit for symbolic link (Unix, 9P2000.u) */
637 #define DMDEVICE 0x00800000 /* mode bit for device file (Unix, 9P2000.u) */
638 #define DMNAMEDPIPE 0x00200000 /* mode bit for named pipe (Unix, 9P2000.u) */
639 #define DMSOCKET 0x00100000 /* mode bit for socket (Unix, 9P2000.u) */
640 #define DMSETUID 0x00080000 /* mode bit for setuid (Unix, 9P2000.u) */
641 #define DMSETGID 0x00040000 /* mode bit for setgid (Unix, 9P2000.u) */
631 #define DMDEVICE 0x00800000 /* mode bit for device files (Unix) */
632 #define DMSYMLINK 0x00400000 /* mode bit for symbolic links (Unix) */
633 #define DMNAMEDPIPE 0x00200000 /* mode bit for named pipes (Unix) */
634 #define DMSOCKET 0x00100000 /* mode bit for sockets (Unix) */
642635
643636 #define DMREAD 0x4 /* mode bit for read permission */
644637 #define DMWRITE 0x2 /* mode bit for write permission */
697690 char *uid; /* owner name */
698691 char *gid; /* group name */
699692 char *muid; /* last modifier name */
700
701 /* 9P2000.u extensions */
702 uint uidnum; /* numeric uid */
703 uint gidnum; /* numeric gid */
704 uint muidnum; /* numeric muid */
705 char *ext; /* extended info */
706693 } Dir;
707694
708695 /* keep /sys/src/ape/lib/ap/plan9/sys9.h in sync with this -rsc */
834821 #define main p9main
835822 #endif
836823
837 #ifdef VARARGCK
838 #pragma varargck type "lld" vlong
839 #pragma varargck type "llx" vlong
840 #pragma varargck type "lld" uvlong
841 #pragma varargck type "llx" uvlong
842 #pragma varargck type "ld" long
843 #pragma varargck type "lx" long
844 #pragma varargck type "ld" ulong
845 #pragma varargck type "lx" ulong
846 #pragma varargck type "d" int
847 #pragma varargck type "x" int
848 #pragma varargck type "c" int
849 #pragma varargck type "C" int
850 #pragma varargck type "d" uint
851 #pragma varargck type "x" uint
852 #pragma varargck type "c" uint
853 #pragma varargck type "C" uint
854 #pragma varargck type "f" double
855 #pragma varargck type "e" double
856 #pragma varargck type "g" double
857 #pragma varargck type "lf" long double
858 #pragma varargck type "le" long double
859 #pragma varargck type "lg" long double
860 #pragma varargck type "s" char*
861 #pragma varargck type "q" char*
862 #pragma varargck type "S" Rune*
863 #pragma varargck type "Q" Rune*
864 #pragma varargck type "r" void
865 #pragma varargck type "%" void
866 #pragma varargck type "n" int*
867 #pragma varargck type "p" void*
868 #pragma varargck type "<" void*
869 #pragma varargck type "[" void*
870 #pragma varargck type "H" void*
871 #pragma varargck type "lH" void*
872
873 #pragma varargck flag ' '
874 #pragma varargck flag '#'
875 #pragma varargck flag '+'
876 #pragma varargck flag ','
877 #pragma varargck flag '-'
878 #pragma varargck flag 'u'
879
880 #pragma varargck argpos fmtprint 2
881 #pragma varargck argpos fprint 2
882 #pragma varargck argpos print 1
883 #pragma varargck argpos runeseprint 3
884 #pragma varargck argpos runesmprint 1
885 #pragma varargck argpos runesnprint 3
886 #pragma varargck argpos runesprint 2
887 #pragma varargck argpos seprint 3
888 #pragma varargck argpos smprint 1
889 #pragma varargck argpos snprint 3
890 #pragma varargck argpos sprint 2
891 #pragma varargck argpos sysfatal 1
892 #pragma varargck argpos p9syslog 3
893 #pragma varargck argpos werrstr 1
894 #endif
895
896824 /* compiler directives on plan 9 */
897825 #define SET(x) ((x)=0)
898826 #define USED(x) if(x){}else{}
901829 # undef USED
902830 # define USED(x) { ulong __y __attribute__ ((unused)); __y = (ulong)(x); }
903831 # endif
832 #endif
833
834 #if defined(__OpenBSD__) || (defined(__NetBSD__) && !defined(sched_yield))
835 #define sched_yield() \
836 do { \
837 struct timespec ts; \
838 ts.tv_sec = 0; \
839 ts.tv_nsec = 10; \
840 nanosleep(&ts, NULL); \
841 } while(0)
904842 #endif
905843
906844 /* command line */
2020 void
2121 lock(Lock *l)
2222 {
23 /*
2324 if(_lock)
2425 (*_lock)(l, 1, getcallerpc(&l));
2526 else
2627 l->held = 1;
28 */
2729 }
2830
2931 int
3032 canlock(Lock *l)
3133 {
34 /*
3235 if(_lock)
3336 return (*_lock)(l, 0, getcallerpc(&l));
3437 else{
3740 l->held = 1;
3841 return 1;
3942 }
43 */
44 return 1;
4045 }
4146
4247 void
4348 unlock(Lock *l)
4449 {
50 /*
4551 if(_unlock)
4652 (*_unlock)(l, getcallerpc(&l));
4753 else
4854 l->held = 0;
55 */
4956 }
5057
5158 void
5259 qlock(QLock *l)
5360 {
61 /*
5462 if(_qlock)
5563 (*_qlock)(l, 1, getcallerpc(&l));
5664 else
5765 l->l.held = 1;
66 */
5867 }
5968
6069 int
6170 canqlock(QLock *l)
6271 {
72 /*
6373 if(_qlock)
6474 return (*_qlock)(l, 0, getcallerpc(&l));
6575 else{
6878 l->l.held = 1;
6979 return 1;
7080 }
81 */
82 return 1;
7183 }
7284
7385 void
7486 qunlock(QLock *l)
7587 {
88 /*
7689 if(_qunlock)
7790 (*_qunlock)(l, getcallerpc(&l));
7891 else
7992 l->l.held = 0;
93 */
8094 }
8195
8296 void
8397 rlock(RWLock *l)
8498 {
99 /*
85100 if(_rlock)
86101 (*_rlock)(l, 1, getcallerpc(&l));
87102 else
88103 l->readers++;
104 */
89105 }
90106
91107 int
92108 canrlock(RWLock *l)
93109 {
110 /*
94111 if(_rlock)
95112 return (*_rlock)(l, 0, getcallerpc(&l));
96113 else{
99116 l->readers++;
100117 return 1;
101118 }
119 */
120 return 1;
102121 }
103122
104123 void
105124 runlock(RWLock *l)
106125 {
126 /*
107127 if(_runlock)
108128 (*_runlock)(l, getcallerpc(&l));
109129 else
110130 l->readers--;
131 */
111132 }
112133
113134 void
114135 wlock(RWLock *l)
115136 {
137 /*
116138 if(_wlock)
117139 (*_wlock)(l, 1, getcallerpc(&l));
118140 else
119141 l->writer = (void*)1;
142 */
120143 }
121144
122145 int
123146 canwlock(RWLock *l)
124147 {
148 /*
125149 if(_wlock)
126150 return (*_wlock)(l, 0, getcallerpc(&l));
127151 else{
130154 l->writer = (void*)1;
131155 return 1;
132156 }
157 */
158 return 1;
133159 }
134160
135161 void
136162 wunlock(RWLock *l)
137163 {
164 /*
138165 if(_wunlock)
139166 (*_wunlock)(l, getcallerpc(&l));
140167 else
141168 l->writer = nil;
169 */
142170 }
143171
144172 void
145173 rsleep(Rendez *r)
146174 {
175 /*
147176 if(_rsleep)
148177 (*_rsleep)(r, getcallerpc(&r));
178 */
149179 }
150180
151181 int
152182 rwakeup(Rendez *r)
153183 {
184 /*
154185 if(_rwakeup)
155186 return (*_rwakeup)(r, 0, getcallerpc(&r));
187 */
156188 return 0;
157189 }
158190
159191 int
160192 rwakeupall(Rendez *r)
161193 {
194 /*
162195 if(_rwakeup)
163196 return (*_rwakeup)(r, 1, getcallerpc(&r));
197 */
164198 return 0;
165199 }
+0
-7
ls/Makefile less more
0 # ls - ls unix port from plan9
1 #
2 # Depends on ../lib9
3
4 TARG = ls
5
6 include ../std.mk
+0
-172
ls/ls.1 less more
0 .TH LS 1
1 .SH NAME
2 ls, lc \- list contents of directory
3 .SH SYNOPSIS
4 .B ls
5 [
6 .B -dlmnpqrstuFQ
7 ]
8 .I name ...
9 .PP
10 .B lc
11 [
12 .B -dlmnpqrstuFQ
13 ]
14 .I name ...
15 .SH DESCRIPTION
16 For each directory argument,
17 .I ls
18 lists the contents of the directory;
19 for each file argument,
20 .I ls
21 repeats its name and any other information requested.
22 When no argument is given, the current directory is listed.
23 By default, the output is sorted alphabetically by name.
24 .PP
25 .I Lc
26 is the same as
27 .IR ls ,
28 but sets the
29 .B -p
30 option and pipes the output through
31 .IR mc (1).
32 .PP
33 There are a number of options:
34 .TP
35 .B -d
36 If argument is a directory, list it, not
37 its contents.
38 .TP
39 .B -l
40 List in long format, giving mode (see below), file system type
41 (e.g., for devices, the
42 .B #
43 code letter that names it; see
44 .IR intro (3)),
45 the instance or subdevice number, owner, group,
46 size in bytes, and time of last modification
47 for each file.
48 .TP
49 .B -m
50 List the name of the user who most recently modified the file.
51 .TP
52 .B -n
53 Don't sort the listing.
54 .TP
55 .B -p
56 Print only the final path element of each file name.
57 .TP
58 .B -q
59 List the
60 .I qid
61 (see
62 .IR stat (3))
63 of each file; the printed fields are in the order
64 path, version, and type.
65 .TP
66 .B -r
67 Reverse the order of sort.
68 .TP
69 .B -s
70 Give size in Kbytes for each entry.
71 .TP
72 .B -t
73 Sort by time modified (latest first) instead of
74 by name.
75 .TP
76 .B -u
77 Under
78 .B -t
79 sort by time of last access;
80 under
81 .B -l
82 print time of last access.
83 .TP
84 .B -F
85 Add the character
86 .B /
87 after all directory names
88 and the character
89 .B *
90 after all executable files.
91 .TP
92 .B -L
93 Print the character
94 .B t
95 before each file if it has the temporary flag set, and
96 .B -
97 otherwise.
98 .TP
99 .B -Q
100 By default, printed file names are quoted if they contain characters special to
101 .IR rc (1).
102 The
103 .B -Q
104 flag disables this behavior.
105 .PP
106 The mode printed under the
107 .B -l
108 option contains 11 characters,
109 interpreted
110 as follows:
111 the first character is
112 .TP
113 .B d
114 if the entry is a directory;
115 .TP
116 .B a
117 if the entry is an append-only file;
118 .TP
119 .B D
120 if the entry is a Unix device;
121 .TP
122 .B L
123 if the entry is a symbolic link;
124 .TP
125 .B P
126 if the entry is a named pipe;
127 .TP
128 .B S
129 if the entry is a socket;
130 .TP
131 .B -
132 if the entry is a plain file.
133 .PD
134 .PP
135 The next letter is
136 .B l
137 if the file is exclusive access (one writer or reader at a time).
138 .PP
139 The last 9 characters are interpreted
140 as three sets of three bits each.
141 The first set refers to owner permissions;
142 the next to permissions to others in the same user-group;
143 and the last to all others.
144 Within each set the three characters indicate
145 permission respectively to read, to write, or to
146 execute the file as a program.
147 For a directory, `execute' permission is interpreted
148 to mean permission to search the directory
149 for a specified file.
150 The permissions are indicated as follows:
151 .TP 3
152 .B r
153 if the file is readable;
154 .PD 0
155 .TP 3
156 .B w
157 if the file is writable;
158 .TP 3
159 .B x
160 if the file is executable;
161 .TP 3
162 .B -
163 if none of the above permissions is granted.
164 .PD
165 .SH SOURCE
166 .B \*9/src/cmd/ls.c
167 .br
168 .B \*9/bin/lc
169 .SH SEE ALSO
170 .IR stat (3),
171 .IR mc (1)
+0
-309
ls/ls.c less more
0 #include <u.h>
1 #include <libc.h>
2 #include <bio.h>
3
4 #define dirbuf p9dirbuf /* avoid conflict on sun */
5
6 typedef struct NDir NDir;
7 struct NDir
8 {
9 Dir *d;
10 char *prefix;
11 };
12
13 int errs = 0;
14 int dflag;
15 int lflag;
16 int mflag;
17 int nflag;
18 int pflag;
19 int qflag;
20 int Qflag;
21 int rflag;
22 int sflag;
23 int tflag;
24 int uflag;
25 int Fflag;
26 int ndirbuf;
27 int ndir;
28 NDir* dirbuf;
29 int ls(char*, int);
30 int compar(NDir*, NDir*);
31 char* asciitime(long);
32 char* darwx(long);
33 void rwx(long, char*);
34 void growto(long);
35 void dowidths(Dir*);
36 void format(Dir*, char*);
37 void output(void);
38 ulong clk;
39 int swidth; /* max width of -s size */
40 int qwidth; /* max width of -q version */
41 int vwidth; /* max width of dev */
42 int uwidth; /* max width of userid */
43 int mwidth; /* max width of muid */
44 int glwidth; /* max width of groupid and length */
45 Biobuf bin;
46
47 void
48 main(int argc, char *argv[])
49 {
50 int i;
51
52 Binit(&bin, 1, OWRITE);
53 ARGBEGIN{
54 case 'F': Fflag++; break;
55 case 'd': dflag++; break;
56 case 'l': lflag++; break;
57 case 'm': mflag++; break;
58 case 'n': nflag++; break;
59 case 'p': pflag++; break;
60 case 'q': qflag++; break;
61 case 'Q': Qflag++; break;
62 case 'r': rflag++; break;
63 case 's': sflag++; break;
64 case 't': tflag++; break;
65 case 'u': uflag++; break;
66 default: fprint(2, "usage: ls [-dlmnpqrstuFQ] [file ...]\n");
67 exits("usage");
68 }ARGEND
69
70 doquote = needsrcquote;
71 quotefmtinstall();
72 fmtinstall('M', dirmodefmt);
73
74 if(lflag)
75 clk = time(0);
76 if(argc == 0)
77 errs = ls(".", 0);
78 else for(i=0; i<argc; i++)
79 errs |= ls(argv[i], 1);
80 output();
81 exits(errs? "errors" : 0);
82 }
83
84 int
85 ls(char *s, int multi)
86 {
87 int fd;
88 long i, n;
89 char *p;
90 Dir *db;
91
92 for(;;) {
93 p = utfrrune(s, '/');
94 if(p == 0 || p[1] != 0 || p == s)
95 break;
96 *p = 0;
97 }
98 db = dirstat(s);
99 if(db == nil){
100 error:
101 fprint(2, "ls: %s: %r\n", s);
102 return 1;
103 }
104 if(db->qid.type&QTDIR && dflag==0){
105 free(db);
106 db = nil;
107 output();
108 fd = open(s, OREAD);
109 if(fd == -1)
110 goto error;
111 n = dirreadall(fd, &db);
112 if(n < 0)
113 goto error;
114 growto(ndir+n);
115 for(i=0; i<n; i++){
116 dirbuf[ndir+i].d = db+i;
117 dirbuf[ndir+i].prefix = multi? s : 0;
118 }
119 ndir += n;
120 close(fd);
121 output();
122 }else{
123 growto(ndir+1);
124 dirbuf[ndir].d = db;
125 dirbuf[ndir].prefix = 0;
126 p = utfrrune(s, '/');
127 if(p){
128 dirbuf[ndir].prefix = s;
129 *p = 0;
130 /* restore original name; don't use result of stat */
131 dirbuf[ndir].d->name = strdup(p+1);
132 }
133 ndir++;
134 }
135 return 0;
136 }
137
138 void
139 output(void)
140 {
141 int i;
142 char buf[4096];
143 char *s;
144
145 if(!nflag)
146 qsort(dirbuf, ndir, sizeof dirbuf[0], (int (*)(const void*, const void*))compar);
147 for(i=0; i<ndir; i++)
148 dowidths(dirbuf[i].d);
149 for(i=0; i<ndir; i++) {
150 if(!pflag && (s = dirbuf[i].prefix)) {
151 if(strcmp(s, "/") ==0) /* / is a special case */
152 s = "";
153 sprint(buf, "%s/%s", s, dirbuf[i].d->name);
154 format(dirbuf[i].d, buf);
155 } else
156 format(dirbuf[i].d, dirbuf[i].d->name);
157 }
158 ndir = 0;
159 Bflush(&bin);
160 }
161
162 void
163 dowidths(Dir *db)
164 {
165 char buf[256];
166 int n;
167
168 if(sflag) {
169 n = sprint(buf, "%llud", (db->length+1023)/1024);
170 if(n > swidth)
171 swidth = n;
172 }
173 if(qflag) {
174 n = sprint(buf, "%lud", db->qid.vers);
175 if(n > qwidth)
176 qwidth = n;
177 }
178 if(mflag) {
179 n = snprint(buf, sizeof buf, "[%s]", db->muid);
180 if(n > mwidth)
181 mwidth = n;
182 }
183 if(lflag) {
184 n = sprint(buf, "%ud", db->dev);
185 if(n > vwidth)
186 vwidth = n;
187 n = strlen(db->uid);
188 if(n > uwidth)
189 uwidth = n;
190 n = sprint(buf, "%llud", db->length);
191 n += strlen(db->gid);
192 if(n > glwidth)
193 glwidth = n;
194 }
195 }
196
197 char*
198 fileflag(Dir *db)
199 {
200 if(Fflag == 0)
201 return "";
202 if(QTDIR & db->qid.type)
203 return "/";
204 if(0111 & db->mode)
205 return "*";
206 return "";
207 }
208
209 void
210 format(Dir *db, char *name)
211 {
212 int i;
213
214 if(sflag)
215 Bprint(&bin, "%*llud ",
216 swidth, (db->length+1023)/1024);
217 if(mflag){
218 Bprint(&bin, "[%s] ", db->muid);
219 for(i=2+strlen(db->muid); i<mwidth; i++)
220 Bprint(&bin, " ");
221 }
222 if(qflag)
223 Bprint(&bin, "(%.16llux %*lud %.2ux) ",
224 db->qid.path,
225 qwidth, db->qid.vers,
226 db->qid.type);
227 if(lflag)
228 Bprint(&bin,
229 Qflag? "%M %C %*ud %*s %s %*llud %s %s\n" : "%M %C %*ud %*s %s %*llud %s %q\n",
230 db->mode, db->type,
231 vwidth, db->dev,
232 -uwidth, db->uid,
233 db->gid,
234 (int)(glwidth-strlen(db->gid)), db->length,
235 asciitime(uflag? db->atime : db->mtime), name);
236 else
237 Bprint(&bin,
238 Qflag? "%s%s\n" : "%q%s\n",
239 name, fileflag(db));
240 }
241
242 void
243 growto(long n)
244 {
245 if(n <= ndirbuf)
246 return;
247 ndirbuf = n;
248 dirbuf=(NDir *)realloc(dirbuf, ndirbuf*sizeof(NDir));
249 if(dirbuf == 0){
250 fprint(2, "ls: malloc fail\n");
251 exits("malloc fail");
252 }
253 }
254
255 int
256 compar(NDir *a, NDir *b)
257 {
258 long i;
259 Dir *ad, *bd;
260
261 ad = a->d;
262 bd = b->d;
263
264 if(tflag){
265 if(uflag)
266 i = bd->atime-ad->atime;
267 else
268 i = bd->mtime-ad->mtime;
269 }else{
270 if(a->prefix && b->prefix){
271 i = strcmp(a->prefix, b->prefix);
272 if(i == 0)
273 i = strcmp(ad->name, bd->name);
274 }else if(a->prefix){
275 i = strcmp(a->prefix, bd->name);
276 if(i == 0)
277 i = 1; /* a is longer than b */
278 }else if(b->prefix){
279 i = strcmp(ad->name, b->prefix);
280 if(i == 0)
281 i = -1; /* b is longer than a */
282 }else
283 i = strcmp(ad->name, bd->name);
284 }
285 if(i == 0)
286 i = (ad<bd? -1 : 1);
287 if(rflag)
288 i = -i;
289 return i;
290 }
291
292 char*
293 asciitime(long l)
294 {
295 static char buf[32];
296 char *t;
297
298 t = ctime(l);
299 /* 6 months in the past or a day in the future */
300 if(l<clk-180L*24*60*60 || clk+24L*60*60<l){
301 memmove(buf, t+4, 7); /* month and day */
302 memmove(buf+7, t+23, 5); /* year */
303 }else
304 memmove(buf, t+4, 12); /* skip day of week */
305 buf[12] = 0;
306 return buf;
307 }
308
0 .TH MK 1
1 .SH NAME
2 mk \- maintain (make) related files
3 .SH SYNOPSIS
4 .B mk
5 [
6 .B -f
7 .I mkfile
8 ] ...
9 [
10 .I option ...
11 ]
12 [
13 .I target ...
14 ]
15 .SH DESCRIPTION
16 .I Mk
17 uses the dependency rules specified in
18 .I mkfile
19 to control the update (usually by compilation) of
20 .I targets
21 (usually files)
22 from the source files upon which they depend.
23 The
24 .I mkfile
25 (default
26 .LR mkfile )
27 contains a
28 .I rule
29 for each target that identifies the files and other
30 targets upon which it depends and an
31 .IR sh (1)
32 script, a
33 .IR recipe ,
34 to update the target.
35 The script is run if the target does not exist
36 or if it is older than any of the files it depends on.
37 .I Mkfile
38 may also contain
39 .I meta-rules
40 that define actions for updating implicit targets.
41 If no
42 .I target
43 is specified, the target of the first rule (not meta-rule) in
44 .I mkfile
45 is updated.
46 .PP
47 The environment variable
48 .B $NPROC
49 determines how many targets may be updated simultaneously;
50 Some operating systems, e.g., Plan 9, set
51 .B $NPROC
52 automatically to the number of CPUs on the current machine.
53 .PP
54 Options are:
55 .TP \w'\fL-d[egp]\ 'u
56 .B -a
57 Assume all targets to be out of date.
58 Thus, everything is updated.
59 .PD 0
60 .TP
61 .BR -d [ egp ]
62 Produce debugging output
63 .RB ( p
64 is for parsing,
65 .B g
66 for graph building,
67 .B e
68 for execution).
69 .TP
70 .B -e
71 Explain why each target is made.
72 .TP
73 .B -i
74 Force any missing intermediate targets to be made.
75 .TP
76 .B -k
77 Do as much work as possible in the face of errors.
78 .TP
79 .B -n
80 Print, but do not execute, the commands
81 needed to update the targets.
82 .TP
83 .B -s
84 Make the command line arguments sequentially rather than in parallel.
85 .TP
86 .B -t
87 Touch (update the modified date of) file targets, without
88 executing any recipes.
89 .TP
90 .BI -w target1 , target2,...
91 Pretend the modify time for each
92 .I target
93 is the current time; useful in conjunction with
94 .B -n
95 to learn what updates would be triggered by
96 modifying the
97 .IR targets .
98 .PD
99 .SS The \fLmkfile\fP
100 A
101 .I mkfile
102 consists of
103 .I assignments
104 (described under `Environment') and
105 .IR rules .
106 A rule contains
107 .I targets
108 and a
109 .IR tail .
110 A target is a literal string
111 and is normally a file name.
112 The tail contains zero or more
113 .I prerequisites
114 and an optional
115 .IR recipe ,
116 which is an
117 .B shell
118 script.
119 Each line of the recipe must begin with white space.
120 A rule takes the form
121 .IP
122 .EX
123 target: prereq1 prereq2
124 \f2recipe using\fP prereq1, prereq2 \f2to build\fP target
125 .EE
126 .PP
127 When the recipe is executed,
128 the first character on every line is elided.
129 .PP
130 After the colon on the target line, a rule may specify
131 .IR attributes ,
132 described below.
133 .PP
134 A
135 .I meta-rule
136 has a target of the form
137 .IB A % B
138 where
139 .I A
140 and
141 .I B
142 are (possibly empty) strings.
143 A meta-rule acts as a rule for any potential target whose
144 name matches
145 .IB A % B
146 with
147 .B %
148 replaced by an arbitrary string, called the
149 .IR stem .
150 In interpreting a meta-rule,
151 the stem is substituted for all occurrences of
152 .B %
153 in the prerequisite names.
154 In the recipe of a meta-rule, the environment variable
155 .B $stem
156 contains the string matched by the
157 .BR % .
158 For example, a meta-rule to compile a C program using
159 .IR 9c (1)
160 might be:
161 .IP
162 .EX
163 %: %.c
164 9c -c $stem.c
165 9l -o $stem $stem.o
166 .EE
167 .PP
168 Meta-rules may contain an ampersand
169 .B &
170 rather than a percent sign
171 .BR % .
172 A
173 .B %
174 matches a maximal length string of any characters;
175 an
176 .B &
177 matches a maximal length string of any characters except period
178 or slash.
179 .PP
180 The text of the
181 .I mkfile
182 is processed as follows.
183 Lines beginning with
184 .B <
185 followed by a file name are replaced by the contents of the named
186 file.
187 Lines beginning with
188 .B "<|"
189 followed by a file name are replaced by the output
190 of the execution of the named
191 file.
192 Blank lines and comments, which run from unquoted
193 .B #
194 characters to the following newline, are deleted.
195 The character sequence backslash-newline is deleted,
196 so long lines in
197 .I mkfile
198 may be folded.
199 Non-recipe lines are processed by substituting for
200 .BI `{ command }
201 the output of the
202 .I command
203 when run by
204 .IR sh .
205 References to variables are replaced by the variables' values.
206 Special characters may be quoted using single quotes
207 .BR \&''
208 as in
209 .IR sh (1).
210 .PP
211 Assignments and rules are distinguished by
212 the first unquoted occurrence of
213 .B :
214 (rule)
215 or
216 .B =
217 (assignment).
218 .PP
219 A later rule may modify or override an existing rule under the
220 following conditions:
221 .TP
222 \-
223 If the targets of the rules exactly match and one rule
224 contains only a prerequisite clause and no recipe, the
225 clause is added to the prerequisites of the other rule.
226 If either or both targets are virtual, the recipe is
227 always executed.
228 .TP
229 \-
230 If the targets of the rules match exactly and the
231 prerequisites do not match and both rules
232 contain recipes,
233 .I mk
234 reports an ``ambiguous recipe'' error.
235 .TP
236 \-
237 If the target and prerequisites of both rules match exactly,
238 the second rule overrides the first.
239 .SS Environment
240 Rules may make use of
241 shell
242 environment variables.
243 A legal reference of the form
244 .B $OBJ
245 or
246 .B ${name}
247 is expanded as in
248 .IR sh (1).
249 A reference of the form
250 .BI ${name: A % B = C\fL%\fID\fL}\fR,
251 where
252 .I A, B, C, D
253 are (possibly empty) strings,
254 has the value formed by expanding
255 .B $name
256 and substituting
257 .I C
258 for
259 .I A
260 and
261 .I D
262 for
263 .I B
264 in each word in
265 .B $name
266 that matches pattern
267 .IB A % B\f1.
268 .PP
269 Variables can be set by
270 assignments of the form
271 .I
272 var\fL=\fR[\fIattr\fL=\fR]\fIvalue\fR
273 .br
274 Blanks in the
275 .I value
276 break it into words.
277 Such variables are exported
278 to the environment of
279 recipes as they are executed, unless
280 .BR U ,
281 the only legal attribute
282 .IR attr ,
283 is present.
284 The initial value of a variable is
285 taken from (in increasing order of precedence)
286 the default values below,
287 .I mk's
288 environment, the
289 .IR mkfiles ,
290 and any command line assignment as an argument to
291 .IR mk .
292 A variable assignment argument overrides the first (but not any subsequent)
293 assignment to that variable.
294 .PP
295 The variable
296 .B MKFLAGS
297 contains all the option arguments (arguments starting with
298 .L -
299 or containing
300 .LR = )
301 and
302 .B MKARGS
303 contains all the targets in the call to
304 .IR mk .
305 .PP
306 The variable
307 .B MKSHELL
308 contains the shell command line
309 .I mk
310 uses to run recipes.
311 If the first word of the command ends in
312 .B rc
313 or
314 .BR rcsh ,
315 .I mk
316 uses
317 .IR rc (1)'s
318 quoting rules; otherwise it uses
319 .IR sh (1)'s.
320 The
321 .B MKSHELL
322 variable is consulted when the mkfile is read, not when it is executed,
323 so that different shells can be used within a single mkfile:
324 .IP
325 .EX
326 MKSHELL=$PLAN9/bin/rc
327 use-rc:V:
328 for(i in a b c) echo $i
329
330 MKSHELL=sh
331 use-sh:V:
332 for i in a b c; do echo $i; done
333 .EE
334 .LP
335 Mkfiles included via
336 .B <
337 or
338 .B <|
339 .RI ( q.v. )
340 see their own private copy of
341 .BR MKSHELL ,
342 which always starts set to
343 .B sh .
344 .PP
345 Dynamic information may be included in the mkfile by using a line of the form
346 .IP
347 \fR<|\fIcommand\fR \fIargs\fR
348 .LP
349 This runs the command
350 .I command
351 with the given arguments
352 .I args
353 and pipes its standard output to
354 .I mk
355 to be included as part of the mkfile. For instance, the Inferno kernels
356 use this technique
357 to run a shell command with an awk script and a configuration
358 file as arguments in order for
359 the
360 .I awk
361 script to process the file and output a set of variables and their values.
362 .SS Execution
363 .PP
364 During execution,
365 .I mk
366 determines which targets must be updated, and in what order,
367 to build the
368 .I names
369 specified on the command line.
370 It then runs the associated recipes.
371 .PP
372 A target is considered up to date if it has no prerequisites or
373 if all its prerequisites are up to date and it is newer
374 than all its prerequisites.
375 Once the recipe for a target has executed, the target is
376 considered up to date.
377 .PP
378 The date stamp
379 used to determine if a target is up to date is computed
380 differently for different types of targets.
381 If a target is
382 .I virtual
383 (the target of a rule with the
384 .B V
385 attribute),
386 its date stamp is initially zero; when the target is
387 updated the date stamp is set to
388 the most recent date stamp of its prerequisites.
389 Otherwise, if a target does not exist as a file,
390 its date stamp is set to the most recent date stamp of its prerequisites,
391 or zero if it has no prerequisites.
392 Otherwise, the target is the name of a file and
393 the target's date stamp is always that file's modification date.
394 The date stamp is computed when the target is needed in
395 the execution of a rule; it is not a static value.
396 .PP
397 Nonexistent targets that have prerequisites
398 and are themselves prerequisites are treated specially.
399 Such a target
400 .I t
401 is given the date stamp of its most recent prerequisite
402 and if this causes all the targets which have
403 .I t
404 as a prerequisite to be up to date,
405 .I t
406 is considered up to date.
407 Otherwise,
408 .I t
409 is made in the normal fashion.
410 The
411 .B -i
412 flag overrides this special treatment.
413 .PP
414 Files may be made in any order that respects
415 the preceding restrictions.
416 .PP
417 A recipe is executed by supplying the recipe as standard input to
418 the command
419 .BR /bin/sh .
420 (Note that unlike
421 .IR make ,
422 .I mk
423 feeds the entire recipe to the shell rather than running each line
424 of the recipe separately.)
425 The environment is augmented by the following variables:
426 .TP 14
427 .B $alltarget
428 all the targets of this rule.
429 .TP
430 .B $newprereq
431 the prerequisites that caused this rule to execute.
432 .TP
433 .B $newmember
434 the prerequisites that are members of an aggregate
435 that caused this rule to execute.
436 When the prerequisites of a rule are members of an
437 aggregate,
438 .B $newprereq
439 contains the name of the aggregate and out of date
440 members, while
441 .B $newmember
442 contains only the name of the members.
443 .TP
444 .B $nproc
445 the process slot for this recipe.
446 It satisfies
447 .RB 0≤ $nproc < $NPROC .
448 .TP
449 .B $pid
450 the process id for the
451 .I mk
452 executing the recipe.
453 .TP
454 .B $prereq
455 all the prerequisites for this rule.
456 .TP
457 .B $stem
458 if this is a meta-rule,
459 .B $stem
460 is the string that matched
461 .B %
462 or
463 .BR & .
464 Otherwise, it is empty.
465 For regular expression meta-rules (see below), the variables
466 .LR stem0 ", ...,"
467 .L stem9
468 are set to the corresponding subexpressions.
469 .TP
470 .B $target
471 the targets for this rule that need to be remade.
472 .PP
473 These variables are available only during the execution of a recipe,
474 not while evaluating the
475 .IR mkfile .
476 .PP
477 Unless the rule has the
478 .B Q
479 attribute,
480 the recipe is printed prior to execution
481 with recognizable environment variables expanded.
482 Commands returning error status
483 cause
484 .I mk
485 to terminate.
486 .PP
487 Recipes and backquoted
488 .B rc
489 commands in places such as assignments
490 execute in a copy of
491 .I mk's
492 environment; changes they make to
493 environment variables are not visible from
494 .IR mk .
495 .PP
496 Variable substitution in a rule is done when
497 the rule is read; variable substitution in the recipe is done
498 when the recipe is executed. For example:
499 .IP
500 .EX
501 bar=a.c
502 foo: $bar
503 $CC -o foo $bar
504 bar=b.c
505 .EE
506 .PP
507 will compile
508 .B b.c
509 into
510 .BR foo ,
511 if
512 .B a.c
513 is newer than
514 .BR foo .
515 .SS Aggregates
516 Names of the form
517 .IR a ( b )
518 refer to member
519 .I b
520 of the aggregate
521 .IR a .
522 Currently, the only aggregates supported are
523 .I 9ar
524 (see
525 .IR 9c (1))
526 archives.
527 .SS Attributes
528 The colon separating the target from the prerequisites
529 may be
530 immediately followed by
531 .I attributes
532 and another colon.
533 The attributes are:
534 .TP
535 .B D
536 If the recipe exits with a non-null status, the target is deleted.
537 .TP
538 .B E
539 Continue execution if the recipe draws errors.
540 .TP
541 .B N
542 If there is no recipe, the target has its time updated.
543 .TP
544 .B n
545 The rule is a meta-rule that cannot be a target of a virtual rule.
546 Only files match the pattern in the target.
547 .TP
548 .B P
549 The characters after the
550 .B P
551 until the terminating
552 .B :
553 are taken as a program name.
554 It will be invoked as
555 .B "sh -c prog 'arg1' 'arg2'"
556 and should return a zero exit status
557 if and only if arg1 is up to date with respect to arg2.
558 Date stamps are still propagated in the normal way.
559 .TP
560 .B Q
561 The recipe is not printed prior to execution.
562 .TP
563 .B R
564 The rule is a meta-rule using regular expressions.
565 In the rule,
566 .B %
567 has no special meaning.
568 The target is interpreted as a regular expression as defined in
569 .IR regexp (7).
570 The prerequisites may contain references
571 to subexpressions in form
572 .BI \e n\f1,
573 as in the substitute command of
574 .IR sed (1).
575 .TP
576 .B U
577 The targets are considered to have been updated
578 even if the recipe did not do so.
579 .TP
580 .B V
581 The targets of this rule are marked as virtual.
582 They are distinct from files of the same name.
583 .PD
584 .SH EXAMPLES
585 A simple mkfile to compile a program:
586 .IP
587 .EX
588 .ta 8n +8n +8n +8n +8n +8n +8n
589 </$objtype/mkfile
590
591 prog: a.$O b.$O c.$O
592 $LD $LDFLAGS -o $target $prereq
593
594 %.$O: %.c
595 $CC $CFLAGS $stem.c
596 .EE
597 .PP
598 Override flag settings in the mkfile:
599 .IP
600 .EX
601 % mk target 'CFLAGS=-S -w'
602 .EE
603 .PP
604 Maintain a library:
605 .IP
606 .EX
607 libc.a(%.$O):N: %.$O
608 libc.a: libc.a(abs.$O) libc.a(access.$O) libc.a(alarm.$O) ...
609 ar r libc.a $newmember
610 .EE
611 .PP
612 String expression variables to derive names from a master list:
613 .IP
614 .EX
615 NAMES=alloc arc bquote builtins expand main match mk var word
616 OBJ=${NAMES:%=%.$O}
617 .EE
618 .PP
619 Regular expression meta-rules:
620 .IP
621 .EX
622 ([^/]*)/(.*)\e.$O:R: \e1/\e2.c
623 cd $stem1; $CC $CFLAGS $stem2.c
624 .EE
625 .PP
626 A correct way to deal with
627 .IR yacc (1)
628 grammars.
629 The file
630 .B lex.c
631 includes the file
632 .B x.tab.h
633 rather than
634 .B y.tab.h
635 in order to reflect changes in content, not just modification time.
636 .IP
637 .EX
638 lex.$O: x.tab.h
639 x.tab.h: y.tab.h
640 cmp -s x.tab.h y.tab.h || cp y.tab.h x.tab.h
641 y.tab.c y.tab.h: gram.y
642 $YACC -d gram.y
643 .EE
644 .PP
645 The above example could also use the
646 .B P
647 attribute for the
648 .B x.tab.h
649 rule:
650 .IP
651 .EX
652 x.tab.h:Pcmp -s: y.tab.h
653 cp y.tab.h x.tab.h
654 .EE
655 .SH SOURCE
656 .B \*9/src/cmd/mk
657 .SH SEE ALSO
658 .IR sh (1),
659 .IR regexp (7)
660 .PP
661 A. Hume,
662 ``Mk: a Successor to Make''
663 (Tenth Edition Research Unix Manuals).
664 .PP
665 Andrew G. Hume and Bob Flandrena,
666 ``Maintaining Files on Plan 9 with Mk''.
667 DOCPREFIX/doc/mk.pdf
668 .SH HISTORY
669 Andrew Hume wrote
670 .I mk
671 for Tenth Edition Research Unix.
672 It was later ported to Plan 9.
673 This software is a port of the Plan 9 version back to Unix.
674 .SH BUGS
675 Identical recipes for regular expression meta-rules only have one target.
676 .PP
677 Seemingly appropriate input like
678 .B CFLAGS=-DHZ=60
679 is parsed as an erroneous attribute; correct it by inserting
680 a space after the first
681 .LR = .
682 .PP
683 The recipes printed by
684 .I mk
685 before being passed to
686 the shell
687 for execution are sometimes erroneously expanded
688 for printing. Don't trust what's printed; rely
689 on what the shell
690 does.
0 ***************
1 *** 445,451 ****
2 .B $nproc
3 the process slot for this recipe.
4 It satisfies
5 - .RB 0??? $nproc < $NPROC .
6 .TP
7 .B $pid
8 the process id for the
9 --- 445,451 ----
10 .B $nproc
11 the process slot for this recipe.
12 It satisfies
13 + .RB $nproc < $NPROC .
14 .TP
15 .B $pid
16 the process id for the
+0
-6
read/Makefile less more
0 # read - read unix port from plan9
1 # Depends on ../lib9
2
3 TARG = read
4
5 include ../std.mk
+0
-108
read/read.1 less more
0 .TH CAT 1
1 .SH NAME
2 cat, read, nobs \- catenate files
3 .SH SYNOPSIS
4 .B cat
5 [
6 .I file ...
7 ]
8 .br
9 .B read
10 [
11 .B -m
12 ] [
13 .B -n
14 .I nline
15 ] [
16 .I file ...
17 ]
18 .br
19 .B nobs
20 [
21 .I file ...
22 ]
23 .SH DESCRIPTION
24 .I Cat
25 reads each
26 .I file
27 in sequence and writes it on the standard output.
28 Thus
29 .IP
30 .L
31 cat file
32 .LP
33 prints a file and
34 .IP
35 .L
36 cat file1 file2 >file3
37 .LP
38 concatenates the first two files and places the result
39 on the third.
40 .PP
41 If no
42 .I file
43 is given,
44 .I cat
45 reads from the standard input.
46 Output is buffered in blocks matching the input.
47 .PP
48 .I Read
49 copies to standard output exactly one line from the named
50 .IR file ,
51 default standard input.
52 It is useful in interactive
53 .IR rc (1)
54 scripts.
55 .PP
56 The
57 .B -m
58 flag causes it to continue reading and writing multiple lines until end of file;
59 .B -n
60 causes it to read no more than
61 .I nline
62 lines.
63 .PP
64 .I Read
65 always executes a single
66 .B write
67 for each line of input, which can be helpful when
68 preparing input to programs that expect line-at-a-time data.
69 It never reads any more data from the input than it prints to the output.
70 .PP
71 .I Nobs
72 copies the named files to
73 standard output except that it removes all backspace
74 characters and the characters that precede them.
75 It is useful to use as
76 .B $PAGER
77 with the Unix version of
78 .IR man (1)
79 when run inside a
80 .I win
81 (see
82 .IR acme (1))
83 window.
84 .SH SOURCE
85 .B \*9/src/cmd/cat.c
86 .br
87 .B \*9/src/cmd/read.c
88 .br
89 .B \*9/bin/nobs
90 .SH SEE ALSO
91 .IR cp (1)
92 .SH DIAGNOSTICS
93 .I Read
94 exits with status
95 .B eof
96 on end of file or, in the
97 .B -n
98 case, if it doesn't read
99 .I nlines
100 lines.
101 .SH BUGS
102 Beware of
103 .L "cat a b >a"
104 and
105 .LR "cat a b >b" ,
106 which
107 destroy input files before reading them.
+0
-91
read/read.c less more
0 #include <u.h>
1 #include <libc.h>
2
3 int multi;
4 int nlines;
5 char *status = nil;
6
7 int
8 line(int fd, char *file)
9 {
10 char c;
11 int m, n, nalloc;
12 char *buf;
13
14 nalloc = 0;
15 buf = nil;
16 for(m=0; ; ){
17 n = read(fd, &c, 1);
18 if(n < 0){
19 fprint(2, "read: error reading %s: %r\n", file);
20 exits("read error");
21 }
22 if(n == 0){
23 if(m == 0)
24 status = "eof";
25 break;
26 }
27 if(m == nalloc){
28 nalloc += 1024;
29 buf = realloc(buf, nalloc);
30 if(buf == nil){
31 fprint(2, "read: malloc error: %r\n");
32 exits("malloc");
33 }
34 }
35 buf[m++] = c;
36 if(c == '\n')
37 break;
38 }
39 if(m > 0)
40 write(1, buf, m);
41 free(buf);
42 return m;
43 }
44
45 void
46 lines(int fd, char *file)
47 {
48 do{
49 if(line(fd, file) == 0)
50 break;
51 }while(multi || --nlines>0);
52 }
53
54 void
55 main(int argc, char *argv[])
56 {
57 int i, fd;
58 char *s;
59
60 ARGBEGIN{
61 case 'm':
62 multi = 1;
63 break;
64 case 'n':
65 s = ARGF();
66 if(s){
67 nlines = atoi(s);
68 break;
69 }
70 /* fall through */
71 default:
72 fprint(2, "usage: read [-m] [-n nlines] [files...]\n");
73 exits("usage");
74 }ARGEND
75
76 if(argc == 0)
77 lines(0, "<stdin>");
78 else
79 for(i=0; i<argc; i++){
80 fd = open(argv[i], OREAD);
81 if(fd < 0){
82 fprint(2, "read: can't open %s: %r\n", argv[i]);
83 exits("open");
84 }
85 lines(fd, argv[i]);
86 close(fd);
87 }
88
89 exits(status);
90 }