cdsh.c 2.1 KB

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