Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – planix.SVN – Blame – /os/branches/planix-v0/sys/src/cmd/sam/sam.c – Rev 2

Subversion Repositories planix.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include "sam.h"
2
 
3
Rune	genbuf[BLOCKSIZE];
4
int	io;
5
int	panicking;
6
int	rescuing;
7
String	genstr;
8
String	rhs;
9
String	curwd;
10
String	cmdstr;
11
Rune	empty[] = { 0 };
12
char	*genc;
13
File	*curfile;
14
File	*flist;
15
File	*cmd;
16
jmp_buf	mainloop;
17
List	tempfile = { 'p' };
18
int	quitok = TRUE;
19
int	downloaded;
20
int	dflag;
21
int	Rflag;
22
char	*machine;
23
char	*home;
24
int	bpipeok;
25
int	termlocked;
26
char	*samterm = SAMTERM;
27
char	*rsamname = RSAM;
28
File	*lastfile;
29
Disk	*disk;
30
long	seq;
31
 
32
Rune	baddir[] = { '<', 'b', 'a', 'd', 'd', 'i', 'r', '>', '\n'};
33
 
34
void	usage(void);
35
 
36
void main(int argc, char *argv[])
37
{
38
	int i;
39
	String *t;
40
	char *termargs[10], **ap;
41
 
42
	ap = termargs;
43
	*ap++ = "samterm";
44
	ARGBEGIN{
45
	case 'd':
46
		dflag++;
47
		break;
48
	case 'r':
49
		machine = EARGF(usage());
50
		break;
51
	case 'R':
52
		Rflag++;
53
		break;
54
	case 't':
55
		samterm = EARGF(usage());
56
		break;
57
	case 's':
58
		rsamname = EARGF(usage());
59
		break;
60
	default:
61
		dprint("sam: unknown flag %c\n", ARGC());
62
		usage();
63
	/* options for samterm */
64
	case 'a':
65
		*ap++ = "-a";
66
		break;
67
	}ARGEND
68
	*ap = nil;
69
 
70
	Strinit(&cmdstr);
71
	Strinit0(&lastpat);
72
	Strinit0(&lastregexp);
73
	Strinit0(&genstr);
74
	Strinit0(&rhs);
75
	Strinit0(&curwd);
76
	Strinit0(&plan9cmd);
77
	home = getenv(HOME);
78
	disk = diskinit();
79
	if(home == 0)
80
		home = "/";
81
	if(!dflag)
82
		startup(machine, Rflag, termargs, argv);
83
	notify(notifyf);
84
	getcurwd();
85
	if(argc>0){
86
		for(i=0; i<argc; i++){
87
			if(!setjmp(mainloop)){
88
				t = tmpcstr(argv[i]);
89
				Straddc(t, '\0');
90
				Strduplstr(&genstr, t);
91
				freetmpstr(t);
92
				fixname(&genstr);
93
				logsetname(newfile(), &genstr);
94
			}
95
		}
96
	}else if(!downloaded)
97
		newfile();
98
	seq++;
99
	if(file.nused)
100
		current(file.filepptr[0]);
101
	setjmp(mainloop);
102
	cmdloop();
103
	trytoquit();	/* if we already q'ed, quitok will be TRUE */
104
	exits(0);
105
}
106
 
107
void
108
usage(void)
109
{
110
	dprint("usage: sam [-d] [-t samterm] [-s sam name] -r machine\n");
111
	exits("usage");
112
}
113
 
114
void
115
rescue(void)
116
{
117
	int i, nblank = 0;
118
	File *f;
119
	char *c;
120
	char buf[256];
121
 
122
	if(rescuing++)
123
		return;
124
	io = -1;
125
	for(i=0; i<file.nused; i++){
126
		f = file.filepptr[i];
127
		if(f==cmd || f->nc==0 || !fileisdirty(f))
128
			continue;
129
		if(io == -1){
130
			sprint(buf, "%s/sam.save", home);
131
			io = create(buf, 1, 0777);
132
			if(io<0)
133
				return;
134
		}
135
		if(f->name.s[0]){
136
			c = Strtoc(&f->name);
137
			strncpy(buf, c, sizeof buf-1);
138
			buf[sizeof buf-1] = 0;
139
			free(c);
140
		}else
141
			sprint(buf, "nameless.%d", nblank++);
142
		fprint(io, "#!%s '%s' $* <<'---%s'\n", SAMSAVECMD, buf, buf);
143
		addr.r.p1 = 0, addr.r.p2 = f->nc;
144
		writeio(f);
145
		fprint(io, "\n---%s\n", (char *)buf);
146
	}
147
}
148
 
