xref: /plan9-contrib/sys/src/cmd/upas/common/libsys.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 #include "common.h"
2 #include <auth.h>
3 #include <ndb.h>
4 
5 /*
6  *  number of predefined fd's
7  */
8 int nsysfile=3;
9 int nofile=128;
10 
11 static char err[ERRLEN];
12 
13 /*
14  *  return the date
15  */
16 extern char *
17 thedate(void)
18 {
19 	static char now[64];
20 	char *cp;
21 
22 	strcpy(now, ctime(time(0)));
23 	cp = strchr(now, '\n');
24 	if(cp)
25 		*cp = 0;
26 	return now;
27 }
28 
29 /*
30  *  return the user id of the current user
31  */
32 extern char *
33 getlog(void)
34 {
35 	static char user[64];
36 	int fd;
37 	int n;
38 
39 	fd = open("/dev/user", 0);
40 	if(fd < 0)
41 		return "Liz.Bimmler";
42 	if((n=read(fd, user, sizeof(user)-1)) <= 0)
43 		strcpy(user, "Liz.Bimmler");
44 	close(fd);
45 	user[n] = 0;
46 	return user;
47 }
48 
49 /*
50  *  return the lock name
51  */
52 static String *
53 lockname(char *path)
54 {
55 	String *lp;
56 	char *cp;
57 
58 	/*
59 	 *  get the name of the lock file
60 	 */
61 	lp = s_new();
62 	cp = strrchr(path, '/');
63 	if(cp){
64 		cp++;
65 		s_nappend(lp, path, cp - path);
66 	} else {
67 
68 		cp = path;
69 	}
70 	s_append(lp, "L.");
71 	s_nappend(lp, cp, NAMELEN-3);
72 
73 	return lp;
74 }
75 
76 /*
77  *  try opening a lock file.  If it doesn't exist try creating it.
78  */
79 static int
80 openlockfile(char *path)
81 {
82 	int fd;
83 	Dir d;
84 
85 	fd = open(path, OWRITE);
86 	if(fd >= 0)
87 		return fd;
88 	if(dirstat(path, &d) < 0){
89 		fd = create(path, OWRITE, CHEXCL|0666);
90 		if(fd >= 0){
91 			if(dirfstat(fd, &d) >= 0){
92 				d.mode |= CHEXCL|0666;
93 				dirfwstat(fd, &d);
94 			}
95 			return fd;
96 		}
97 	}
98 	return -1;
99 }
100 
101 #define LSECS 5*60
102 
103 /*
104  *  Set a lock for a particular file.  The lock is a file in the same directory
105  *  and has L. prepended to the name of the last element of the file name.
106  */
107 extern Lock *
108 lock(char *path)
109 {
110 	Lock *l;
111 	int tries;
112 
113 	l = malloc(sizeof(Lock));
114 	if(l == 0)
115 		return 0;
116 
117 	/*
118 	 *  wait LSECS seconds for it to unlock
119 	 */
120 	l->name = lockname(path);
121 	for(tries = 0; tries < LSECS*2; tries++){
122 		l->fd = openlockfile(s_to_c(l->name));
123 		if(l->fd >= 0)
124 			return l;
125 		sleep(500);	/* wait 1/2 second */
126 	}
127 
128 	s_free(l->name);
129 	free(l);
130 	return 0;
131 }
132 
133 /*
134  *  like lock except don't wait
135  */
136 extern Lock *
137 trylock(char *path)
138 {
139 	Lock *l;
140 
141 	l = malloc(sizeof(Lock));
142 	if(l == 0)
143 		return 0;
144 
145 	l->name = lockname(path);
146 	l->fd = openlockfile(s_to_c(l->name));
147 
148 	if(l->fd < 0){
149 		s_free(l->name);
150 		free(l);
151 		return 0;
152 	}
153 	return l;
154 }
155 
156 extern void
157 unlock(Lock *l)
158 {
159 	if(l == 0)
160 		return;
161 	if(l->name){
162 		s_free(l->name);
163 	}
164 	if(l->fd >= 0)
165 		close(l->fd);
166 	free(l);
167 }
168 
169 /*
170  *  Open a file.  The modes are:
171  *
172  *	l	- locked
173  *	a	- set append permissions
174  *	r	- readable
175  *	w	- writable
176  *	A	- append only (doesn't exist in Bio)
177  */
178 extern Biobuf *
179 sysopen(char *path, char *mode, ulong perm)
180 {
181 	int sysperm;
182 	int sysmode;
183 	int fd;
184 	int docreate;
185 	int append;
186 	Dir d;
187 	Biobuf *bp;
188 
189 	/*
190 	 *  decode the request
191 	 */
192 	sysperm = 0;
193 	sysmode = -1;
194 	docreate = 0;
195 	append = 0;
196  	for(; mode && *mode; mode++)
197 		switch(*mode){
198 		case 'A':
199 			sysmode = OWRITE;
200 			append = 1;
201 			break;
202 		case 'c':
203 			docreate = 1;
204 			break;
205 		case 'l':
206 			sysperm |= CHEXCL;
207 			break;
208 		case 'a':
209 			sysperm |= CHAPPEND;
210 			break;
211 		case 'w':
212 			if(sysmode == -1)
213 				sysmode = OWRITE;
214 			else
215 				sysmode = ORDWR;
216 			break;
217 		case 'r':
218 			if(sysmode == -1)
219 				sysmode = OREAD;
220 			else
221 				sysmode = ORDWR;
222 			break;
223 		default:
224 			break;
225 		}
226 	switch(sysmode){
227 	case OREAD:
228 	case OWRITE:
229 	case ORDWR:
230 		break;
231 	default:
232 		if(sysperm&CHAPPEND)
233 			sysmode = OWRITE;
234 		else
235 			sysmode = OREAD;
236 		break;
237 	}
238 
239 	/*
240 	 *  create file if we need to
241 	 */
242 	fd = open(path, sysmode);
243 	if(fd < 0){
244 		if(dirstat(path, &d) < 0){
245 			if(docreate == 0)
246 				return 0;
247 
248 			fd = create(path, sysmode, sysperm|perm);
249 			if(fd < 0)
250 				return 0;
251 			if(dirfstat(fd, &d) >= 0){
252 				d.mode |= sysperm|perm;
253 				dirfwstat(fd, &d);
254 			}
255 		} else
256 			return 0;
257 	}
258 
259 	bp = (Biobuf*)malloc(sizeof(Biobuf));
260 	if(bp == 0){
261 		close(fd);
262 		return 0;
263 	}
264 	Binit(bp, fd, sysmode);
265 
266 	/*
267 	 *  try opening
268 	 */
269 	if(append)
270 		Bseek(bp, 0, 2);
271 	return bp;
272 }
273 
274 /*
275  *  close the file, etc.
276  */
277 int
278 sysclose(Biobuf *bp)
279 {
280 	int rv;
281 
282 	rv = Bterm(bp);
283 	close(Bfildes(bp));
284 	free(bp);
285 	return rv;
286 }
287 
288 /*
289  *  create a file
290  */
291 int
292 syscreate(char *file, int mode)
293 {
294 	return create(file, ORDWR, mode);
295 }
296 
297 /*
298  *  make a directory
299  */
300 int
301 sysmkdir(char *file, ulong perm)
302 {
303 	int fd;
304 
305 	if((fd = create(file, OREAD, 0x80000000L + perm)) < 0)
306 		return -1;
307 	close(fd);
308 	return 0;
309 }
310 
311 /*
312  *  change the group of a file
313  */
314 int
315 syschgrp(char *file, char *group)
316 {
317 	Dir d;
318 
319 	if(dirstat(file, &d) < 0)
320 		return -1;
321 	strncpy(d.gid, group, sizeof(d.gid));
322 	return dirwstat(file, &d);
323 }
324 
325 /*
326  *  read in the system name
327  */
328 extern char *
329 sysname_read(void)
330 {
331 	static char name[128];
332 	char *cp;
333 
334 	cp = getenv("site");
335 	if(cp == 0)
336 		cp = alt_sysname_read();
337 	if(cp == 0)
338 		cp = "kremvax";
339 	strcpy(name, cp);
340 	return name;
341 }
342 extern char *
343 alt_sysname_read(void)
344 {
345 	static char name[128];
346 	int n, fd;
347 
348 	fd = open("/dev/sysname", OREAD);
349 	if(fd < 0)
350 		return 0;
351 	n = read(fd, name, sizeof(name)-1);
352 	close(fd);
353 	if(n <= 0)
354 		return 0;
355 	name[n] = 0;
356 	return name;
357 }
358 
359 /*
360  *  get domain name
361  */
362 extern char *
363 domainname_read(void)
364 {
365 	static char domain[Ndbvlen];
366 	Ndbtuple *t;
367 
368 	t = csgetval("sys", alt_sysname_read(), "dom", domain);
369 	if(t)
370 		ndbfree(t);
371 	return domain;
372 }
373 
374 /*
375  *  return true if the last error message meant file
376  *  did not exist.
377  */
378 extern int
379 e_nonexistant(void)
380 {
381 	errstr(err);
382 	return strcmp(err, "file does not exist") == 0;
383 }
384 
385 /*
386  *  return true if the last error message meant file
387  *  was locked.
388  */
389 extern int
390 e_locked(void)
391 {
392 	errstr(err);
393 	return strcmp(err, "open/create -- file is locked") == 0;
394 }
395 
396 /*
397  *  return the length of a file
398  */
399 extern ulong
400 sysfilelen(Biobuf *fp)
401 {
402 	Dir	d;
403 
404 	if(dirfstat(Bfildes(fp), &d)<0)
405 		return -1;
406 	return d.length;
407 }
408 
409 /*
410  *  remove a file
411  */
412 extern int
413 sysremove(char *path)
414 {
415 	return remove(path);
416 }
417 
418 /*
419  *  rename a file, fails unless both are in the same directory
420  */
421 extern int
422 sysrename(char *old, char *new)
423 {
424 	Dir d;
425 	char *obase;
426 	char *nbase;
427 
428 	obase = strrchr(old, '/');
429 	nbase = strrchr(new, '/');
430 	if(obase){
431 		if(nbase == 0)
432 			return -1;
433 		if(strncmp(old, new, obase-old) != 0)
434 			return -1;
435 		nbase++;
436 	} else {
437 		if(nbase)
438 			return -1;
439 		nbase = new;
440 	}
441 	if(dirstat(old, &d) < 0)
442 		return -1;
443 	strcpy(d.name, nbase);
444 	return dirwstat(old, &d);
445 }
446 
447 /*
448  *  see if a file exists
449  */
450 extern int
451 sysexist(char *file)
452 {
453 	Dir	d;
454 
455 	return dirstat(file, &d) == 0;
456 }
457 
458 /*
459  *  kill a process
460  */
461 extern int
462 syskill(int pid)
463 {
464 	char name[64];
465 	int fd;
466 
467 	sprint(name, "/proc/%d/note", pid);
468 	fd = open(name, 1);
469 	if(fd < 0)
470 		return -1;
471 	if(write(fd, "die: yankee pig dog\n", sizeof("die: yankee pig dog\n") - 1) <= 0){
472 		close(fd);
473 		return -1;
474 	}
475 	close(fd);
476 	return 0;
477 
478 }
479 
480 /*
481  *  catch a write on a closed pipe
482  */
483 static int *closedflag;
484 static int
485 catchpipe(void *a, char *msg)
486 {
487 	static char *foo = "sys: write on closed pipe";
488 
489 	USED(a);
490 	if(strncmp(msg, foo, strlen(foo)) == 0){
491 		*closedflag = 1;
492 		return 1;
493 	}
494 	return 0;
495 }
496 void
497 pipesig(int *flagp)
498 {
499 	closedflag = flagp;
500 	atnotify(catchpipe, 1);
501 }
502 void
503 pipesigoff(void)
504 {
505 	atnotify(catchpipe, 0);
506 }
507 
508 void
509 exit(int i)
510 {
511 	char buf[32];
512 
513 	if(i == 0)
514 		exits(0);
515 	sprint(buf, "%d", i);
516 	exits(buf);
517 }
518 
519 /*
520  *  New process group.  Divest this process of at least signals associated
521  *  with other processes.  On Plan 9 fork the name space and environment
522  *  variables also.
523  */
524 void
525 newprocgroup(void)
526 {
527 	rfork(RFENVG|RFNAMEG|RFNOTEG);
528 }
529 
530 /*
531  *  become a powerless user
532  */
533 void
534 becomenone(void)
535 {
536 	int fd;
537 
538 	fd = open("#c/user", OWRITE);
539 	if(fd < 0 || write(fd, "none", strlen("none")) < 0)
540 		fprint(2, "can't become none\n");
541 	close(fd);
542 	if(newns("none", 0))
543 		fprint(2, "can't set new namespace\n");
544 }
545 
546 /*
547  *  query the connection server
548  */
549 char*
550 csquery(char *attr, char *val, char *rattr)
551 {
552 	char token[Ndbvlen+4];
553 	char buf[256], *p, *sp;
554 	int fd, n;
555 
556 	fd = open("/net/cs", ORDWR);
557 	if(fd < 0)
558 		return 0;
559 	fprint(fd, "!%s=%s", attr, val);
560 	seek(fd, 0, 0);
561 	snprint(token, sizeof(token), "%s=", rattr);
562 	for(;;){
563 		n = read(fd, buf, sizeof(buf)-1);
564 		if(n <= 0)
565 			break;
566 		buf[n] = 0;
567 		p = strstr(buf, token);
568 		if(p && (p == buf || *(p-1) == 0)){
569 			close(fd);
570 			sp = strchr(p, ' ');
571 			if(sp)
572 				*sp = 0;
573 			p = strchr(p, '=');
574 			if(p == 0)
575 				return 0;
576 			return strdup(p+1);
577 		}
578 	}
579 	close(fd);
580 	return 0;
581 }
582 
583 extern int
584 islikeatty(int fd)
585 {
586 	Dir d;
587 
588 	if(dirfstat(fd, &d) < 0)
589 		return 0;
590 	return strcmp(d.name, "cons") == 0;
591 }
592 
593 extern int
594 holdon(void)
595 {
596 	int fd;
597 
598 	if(!islikeatty(0))
599 		return -1;
600 
601 	fd = open("/dev/consctl", OWRITE);
602 	write(fd, "holdon", 6);
603 
604 	return fd;
605 }
606 
607 extern void
608 holdoff(int fd)
609 {
610 	write(fd, "holdoff", 7);
611 	close(fd);
612 }
613