lock.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. /*
  10. * lock - keep a lock alive while a command runs
  11. */
  12. #include <u.h>
  13. #include <libc.h>
  14. #include <ctype.h>
  15. static int debug;
  16. static int lockwait;
  17. void error(char*);
  18. void notifyf(void *c, char*);
  19. static void
  20. usage(void)
  21. {
  22. fprint(2, "usage: %s [-dw] lock [command [file]...]\n", argv0);
  23. exits("usage");
  24. }
  25. static Waitmsg *
  26. waitfor(int pid)
  27. {
  28. char err[ERRMAX];
  29. Waitmsg *w;
  30. for (;;) {
  31. w = wait();
  32. if (w == nil){
  33. errstr(err, sizeof err);
  34. if(strcmp(err, "interrupted") == 0)
  35. continue;
  36. return nil;
  37. }
  38. if (w->pid == pid)
  39. return w;
  40. }
  41. }
  42. static int
  43. openlock(char *lock)
  44. {
  45. int lckfd;
  46. Dir *dir;
  47. /* first ensure that the lock file has the lock bit set */
  48. dir = dirstat(lock);
  49. if (dir == nil)
  50. sysfatal("can't stat %s: %r", lock);
  51. if (!(dir->mode & DMEXCL)) {
  52. dir->mode |= DMEXCL;
  53. dir->qid.type |= QTEXCL;
  54. if (dirwstat(lock, dir) < 0)
  55. sysfatal("can't make %s exclusive access: %r", lock);
  56. }
  57. free(dir);
  58. if (lockwait)
  59. while ((lckfd = open(lock, ORDWR)) < 0)
  60. sleep(1000);
  61. else
  62. lckfd = open(lock, ORDWR);
  63. if (lckfd < 0)
  64. sysfatal("can't open %s read/write: %r", lock);
  65. return lckfd;
  66. }
  67. void
  68. main(int argc, char *argv[])
  69. {
  70. int fd, lckfd, lckpid, cmdpid;
  71. char *cmd, *p, *lock;
  72. char **args;
  73. char *argarr[2];
  74. Waitmsg *w;
  75. ARGBEGIN {
  76. case 'd':
  77. ++debug;
  78. break;
  79. case 'w':
  80. ++lockwait;
  81. break;
  82. default:
  83. usage();
  84. break;
  85. } ARGEND
  86. if (argc < 1)
  87. usage();
  88. if (argc == 1) {
  89. args = argarr;
  90. args[0] = cmd = "rc";
  91. args[1] = nil;
  92. } else {
  93. cmd = argv[1];
  94. args = &argv[1];
  95. }
  96. /* set up lock and process to keep it alive */
  97. lock = argv[0];
  98. lckfd = openlock(lock);
  99. lckpid = fork();
  100. switch(lckpid){
  101. case -1:
  102. error("fork");
  103. case 0:
  104. /* keep lock alive until killed */
  105. for (;;) {
  106. sleep(60*1000);
  107. seek(lckfd, 0, 0);
  108. fprint(lckfd, "\n");
  109. }
  110. }
  111. /* spawn argument command */
  112. cmdpid = rfork(RFFDG|RFREND|RFPROC|RFENVG);
  113. switch(cmdpid){
  114. case -1:
  115. error("fork");
  116. case 0:
  117. fd = create("/env/prompt", OWRITE, 0666);
  118. if (fd >= 0) {
  119. fprint(fd, "%s%% ", lock);
  120. close(fd);
  121. }
  122. exec(cmd, args);
  123. if(cmd[0] != '/' && strncmp(cmd, "./", 2) != 0 &&
  124. strncmp(cmd, "../", 3) != 0)
  125. exec(smprint("/bin/%s", cmd), args);
  126. error(cmd);
  127. }
  128. notify(notifyf);
  129. w = waitfor(cmdpid);
  130. if (w == nil)
  131. error("wait");
  132. postnote(PNPROC, lckpid, "die");
  133. waitfor(lckpid);
  134. if(w->msg[0]){
  135. p = utfrune(w->msg, ':');
  136. if(p && p[1])
  137. p++;
  138. else
  139. p = w->msg;
  140. while (isspace(*p))
  141. p++;
  142. fprint(2, "%s: %s # status=%s\n", argv0, cmd, p);
  143. }
  144. exits(w->msg);
  145. }
  146. void
  147. error(char *s)
  148. {
  149. fprint(2, "%s: %s: %r\n", argv0, s);
  150. exits(s);
  151. }
  152. void
  153. notifyf(void *a, char *s)
  154. {
  155. USED(a);
  156. if(strcmp(s, "interrupt") == 0)
  157. noted(NCONT);
  158. noted(NDFLT);
  159. }