149
void
150
panic(char *s)
151
{
152
	int wasd;
153
 
154
	if(!panicking++ && !setjmp(mainloop)){
155
		wasd = downloaded;
156
		downloaded = 0;
157
		dprint("sam: panic: %s: %r\n", s);
158
		if(wasd)
159
			fprint(2, "sam: panic: %s: %r\n", s);
160
		rescue();
161
		abort();
162
	}
163
}
164
 
165
void
166
hiccough(char *s)
167
{
168
	File *f;
169
	int i;
170
 
171
	if(rescuing)
172
		exits("rescue");
173
	if(s)
174
		dprint("%s\n", s);
175
	resetcmd();
176
	resetxec();
177
	resetsys();
178
	if(io > 0)
179
		close(io);
180
 
181
	/*
182
	 * back out any logged changes & restore old sequences
183
	 */
184
	for(i=0; i<file.nused; i++){
185
		f = file.filepptr[i];
186
		if(f==cmd)
187
			continue;
188
		if(f->seq==seq){
189
			bufdelete(&f->epsilon, 0, f->epsilon.nc);
190
			f->seq = f->prevseq;
191
			f->dot.r = f->prevdot;
192
			f->mark = f->prevmark;
193
			state(f, f->prevmod ? Dirty: Clean);
194
		}
195
	}
196
 
197
	update();
198
	if (curfile) {
199
		if (curfile->unread)
200
			curfile->unread = FALSE;
201
		else if (downloaded)
202
			outTs(Hcurrent, curfile->tag);
203
	}
204
	longjmp(mainloop, 1);
205
}
206
 
207
void
208
intr(void)
209
{
210
	error(Eintr);
211
}
212
 
213
void
214
trytoclose(File *f)
215
{
216
	char *t;
217
	char buf[256];
218
 
219
	if(f == cmd)	/* possible? */
220
		return;
221
	if(f->deleted)
222
		return;
223
	if(fileisdirty(f) && !f->closeok){
224
		f->closeok = TRUE;
225
		if(f->name.s[0]){
226
			t = Strtoc(&f->name);
227
			strncpy(buf, t, sizeof buf-1);
228
			free(t);
229
		}else
230
			strcpy(buf, "nameless file");
231
		error_s(Emodified, buf);
232
	}
233
	f->deleted = TRUE;
234
}
235
 
236
void
237
trytoquit(void)
238
{
239
	int c;
240
	File *f;
241
 
242
	if(!quitok){
243
		for(c = 0; c<file.nused; c++){
244
			f = file.filepptr[c];
245
			if(f!=cmd && fileisdirty(f)){
246
				quitok = TRUE;
247
				eof = FALSE;
248
				error(Echanges);
249
			}
250
		}
251
	}
252
}
253
 
254
void
255
load(File *f)
256
{
257
	Address saveaddr;
258
 
259
	Strduplstr(&genstr, &f->name);
260
	filename(f);
261
	if(f->name.s[0]){
262
		saveaddr = addr;
263
		edit(f, 'I');
264
		addr = saveaddr;
265
	}else{
266
		f->unread = 0;
267
		f->cleanseq = f->seq;
268
	}
269
 
270
	fileupdate(f, TRUE, TRUE);
271
}
272
 
273
void
274
cmdupdate(void)
275
{
276
	if(cmd && cmd->seq!=0){
277
		fileupdate(cmd, FALSE, downloaded);
278
		cmd->dot.r.p1 = cmd->dot.r.p2 = cmd->nc;
279
		telldot(cmd);
280
	}
281
}
282
 
283
void
284
delete(File *f)
285
{
286
	if(downloaded && f->rasp)
287
		outTs(Hclose, f->tag);
288
	delfile(f);
289
	if(f == curfile)
290
		current(0);
291
}
292
 
293
void
294
update(void)
295
{
296
	int i, anymod;
297
	File *f;
298
 
299
	settempfile();
300
	for(anymod = i=0; i<tempfile.nused; i++){
301
		f = tempfile.filepptr[i];
302
		if(f==cmd)	/* cmd gets done in main() */
303
			continue;
304
		if(f->deleted) {
305
			delete(f);
306
			continue;
307
		}
308
		if(f->seq==seq && fileupdate(f, FALSE, downloaded))
309
			anymod++;
310
		if(f->rasp)
311
			telldot(f);
312
	}
313
	if(anymod)
314
		seq++;
315
}
316
 
