Skip to content

Instantly share code, notes, and snippets.

@hdonnay
Created October 13, 2017 17:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hdonnay/9bb0b598b2461fa518df86c0fe2c2782 to your computer and use it in GitHub Desktop.
Save hdonnay/9bb0b598b2461fa518df86c0fe2c2782 to your computer and use it in GitHub Desktop.
work (nix-shell wrapper)
#define _XOPEN_SOURCE 700
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
extern char **environ;
static char *cfgdirs[] = {
"/.nix-profile/cfg/work/",
"/lib/work/",
NULL,
};
static char *nixdirs[] = {
"/nixpkgs", // First one is tried without the workspace appended.
"/nixpkgs-",
NULL,
};
char *workdir(char *n) {
char *d;
struct stat s;
size_t sz;
d = getenv("WORK_DIR");
if(d != NULL)
return d;
sz = 7 + strlen(getenv("HOME")) + strlen(n);
d = malloc(sz);
snprintf(d, sz,"%s/work/%s", getenv("HOME"), n);
if(stat(d, &s) != 0)
mkdir(d, 0755); // Don't care if this fails.
return d;
}
char *workcfgdir() {
char *d;
int i;
size_t sz;
struct stat s;
d = getenv("WORK_CFG_DIR");
if(d != NULL)
return d;
sz = 24 + strlen(getenv("HOME"));
d = malloc(sz);
strncpy(d, getenv("HOME"), sz);
for(i = 0; cfgdirs[i] != NULL; i++){
strcat(d, cfgdirs[i]);
if(stat(d, &s) == 0){
break;
}
}
if(cfgdirs[i] == NULL){
perror("no config dirs exist");
exit(EXIT_FAILURE);
}
return d;
}
char *nixpath(char *wd, char *n) {
int i;
char *np, d[4096];
struct stat s;
np = malloc(4096);
strcpy(np, getenv("NIX_PATH"));
for(i = 0; nixdirs[i] != NULL; i++, d[0] = '\0'){
strcat(d, wd);
strcat(d, nixdirs[i]);
if(i != 0)
strcat(d, n);
if(stat(d, &s) == 0){
strcat(np, ":");
strcat(np, n);
strcat(np, "=");
strcat(np, d);
break;
}
}
strcat(np, ":ssh-config-file=/dev/null:ssh-auth-sock=/dev/null");
return np;
}
int main(int argc, char *argv[]) {
char *wd, *wcd, *np;
if(argc != 2){
fprintf(stderr, "specify work directory\n");
exit(EXIT_FAILURE);
}
wd = workdir(argv[1]);
if(setenv("WORK_DIR", wd, 1) != 0){
perror("unable to set environment");
exit(EXIT_FAILURE);
}
printf("# work dir: %s\n", wd);
wcd = workcfgdir();
if(setenv("WORK_CFG_DIR", wcd, 1) != 0){
perror("unable to set environment");
exit(EXIT_FAILURE);
}
printf("# config dir: %s\n", wcd);
np = nixpath(wd, argv[1]);
if(setenv("NIX_PATH", np, 1) != 0){
perror("unable to set environment");
exit(EXIT_FAILURE);
}
printf("# using NIX_PATH: %s\n", np);
char *sh;
sh = getenv("SHELL");
if(sh == NULL)
sh = "bash";
int sz;
sz = 5 + strlen(argv[1]) + strlen(wcd);
char nf[sz];
snprintf(nf, sz, "%s%s.nix", wcd, argv[1]);
execlp("nix-shell", "--show-trace", "--command", sh, nf, NULL);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment