todo
[hband-ld-preload-libs.git] / src / cupsgetpass.c
blobb987950b9a8156f7c05ce870784a2834e2af8d5d
1 #define _GNU_SOURCE
2 #include <stdlib.h>
3 #include <stdio.h>
4 #include <unistd.h>
5 #include <dlfcn.h>
6 #include <string.h>
7 #include <err.h>
8 #include <errno.h>
9 #include <sys/types.h>
10 #include <sys/stat.h>
11 #include <limits.h>
13 #ifndef PASS_MAX
14 #define PASS_MAX 255
15 #endif
17 char *getpass(const char *prompt)
19 char * (*real_getpass)(const char *prompt) = NULL;
20 //warnx("intercepted \"%s\"", prompt);
21 char *env;
22 char *getpass_pwd = NULL;
24 if(real_getpass == NULL)
26 void *handle = dlopen("/lib/i386-linux-gnu/libc.so.6", RTLD_LAZY);
27 if (handle == NULL)
28 errx(1, "dlopen: %s", dlerror());
29 real_getpass = dlsym(handle, "getpass");
30 if (real_getpass == NULL)
31 errx(1, "dlopen: %s", dlerror());
34 env = getenv("CUPS_PASSWORD");
35 if(env != NULL)
37 getpass_pwd = malloc(PASS_MAX);
38 strncpy(getpass_pwd, env, PASS_MAX);
40 else
42 env = getenv("CUPS_ASKPASS");
43 if(env != NULL)
45 int pipe_in[2];
46 int pipe_ex[2];
47 FILE *pipe_in_1;
48 FILE *pipe_ex_0;
49 pid_t pid;
50 int status;
52 pipe(pipe_in);
53 pipe(pipe_ex);
54 pid = fork();
55 if(pid == 0)
57 char *args[3] = {NULL, "stdin", NULL};
58 args[0] = env;
59 close(pipe_in[1]);
60 dup2(pipe_in[0], STDIN_FILENO);
61 close(pipe_ex[0]);
62 dup2(pipe_ex[1], STDOUT_FILENO);
63 exit(execvp(env, args));
65 else if(pid > 0)
67 close(pipe_in[0]);
68 close(pipe_ex[1]);
69 pipe_in_1 = fdopen(pipe_in[1], "w");
70 pipe_ex_0 = fdopen(pipe_ex[0], "r");
72 fprintf(pipe_in_1, "prompt=%s\nanswer=password\n", prompt);
73 fflush(pipe_in_1);
74 close(pipe_in[1]);
76 getpass_pwd = malloc(PASS_MAX);
77 if(fgets(getpass_pwd, PASS_MAX, pipe_ex_0) == NULL)
79 free(getpass_pwd);
80 getpass_pwd = NULL;
82 else if(getpass_pwd[strlen(getpass_pwd)-1] == '\n')
84 getpass_pwd[strlen(getpass_pwd)-1] = '\0';
86 close(pipe_ex[0]);
88 if(waitpid(pid, &status, 0) != -1)
90 if(WEXITSTATUS(status) == 0)
93 else
95 free(getpass_pwd);
96 getpass_pwd = NULL;
97 warnx("%s: %s: exited %d", __FILE__, env, WEXITSTATUS(status));
100 else
102 warn("%s: waitpid", __FILE__);
105 else
107 close(pipe_in[0]);
108 close(pipe_in[1]);
109 close(pipe_ex[0]);
110 close(pipe_ex[1]);
111 warn("%s: fork", __FILE__);
114 else
116 warnx("Neither CUPS_PASSWORD or CUPS_ASKPASS are set.");
117 return real_getpass(prompt);
121 return getpass_pwd;