317
File *
318
current(File *f)
319
{
320
	return curfile = f;
321
}
322
 
323
void
324
edit(File *f, int cmd)
325
{
326
	int empty = TRUE;
327
	Posn p;
328
	int nulls;
329
 
330
	if(cmd == 'r')
331
		logdelete(f, addr.r.p1, addr.r.p2);
332
	if(cmd=='e' || cmd=='I'){
333
		logdelete(f, (Posn)0, f->nc);
334
		addr.r.p2 = f->nc;
335
	}else if(f->nc!=0 || (f->name.s[0] && Strcmp(&genstr, &f->name)!=0))
336
		empty = FALSE;
337
	if((io = open(genc, OREAD))<0) {
338
		if (curfile && curfile->unread)
339
			curfile->unread = FALSE;
340
		error_r(Eopen, genc);
341
	}
342
	p = readio(f, &nulls, empty, TRUE);
343
	closeio((cmd=='e' || cmd=='I')? -1 : p);
344
	if(cmd == 'r')
345
		f->ndot.r.p1 = addr.r.p2, f->ndot.r.p2 = addr.r.p2+p;
346
	else
347
		f->ndot.r.p1 = f->ndot.r.p2 = 0;
348
	f->closeok = empty;
349
	if (quitok)
350
		quitok = empty;
351
	else
352
		quitok = FALSE;
353
	state(f, empty && !nulls? Clean : Dirty);
354
	if(empty && !nulls)
355
		f->cleanseq = f->seq;
356
	if(cmd == 'e')
357
		filename(f);
358
}
359
 
360
int
361
getname(File *f, String *s, int save)
362
{
363
	int c, i;
364
 
365
	Strzero(&genstr);
366
	if(genc){
367
		free(genc);
368
		genc = 0;
369
	}
370
	if(s==0 || (c = s->s[0])==0){		/* no name provided */
371
		if(f)
372
			Strduplstr(&genstr, &f->name);
373
		goto Return;
374
	}
375
	if(c!=' ' && c!='\t')
376
		error(Eblank);
377
	for(i=0; (c=s->s[i])==' ' || c=='\t'; i++)
378
		;
379
	while(s->s[i] > ' ')
380
		Straddc(&genstr, s->s[i++]);
381
	if(s->s[i])
382
		error(Enewline);
383
	fixname(&genstr);
384
	if(f && (save || f->name.s[0]==0)){
385
		logsetname(f, &genstr);
386
		if(Strcmp(&f->name, &genstr)){
387
			quitok = f->closeok = FALSE;
388
			f->qidpath = 0;
389
			f->mtime = 0;
390
			state(f, Dirty); /* if it's 'e', fix later */
391
		}
392
	}
393
    Return:
394
	genc = Strtoc(&genstr);
395
	i = genstr.n;
396
	if(i && genstr.s[i-1]==0)
397
		i--;
398
	return i;	/* strlen(name) */
399
}
400
 
401
void
402
filename(File *f)
403
{
404
	if(genc)
405
		free(genc);
406
	genc = Strtoc(&genstr);
407
	dprint("%c%c%c %s\n", " '"[f->mod],
408
		"-+"[f->rasp!=0], " ."[f==curfile], genc);
409
}
410
 
411
void
412
undostep(File *f, int isundo)
413
{
414
	uint p1, p2;
415
	int mod;
416
 
417
	mod = f->mod;
418
	fileundo(f, isundo, 1, &p1, &p2, TRUE);
419
	f->ndot = f->dot;
420
	if(f->mod){
421
		f->closeok = 0;
422
		quitok = 0;
423
	}else
424
		f->closeok = 1;
425
 
426
	if(f->mod != mod){
427
		f->mod = mod;
428
		if(mod)
429
			mod = Clean;
430
		else
431
			mod = Dirty;
432
		state(f, mod);
433
	}
434
}
435
 
436
int
437
undo(int isundo)
438
{
439
	File *f;
440
	int i;
441
	Mod max;
442
 
443
	max = undoseq(curfile, isundo);
444
	if(max == 0)
445
		return 0;
446
	settempfile();
447
	for(i = 0; i<tempfile.nused; i++){
448
		f = tempfile.filepptr[i];
449
		if(f!=cmd && undoseq(f, isundo)==max)
450
			undostep(f, isundo);
451
	}
452
	return 1;
453
}
454
 
