|
Lines 75-80
Link Here
|
| 75 |
#include <sys/wait.h> |
75 |
#include <sys/wait.h> |
| 76 |
#include <termios.h> |
76 |
#include <termios.h> |
| 77 |
#include <net/if.h> |
77 |
#include <net/if.h> |
|
|
78 |
#include <glob.h> |
| 78 |
|
79 |
|
| 79 |
#include "shvar.h" |
80 |
#include "shvar.h" |
| 80 |
#include "alloc.h" |
81 |
#include "alloc.h" |
|
Lines 116-121
Link Here
|
| 116 |
} |
117 |
} |
| 117 |
|
118 |
|
| 118 |
|
119 |
|
|
|
120 |
// Returns pid of pppd (must be /usr/sbin/pppd) process that has |
| 121 |
// "linkname device" in its command line. 0 if not found, -1 on error. |
| 122 |
static int |
| 123 |
get_pppd_pid(char *device) { |
| 124 |
int i; |
| 125 |
glob_t globbuf; |
| 126 |
int ge = glob("/proc/*/cmdline", 0, NULL, &globbuf); |
| 127 |
if (!ge) { |
| 128 |
for (i = 0; i < globbuf.gl_pathc; ++i) { |
| 129 |
FILE *fcmdline; |
| 130 |
char cmdline[1024]; // hope this will be enough |
| 131 |
if (fcmdline = fopen(globbuf.gl_pathv[i], "r")) { |
| 132 |
int num_read; |
| 133 |
num_read = fread(cmdline, 1, 1024, fcmdline); |
| 134 |
if (num_read > 0 && !strcmp(cmdline, "/usr/sbin/pppd")) { |
| 135 |
int prev_linkname = 0; |
| 136 |
char *p = cmdline; |
| 137 |
while (*p && p - cmdline < 1024) { |
| 138 |
if (prev_linkname && !strcmp(p, device)) { |
| 139 |
int retval; |
| 140 |
globbuf.gl_pathv[i][strlen(globbuf.gl_pathv[i])-8] = 0; |
| 141 |
retval = atoi(globbuf.gl_pathv[i]+6); |
| 142 |
globfree(&globbuf); |
| 143 |
fclose(fcmdline); |
| 144 |
return retval; |
| 145 |
} |
| 146 |
prev_linkname = !strcmp(p, "linkname"); |
| 147 |
p += strlen(p) + 1; |
| 148 |
} |
| 149 |
} |
| 150 |
fclose(fcmdline); |
| 151 |
} |
| 152 |
} |
| 153 |
globfree(&globbuf); |
| 154 |
return 0; |
| 155 |
} |
| 156 |
else |
| 157 |
return -1; |
| 158 |
} |
| 159 |
|
| 160 |
// If there exists only one child of specified process, returns its pid. |
| 161 |
// Otherwise (if no children or more than 1) returns 0. -1 on error. |
| 162 |
static int get_only_child(int parent_pid) { |
| 163 |
int i; |
| 164 |
glob_t globbuf; |
| 165 |
int ge = glob("/proc/*/status", 0, NULL, &globbuf); |
| 166 |
if (!ge) { |
| 167 |
int result_pid = 0; |
| 168 |
for (i = 0; i < globbuf.gl_pathc; ++i) { |
| 169 |
FILE *fstatus; |
| 170 |
char status[1024]; // hope this will be enough |
| 171 |
if (fstatus = fopen(globbuf.gl_pathv[i], "r")) { |
| 172 |
int num_read; |
| 173 |
num_read = fread(status, 1, 1023, fstatus); |
| 174 |
if (num_read > 0) { |
| 175 |
char *ppid_pos; |
| 176 |
status[num_read] = 0; |
| 177 |
ppid_pos = strstr(status, "PPid:\t"); |
| 178 |
if (ppid_pos) |
| 179 |
{ |
| 180 |
int cur_ppid = atoi(ppid_pos+6); |
| 181 |
if (cur_ppid == parent_pid) |
| 182 |
{ |
| 183 |
// Heuristics: we look only for those chldren |
| 184 |
// which have non-empty commandline |
| 185 |
char cmdline[256], *p; |
| 186 |
FILE *fcmdline; |
| 187 |
strcpy(cmdline, globbuf.gl_pathv[i]); |
| 188 |
for(p=cmdline+strlen(cmdline); *p!='/' && p>=cmdline; --p); |
| 189 |
++p; |
| 190 |
strcpy(p, "cmdline"); |
| 191 |
if (!(fcmdline = fopen(cmdline, "r")) |
| 192 |
|| !fread(cmdline, 1, 256, fcmdline)) |
| 193 |
{ |
| 194 |
fclose(fstatus); |
| 195 |
continue; |
| 196 |
} |
| 197 |
fclose(fcmdline); |
| 198 |
if (result_pid) |
| 199 |
{ |
| 200 |
globfree(&globbuf); |
| 201 |
fclose(fstatus); |
| 202 |
return 0; |
| 203 |
} |
| 204 |
else |
| 205 |
result_pid = atoi(globbuf.gl_pathv[i]+6); |
| 206 |
} |
| 207 |
} |
| 208 |
} |
| 209 |
fclose(fstatus); |
| 210 |
} |
| 211 |
} |
| 212 |
globfree(&globbuf); |
| 213 |
return result_pid; |
| 214 |
} |
| 215 |
else |
| 216 |
return -1; |
| 217 |
} |
| 119 |
|
218 |
|
| 120 |
static void |
219 |
static void |
| 121 |
detach(int now, int parentExitCode, char *device) { |
220 |
detach(int now, int parentExitCode, char *device) { |
|
Lines 541-546
Link Here
|
| 541 |
sigsuspend(&unblockedsigs); |
640 |
sigsuspend(&unblockedsigs); |
| 542 |
|
641 |
|
| 543 |
if (theSigterm || theSigint) { |
642 |
if (theSigterm || theSigint) { |
|
|
643 |
int proc_pppd_pid, chat_pid, i; |
| 544 |
theSigterm = theSigint = 0; |
644 |
theSigterm = theSigint = 0; |
| 545 |
|
645 |
|
| 546 |
if (dieing) sendsig = SIGKILL; |
646 |
if (dieing) sendsig = SIGKILL; |
|
Lines 550-555
Link Here
|
| 550 |
if (physicalDevice) { free(physicalDevice); physicalDevice = NULL; } |
650 |
if (physicalDevice) { free(physicalDevice); physicalDevice = NULL; } |
| 551 |
physicalDevice = pppLogicalToPhysical(&pppdPid, real_device); |
651 |
physicalDevice = pppLogicalToPhysical(&pppdPid, real_device); |
| 552 |
if (physicalDevice) { free(physicalDevice); physicalDevice = NULL; } |
652 |
if (physicalDevice) { free(physicalDevice); physicalDevice = NULL; } |
|
|
653 |
// We suspect that pppd is running, but haven't created |
| 654 |
// .pid file yet. Keep waiting for .pid file and try |
| 655 |
// to find chat or whatever pppd uses |
| 656 |
// to establish connection. |
| 657 |
for (i=0; !pppdPid && (proc_pppd_pid = get_pppd_pid(device)) |
| 658 |
&& !(chat_pid = get_only_child(proc_pppd_pid)) |
| 659 |
&& i<60000; |
| 660 |
++i) |
| 661 |
{ |
| 662 |
physicalDevice = pppLogicalToPhysical(&pppdPid, real_device); |
| 663 |
if (physicalDevice) { free(physicalDevice); physicalDevice = NULL; } |
| 664 |
usleep(1000); |
| 665 |
} |
| 666 |
if (pppdPid) |
| 667 |
sleep(2); // Else pppd may hangup, seems there's a bug in it |
| 668 |
else |
| 669 |
if (chat_pid) |
| 670 |
{ |
| 671 |
// Found chat or whatever. |
| 672 |
// Let's kill it instead of pppd. |
| 673 |
pppdPid = chat_pid; |
| 674 |
} |
| 553 |
if (!pppdPid) cleanExit(35); |
675 |
if (!pppdPid) cleanExit(35); |
| 554 |
kill(pppdPid, sendsig); |
676 |
kill(pppdPid, sendsig); |
| 555 |
if (sendsig == SIGKILL) { |
677 |
if (sendsig == SIGKILL) { |
|
Lines 617-623
Link Here
|
| 617 |
pppdPid = 0; |
739 |
pppdPid = 0; |
| 618 |
|
740 |
|
| 619 |
if (!WIFEXITED(status)) cleanExit(29); |
741 |
if (!WIFEXITED(status)) cleanExit(29); |
| 620 |
if (dieing) cleanExit(WEXITSTATUS(status)); |
742 |
// We want to know if user terminated dialing, even if it was |
|
|
743 |
// during execution of connect script. |
| 744 |
if (dieing) cleanExit(WEXITSTATUS(status)==8?5:WEXITSTATUS(status)); |
| 621 |
|
745 |
|
| 622 |
/* error conditions from which we do not expect to recover |
746 |
/* error conditions from which we do not expect to recover |
| 623 |
* without user intervention -- do not fill up the logs. |
747 |
* without user intervention -- do not fill up the logs. |