contrib/hgsh/hgsh.c
changeset 2602 9cbeef33eaa3
parent 2341 dbbe7f72d15a
child 4419 59ddd43f609f
equal deleted inserted replaced
2601:00fc88b0b256 2602:9cbeef33eaa3
   242     execv(hg_shell, nargv);
   242     execv(hg_shell, nargv);
   243     perror(hg_shell);
   243     perror(hg_shell);
   244     exit(EX_OSFILE);
   244     exit(EX_OSFILE);
   245 }
   245 }
   246 
   246 
       
   247 enum cmdline {
       
   248     hg_init,
       
   249     hg_serve,
       
   250 };
       
   251 
       
   252     
   247 /*
   253 /*
   248  * paranoid wrapper, runs hg executable in server mode.
   254  * paranoid wrapper, runs hg executable in server mode.
   249  */
   255  */
   250 static void serve_data(int argc, char **argv)
   256 static void serve_data(int argc, char **argv)
   251 {
   257 {
   252     char *hg_root = HG_ROOT;
   258     char *hg_root = HG_ROOT;
   253     char *repo, *abspath;
   259     char *repo, *repo_root;
       
   260     enum cmdline cmd;
   254     char *nargv[6];
   261     char *nargv[6];
   255     struct stat st;
   262     struct stat st;
   256     size_t repolen;
   263     size_t repolen;
   257     int i;
   264     int i;
   258 
   265 
   273 
   280 
   274     if (strcmp(argv[1], "-c") != 0) {
   281     if (strcmp(argv[1], "-c") != 0) {
   275         goto badargs;
   282         goto badargs;
   276     }
   283     }
   277 
   284 
   278     if (sscanf(argv[2], "hg -R %as serve --stdio", &repo) != 1) {
   285     if (sscanf(argv[2], "hg init %as", &repo) == 1) {
       
   286 	cmd = hg_init;
       
   287     }
       
   288     else if (sscanf(argv[2], "hg -R %as serve --stdio", &repo) == 1) {
       
   289 	cmd = hg_serve;
       
   290     } else {
   279         goto badargs;
   291         goto badargs;
   280     }
   292     }
   281 
   293 
   282     repolen = repo ? strlen(repo) : 0;
   294     repolen = repo ? strlen(repo) : 0;
   283 
   295 
   284     if (repolen == 0) {
   296     if (repolen == 0) {
   285         goto badargs;
   297         goto badargs;
   286     }
   298     }
   287 
   299 
   288     if (hg_root) {
   300     if (hg_root) {
   289         if (asprintf(&abspath, "%s/%s/.hg/data", hg_root, repo) == -1) {
   301         if (asprintf(&repo_root, "%s/%s/", hg_root, repo) == -1) {
   290             goto badargs;
   302             goto badargs;
   291         }
   303         }
   292 
   304 
   293         /*
   305         /*
   294          * attempt to stop break out from inside the repository tree. could
   306          * attempt to stop break out from inside the repository tree. could
   295          * do something more clever here, because e.g. we could traverse a
   307          * do something more clever here, because e.g. we could traverse a
   296          * symlink that looks safe, but really breaks us out of tree.
   308          * symlink that looks safe, but really breaks us out of tree.
   297          */
   309          */
   298 
   310 
   299         if (strstr(abspath, "/../") != NULL) {
   311         if (strstr(repo_root, "/../") != NULL) {
   300             goto badargs;
   312             goto badargs;
   301         }
   313         }
   302 
   314 
   303         /* verify that we really are looking at valid repo. */
   315 	/* only hg init expects no repo. */
   304 
   316 
   305         if (stat(abspath, &st) == -1) {
   317 	if (cmd != hg_init) {
   306             perror(repo);
   318 	    char *abs_path;
   307             exit(EX_DATAERR);
   319 	    
   308         }
   320 	    if (asprintf(&abs_path, "%s.hg/data", repo_root) == -1) {
       
   321 		goto badargs;
       
   322 	    }
       
   323 
       
   324 	    /* verify that we really are looking at valid repo. */
       
   325 
       
   326 	    if (stat(abs_path, &st) == -1) {
       
   327 		perror(repo);
       
   328 		exit(EX_DATAERR);
       
   329 	    }
       
   330 	}
   309 
   331 
   310         if (chdir(hg_root) == -1) {
   332         if (chdir(hg_root) == -1) {
   311             perror(hg_root);
   333             perror(hg_root);
   312             exit(EX_SOFTWARE);
   334             exit(EX_SOFTWARE);
   313         }
   335         }
   314     }
   336     }
   315 
   337 
   316     i = 0;
   338     i = 0;
   317     nargv[i++] = HG;
   339 
   318     nargv[i++] = "-R";
   340     switch (cmd) {
   319     nargv[i++] = repo;
   341     case hg_serve:
   320     nargv[i++] = "serve";
   342 	nargv[i++] = HG;
   321     nargv[i++] = "--stdio";
   343 	nargv[i++] = "-R";
       
   344 	nargv[i++] = repo;
       
   345 	nargv[i++] = "serve";
       
   346 	nargv[i++] = "--stdio";
       
   347 	break;
       
   348     case hg_init:
       
   349 	nargv[i++] = HG;
       
   350 	nargv[i++] = "init";
       
   351 	nargv[i++] = repo;
       
   352 	break;
       
   353     }
       
   354     
   322     nargv[i] = NULL;
   355     nargv[i] = NULL;
   323 
   356 
   324     if (debug) {
   357     if (debug) {
   325         print_cmdline(i, nargv);
   358         print_cmdline(i, nargv);
   326     }
   359     }