455
int
456
readcmd(String *s)
457
{
458
	int retcode;
459
 
460
	if(flist != 0)
461
		fileclose(flist);
462
	flist = fileopen();
463
 
464
	addr.r.p1 = 0, addr.r.p2 = flist->nc;
465
	retcode = plan9(flist, '<', s, FALSE);
466
	fileupdate(flist, FALSE, FALSE);
467
	flist->seq = 0;
468
	if (flist->nc > BLOCKSIZE)
469
		error(Etoolong);
470
	Strzero(&genstr);
471
	Strinsure(&genstr, flist->nc);
472
	bufread(flist, (Posn)0, genbuf, flist->nc);
473
	memmove(genstr.s, genbuf, flist->nc*RUNESIZE);
474
	genstr.n = flist->nc;
475
	Straddc(&genstr, '\0');
476
	return retcode;
477
}
478
 
479
void
480
getcurwd(void)
481
{
482
	String *t;
483
	char buf[256];
484
 
485
	buf[0] = 0;
486
	getwd(buf, sizeof(buf));
487
	t = tmpcstr(buf);
488
	Strduplstr(&curwd, t);
489
	freetmpstr(t);
490
	if(curwd.n == 0)
491
		warn(Wpwd);
492
	else if(curwd.s[curwd.n-1] != '/')
493
		Straddc(&curwd, '/');
494
}
495
 
496
void
497
cd(String *str)
498
{
499
	int i, fd;
500
	char *s;
501
	File *f;
502
	String owd;
503
 
504
	getcurwd();
505
	if(getname((File *)0, str, FALSE))
506
		s = genc;
507
	else
508
		s = home;
509
	if(chdir(s))
510
		syserror("chdir");
511
	fd = open("/dev/wdir", OWRITE);
512
	if(fd > 0)
513
		write(fd, s, strlen(s));
514
	dprint("!\n");
515
	Strinit(&owd);
516
	Strduplstr(&owd, &curwd);
517
	getcurwd();
518
	settempfile();
519
	for(i=0; i<tempfile.nused; i++){
520
		f = tempfile.filepptr[i];
521
		if(f!=cmd && f->name.s[0]!='/' && f->name.s[0]!=0){
522
			Strinsert(&f->name, &owd, (Posn)0);
523
			fixname(&f->name);
524
			sortname(f);
525
		}else if(f != cmd && Strispre(&curwd, &f->name)){
526
			fixname(&f->name);
527
			sortname(f);
528
		}
529
	}
530
	Strclose(&owd);
531
}
532
 
533
int
534
loadflist(String *s)
535
{
536
	int c, i;
537
 
538
	c = s->s[0];
539
	for(i = 0; s->s[i]==' ' || s->s[i]=='\t'; i++)
540
		;
541
	if((c==' ' || c=='\t') && s->s[i]!='\n'){
542
		if(s->s[i]=='<'){
543
			Strdelete(s, 0L, (long)i+1);
544
			readcmd(s);
545
		}else{
546
			Strzero(&genstr);
547
			while((c = s->s[i++]) && c!='\n')
548
				Straddc(&genstr, c);
549
			Straddc(&genstr, '\0');
550
		}
551
	}else{
552
		if(c != '\n')
553
			error(Eblank);
554
		Strdupl(&genstr, empty);
555
	}
556
	if(genc)
557
		free(genc);
558
	genc = Strtoc(&genstr);
559
	return genstr.s[0];
560
}
561
 
562
File *
563
readflist(int readall, int delete)
564
{
565
	Posn i;
566
	int c;
567
	File *f;
568
	String t;
569
 
570
	Strinit(&t);
571
	for(i=0,f=0; f==0 || readall || delete; i++){	/* ++ skips blank */
572
		Strdelete(&genstr, (Posn)0, i);
573
		for(i=0; (c = genstr.s[i])==' ' || c=='\t' || c=='\n'; i++)
574
			;
575
		if(i >= genstr.n)
576
			break;
577
		Strdelete(&genstr, (Posn)0, i);
578
		for(i=0; (c=genstr.s[i]) && c!=' ' && c!='\t' && c!='\n'; i++)
579
			;
580
 
581
		if(i == 0)
582
			break;
583
		genstr.s[i] = 0;
584
		Strduplstr(&t, tmprstr(genstr.s, i+1));
585
		fixname(&t);
586
		f = lookfile(&t);
587
		if(delete){
588
			if(f == 0)
589
				warn_S(Wfile, &t);
590
			else
591
				trytoclose(f);
592
		}else if(f==0 && readall)
593
			logsetname(f = newfile(), &t);
594
	}
595
	Strclose(&t);
596
	return f;
597
}
598
 
