conswdir.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. /*
  2. * Process in-band messages about window title changes.
  3. * The messages are of the form:
  4. *
  5. * \033];xxx\007
  6. *
  7. * where xxx is the new directory. This format was chosen
  8. * because it changes the label on xterm windows.
  9. */
  10. #include <u.h>
  11. #include <libc.h>
  12. struct {
  13. char *file;
  14. char name[512];
  15. } keep[] = {
  16. { "/dev/label" },
  17. { "/dev/wdir" }
  18. };
  19. char *prog = "/bin/rwd";
  20. void
  21. usage(void)
  22. {
  23. fprint(2, "usage: conswdir [/bin/rwd]\n");
  24. exits("usage");
  25. }
  26. void
  27. save(void)
  28. {
  29. int i, fd;
  30. for(i = 0; i < nelem(keep); i++){
  31. *keep[i].name = 0;
  32. if((fd = open(keep[i].file, OREAD)) != -1){
  33. read(fd, keep[i].name, sizeof(keep[i].name));
  34. close(fd);
  35. }
  36. }
  37. }
  38. void
  39. rest(void)
  40. {
  41. int i, fd;
  42. for(i = 0; i < nelem(keep); i++)
  43. if((fd = open(keep[i].file, OWRITE)) != -1){
  44. write(fd, keep[i].name, strlen(keep[i].name));
  45. close(fd);
  46. }
  47. }
  48. void
  49. setpath(char *s)
  50. {
  51. switch(rfork(RFPROC|RFFDG|RFNOWAIT)){
  52. case 0:
  53. execl(prog, prog, s, nil);
  54. _exits(nil);
  55. }
  56. }
  57. enum
  58. {
  59. None,
  60. Esc,
  61. Brack,
  62. Semi,
  63. Bell,
  64. };
  65. int
  66. process(char *buf, int n, int *pn)
  67. {
  68. char *p;
  69. char path[4096];
  70. int start, state;
  71. start = 0;
  72. state = None;
  73. for(p=buf; p<buf+n; p++){
  74. switch(state){
  75. case None:
  76. if(*p == '\033'){
  77. start = p-buf;
  78. state++;
  79. }
  80. break;
  81. case Esc:
  82. if(*p == ']')
  83. state++;
  84. else
  85. state = None;
  86. break;
  87. case Brack:
  88. if(*p == ';')
  89. state++;
  90. else
  91. state = None;
  92. break;
  93. case Semi:
  94. if(*p == '\007')
  95. state++;
  96. else if((uchar)*p < 040)
  97. state = None;
  98. break;
  99. }
  100. if(state == Bell){
  101. memmove(path, buf+start+3, p - (buf+start+3));
  102. path[p-(buf+start+3)] = 0;
  103. p++;
  104. memmove(buf+start, p, n-(p-buf));
  105. n -= p-(buf+start);
  106. p = buf+start;
  107. p--;
  108. start = 0;
  109. state = None;
  110. setpath(path);
  111. }
  112. }
  113. /* give up if we go too long without seeing the close */
  114. *pn = n;
  115. if(state == None || p-(buf+start) >= 2048)
  116. return (p - buf);
  117. else
  118. return start;
  119. }
  120. static void
  121. catchint(void*, char *msg)
  122. {
  123. if(strstr(msg, "interrupt"))
  124. noted(NCONT);
  125. else if(strstr(msg, "kill"))
  126. noted(NDFLT);
  127. else
  128. noted(NCONT);
  129. }
  130. void
  131. main(int argc, char **argv)
  132. {
  133. char buf[4096];
  134. int n, m;
  135. notify(catchint);
  136. ARGBEGIN{
  137. default:
  138. usage();
  139. }ARGEND
  140. if(argc > 1)
  141. usage();
  142. if(argc == 1)
  143. prog = argv[0];
  144. save();
  145. n = 0;
  146. for(;;){
  147. m = read(0, buf+n, sizeof buf-n);
  148. if(m < 0){
  149. rerrstr(buf, sizeof buf);
  150. if(strstr(buf, "interrupt"))
  151. continue;
  152. break;
  153. }
  154. n += m;
  155. m = process(buf, n, &n);
  156. if(m > 0){
  157. write(1, buf, m);
  158. memmove(buf, buf+m, n-m);
  159. n -= m;
  160. }
  161. }
  162. rest();
  163. exits(nil);
  164. }