cdsh.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  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. * The `cd' shell.
  11. * Just has cd and lc.
  12. */
  13. #include <u.h>
  14. #include <libc.h>
  15. #include <bio.h>
  16. char *pwd;
  17. char *root = "/";
  18. void
  19. usage(void)
  20. {
  21. fprint(2, "usage: cdsh [-r root]\n");
  22. exits("usage");
  23. }
  24. int
  25. system(char *cmd)
  26. {
  27. int pid;
  28. if((pid = fork()) < 0)
  29. return -1;
  30. if(pid == 0) {
  31. dup(2, 1);
  32. execl("/bin/rc", "rc", "-c", cmd, nil);
  33. exits("exec");
  34. }
  35. waitpid();
  36. return 0;
  37. }
  38. int
  39. cd(char *s)
  40. {
  41. char *newpwd;
  42. int l;
  43. if(s[0] == '/') {
  44. cleanname(s);
  45. newpwd = strdup(s);
  46. } else {
  47. l = strlen(pwd)+1+strlen(s)+1+50; /* 50 = crud for unicode mistakes */
  48. newpwd = malloc(l);
  49. snprint(newpwd, l, "%s/%s", pwd, s);
  50. cleanname(newpwd);
  51. assert(newpwd[0] == '/');
  52. }
  53. if(chdir(root) < 0 || (newpwd[1] != '\0' && chdir(newpwd+1) < 0)) {
  54. chdir(root);
  55. chdir(pwd+1);
  56. free(newpwd);
  57. return -1;
  58. } else {
  59. free(pwd);
  60. pwd = newpwd;
  61. return 0;
  62. }
  63. }
  64. void
  65. main(int argc, char **argv)
  66. {
  67. char *p;
  68. Biobuf bin;
  69. char *f[2];
  70. int nf;
  71. ARGBEGIN{
  72. case 'r':
  73. root = ARGF();
  74. if(root == nil)
  75. usage();
  76. if(root[0] != '/') {
  77. fprint(2, "root must be rooted\n");
  78. exits("root");
  79. }
  80. break;
  81. default:
  82. usage();
  83. }ARGEND;
  84. if(argc != 0)
  85. usage();
  86. cleanname(root);
  87. if(cd("/") < 0) {
  88. fprint(2, "cannot cd %s: %r\n", root);
  89. exits("root");
  90. }
  91. Binit(&bin, 0, OREAD);
  92. while(fprint(2, "%s%% ", pwd), (p = Brdline(&bin, '\n'))) {
  93. p[Blinelen(&bin)-1] = '\0';
  94. nf = tokenize(p, f, nelem(f));
  95. if(nf < 1)
  96. continue;
  97. if(strcmp(f[0], "exit") == 0)
  98. break;
  99. if(strcmp(f[0], "lc") == 0) {
  100. if(nf == 1) {
  101. if(system("/bin/lc") < 0)
  102. fprint(2, "lc: %r\n");
  103. } else if(nf == 2) {
  104. if(strpbrk(p, "'`{}^@$#&()|\\;><"))
  105. fprint(2, "no shell characters allowed\n");
  106. else {
  107. p = f[1];
  108. *--p = ' ';
  109. *--p = 'c';
  110. *--p = 'l';
  111. if(system(p) < 0)
  112. fprint(2, "lc: %r\n");
  113. }
  114. }
  115. continue;
  116. }
  117. if(strcmp(f[0], "cd") == 0) {
  118. if(nf < 2)
  119. fprint(2, "usage: cd dir\n");
  120. else if(cd(f[1]) < 0)
  121. fprint(2, "cd: %r\n");
  122. continue;
  123. }
  124. fprint(2, "commands are cd, lc, and exit\n");
  125. }
  126. print("%s\n", pwd);
  127. }