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