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. |