1 /* Copyright (c) 1999 Anthony Towns
2 * Copyright (c) 2000, 2002 Matthias Klose
3 * Copyright (c) 2008 Canonical Ltd
5 * You may freely use, distribute, and modify this program.
8 // Don't rely on /bin/sh and popen!
16 #include <sys/types.h>
19 /* XXX: evil kludge, deal with arbitrary name lengths */
26 int check_predepends(void)
30 switch(child = fork()) {
38 execl( "/usr/bin/dpkg", "/usr/bin/dpkg",
39 "--assert-support-predepends", NULL );
50 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
61 int md5sum_match(char *fn, char* fn_digest)
64 md5_byte_t digest[16];
65 unsigned char hexdigest[33];
68 md5_byte_t buf[BUFSIZE];
70 // if not existant, md5sums don't match
73 if ((fd = open(fn, O_RDONLY)) == -1)
77 while (nbytes = read(fd, buf, BUFSIZE))
78 md5_append(&md5, buf, nbytes);
79 md5_finish(&md5, digest);
82 for (i = j = 0; i < 16; i++) {
84 c = (digest[i] >> 4) & 0xf;
85 c = (c > 9) ? c + 'a' - 10 : c + '0';
87 c = (digest[i] & 0xf);
88 c = (c > 9) ? c + 'a' - 10 : c + '0';
93 fprintf(stderr, "fn=%s, md5sum=%s, expected=%s\n", fn, hexdigest, fn_digest);
95 return !strcmp(fn_digest, hexdigest);
98 int unmodified_file(char *fn, int md5sumc, unsigned char* md5sumv[])
102 // if not existant, pretend its unmodified
103 if (access(fn, R_OK))
105 for (i = 0; i < md5sumc; i++) {
106 if (md5sum_match(fn, md5sumv[i]))
112 unsigned char *md5sumv_bash_profile[] = {
113 "d1a8c44e7dd1bed2f3e75d1343b6e4e1", // dapper, edgy, etch
114 "0bc1802860b758732b862ef973cd79ff", // feisty, gutsy
116 const int md5sumc_bash_profile = sizeof(md5sumv_bash_profile) / sizeof (char *);
118 unsigned char *md5sumv_profile[] = {
119 "7d97942254c076a2ea5ea72180266420", // feisty, gutsy
121 const int md5sumc_profile = sizeof(md5sumv_profile) / sizeof (char *);
124 unsigned char *md5sumv_completion[] = {
125 "2bc0b6cf841eefd31d607e618f1ae29d", // dapper
126 "ae1d298e51ea7f8253eea8b99333561f", // edgy
127 "adc2e9fec28bd2d4a720e725294650f0", // feisty
128 "c8bce25ea68fb0312579a421df99955c", // gutsy, and last one in bash
129 "9da8d1c95748865d516764fb9af82af9", // etch, sid (last one in bash)
131 const int md5sumc_completion = sizeof(md5sumv_completion) / sizeof (char *);
134 char *check_diversion(void)
143 switch(child = fork()) {
153 if (dup2(pipedes[STDOUT_FILENO], STDOUT_FILENO) < 0)
155 close(pipedes[STDIN_FILENO]);
156 close(pipedes[STDOUT_FILENO]);
157 execl( "/usr/sbin/dpkg-divert", "/usr/sbin/dpkg-divert",
158 "--list", "/bin/sh", NULL );
165 static char line[1024];
168 close (pipedes[STDOUT_FILENO]);
169 fcntl (pipedes[STDIN_FILENO], F_SETFD, FD_CLOEXEC);
170 fd = fdopen (pipedes[STDIN_FILENO], "r");
172 while (fgets(line, 1024, fd) != NULL) {
173 line[strlen(line)-1] = '\0';
184 "As bash for Debian is destined to provide a working /bin/sh (pointing to\n"
185 "/bin/bash) your link will be overwritten by a default link.\n\n"
186 "If you don't want further upgrades to overwrite your customization, please\n"
187 "read /usr/share/doc/bash/README.Debian.gz for a more permanent solution.\n\n"
188 "[Press RETURN to continue]";
192 char target[PATH_MAX+1], answer[1024], *fn;
194 fn = "/etc/skel/.bash_profile";
195 if (!access(fn, R_OK)) {
196 if (unmodified_file(fn, md5sumc_bash_profile, md5sumv_bash_profile)) {
197 printf("removing %s in favour of /etc/skel/.profile\n", fn);
201 fn = "/etc/skel/.profile";
202 if (!access(fn, R_OK)) {
203 if (unmodified_file(fn, md5sumc_profile, md5sumv_profile)) {
204 printf("renaming /etc/skel/.bash_profile to %s\n", fn);
205 rename("/etc/skel/.bash_profile", fn);
212 fn = "/etc/bash_completion";
213 if (!access(fn, R_OK)) {
214 if (unmodified_file(fn, md5sumc_completion, md5sumv_completion)) {
215 printf("removing unmodified %s, now in package bash-completion\n", fn);
221 if (check_predepends() != EXIT_SUCCESS) {
222 printf("\nPlease upgrade to a new version of dpkg\n\n");
225 targetlen = readlink("/bin/sh", target, PATH_MAX);
226 if (targetlen == -1) {
227 // error reading link. Will be overwritten.
228 puts("The bash upgrade discovered that something is wrong with your /bin/sh link.");
230 fgets(answer, 1024, stdin);
233 target[targetlen] = '\0';
234 if (strcmp(target, "bash") != 0 && strcmp(target, "/bin/bash") != 0) {
235 char *diversion = check_diversion();
237 if (diversion == NULL)
239 // printf("diversion: /%s/\n", diversion);
240 if (strcmp(diversion, "") != 0)
243 printf("The bash upgrade discovered that your /bin/sh link points to %s.\n", target);
245 fgets(answer, 1024, stdin);