599
File *
600
tofile(String *s)
601
{
602
	File *f;
603
 
604
	if(s->s[0] != ' ')
605
		error(Eblank);
606
	if(loadflist(s) == 0){
607
		f = lookfile(&genstr);	/* empty string ==> nameless file */
608
		if(f == 0)
609
			error_s(Emenu, genc);
610
	}else if((f=readflist(FALSE, FALSE)) == 0)
611
		error_s(Emenu, genc);
612
	return current(f);
613
}
614
 
615
File *
616
getfile(String *s)
617
{
618
	File *f;
619
 
620
	if(loadflist(s) == 0)
621
		logsetname(f = newfile(), &genstr);
622
	else if((f=readflist(TRUE, FALSE)) == 0)
623
		error(Eblank);
624
	return current(f);
625
}
626
 
627
void
628
closefiles(File *f, String *s)
629
{
630
	if(s->s[0] == 0){
631
		if(f == 0)
632
			error(Enofile);
633
		trytoclose(f);
634
		return;
635
	}
636
	if(s->s[0] != ' ')
637
		error(Eblank);
638
	if(loadflist(s) == 0)
639
		error(Enewline);
640
	readflist(FALSE, TRUE);
641
}
642
 
643
void
644
copy(File *f, Address addr2)
645
{
646
	Posn p;
647
	int ni;
648
	for(p=addr.r.p1; p<addr.r.p2; p+=ni){
649
		ni = addr.r.p2-p;
650
		if(ni > BLOCKSIZE)
651
			ni = BLOCKSIZE;
652
		bufread(f, p, genbuf, ni);
653
		loginsert(addr2.f, addr2.r.p2, tmprstr(genbuf, ni)->s, ni);
654
	}
655
	addr2.f->ndot.r.p2 = addr2.r.p2+(f->dot.r.p2-f->dot.r.p1);
656
	addr2.f->ndot.r.p1 = addr2.r.p2;
657
}
658
 
659
void
660
move(File *f, Address addr2)
661
{
662
	if(addr.r.p2 <= addr2.r.p2){
663
		logdelete(f, addr.r.p1, addr.r.p2);
664
		copy(f, addr2);
665
	}else if(addr.r.p1 >= addr2.r.p2){
666
		copy(f, addr2);
667
		logdelete(f, addr.r.p1, addr.r.p2);
668
	}else
669
		error(Eoverlap);
670
}
671
 
672
Posn
673
nlcount(File *f, Posn p0, Posn p1)
674
{
675
	Posn nl = 0;
676
 
677
	while(p0 < p1)
678
		if(filereadc(f, p0++)=='\n')
679
			nl++;
680
	return nl;
681
}
682
 
683
void
684
printposn(File *f, int charsonly)
685
{
686
	Posn l1, l2;
687
 
688
	if(!charsonly){
689
		l1 = 1+nlcount(f, (Posn)0, addr.r.p1);
690
		l2 = l1+nlcount(f, addr.r.p1, addr.r.p2);
691
		/* check if addr ends with '\n' */
692
		if(addr.r.p2>0 && addr.r.p2>addr.r.p1 && filereadc(f, addr.r.p2-1)=='\n')
693
			--l2;
694
		dprint("%lud", l1);
695
		if(l2 != l1)
696
			dprint(",%lud", l2);
697
		dprint("; ");
698
	}
699
	dprint("#%lud", addr.r.p1);
700
	if(addr.r.p2 != addr.r.p1)
701
		dprint(",#%lud", addr.r.p2);
702
	dprint("\n");
703
}
704
 
705
void
706
settempfile(void)
707
{
708
	if(tempfile.nalloc < file.nused){
709
		if(tempfile.filepptr)
710
			free(tempfile.filepptr);
711
		tempfile.filepptr = emalloc(sizeof(File*)*file.nused);
712
		tempfile.nalloc = file.nused;
713
	}
714
	memmove(tempfile.filepptr, file.filepptr, sizeof(File*)*file.nused);
715
	tempfile.nused = file.nused;
716
}