Show More
@@ -84,8 +84,9 b' static void initcontext(context_t *ctx)' | |||||
84 |
|
84 | |||
85 | static void enlargecontext(context_t *ctx, size_t newsize) |
|
85 | static void enlargecontext(context_t *ctx, size_t newsize) | |
86 | { |
|
86 | { | |
87 | if (newsize <= ctx->maxdatasize) |
|
87 | if (newsize <= ctx->maxdatasize) { | |
88 | return; |
|
88 | return; | |
|
89 | } | |||
89 |
|
90 | |||
90 | newsize = defaultdatasize * |
|
91 | newsize = defaultdatasize * | |
91 | ((newsize + defaultdatasize - 1) / defaultdatasize); |
|
92 | ((newsize + defaultdatasize - 1) / defaultdatasize); | |
@@ -117,22 +118,25 b' static void readchannel(hgclient_t *hgc)' | |||||
117 |
|
118 | |||
118 | uint32_t datasize_n; |
|
119 | uint32_t datasize_n; | |
119 | rsize = recv(hgc->sockfd, &datasize_n, sizeof(datasize_n), 0); |
|
120 | rsize = recv(hgc->sockfd, &datasize_n, sizeof(datasize_n), 0); | |
120 | if (rsize != sizeof(datasize_n)) |
|
121 | if (rsize != sizeof(datasize_n)) { | |
121 | abortmsg("failed to read data size"); |
|
122 | abortmsg("failed to read data size"); | |
|
123 | } | |||
122 |
|
124 | |||
123 | /* datasize denotes the maximum size to write if input request */ |
|
125 | /* datasize denotes the maximum size to write if input request */ | |
124 | hgc->ctx.datasize = ntohl(datasize_n); |
|
126 | hgc->ctx.datasize = ntohl(datasize_n); | |
125 | enlargecontext(&hgc->ctx, hgc->ctx.datasize); |
|
127 | enlargecontext(&hgc->ctx, hgc->ctx.datasize); | |
126 |
|
128 | |||
127 | if (isupper(hgc->ctx.ch) && hgc->ctx.ch != 'S') |
|
129 | if (isupper(hgc->ctx.ch) && hgc->ctx.ch != 'S') { | |
128 | return; /* assumes input request */ |
|
130 | return; /* assumes input request */ | |
|
131 | } | |||
129 |
|
132 | |||
130 | size_t cursize = 0; |
|
133 | size_t cursize = 0; | |
131 | while (cursize < hgc->ctx.datasize) { |
|
134 | while (cursize < hgc->ctx.datasize) { | |
132 | rsize = recv(hgc->sockfd, hgc->ctx.data + cursize, |
|
135 | rsize = recv(hgc->sockfd, hgc->ctx.data + cursize, | |
133 | hgc->ctx.datasize - cursize, 0); |
|
136 | hgc->ctx.datasize - cursize, 0); | |
134 | if (rsize < 1) |
|
137 | if (rsize < 1) { | |
135 | abortmsg("failed to read data block"); |
|
138 | abortmsg("failed to read data block"); | |
|
139 | } | |||
136 | cursize += rsize; |
|
140 | cursize += rsize; | |
137 | } |
|
141 | } | |
138 | } |
|
142 | } | |
@@ -143,8 +147,9 b' static void sendall(int sockfd, const vo' | |||||
143 | const char *const endp = p + datasize; |
|
147 | const char *const endp = p + datasize; | |
144 | while (p < endp) { |
|
148 | while (p < endp) { | |
145 | ssize_t r = send(sockfd, p, endp - p, 0); |
|
149 | ssize_t r = send(sockfd, p, endp - p, 0); | |
146 | if (r < 0) |
|
150 | if (r < 0) { | |
147 | abortmsgerrno("cannot communicate"); |
|
151 | abortmsgerrno("cannot communicate"); | |
|
152 | } | |||
148 | p += r; |
|
153 | p += r; | |
149 | } |
|
154 | } | |
150 | } |
|
155 | } | |
@@ -186,8 +191,9 b' static void packcmdargs(context_t *ctx, ' | |||||
186 | ctx->datasize += n; |
|
191 | ctx->datasize += n; | |
187 | } |
|
192 | } | |
188 |
|
193 | |||
189 | if (ctx->datasize > 0) |
|
194 | if (ctx->datasize > 0) { | |
190 | --ctx->datasize; /* strip last '\0' */ |
|
195 | --ctx->datasize; /* strip last '\0' */ | |
|
196 | } | |||
191 | } |
|
197 | } | |
192 |
|
198 | |||
193 | /* Extract '\0'-separated list of args to new buffer, terminated by NULL */ |
|
199 | /* Extract '\0'-separated list of args to new buffer, terminated by NULL */ | |
@@ -205,8 +211,9 b' static const char **unpackcmdargsnul(con' | |||||
205 | args[nargs] = s; |
|
211 | args[nargs] = s; | |
206 | nargs++; |
|
212 | nargs++; | |
207 | s = memchr(s, '\0', e - s); |
|
213 | s = memchr(s, '\0', e - s); | |
208 | if (!s) |
|
214 | if (!s) { | |
209 | break; |
|
215 | break; | |
|
216 | } | |||
210 | s++; |
|
217 | s++; | |
211 | } |
|
218 | } | |
212 | args[nargs] = NULL; |
|
219 | args[nargs] = NULL; | |
@@ -225,8 +232,9 b' static void handlereadrequest(hgclient_t' | |||||
225 | static void handlereadlinerequest(hgclient_t *hgc) |
|
232 | static void handlereadlinerequest(hgclient_t *hgc) | |
226 | { |
|
233 | { | |
227 | context_t *ctx = &hgc->ctx; |
|
234 | context_t *ctx = &hgc->ctx; | |
228 | if (!fgets(ctx->data, ctx->datasize, stdin)) |
|
235 | if (!fgets(ctx->data, ctx->datasize, stdin)) { | |
229 | ctx->data[0] = '\0'; |
|
236 | ctx->data[0] = '\0'; | |
|
237 | } | |||
230 | ctx->datasize = strlen(ctx->data); |
|
238 | ctx->datasize = strlen(ctx->data); | |
231 | writeblock(hgc); |
|
239 | writeblock(hgc); | |
232 | } |
|
240 | } | |
@@ -239,8 +247,9 b' static void handlesystemrequest(hgclient' | |||||
239 | ctx->data[ctx->datasize] = '\0'; /* terminate last string */ |
|
247 | ctx->data[ctx->datasize] = '\0'; /* terminate last string */ | |
240 |
|
248 | |||
241 | const char **args = unpackcmdargsnul(ctx); |
|
249 | const char **args = unpackcmdargsnul(ctx); | |
242 | if (!args[0] || !args[1] || !args[2]) |
|
250 | if (!args[0] || !args[1] || !args[2]) { | |
243 | abortmsg("missing type or command or cwd in system request"); |
|
251 | abortmsg("missing type or command or cwd in system request"); | |
|
252 | } | |||
244 | if (strcmp(args[0], "system") == 0) { |
|
253 | if (strcmp(args[0], "system") == 0) { | |
245 | debugmsg("run '%s' at '%s'", args[1], args[2]); |
|
254 | debugmsg("run '%s' at '%s'", args[1], args[2]); | |
246 | int32_t r = runshellcmd(args[1], args + 3, args[2]); |
|
255 | int32_t r = runshellcmd(args[1], args + 3, args[2]); | |
@@ -252,8 +261,9 b' static void handlesystemrequest(hgclient' | |||||
252 | writeblock(hgc); |
|
261 | writeblock(hgc); | |
253 | } else if (strcmp(args[0], "pager") == 0) { |
|
262 | } else if (strcmp(args[0], "pager") == 0) { | |
254 | setuppager(args[1], args + 3); |
|
263 | setuppager(args[1], args + 3); | |
255 | if (hgc->capflags & CAP_ATTACHIO) |
|
264 | if (hgc->capflags & CAP_ATTACHIO) { | |
256 | attachio(hgc); |
|
265 | attachio(hgc); | |
|
266 | } | |||
257 | /* unblock the server */ |
|
267 | /* unblock the server */ | |
258 | static const char emptycmd[] = "\n"; |
|
268 | static const char emptycmd[] = "\n"; | |
259 | sendall(hgc->sockfd, emptycmd, sizeof(emptycmd) - 1); |
|
269 | sendall(hgc->sockfd, emptycmd, sizeof(emptycmd) - 1); | |
@@ -296,9 +306,10 b' static void handleresponse(hgclient_t *h' | |||||
296 | handlesystemrequest(hgc); |
|
306 | handlesystemrequest(hgc); | |
297 | break; |
|
307 | break; | |
298 | default: |
|
308 | default: | |
299 | if (isupper(ctx->ch)) |
|
309 | if (isupper(ctx->ch)) { | |
300 | abortmsg("cannot handle response (ch = %c)", |
|
310 | abortmsg("cannot handle response (ch = %c)", | |
301 | ctx->ch); |
|
311 | ctx->ch); | |
|
312 | } | |||
302 | } |
|
313 | } | |
303 | } |
|
314 | } | |
304 | } |
|
315 | } | |
@@ -308,8 +319,9 b' static unsigned int parsecapabilities(co' | |||||
308 | unsigned int flags = 0; |
|
319 | unsigned int flags = 0; | |
309 | while (s < e) { |
|
320 | while (s < e) { | |
310 | const char *t = strchr(s, ' '); |
|
321 | const char *t = strchr(s, ' '); | |
311 | if (!t || t > e) |
|
322 | if (!t || t > e) { | |
312 | t = e; |
|
323 | t = e; | |
|
324 | } | |||
313 | const cappair_t *cap; |
|
325 | const cappair_t *cap; | |
314 | for (cap = captable; cap->flag; ++cap) { |
|
326 | for (cap = captable; cap->flag; ++cap) { | |
315 | size_t n = t - s; |
|
327 | size_t n = t - s; | |
@@ -346,11 +358,13 b' static void readhello(hgclient_t *hgc)' | |||||
346 | const char *const dataend = ctx->data + ctx->datasize; |
|
358 | const char *const dataend = ctx->data + ctx->datasize; | |
347 | while (s < dataend) { |
|
359 | while (s < dataend) { | |
348 | const char *t = strchr(s, ':'); |
|
360 | const char *t = strchr(s, ':'); | |
349 | if (!t || t[1] != ' ') |
|
361 | if (!t || t[1] != ' ') { | |
350 | break; |
|
362 | break; | |
|
363 | } | |||
351 | const char *u = strchr(t + 2, '\n'); |
|
364 | const char *u = strchr(t + 2, '\n'); | |
352 | if (!u) |
|
365 | if (!u) { | |
353 | u = dataend; |
|
366 | u = dataend; | |
|
367 | } | |||
354 | if (strncmp(s, "capabilities:", t - s + 1) == 0) { |
|
368 | if (strncmp(s, "capabilities:", t - s + 1) == 0) { | |
355 | hgc->capflags = parsecapabilities(t + 2, u); |
|
369 | hgc->capflags = parsecapabilities(t + 2, u); | |
356 | } else if (strncmp(s, "pgid:", t - s + 1) == 0) { |
|
370 | } else if (strncmp(s, "pgid:", t - s + 1) == 0) { | |
@@ -367,8 +381,9 b' static void updateprocname(hgclient_t *h' | |||||
367 | { |
|
381 | { | |
368 | int r = snprintf(hgc->ctx.data, hgc->ctx.maxdatasize, "chg[worker/%d]", |
|
382 | int r = snprintf(hgc->ctx.data, hgc->ctx.maxdatasize, "chg[worker/%d]", | |
369 | (int)getpid()); |
|
383 | (int)getpid()); | |
370 | if (r < 0 || (size_t)r >= hgc->ctx.maxdatasize) |
|
384 | if (r < 0 || (size_t)r >= hgc->ctx.maxdatasize) { | |
371 | abortmsg("insufficient buffer to write procname (r = %d)", r); |
|
385 | abortmsg("insufficient buffer to write procname (r = %d)", r); | |
|
386 | } | |||
372 | hgc->ctx.datasize = (size_t)r; |
|
387 | hgc->ctx.datasize = (size_t)r; | |
373 | writeblockrequest(hgc, "setprocname"); |
|
388 | writeblockrequest(hgc, "setprocname"); | |
374 | } |
|
389 | } | |
@@ -380,8 +395,9 b' static void attachio(hgclient_t *hgc)' | |||||
380 | sendall(hgc->sockfd, chcmd, sizeof(chcmd) - 1); |
|
395 | sendall(hgc->sockfd, chcmd, sizeof(chcmd) - 1); | |
381 | readchannel(hgc); |
|
396 | readchannel(hgc); | |
382 | context_t *ctx = &hgc->ctx; |
|
397 | context_t *ctx = &hgc->ctx; | |
383 | if (ctx->ch != 'I') |
|
398 | if (ctx->ch != 'I') { | |
384 | abortmsg("unexpected response for attachio (ch = %c)", ctx->ch); |
|
399 | abortmsg("unexpected response for attachio (ch = %c)", ctx->ch); | |
|
400 | } | |||
385 |
|
401 | |||
386 | static const int fds[3] = {STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO}; |
|
402 | static const int fds[3] = {STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO}; | |
387 | struct msghdr msgh; |
|
403 | struct msghdr msgh; | |
@@ -399,23 +415,27 b' static void attachio(hgclient_t *hgc)' | |||||
399 | memcpy(CMSG_DATA(cmsg), fds, sizeof(fds)); |
|
415 | memcpy(CMSG_DATA(cmsg), fds, sizeof(fds)); | |
400 | msgh.msg_controllen = cmsg->cmsg_len; |
|
416 | msgh.msg_controllen = cmsg->cmsg_len; | |
401 | ssize_t r = sendmsg(hgc->sockfd, &msgh, 0); |
|
417 | ssize_t r = sendmsg(hgc->sockfd, &msgh, 0); | |
402 | if (r < 0) |
|
418 | if (r < 0) { | |
403 | abortmsgerrno("sendmsg failed"); |
|
419 | abortmsgerrno("sendmsg failed"); | |
|
420 | } | |||
404 |
|
421 | |||
405 | handleresponse(hgc); |
|
422 | handleresponse(hgc); | |
406 | int32_t n; |
|
423 | int32_t n; | |
407 | if (ctx->datasize != sizeof(n)) |
|
424 | if (ctx->datasize != sizeof(n)) { | |
408 | abortmsg("unexpected size of attachio result"); |
|
425 | abortmsg("unexpected size of attachio result"); | |
|
426 | } | |||
409 | memcpy(&n, ctx->data, sizeof(n)); |
|
427 | memcpy(&n, ctx->data, sizeof(n)); | |
410 | n = ntohl(n); |
|
428 | n = ntohl(n); | |
411 | if (n != sizeof(fds) / sizeof(fds[0])) |
|
429 | if (n != sizeof(fds) / sizeof(fds[0])) { | |
412 | abortmsg("failed to send fds (n = %d)", n); |
|
430 | abortmsg("failed to send fds (n = %d)", n); | |
|
431 | } | |||
413 | } |
|
432 | } | |
414 |
|
433 | |||
415 | static void chdirtocwd(hgclient_t *hgc) |
|
434 | static void chdirtocwd(hgclient_t *hgc) | |
416 | { |
|
435 | { | |
417 | if (!getcwd(hgc->ctx.data, hgc->ctx.maxdatasize)) |
|
436 | if (!getcwd(hgc->ctx.data, hgc->ctx.maxdatasize)) { | |
418 | abortmsgerrno("failed to getcwd"); |
|
437 | abortmsgerrno("failed to getcwd"); | |
|
438 | } | |||
419 | hgc->ctx.datasize = strlen(hgc->ctx.data); |
|
439 | hgc->ctx.datasize = strlen(hgc->ctx.data); | |
420 | writeblockrequest(hgc, "chdir"); |
|
440 | writeblockrequest(hgc, "chdir"); | |
421 | } |
|
441 | } | |
@@ -440,8 +460,9 b' static void forwardumask(hgclient_t *hgc' | |||||
440 | hgclient_t *hgc_open(const char *sockname) |
|
460 | hgclient_t *hgc_open(const char *sockname) | |
441 | { |
|
461 | { | |
442 | int fd = socket(AF_UNIX, SOCK_STREAM, 0); |
|
462 | int fd = socket(AF_UNIX, SOCK_STREAM, 0); | |
443 | if (fd < 0) |
|
463 | if (fd < 0) { | |
444 | abortmsgerrno("cannot create socket"); |
|
464 | abortmsgerrno("cannot create socket"); | |
|
465 | } | |||
445 |
|
466 | |||
446 | /* don't keep fd on fork(), so that it can be closed when the parent |
|
467 | /* don't keep fd on fork(), so that it can be closed when the parent | |
447 | * process get terminated. */ |
|
468 | * process get terminated. */ | |
@@ -456,34 +477,39 b' hgclient_t *hgc_open(const char *socknam' | |||||
456 | { |
|
477 | { | |
457 | const char *split = strrchr(sockname, '/'); |
|
478 | const char *split = strrchr(sockname, '/'); | |
458 | if (split && split != sockname) { |
|
479 | if (split && split != sockname) { | |
459 | if (split[1] == '\0') |
|
480 | if (split[1] == '\0') { | |
460 | abortmsg("sockname cannot end with a slash"); |
|
481 | abortmsg("sockname cannot end with a slash"); | |
|
482 | } | |||
461 | size_t len = split - sockname; |
|
483 | size_t len = split - sockname; | |
462 | char sockdir[len + 1]; |
|
484 | char sockdir[len + 1]; | |
463 | memcpy(sockdir, sockname, len); |
|
485 | memcpy(sockdir, sockname, len); | |
464 | sockdir[len] = '\0'; |
|
486 | sockdir[len] = '\0'; | |
465 |
|
487 | |||
466 | bakfd = open(".", O_DIRECTORY); |
|
488 | bakfd = open(".", O_DIRECTORY); | |
467 | if (bakfd == -1) |
|
489 | if (bakfd == -1) { | |
468 | abortmsgerrno("cannot open cwd"); |
|
490 | abortmsgerrno("cannot open cwd"); | |
|
491 | } | |||
469 |
|
492 | |||
470 | int r = chdir(sockdir); |
|
493 | int r = chdir(sockdir); | |
471 | if (r != 0) |
|
494 | if (r != 0) { | |
472 | abortmsgerrno("cannot chdir %s", sockdir); |
|
495 | abortmsgerrno("cannot chdir %s", sockdir); | |
|
496 | } | |||
473 |
|
497 | |||
474 | basename = split + 1; |
|
498 | basename = split + 1; | |
475 | } |
|
499 | } | |
476 | } |
|
500 | } | |
477 | if (strlen(basename) >= sizeof(addr.sun_path)) |
|
501 | if (strlen(basename) >= sizeof(addr.sun_path)) { | |
478 | abortmsg("sockname is too long: %s", basename); |
|
502 | abortmsg("sockname is too long: %s", basename); | |
|
503 | } | |||
479 | strncpy(addr.sun_path, basename, sizeof(addr.sun_path)); |
|
504 | strncpy(addr.sun_path, basename, sizeof(addr.sun_path)); | |
480 | addr.sun_path[sizeof(addr.sun_path) - 1] = '\0'; |
|
505 | addr.sun_path[sizeof(addr.sun_path) - 1] = '\0'; | |
481 |
|
506 | |||
482 | /* real connect */ |
|
507 | /* real connect */ | |
483 | int r = connect(fd, (struct sockaddr *)&addr, sizeof(addr)); |
|
508 | int r = connect(fd, (struct sockaddr *)&addr, sizeof(addr)); | |
484 | if (r < 0) { |
|
509 | if (r < 0) { | |
485 | if (errno != ENOENT && errno != ECONNREFUSED) |
|
510 | if (errno != ENOENT && errno != ECONNREFUSED) { | |
486 | abortmsgerrno("cannot connect to %s", sockname); |
|
511 | abortmsgerrno("cannot connect to %s", sockname); | |
|
512 | } | |||
487 | } |
|
513 | } | |
488 | if (bakfd != -1) { |
|
514 | if (bakfd != -1) { | |
489 | fchdirx(bakfd); |
|
515 | fchdirx(bakfd); | |
@@ -501,16 +527,21 b' hgclient_t *hgc_open(const char *socknam' | |||||
501 | initcontext(&hgc->ctx); |
|
527 | initcontext(&hgc->ctx); | |
502 |
|
528 | |||
503 | readhello(hgc); |
|
529 | readhello(hgc); | |
504 | if (!(hgc->capflags & CAP_RUNCOMMAND)) |
|
530 | if (!(hgc->capflags & CAP_RUNCOMMAND)) { | |
505 | abortmsg("insufficient capability: runcommand"); |
|
531 | abortmsg("insufficient capability: runcommand"); | |
506 | if (hgc->capflags & CAP_SETPROCNAME) |
|
532 | } | |
|
533 | if (hgc->capflags & CAP_SETPROCNAME) { | |||
507 | updateprocname(hgc); |
|
534 | updateprocname(hgc); | |
508 | if (hgc->capflags & CAP_ATTACHIO) |
|
535 | } | |
|
536 | if (hgc->capflags & CAP_ATTACHIO) { | |||
509 | attachio(hgc); |
|
537 | attachio(hgc); | |
510 | if (hgc->capflags & CAP_CHDIR) |
|
538 | } | |
|
539 | if (hgc->capflags & CAP_CHDIR) { | |||
511 | chdirtocwd(hgc); |
|
540 | chdirtocwd(hgc); | |
512 | if (hgc->capflags & CAP_SETUMASK2) |
|
541 | } | |
|
542 | if (hgc->capflags & CAP_SETUMASK2) { | |||
513 | forwardumask(hgc); |
|
543 | forwardumask(hgc); | |
|
544 | } | |||
514 |
|
545 | |||
515 | return hgc; |
|
546 | return hgc; | |
516 | } |
|
547 | } | |
@@ -555,16 +586,18 b' const char **hgc_validate(hgclient_t *hg' | |||||
555 | size_t argsize) |
|
586 | size_t argsize) | |
556 | { |
|
587 | { | |
557 | assert(hgc); |
|
588 | assert(hgc); | |
558 | if (!(hgc->capflags & CAP_VALIDATE)) |
|
589 | if (!(hgc->capflags & CAP_VALIDATE)) { | |
559 | return NULL; |
|
590 | return NULL; | |
|
591 | } | |||
560 |
|
592 | |||
561 | packcmdargs(&hgc->ctx, args, argsize); |
|
593 | packcmdargs(&hgc->ctx, args, argsize); | |
562 | writeblockrequest(hgc, "validate"); |
|
594 | writeblockrequest(hgc, "validate"); | |
563 | handleresponse(hgc); |
|
595 | handleresponse(hgc); | |
564 |
|
596 | |||
565 | /* the server returns '\0' if it can handle our request */ |
|
597 | /* the server returns '\0' if it can handle our request */ | |
566 | if (hgc->ctx.datasize <= 1) |
|
598 | if (hgc->ctx.datasize <= 1) { | |
567 | return NULL; |
|
599 | return NULL; | |
|
600 | } | |||
568 |
|
601 | |||
569 | /* make sure the buffer is '\0' terminated */ |
|
602 | /* make sure the buffer is '\0' terminated */ | |
570 | enlargecontext(&hgc->ctx, hgc->ctx.datasize + 1); |
|
603 | enlargecontext(&hgc->ctx, hgc->ctx.datasize + 1); | |
@@ -599,8 +632,9 b' int hgc_runcommand(hgclient_t *hgc, cons' | |||||
599 | void hgc_attachio(hgclient_t *hgc) |
|
632 | void hgc_attachio(hgclient_t *hgc) | |
600 | { |
|
633 | { | |
601 | assert(hgc); |
|
634 | assert(hgc); | |
602 | if (!(hgc->capflags & CAP_ATTACHIO)) |
|
635 | if (!(hgc->capflags & CAP_ATTACHIO)) { | |
603 | return; |
|
636 | return; | |
|
637 | } | |||
604 | attachio(hgc); |
|
638 | attachio(hgc); | |
605 | } |
|
639 | } | |
606 |
|
640 | |||
@@ -613,8 +647,9 b' void hgc_attachio(hgclient_t *hgc)' | |||||
613 | void hgc_setenv(hgclient_t *hgc, const char *const envp[]) |
|
647 | void hgc_setenv(hgclient_t *hgc, const char *const envp[]) | |
614 | { |
|
648 | { | |
615 | assert(hgc && envp); |
|
649 | assert(hgc && envp); | |
616 | if (!(hgc->capflags & CAP_SETENV)) |
|
650 | if (!(hgc->capflags & CAP_SETENV)) { | |
617 | return; |
|
651 | return; | |
|
652 | } | |||
618 | packcmdargs(&hgc->ctx, envp, /*argsize*/ -1); |
|
653 | packcmdargs(&hgc->ctx, envp, /*argsize*/ -1); | |
619 | writeblockrequest(hgc, "setenv"); |
|
654 | writeblockrequest(hgc, "setenv"); | |
620 | } |
|
655 | } |
@@ -25,8 +25,9 b' static pid_t peerpid = 0;' | |||||
25 | static void forwardsignal(int sig) |
|
25 | static void forwardsignal(int sig) | |
26 | { |
|
26 | { | |
27 | assert(peerpid > 0); |
|
27 | assert(peerpid > 0); | |
28 | if (kill(peerpid, sig) < 0) |
|
28 | if (kill(peerpid, sig) < 0) { | |
29 | abortmsgerrno("cannot kill %d", peerpid); |
|
29 | abortmsgerrno("cannot kill %d", peerpid); | |
|
30 | } | |||
30 | debugmsg("forward signal %d", sig); |
|
31 | debugmsg("forward signal %d", sig); | |
31 | } |
|
32 | } | |
32 |
|
33 | |||
@@ -34,8 +35,9 b' static void forwardsignaltogroup(int sig' | |||||
34 | { |
|
35 | { | |
35 | /* prefer kill(-pgid, sig), fallback to pid if pgid is invalid */ |
|
36 | /* prefer kill(-pgid, sig), fallback to pid if pgid is invalid */ | |
36 | pid_t killpid = peerpgid > 1 ? -peerpgid : peerpid; |
|
37 | pid_t killpid = peerpgid > 1 ? -peerpgid : peerpid; | |
37 | if (kill(killpid, sig) < 0) |
|
38 | if (kill(killpid, sig) < 0) { | |
38 | abortmsgerrno("cannot kill %d", killpid); |
|
39 | abortmsgerrno("cannot kill %d", killpid); | |
|
40 | } | |||
39 | debugmsg("forward signal %d to %d", sig, killpid); |
|
41 | debugmsg("forward signal %d to %d", sig, killpid); | |
40 | } |
|
42 | } | |
41 |
|
43 | |||
@@ -43,28 +45,36 b' static void handlestopsignal(int sig)' | |||||
43 | { |
|
45 | { | |
44 | sigset_t unblockset, oldset; |
|
46 | sigset_t unblockset, oldset; | |
45 | struct sigaction sa, oldsa; |
|
47 | struct sigaction sa, oldsa; | |
46 | if (sigemptyset(&unblockset) < 0) |
|
48 | if (sigemptyset(&unblockset) < 0) { | |
47 | goto error; |
|
49 | goto error; | |
48 | if (sigaddset(&unblockset, sig) < 0) |
|
50 | } | |
|
51 | if (sigaddset(&unblockset, sig) < 0) { | |||
49 | goto error; |
|
52 | goto error; | |
|
53 | } | |||
50 | memset(&sa, 0, sizeof(sa)); |
|
54 | memset(&sa, 0, sizeof(sa)); | |
51 | sa.sa_handler = SIG_DFL; |
|
55 | sa.sa_handler = SIG_DFL; | |
52 | sa.sa_flags = SA_RESTART; |
|
56 | sa.sa_flags = SA_RESTART; | |
53 | if (sigemptyset(&sa.sa_mask) < 0) |
|
57 | if (sigemptyset(&sa.sa_mask) < 0) { | |
54 | goto error; |
|
58 | goto error; | |
|
59 | } | |||
55 |
|
60 | |||
56 | forwardsignal(sig); |
|
61 | forwardsignal(sig); | |
57 | if (raise(sig) < 0) /* resend to self */ |
|
62 | if (raise(sig) < 0) { /* resend to self */ | |
58 | goto error; |
|
63 | goto error; | |
59 | if (sigaction(sig, &sa, &oldsa) < 0) |
|
64 | } | |
|
65 | if (sigaction(sig, &sa, &oldsa) < 0) { | |||
60 | goto error; |
|
66 | goto error; | |
61 | if (sigprocmask(SIG_UNBLOCK, &unblockset, &oldset) < 0) |
|
67 | } | |
|
68 | if (sigprocmask(SIG_UNBLOCK, &unblockset, &oldset) < 0) { | |||
62 | goto error; |
|
69 | goto error; | |
|
70 | } | |||
63 | /* resent signal will be handled before sigprocmask() returns */ |
|
71 | /* resent signal will be handled before sigprocmask() returns */ | |
64 | if (sigprocmask(SIG_SETMASK, &oldset, NULL) < 0) |
|
72 | if (sigprocmask(SIG_SETMASK, &oldset, NULL) < 0) { | |
65 | goto error; |
|
73 | goto error; | |
66 | if (sigaction(sig, &oldsa, NULL) < 0) |
|
74 | } | |
|
75 | if (sigaction(sig, &oldsa, NULL) < 0) { | |||
67 | goto error; |
|
76 | goto error; | |
|
77 | } | |||
68 | return; |
|
78 | return; | |
69 |
|
79 | |||
70 | error: |
|
80 | error: | |
@@ -73,19 +83,22 b' error:' | |||||
73 |
|
83 | |||
74 | static void handlechildsignal(int sig UNUSED_) |
|
84 | static void handlechildsignal(int sig UNUSED_) | |
75 | { |
|
85 | { | |
76 | if (peerpid == 0 || pagerpid == 0) |
|
86 | if (peerpid == 0 || pagerpid == 0) { | |
77 | return; |
|
87 | return; | |
|
88 | } | |||
78 | /* if pager exits, notify the server with SIGPIPE immediately. |
|
89 | /* if pager exits, notify the server with SIGPIPE immediately. | |
79 | * otherwise the server won't get SIGPIPE if it does not write |
|
90 | * otherwise the server won't get SIGPIPE if it does not write | |
80 | * anything. (issue5278) */ |
|
91 | * anything. (issue5278) */ | |
81 | if (waitpid(pagerpid, NULL, WNOHANG) == pagerpid) |
|
92 | if (waitpid(pagerpid, NULL, WNOHANG) == pagerpid) { | |
82 | kill(peerpid, SIGPIPE); |
|
93 | kill(peerpid, SIGPIPE); | |
|
94 | } | |||
83 | } |
|
95 | } | |
84 |
|
96 | |||
85 | void setupsignalhandler(pid_t pid, pid_t pgid) |
|
97 | void setupsignalhandler(pid_t pid, pid_t pgid) | |
86 | { |
|
98 | { | |
87 | if (pid <= 0) |
|
99 | if (pid <= 0) { | |
88 | return; |
|
100 | return; | |
|
101 | } | |||
89 | peerpid = pid; |
|
102 | peerpid = pid; | |
90 | peerpgid = (pgid <= 1 ? 0 : pgid); |
|
103 | peerpgid = (pgid <= 1 ? 0 : pgid); | |
91 |
|
104 | |||
@@ -98,42 +111,52 b' void setupsignalhandler(pid_t pid, pid_t' | |||||
98 | * - SIGINT: usually generated by the terminal */ |
|
111 | * - SIGINT: usually generated by the terminal */ | |
99 | sa.sa_handler = forwardsignaltogroup; |
|
112 | sa.sa_handler = forwardsignaltogroup; | |
100 | sa.sa_flags = SA_RESTART; |
|
113 | sa.sa_flags = SA_RESTART; | |
101 | if (sigemptyset(&sa.sa_mask) < 0) |
|
114 | if (sigemptyset(&sa.sa_mask) < 0) { | |
|
115 | goto error; | |||
|
116 | } | |||
|
117 | if (sigaction(SIGHUP, &sa, NULL) < 0) { | |||
102 | goto error; |
|
118 | goto error; | |
103 | if (sigaction(SIGHUP, &sa, NULL) < 0) |
|
119 | } | |
|
120 | if (sigaction(SIGINT, &sa, NULL) < 0) { | |||
104 | goto error; |
|
121 | goto error; | |
105 | if (sigaction(SIGINT, &sa, NULL) < 0) |
|
122 | } | |
106 | goto error; |
|
|||
107 |
|
123 | |||
108 | /* terminate frontend by double SIGTERM in case of server freeze */ |
|
124 | /* terminate frontend by double SIGTERM in case of server freeze */ | |
109 | sa.sa_handler = forwardsignal; |
|
125 | sa.sa_handler = forwardsignal; | |
110 | sa.sa_flags |= SA_RESETHAND; |
|
126 | sa.sa_flags |= SA_RESETHAND; | |
111 | if (sigaction(SIGTERM, &sa, NULL) < 0) |
|
127 | if (sigaction(SIGTERM, &sa, NULL) < 0) { | |
112 | goto error; |
|
128 | goto error; | |
|
129 | } | |||
113 |
|
130 | |||
114 | /* notify the worker about window resize events */ |
|
131 | /* notify the worker about window resize events */ | |
115 | sa.sa_flags = SA_RESTART; |
|
132 | sa.sa_flags = SA_RESTART; | |
116 | if (sigaction(SIGWINCH, &sa, NULL) < 0) |
|
133 | if (sigaction(SIGWINCH, &sa, NULL) < 0) { | |
117 | goto error; |
|
134 | goto error; | |
|
135 | } | |||
118 | /* forward user-defined signals */ |
|
136 | /* forward user-defined signals */ | |
119 | if (sigaction(SIGUSR1, &sa, NULL) < 0) |
|
137 | if (sigaction(SIGUSR1, &sa, NULL) < 0) { | |
120 | goto error; |
|
138 | goto error; | |
121 | if (sigaction(SIGUSR2, &sa, NULL) < 0) |
|
139 | } | |
|
140 | if (sigaction(SIGUSR2, &sa, NULL) < 0) { | |||
122 | goto error; |
|
141 | goto error; | |
|
142 | } | |||
123 | /* propagate job control requests to worker */ |
|
143 | /* propagate job control requests to worker */ | |
124 | sa.sa_handler = forwardsignal; |
|
144 | sa.sa_handler = forwardsignal; | |
125 | sa.sa_flags = SA_RESTART; |
|
145 | sa.sa_flags = SA_RESTART; | |
126 | if (sigaction(SIGCONT, &sa, NULL) < 0) |
|
146 | if (sigaction(SIGCONT, &sa, NULL) < 0) { | |
127 | goto error; |
|
147 | goto error; | |
|
148 | } | |||
128 | sa.sa_handler = handlestopsignal; |
|
149 | sa.sa_handler = handlestopsignal; | |
129 | sa.sa_flags = SA_RESTART; |
|
150 | sa.sa_flags = SA_RESTART; | |
130 | if (sigaction(SIGTSTP, &sa, NULL) < 0) |
|
151 | if (sigaction(SIGTSTP, &sa, NULL) < 0) { | |
131 | goto error; |
|
152 | goto error; | |
|
153 | } | |||
132 | /* get notified when pager exits */ |
|
154 | /* get notified when pager exits */ | |
133 | sa.sa_handler = handlechildsignal; |
|
155 | sa.sa_handler = handlechildsignal; | |
134 | sa.sa_flags = SA_RESTART; |
|
156 | sa.sa_flags = SA_RESTART; | |
135 | if (sigaction(SIGCHLD, &sa, NULL) < 0) |
|
157 | if (sigaction(SIGCHLD, &sa, NULL) < 0) { | |
136 | goto error; |
|
158 | goto error; | |
|
159 | } | |||
137 |
|
160 | |||
138 | return; |
|
161 | return; | |
139 |
|
162 | |||
@@ -147,26 +170,34 b' void restoresignalhandler(void)' | |||||
147 | memset(&sa, 0, sizeof(sa)); |
|
170 | memset(&sa, 0, sizeof(sa)); | |
148 | sa.sa_handler = SIG_DFL; |
|
171 | sa.sa_handler = SIG_DFL; | |
149 | sa.sa_flags = SA_RESTART; |
|
172 | sa.sa_flags = SA_RESTART; | |
150 | if (sigemptyset(&sa.sa_mask) < 0) |
|
173 | if (sigemptyset(&sa.sa_mask) < 0) { | |
151 | goto error; |
|
174 | goto error; | |
|
175 | } | |||
152 |
|
176 | |||
153 | if (sigaction(SIGHUP, &sa, NULL) < 0) |
|
177 | if (sigaction(SIGHUP, &sa, NULL) < 0) { | |
154 | goto error; |
|
178 | goto error; | |
155 | if (sigaction(SIGTERM, &sa, NULL) < 0) |
|
179 | } | |
|
180 | if (sigaction(SIGTERM, &sa, NULL) < 0) { | |||
156 | goto error; |
|
181 | goto error; | |
157 | if (sigaction(SIGWINCH, &sa, NULL) < 0) |
|
182 | } | |
|
183 | if (sigaction(SIGWINCH, &sa, NULL) < 0) { | |||
158 | goto error; |
|
184 | goto error; | |
159 | if (sigaction(SIGCONT, &sa, NULL) < 0) |
|
185 | } | |
|
186 | if (sigaction(SIGCONT, &sa, NULL) < 0) { | |||
160 | goto error; |
|
187 | goto error; | |
161 | if (sigaction(SIGTSTP, &sa, NULL) < 0) |
|
188 | } | |
|
189 | if (sigaction(SIGTSTP, &sa, NULL) < 0) { | |||
162 | goto error; |
|
190 | goto error; | |
163 | if (sigaction(SIGCHLD, &sa, NULL) < 0) |
|
191 | } | |
|
192 | if (sigaction(SIGCHLD, &sa, NULL) < 0) { | |||
164 | goto error; |
|
193 | goto error; | |
|
194 | } | |||
165 |
|
195 | |||
166 | /* ignore Ctrl+C while shutting down to make pager exits cleanly */ |
|
196 | /* ignore Ctrl+C while shutting down to make pager exits cleanly */ | |
167 | sa.sa_handler = SIG_IGN; |
|
197 | sa.sa_handler = SIG_IGN; | |
168 | if (sigaction(SIGINT, &sa, NULL) < 0) |
|
198 | if (sigaction(SIGINT, &sa, NULL) < 0) { | |
169 | goto error; |
|
199 | goto error; | |
|
200 | } | |||
170 |
|
201 | |||
171 | peerpid = 0; |
|
202 | peerpid = 0; | |
172 | return; |
|
203 | return; | |
@@ -180,22 +211,27 b' error:' | |||||
180 | pid_t setuppager(const char *pagercmd, const char *envp[]) |
|
211 | pid_t setuppager(const char *pagercmd, const char *envp[]) | |
181 | { |
|
212 | { | |
182 | assert(pagerpid == 0); |
|
213 | assert(pagerpid == 0); | |
183 | if (!pagercmd) |
|
214 | if (!pagercmd) { | |
184 | return 0; |
|
215 | return 0; | |
|
216 | } | |||
185 |
|
217 | |||
186 | int pipefds[2]; |
|
218 | int pipefds[2]; | |
187 | if (pipe(pipefds) < 0) |
|
219 | if (pipe(pipefds) < 0) { | |
188 | return 0; |
|
220 | return 0; | |
|
221 | } | |||
189 | pid_t pid = fork(); |
|
222 | pid_t pid = fork(); | |
190 | if (pid < 0) |
|
223 | if (pid < 0) { | |
191 | goto error; |
|
224 | goto error; | |
|
225 | } | |||
192 | if (pid > 0) { |
|
226 | if (pid > 0) { | |
193 | close(pipefds[0]); |
|
227 | close(pipefds[0]); | |
194 | if (dup2(pipefds[1], fileno(stdout)) < 0) |
|
228 | if (dup2(pipefds[1], fileno(stdout)) < 0) { | |
195 | goto error; |
|
229 | goto error; | |
|
230 | } | |||
196 | if (isatty(fileno(stderr))) { |
|
231 | if (isatty(fileno(stderr))) { | |
197 | if (dup2(pipefds[1], fileno(stderr)) < 0) |
|
232 | if (dup2(pipefds[1], fileno(stderr)) < 0) { | |
198 | goto error; |
|
233 | goto error; | |
|
234 | } | |||
199 | } |
|
235 | } | |
200 | close(pipefds[1]); |
|
236 | close(pipefds[1]); | |
201 | pagerpid = pid; |
|
237 | pagerpid = pid; | |
@@ -222,16 +258,18 b' error:' | |||||
222 |
|
258 | |||
223 | void waitpager(void) |
|
259 | void waitpager(void) | |
224 | { |
|
260 | { | |
225 | if (pagerpid == 0) |
|
261 | if (pagerpid == 0) { | |
226 | return; |
|
262 | return; | |
|
263 | } | |||
227 |
|
264 | |||
228 | /* close output streams to notify the pager its input ends */ |
|
265 | /* close output streams to notify the pager its input ends */ | |
229 | fclose(stdout); |
|
266 | fclose(stdout); | |
230 | fclose(stderr); |
|
267 | fclose(stderr); | |
231 | while (1) { |
|
268 | while (1) { | |
232 | pid_t ret = waitpid(pagerpid, NULL, 0); |
|
269 | pid_t ret = waitpid(pagerpid, NULL, 0); | |
233 | if (ret == -1 && errno == EINTR) |
|
270 | if (ret == -1 && errno == EINTR) { | |
234 | continue; |
|
271 | continue; | |
|
272 | } | |||
235 | break; |
|
273 | break; | |
236 | } |
|
274 | } | |
237 | } |
|
275 | } |
@@ -25,8 +25,9 b' static int colorenabled = 0;' | |||||
25 |
|
25 | |||
26 | static inline void fsetcolor(FILE *fp, const char *code) |
|
26 | static inline void fsetcolor(FILE *fp, const char *code) | |
27 | { |
|
27 | { | |
28 | if (!colorenabled) |
|
28 | if (!colorenabled) { | |
29 | return; |
|
29 | return; | |
|
30 | } | |||
30 | fprintf(fp, "\033[%sm", code); |
|
31 | fprintf(fp, "\033[%sm", code); | |
31 | } |
|
32 | } | |
32 |
|
33 | |||
@@ -35,8 +36,9 b' static void vabortmsgerrno(int no, const' | |||||
35 | fsetcolor(stderr, "1;31"); |
|
36 | fsetcolor(stderr, "1;31"); | |
36 | fputs("chg: abort: ", stderr); |
|
37 | fputs("chg: abort: ", stderr); | |
37 | vfprintf(stderr, fmt, args); |
|
38 | vfprintf(stderr, fmt, args); | |
38 | if (no != 0) |
|
39 | if (no != 0) { | |
39 | fprintf(stderr, " (errno = %d, %s)", no, strerror(no)); |
|
40 | fprintf(stderr, " (errno = %d, %s)", no, strerror(no)); | |
|
41 | } | |||
40 | fsetcolor(stderr, ""); |
|
42 | fsetcolor(stderr, ""); | |
41 | fputc('\n', stderr); |
|
43 | fputc('\n', stderr); | |
42 | exit(255); |
|
44 | exit(255); | |
@@ -82,8 +84,9 b' void enabledebugmsg(void)' | |||||
82 |
|
84 | |||
83 | void debugmsg(const char *fmt, ...) |
|
85 | void debugmsg(const char *fmt, ...) | |
84 | { |
|
86 | { | |
85 | if (!debugmsgenabled) |
|
87 | if (!debugmsgenabled) { | |
86 | return; |
|
88 | return; | |
|
89 | } | |||
87 |
|
90 | |||
88 | va_list args; |
|
91 | va_list args; | |
89 | va_start(args, fmt); |
|
92 | va_start(args, fmt); | |
@@ -98,32 +101,37 b' void debugmsg(const char *fmt, ...)' | |||||
98 | void fchdirx(int dirfd) |
|
101 | void fchdirx(int dirfd) | |
99 | { |
|
102 | { | |
100 | int r = fchdir(dirfd); |
|
103 | int r = fchdir(dirfd); | |
101 | if (r == -1) |
|
104 | if (r == -1) { | |
102 | abortmsgerrno("failed to fchdir"); |
|
105 | abortmsgerrno("failed to fchdir"); | |
|
106 | } | |||
103 | } |
|
107 | } | |
104 |
|
108 | |||
105 | void fsetcloexec(int fd) |
|
109 | void fsetcloexec(int fd) | |
106 | { |
|
110 | { | |
107 | int flags = fcntl(fd, F_GETFD); |
|
111 | int flags = fcntl(fd, F_GETFD); | |
108 | if (flags < 0) |
|
112 | if (flags < 0) { | |
109 | abortmsgerrno("cannot get flags of fd %d", fd); |
|
113 | abortmsgerrno("cannot get flags of fd %d", fd); | |
110 | if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) |
|
114 | } | |
|
115 | if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) { | |||
111 | abortmsgerrno("cannot set flags of fd %d", fd); |
|
116 | abortmsgerrno("cannot set flags of fd %d", fd); | |
|
117 | } | |||
112 | } |
|
118 | } | |
113 |
|
119 | |||
114 | void *mallocx(size_t size) |
|
120 | void *mallocx(size_t size) | |
115 | { |
|
121 | { | |
116 | void *result = malloc(size); |
|
122 | void *result = malloc(size); | |
117 | if (!result) |
|
123 | if (!result) { | |
118 | abortmsg("failed to malloc"); |
|
124 | abortmsg("failed to malloc"); | |
|
125 | } | |||
119 | return result; |
|
126 | return result; | |
120 | } |
|
127 | } | |
121 |
|
128 | |||
122 | void *reallocx(void *ptr, size_t size) |
|
129 | void *reallocx(void *ptr, size_t size) | |
123 | { |
|
130 | { | |
124 | void *result = realloc(ptr, size); |
|
131 | void *result = realloc(ptr, size); | |
125 | if (!result) |
|
132 | if (!result) { | |
126 | abortmsg("failed to realloc"); |
|
133 | abortmsg("failed to realloc"); | |
|
134 | } | |||
127 | return result; |
|
135 | return result; | |
128 | } |
|
136 | } | |
129 |
|
137 | |||
@@ -144,30 +152,37 b' int runshellcmd(const char *cmd, const c' | |||||
144 | memset(&newsa, 0, sizeof(newsa)); |
|
152 | memset(&newsa, 0, sizeof(newsa)); | |
145 | newsa.sa_handler = SIG_IGN; |
|
153 | newsa.sa_handler = SIG_IGN; | |
146 | newsa.sa_flags = 0; |
|
154 | newsa.sa_flags = 0; | |
147 | if (sigemptyset(&newsa.sa_mask) < 0) |
|
155 | if (sigemptyset(&newsa.sa_mask) < 0) { | |
148 | goto done; |
|
156 | goto done; | |
149 | if (sigaction(SIGINT, &newsa, &oldsaint) < 0) |
|
157 | } | |
|
158 | if (sigaction(SIGINT, &newsa, &oldsaint) < 0) { | |||
150 | goto done; |
|
159 | goto done; | |
|
160 | } | |||
151 | doneflags |= F_SIGINT; |
|
161 | doneflags |= F_SIGINT; | |
152 | if (sigaction(SIGQUIT, &newsa, &oldsaquit) < 0) |
|
162 | if (sigaction(SIGQUIT, &newsa, &oldsaquit) < 0) { | |
153 | goto done; |
|
163 | goto done; | |
|
164 | } | |||
154 | doneflags |= F_SIGQUIT; |
|
165 | doneflags |= F_SIGQUIT; | |
155 |
|
166 | |||
156 | if (sigaddset(&newsa.sa_mask, SIGCHLD) < 0) |
|
167 | if (sigaddset(&newsa.sa_mask, SIGCHLD) < 0) { | |
157 | goto done; |
|
168 | goto done; | |
158 | if (sigprocmask(SIG_BLOCK, &newsa.sa_mask, &oldmask) < 0) |
|
169 | } | |
|
170 | if (sigprocmask(SIG_BLOCK, &newsa.sa_mask, &oldmask) < 0) { | |||
159 | goto done; |
|
171 | goto done; | |
|
172 | } | |||
160 | doneflags |= F_SIGMASK; |
|
173 | doneflags |= F_SIGMASK; | |
161 |
|
174 | |||
162 | pid_t pid = fork(); |
|
175 | pid_t pid = fork(); | |
163 | if (pid < 0) |
|
176 | if (pid < 0) { | |
164 | goto done; |
|
177 | goto done; | |
|
178 | } | |||
165 | if (pid == 0) { |
|
179 | if (pid == 0) { | |
166 | sigaction(SIGINT, &oldsaint, NULL); |
|
180 | sigaction(SIGINT, &oldsaint, NULL); | |
167 | sigaction(SIGQUIT, &oldsaquit, NULL); |
|
181 | sigaction(SIGQUIT, &oldsaquit, NULL); | |
168 | sigprocmask(SIG_SETMASK, &oldmask, NULL); |
|
182 | sigprocmask(SIG_SETMASK, &oldmask, NULL); | |
169 | if (cwd && chdir(cwd) < 0) |
|
183 | if (cwd && chdir(cwd) < 0) { | |
170 | _exit(127); |
|
184 | _exit(127); | |
|
185 | } | |||
171 | const char *argv[] = {"sh", "-c", cmd, NULL}; |
|
186 | const char *argv[] = {"sh", "-c", cmd, NULL}; | |
172 | if (envp) { |
|
187 | if (envp) { | |
173 | execve("/bin/sh", (char **)argv, (char **)envp); |
|
188 | execve("/bin/sh", (char **)argv, (char **)envp); | |
@@ -176,25 +191,32 b' int runshellcmd(const char *cmd, const c' | |||||
176 | } |
|
191 | } | |
177 | _exit(127); |
|
192 | _exit(127); | |
178 | } else { |
|
193 | } else { | |
179 | if (waitpid(pid, &status, 0) < 0) |
|
194 | if (waitpid(pid, &status, 0) < 0) { | |
180 | goto done; |
|
195 | goto done; | |
|
196 | } | |||
181 | doneflags |= F_WAITPID; |
|
197 | doneflags |= F_WAITPID; | |
182 | } |
|
198 | } | |
183 |
|
199 | |||
184 | done: |
|
200 | done: | |
185 | if (doneflags & F_SIGINT) |
|
201 | if (doneflags & F_SIGINT) { | |
186 | sigaction(SIGINT, &oldsaint, NULL); |
|
202 | sigaction(SIGINT, &oldsaint, NULL); | |
187 | if (doneflags & F_SIGQUIT) |
|
203 | } | |
|
204 | if (doneflags & F_SIGQUIT) { | |||
188 | sigaction(SIGQUIT, &oldsaquit, NULL); |
|
205 | sigaction(SIGQUIT, &oldsaquit, NULL); | |
189 | if (doneflags & F_SIGMASK) |
|
206 | } | |
|
207 | if (doneflags & F_SIGMASK) { | |||
190 | sigprocmask(SIG_SETMASK, &oldmask, NULL); |
|
208 | sigprocmask(SIG_SETMASK, &oldmask, NULL); | |
|
209 | } | |||
191 |
|
210 | |||
192 | /* no way to report other errors, use 127 (= shell termination) */ |
|
211 | /* no way to report other errors, use 127 (= shell termination) */ | |
193 | if (!(doneflags & F_WAITPID)) |
|
212 | if (!(doneflags & F_WAITPID)) { | |
194 | return 127; |
|
213 | return 127; | |
195 | if (WIFEXITED(status)) |
|
214 | } | |
|
215 | if (WIFEXITED(status)) { | |||
196 | return WEXITSTATUS(status); |
|
216 | return WEXITSTATUS(status); | |
197 | if (WIFSIGNALED(status)) |
|
217 | } | |
|
218 | if (WIFSIGNALED(status)) { | |||
198 | return -WTERMSIG(status); |
|
219 | return -WTERMSIG(status); | |
|
220 | } | |||
199 | return 127; |
|
221 | return 127; | |
200 | } |
|
222 | } |
@@ -35,15 +35,19 b' int bdiff_splitlines(const char *a, ssiz' | |||||
35 |
|
35 | |||
36 | /* count the lines */ |
|
36 | /* count the lines */ | |
37 | i = 1; /* extra line for sentinel */ |
|
37 | i = 1; /* extra line for sentinel */ | |
38 | for (p = a; p < plast; p++) |
|
38 | for (p = a; p < plast; p++) { | |
39 | if (*p == '\n') |
|
39 | if (*p == '\n') { | |
40 | i++; |
|
40 | i++; | |
41 | if (p == plast) |
|
41 | } | |
|
42 | } | |||
|
43 | if (p == plast) { | |||
42 | i++; |
|
44 | i++; | |
|
45 | } | |||
43 |
|
46 | |||
44 | *lr = l = (struct bdiff_line *)calloc(i, sizeof(struct bdiff_line)); |
|
47 | *lr = l = (struct bdiff_line *)calloc(i, sizeof(struct bdiff_line)); | |
45 | if (!l) |
|
48 | if (!l) { | |
46 | return -1; |
|
49 | return -1; | |
|
50 | } | |||
47 |
|
51 | |||
48 | /* build the line array and calculate hashes */ |
|
52 | /* build the line array and calculate hashes */ | |
49 | hash = 0; |
|
53 | hash = 0; | |
@@ -90,18 +94,21 b' static int equatelines(struct bdiff_line' | |||||
90 | struct pos *h = NULL; |
|
94 | struct pos *h = NULL; | |
91 |
|
95 | |||
92 | /* build a hash table of the next highest power of 2 */ |
|
96 | /* build a hash table of the next highest power of 2 */ | |
93 | while (buckets < bn + 1) |
|
97 | while (buckets < bn + 1) { | |
94 | buckets *= 2; |
|
98 | buckets *= 2; | |
|
99 | } | |||
95 |
|
100 | |||
96 | /* try to allocate a large hash table to avoid collisions */ |
|
101 | /* try to allocate a large hash table to avoid collisions */ | |
97 | for (scale = 4; scale; scale /= 2) { |
|
102 | for (scale = 4; scale; scale /= 2) { | |
98 | h = (struct pos *)calloc(buckets, scale * sizeof(struct pos)); |
|
103 | h = (struct pos *)calloc(buckets, scale * sizeof(struct pos)); | |
99 | if (h) |
|
104 | if (h) { | |
100 | break; |
|
105 | break; | |
|
106 | } | |||
101 | } |
|
107 | } | |
102 |
|
108 | |||
103 | if (!h) |
|
109 | if (!h) { | |
104 | return 0; |
|
110 | return 0; | |
|
111 | } | |||
105 |
|
112 | |||
106 | buckets = buckets * scale - 1; |
|
113 | buckets = buckets * scale - 1; | |
107 |
|
114 | |||
@@ -115,9 +122,11 b' static int equatelines(struct bdiff_line' | |||||
115 | for (i = 0; i < bn; i++) { |
|
122 | for (i = 0; i < bn; i++) { | |
116 | /* find the equivalence class */ |
|
123 | /* find the equivalence class */ | |
117 | for (j = b[i].hash & buckets; h[j].pos != -1; |
|
124 | for (j = b[i].hash & buckets; h[j].pos != -1; | |
118 | j = (j + 1) & buckets) |
|
125 | j = (j + 1) & buckets) { | |
119 | if (!cmp(b + i, b + h[j].pos)) |
|
126 | if (!cmp(b + i, b + h[j].pos)) { | |
120 | break; |
|
127 | break; | |
|
128 | } | |||
|
129 | } | |||
121 |
|
130 | |||
122 | /* add to the head of the equivalence class */ |
|
131 | /* add to the head of the equivalence class */ | |
123 | b[i].n = h[j].pos; |
|
132 | b[i].n = h[j].pos; | |
@@ -133,15 +142,18 b' static int equatelines(struct bdiff_line' | |||||
133 | for (i = 0; i < an; i++) { |
|
142 | for (i = 0; i < an; i++) { | |
134 | /* find the equivalence class */ |
|
143 | /* find the equivalence class */ | |
135 | for (j = a[i].hash & buckets; h[j].pos != -1; |
|
144 | for (j = a[i].hash & buckets; h[j].pos != -1; | |
136 | j = (j + 1) & buckets) |
|
145 | j = (j + 1) & buckets) { | |
137 | if (!cmp(a + i, b + h[j].pos)) |
|
146 | if (!cmp(a + i, b + h[j].pos)) { | |
138 | break; |
|
147 | break; | |
|
148 | } | |||
|
149 | } | |||
139 |
|
150 | |||
140 | a[i].e = j; /* use equivalence class for quick compare */ |
|
151 | a[i].e = j; /* use equivalence class for quick compare */ | |
141 | if (h[j].len <= t) |
|
152 | if (h[j].len <= t) { | |
142 | a[i].n = h[j].pos; /* point to head of match list */ |
|
153 | a[i].n = h[j].pos; /* point to head of match list */ | |
143 | else |
|
154 | } else { | |
144 | a[i].n = -1; /* too popular */ |
|
155 | a[i].n = -1; /* too popular */ | |
|
156 | } | |||
145 | } |
|
157 | } | |
146 |
|
158 | |||
147 | /* discard hash tables */ |
|
159 | /* discard hash tables */ | |
@@ -158,16 +170,18 b' static int longest_match(struct bdiff_li' | |||||
158 | /* window our search on large regions to better bound |
|
170 | /* window our search on large regions to better bound | |
159 | worst-case performance. by choosing a window at the end, we |
|
171 | worst-case performance. by choosing a window at the end, we | |
160 | reduce skipping overhead on the b chains. */ |
|
172 | reduce skipping overhead on the b chains. */ | |
161 | if (a2 - a1 > 30000) |
|
173 | if (a2 - a1 > 30000) { | |
162 | a1 = a2 - 30000; |
|
174 | a1 = a2 - 30000; | |
|
175 | } | |||
163 |
|
176 | |||
164 | half = (a1 + a2 - 1) / 2; |
|
177 | half = (a1 + a2 - 1) / 2; | |
165 | bhalf = (b1 + b2 - 1) / 2; |
|
178 | bhalf = (b1 + b2 - 1) / 2; | |
166 |
|
179 | |||
167 | for (i = a1; i < a2; i++) { |
|
180 | for (i = a1; i < a2; i++) { | |
168 | /* skip all lines in b after the current block */ |
|
181 | /* skip all lines in b after the current block */ | |
169 | for (j = a[i].n; j >= b2; j = b[j].n) |
|
182 | for (j = a[i].n; j >= b2; j = b[j].n) { | |
170 | ; |
|
183 | ; | |
|
184 | } | |||
171 |
|
185 | |||
172 | /* loop through all lines match a[i] in b */ |
|
186 | /* loop through all lines match a[i] in b */ | |
173 | for (; j >= b1; j = b[j].n) { |
|
187 | for (; j >= b1; j = b[j].n) { | |
@@ -179,8 +193,9 b' static int longest_match(struct bdiff_li' | |||||
179 | break; |
|
193 | break; | |
180 | } |
|
194 | } | |
181 | /* previous line mismatch? */ |
|
195 | /* previous line mismatch? */ | |
182 | if (a[i - k].e != b[j - k].e) |
|
196 | if (a[i - k].e != b[j - k].e) { | |
183 | break; |
|
197 | break; | |
|
198 | } | |||
184 | } |
|
199 | } | |
185 |
|
200 | |||
186 | pos[j].pos = i; |
|
201 | pos[j].pos = i; | |
@@ -212,8 +227,9 b' static int longest_match(struct bdiff_li' | |||||
212 | } |
|
227 | } | |
213 |
|
228 | |||
214 | /* expand match to include subsequent popular lines */ |
|
229 | /* expand match to include subsequent popular lines */ | |
215 | while (mi + mk < a2 && mj + mk < b2 && a[mi + mk].e == b[mj + mk].e) |
|
230 | while (mi + mk < a2 && mj + mk < b2 && a[mi + mk].e == b[mj + mk].e) { | |
216 | mk++; |
|
231 | mk++; | |
|
232 | } | |||
217 |
|
233 | |||
218 | *omi = mi; |
|
234 | *omi = mi; | |
219 | *omj = mj; |
|
235 | *omj = mj; | |
@@ -230,18 +246,21 b' static struct bdiff_hunk *recurse(struct' | |||||
230 | while (1) { |
|
246 | while (1) { | |
231 | /* find the longest match in this chunk */ |
|
247 | /* find the longest match in this chunk */ | |
232 | k = longest_match(a, b, pos, a1, a2, b1, b2, &i, &j); |
|
248 | k = longest_match(a, b, pos, a1, a2, b1, b2, &i, &j); | |
233 | if (!k) |
|
249 | if (!k) { | |
234 | return l; |
|
250 | return l; | |
|
251 | } | |||
235 |
|
252 | |||
236 | /* and recurse on the remaining chunks on either side */ |
|
253 | /* and recurse on the remaining chunks on either side */ | |
237 | l = recurse(a, b, pos, a1, i, b1, j, l); |
|
254 | l = recurse(a, b, pos, a1, i, b1, j, l); | |
238 | if (!l) |
|
255 | if (!l) { | |
239 | return NULL; |
|
256 | return NULL; | |
|
257 | } | |||
240 |
|
258 | |||
241 | l->next = |
|
259 | l->next = | |
242 | (struct bdiff_hunk *)malloc(sizeof(struct bdiff_hunk)); |
|
260 | (struct bdiff_hunk *)malloc(sizeof(struct bdiff_hunk)); | |
243 | if (!l->next) |
|
261 | if (!l->next) { | |
244 | return NULL; |
|
262 | return NULL; | |
|
263 | } | |||
245 |
|
264 | |||
246 | l = l->next; |
|
265 | l = l->next; | |
247 | l->a1 = i; |
|
266 | l->a1 = i; | |
@@ -271,14 +290,16 b' int bdiff_diff(struct bdiff_line *a, int' | |||||
271 | /* generate the matching block list */ |
|
290 | /* generate the matching block list */ | |
272 |
|
291 | |||
273 | curr = recurse(a, b, pos, 0, an, 0, bn, base); |
|
292 | curr = recurse(a, b, pos, 0, an, 0, bn, base); | |
274 | if (!curr) |
|
293 | if (!curr) { | |
275 | return -1; |
|
294 | return -1; | |
|
295 | } | |||
276 |
|
296 | |||
277 | /* sentinel end hunk */ |
|
297 | /* sentinel end hunk */ | |
278 | curr->next = |
|
298 | curr->next = | |
279 | (struct bdiff_hunk *)malloc(sizeof(struct bdiff_hunk)); |
|
299 | (struct bdiff_hunk *)malloc(sizeof(struct bdiff_hunk)); | |
280 | if (!curr->next) |
|
300 | if (!curr->next) { | |
281 | return -1; |
|
301 | return -1; | |
|
302 | } | |||
282 | curr = curr->next; |
|
303 | curr = curr->next; | |
283 | curr->a1 = curr->a2 = an; |
|
304 | curr->a1 = curr->a2 = an; | |
284 | curr->b1 = curr->b2 = bn; |
|
305 | curr->b1 = curr->b2 = bn; | |
@@ -291,10 +312,11 b' int bdiff_diff(struct bdiff_line *a, int' | |||||
291 | for (curr = base->next; curr; curr = curr->next) { |
|
312 | for (curr = base->next; curr; curr = curr->next) { | |
292 | struct bdiff_hunk *next = curr->next; |
|
313 | struct bdiff_hunk *next = curr->next; | |
293 |
|
314 | |||
294 | if (!next) |
|
315 | if (!next) { | |
295 | break; |
|
316 | break; | |
|
317 | } | |||
296 |
|
318 | |||
297 | if (curr->a2 == next->a1 || curr->b2 == next->b1) |
|
319 | if (curr->a2 == next->a1 || curr->b2 == next->b1) { | |
298 | while (curr->a2 < an && curr->b2 < bn && |
|
320 | while (curr->a2 < an && curr->b2 < bn && | |
299 | next->a1 < next->a2 && next->b1 < next->b2 && |
|
321 | next->a1 < next->a2 && next->b1 < next->b2 && | |
300 | !cmp(a + curr->a2, b + curr->b2)) { |
|
322 | !cmp(a + curr->a2, b + curr->b2)) { | |
@@ -303,10 +325,12 b' int bdiff_diff(struct bdiff_line *a, int' | |||||
303 | curr->b2++; |
|
325 | curr->b2++; | |
304 | next->b1++; |
|
326 | next->b1++; | |
305 | } |
|
327 | } | |
|
328 | } | |||
306 | } |
|
329 | } | |
307 |
|
330 | |||
308 | for (curr = base->next; curr; curr = curr->next) |
|
331 | for (curr = base->next; curr; curr = curr->next) { | |
309 | count++; |
|
332 | count++; | |
|
333 | } | |||
310 | return count; |
|
334 | return count; | |
311 | } |
|
335 | } | |
312 |
|
336 |
@@ -24,8 +24,9 b' static void b85prep(void)' | |||||
24 | unsigned i; |
|
24 | unsigned i; | |
25 |
|
25 | |||
26 | memset(b85dec, 0, sizeof(b85dec)); |
|
26 | memset(b85dec, 0, sizeof(b85dec)); | |
27 | for (i = 0; i < sizeof(b85chars); i++) |
|
27 | for (i = 0; i < sizeof(b85chars); i++) { | |
28 | b85dec[(int)(b85chars[i])] = i + 1; |
|
28 | b85dec[(int)(b85chars[i])] = i + 1; | |
|
29 | } | |||
29 | } |
|
30 | } | |
30 |
|
31 | |||
31 | static PyObject *b85encode(PyObject *self, PyObject *args) |
|
32 | static PyObject *b85encode(PyObject *self, PyObject *args) | |
@@ -37,19 +38,22 b' static PyObject *b85encode(PyObject *sel' | |||||
37 | unsigned int acc, val, ch; |
|
38 | unsigned int acc, val, ch; | |
38 | int pad = 0; |
|
39 | int pad = 0; | |
39 |
|
40 | |||
40 | if (!PyArg_ParseTuple(args, PY23("s#|i", "y#|i"), &text, &len, &pad)) |
|
41 | if (!PyArg_ParseTuple(args, PY23("s#|i", "y#|i"), &text, &len, &pad)) { | |
41 | return NULL; |
|
42 | return NULL; | |
|
43 | } | |||
42 |
|
44 | |||
43 | if (pad) |
|
45 | if (pad) { | |
44 | olen = ((len + 3) / 4 * 5) - 3; |
|
46 | olen = ((len + 3) / 4 * 5) - 3; | |
45 | else { |
|
47 | } else { | |
46 | olen = len % 4; |
|
48 | olen = len % 4; | |
47 | if (olen) |
|
49 | if (olen) { | |
48 | olen++; |
|
50 | olen++; | |
|
51 | } | |||
49 | olen += len / 4 * 5; |
|
52 | olen += len / 4 * 5; | |
50 | } |
|
53 | } | |
51 | if (!(out = PyBytes_FromStringAndSize(NULL, olen + 3))) |
|
54 | if (!(out = PyBytes_FromStringAndSize(NULL, olen + 3))) { | |
52 | return NULL; |
|
55 | return NULL; | |
|
56 | } | |||
53 |
|
57 | |||
54 | dst = PyBytes_AsString(out); |
|
58 | dst = PyBytes_AsString(out); | |
55 |
|
59 | |||
@@ -58,8 +62,9 b' static PyObject *b85encode(PyObject *sel' | |||||
58 | for (i = 24; i >= 0; i -= 8) { |
|
62 | for (i = 24; i >= 0; i -= 8) { | |
59 | ch = *text++; |
|
63 | ch = *text++; | |
60 | acc |= ch << i; |
|
64 | acc |= ch << i; | |
61 | if (--len == 0) |
|
65 | if (--len == 0) { | |
62 | break; |
|
66 | break; | |
|
67 | } | |||
63 | } |
|
68 | } | |
64 | for (i = 4; i >= 0; i--) { |
|
69 | for (i = 4; i >= 0; i--) { | |
65 | val = acc % 85; |
|
70 | val = acc % 85; | |
@@ -69,8 +74,9 b' static PyObject *b85encode(PyObject *sel' | |||||
69 | dst += 5; |
|
74 | dst += 5; | |
70 | } |
|
75 | } | |
71 |
|
76 | |||
72 | if (!pad) |
|
77 | if (!pad) { | |
73 | _PyBytes_Resize(&out, olen); |
|
78 | _PyBytes_Resize(&out, olen); | |
|
79 | } | |||
74 |
|
80 | |||
75 | return out; |
|
81 | return out; | |
76 | } |
|
82 | } | |
@@ -84,15 +90,18 b' static PyObject *b85decode(PyObject *sel' | |||||
84 | int c; |
|
90 | int c; | |
85 | unsigned int acc; |
|
91 | unsigned int acc; | |
86 |
|
92 | |||
87 | if (!PyArg_ParseTuple(args, PY23("s#", "y#"), &text, &len)) |
|
93 | if (!PyArg_ParseTuple(args, PY23("s#", "y#"), &text, &len)) { | |
88 | return NULL; |
|
94 | return NULL; | |
|
95 | } | |||
89 |
|
96 | |||
90 | olen = len / 5 * 4; |
|
97 | olen = len / 5 * 4; | |
91 | i = len % 5; |
|
98 | i = len % 5; | |
92 | if (i) |
|
99 | if (i) { | |
93 | olen += i - 1; |
|
100 | olen += i - 1; | |
94 | if (!(out = PyBytes_FromStringAndSize(NULL, olen))) |
|
101 | } | |
|
102 | if (!(out = PyBytes_FromStringAndSize(NULL, olen))) { | |||
95 | return NULL; |
|
103 | return NULL; | |
|
104 | } | |||
96 |
|
105 | |||
97 | dst = PyBytes_AsString(out); |
|
106 | dst = PyBytes_AsString(out); | |
98 |
|
107 | |||
@@ -100,8 +109,9 b' static PyObject *b85decode(PyObject *sel' | |||||
100 | while (i < len) { |
|
109 | while (i < len) { | |
101 | acc = 0; |
|
110 | acc = 0; | |
102 | cap = len - i - 1; |
|
111 | cap = len - i - 1; | |
103 | if (cap > 4) |
|
112 | if (cap > 4) { | |
104 | cap = 4; |
|
113 | cap = 4; | |
|
114 | } | |||
105 | for (j = 0; j < cap; i++, j++) { |
|
115 | for (j = 0; j < cap; i++, j++) { | |
106 | c = b85dec[(int)*text++] - 1; |
|
116 | c = b85dec[(int)*text++] - 1; | |
107 | if (c < 0) { |
|
117 | if (c < 0) { | |
@@ -136,10 +146,12 b' static PyObject *b85decode(PyObject *sel' | |||||
136 |
|
146 | |||
137 | cap = olen < 4 ? olen : 4; |
|
147 | cap = olen < 4 ? olen : 4; | |
138 | olen -= cap; |
|
148 | olen -= cap; | |
139 | for (j = 0; j < 4 - cap; j++) |
|
149 | for (j = 0; j < 4 - cap; j++) { | |
140 | acc *= 85; |
|
150 | acc *= 85; | |
141 | if (cap && cap < 4) |
|
151 | } | |
|
152 | if (cap && cap < 4) { | |||
142 | acc += 0xffffff >> (cap - 1) * 8; |
|
153 | acc += 0xffffff >> (cap - 1) * 8; | |
|
154 | } | |||
143 | for (j = 0; j < cap; j++) { |
|
155 | for (j = 0; j < cap; j++) { | |
144 | acc = (acc << 8) | (acc >> 24); |
|
156 | acc = (acc << 8) | (acc >> 24); | |
145 | *dst++ = acc; |
|
157 | *dst++ = acc; |
@@ -29,22 +29,26 b' static PyObject *blocks(PyObject *self, ' | |||||
29 |
|
29 | |||
30 | l.next = NULL; |
|
30 | l.next = NULL; | |
31 |
|
31 | |||
32 | if (!PyArg_ParseTuple(args, "SS:bdiff", &sa, &sb)) |
|
32 | if (!PyArg_ParseTuple(args, "SS:bdiff", &sa, &sb)) { | |
33 | return NULL; |
|
33 | return NULL; | |
|
34 | } | |||
34 |
|
35 | |||
35 | an = bdiff_splitlines(PyBytes_AsString(sa), PyBytes_Size(sa), &a); |
|
36 | an = bdiff_splitlines(PyBytes_AsString(sa), PyBytes_Size(sa), &a); | |
36 | bn = bdiff_splitlines(PyBytes_AsString(sb), PyBytes_Size(sb), &b); |
|
37 | bn = bdiff_splitlines(PyBytes_AsString(sb), PyBytes_Size(sb), &b); | |
37 |
|
38 | |||
38 | if (!a || !b) |
|
39 | if (!a || !b) { | |
39 | goto nomem; |
|
40 | goto nomem; | |
|
41 | } | |||
40 |
|
42 | |||
41 | count = bdiff_diff(a, an, b, bn, &l); |
|
43 | count = bdiff_diff(a, an, b, bn, &l); | |
42 | if (count < 0) |
|
44 | if (count < 0) { | |
43 | goto nomem; |
|
45 | goto nomem; | |
|
46 | } | |||
44 |
|
47 | |||
45 | rl = PyList_New(count); |
|
48 | rl = PyList_New(count); | |
46 | if (!rl) |
|
49 | if (!rl) { | |
47 | goto nomem; |
|
50 | goto nomem; | |
|
51 | } | |||
48 |
|
52 | |||
49 | for (h = l.next; h; h = h->next) { |
|
53 | for (h = l.next; h; h = h->next) { | |
50 | m = Py_BuildValue("iiii", h->a1, h->a2, h->b1, h->b2); |
|
54 | m = Py_BuildValue("iiii", h->a1, h->a2, h->b1, h->b2); | |
@@ -72,8 +76,10 b' static PyObject *bdiff(PyObject *self, P' | |||||
72 |
|
76 | |||
73 | l.next = NULL; |
|
77 | l.next = NULL; | |
74 |
|
78 | |||
75 |
if (!PyArg_ParseTuple(args, PY23("s*s*:bdiff", "y*y*:bdiff"), &ba, |
|
79 | if (!PyArg_ParseTuple(args, PY23("s*s*:bdiff", "y*y*:bdiff"), &ba, | |
|
80 | &bb)) { | |||
76 | return NULL; |
|
81 | return NULL; | |
|
82 | } | |||
77 |
|
83 | |||
78 | if (!PyBuffer_IsContiguous(&ba, 'C') || ba.ndim > 1) { |
|
84 | if (!PyBuffer_IsContiguous(&ba, 'C') || ba.ndim > 1) { | |
79 | PyErr_SetString(PyExc_ValueError, "bdiff input not contiguous"); |
|
85 | PyErr_SetString(PyExc_ValueError, "bdiff input not contiguous"); | |
@@ -98,8 +104,9 b' static PyObject *bdiff(PyObject *self, P' | |||||
98 | lmax = la > lb ? lb : la; |
|
104 | lmax = la > lb ? lb : la; | |
99 | for (ia = ba.buf, ib = bb.buf; li < lmax && *ia == *ib; |
|
105 | for (ia = ba.buf, ib = bb.buf; li < lmax && *ia == *ib; | |
100 | ++li, ++ia, ++ib) { |
|
106 | ++li, ++ia, ++ib) { | |
101 | if (*ia == '\n') |
|
107 | if (*ia == '\n') { | |
102 | lcommon = li + 1; |
|
108 | lcommon = li + 1; | |
|
109 | } | |||
103 | } |
|
110 | } | |
104 | /* we can almost add: if (li == lmax) lcommon = li; */ |
|
111 | /* we can almost add: if (li == lmax) lcommon = li; */ | |
105 |
|
112 | |||
@@ -119,8 +126,9 b' static PyObject *bdiff(PyObject *self, P' | |||||
119 | /* calculate length of output */ |
|
126 | /* calculate length of output */ | |
120 | la = lb = 0; |
|
127 | la = lb = 0; | |
121 | for (h = l.next; h; h = h->next) { |
|
128 | for (h = l.next; h; h = h->next) { | |
122 | if (h->a1 != la || h->b1 != lb) |
|
129 | if (h->a1 != la || h->b1 != lb) { | |
123 | len += 12 + bl[h->b1].l - bl[lb].l; |
|
130 | len += 12 + bl[h->b1].l - bl[lb].l; | |
|
131 | } | |||
124 | la = h->a2; |
|
132 | la = h->a2; | |
125 | lb = h->b2; |
|
133 | lb = h->b2; | |
126 | } |
|
134 | } | |
@@ -129,8 +137,9 b' static PyObject *bdiff(PyObject *self, P' | |||||
129 |
|
137 | |||
130 | result = PyBytes_FromStringAndSize(NULL, len); |
|
138 | result = PyBytes_FromStringAndSize(NULL, len); | |
131 |
|
139 | |||
132 | if (!result) |
|
140 | if (!result) { | |
133 | goto cleanup; |
|
141 | goto cleanup; | |
|
142 | } | |||
134 |
|
143 | |||
135 | /* build binary patch */ |
|
144 | /* build binary patch */ | |
136 | rb = PyBytes_AsString(result); |
|
145 | rb = PyBytes_AsString(result); | |
@@ -151,8 +160,9 b' static PyObject *bdiff(PyObject *self, P' | |||||
151 | } |
|
160 | } | |
152 |
|
161 | |||
153 | cleanup: |
|
162 | cleanup: | |
154 | if (_save) |
|
163 | if (_save) { | |
155 | PyEval_RestoreThread(_save); |
|
164 | PyEval_RestoreThread(_save); | |
|
165 | } | |||
156 | PyBuffer_Release(&ba); |
|
166 | PyBuffer_Release(&ba); | |
157 | PyBuffer_Release(&bb); |
|
167 | PyBuffer_Release(&bb); | |
158 | free(al); |
|
168 | free(al); | |
@@ -174,20 +184,23 b' static PyObject *fixws(PyObject *self, P' | |||||
174 | Py_ssize_t i, rlen, wlen = 0; |
|
184 | Py_ssize_t i, rlen, wlen = 0; | |
175 | char *w; |
|
185 | char *w; | |
176 |
|
186 | |||
177 | if (!PyArg_ParseTuple(args, "Sb:fixws", &s, &allws)) |
|
187 | if (!PyArg_ParseTuple(args, "Sb:fixws", &s, &allws)) { | |
178 | return NULL; |
|
188 | return NULL; | |
|
189 | } | |||
179 | r = PyBytes_AsString(s); |
|
190 | r = PyBytes_AsString(s); | |
180 | rlen = PyBytes_Size(s); |
|
191 | rlen = PyBytes_Size(s); | |
181 |
|
192 | |||
182 | w = (char *)PyMem_Malloc(rlen ? rlen : 1); |
|
193 | w = (char *)PyMem_Malloc(rlen ? rlen : 1); | |
183 | if (!w) |
|
194 | if (!w) { | |
184 | goto nomem; |
|
195 | goto nomem; | |
|
196 | } | |||
185 |
|
197 | |||
186 | for (i = 0; i != rlen; i++) { |
|
198 | for (i = 0; i != rlen; i++) { | |
187 | c = r[i]; |
|
199 | c = r[i]; | |
188 | if (c == ' ' || c == '\t' || c == '\r') { |
|
200 | if (c == ' ' || c == '\t' || c == '\r') { | |
189 | if (!allws && (wlen == 0 || w[wlen - 1] != ' ')) |
|
201 | if (!allws && (wlen == 0 || w[wlen - 1] != ' ')) { | |
190 | w[wlen++] = ' '; |
|
202 | w[wlen++] = ' '; | |
|
203 | } | |||
191 | } else if (c == '\n' && !allws && wlen > 0 && |
|
204 | } else if (c == '\n' && !allws && wlen > 0 && | |
192 | w[wlen - 1] == ' ') { |
|
205 | w[wlen - 1] == ' ') { | |
193 | w[wlen - 1] = '\n'; |
|
206 | w[wlen - 1] = '\n'; | |
@@ -207,8 +220,9 b' static bool sliceintolist(PyObject *list' | |||||
207 | const char *source, Py_ssize_t len) |
|
220 | const char *source, Py_ssize_t len) | |
208 | { |
|
221 | { | |
209 | PyObject *sliced = PyBytes_FromStringAndSize(source, len); |
|
222 | PyObject *sliced = PyBytes_FromStringAndSize(source, len); | |
210 | if (sliced == NULL) |
|
223 | if (sliced == NULL) { | |
211 | return false; |
|
224 | return false; | |
|
225 | } | |||
212 | PyList_SET_ITEM(list, destidx, sliced); |
|
226 | PyList_SET_ITEM(list, destidx, sliced); | |
213 | return true; |
|
227 | return true; | |
214 | } |
|
228 | } | |
@@ -232,19 +246,22 b' static PyObject *splitnewlines(PyObject ' | |||||
232 | ++nelts; |
|
246 | ++nelts; | |
233 | } |
|
247 | } | |
234 | } |
|
248 | } | |
235 | if ((result = PyList_New(nelts + 1)) == NULL) |
|
249 | if ((result = PyList_New(nelts + 1)) == NULL) { | |
236 | goto abort; |
|
250 | goto abort; | |
|
251 | } | |||
237 | nelts = 0; |
|
252 | nelts = 0; | |
238 | for (i = 0; i < size - 1; ++i) { |
|
253 | for (i = 0; i < size - 1; ++i) { | |
239 | if (text[i] == '\n') { |
|
254 | if (text[i] == '\n') { | |
240 | if (!sliceintolist(result, nelts++, text + start, |
|
255 | if (!sliceintolist(result, nelts++, text + start, | |
241 | i - start + 1)) |
|
256 | i - start + 1)) { | |
242 | goto abort; |
|
257 | goto abort; | |
|
258 | } | |||
243 | start = i + 1; |
|
259 | start = i + 1; | |
244 | } |
|
260 | } | |
245 | } |
|
261 | } | |
246 | if (!sliceintolist(result, nelts++, text + start, size - start)) |
|
262 | if (!sliceintolist(result, nelts++, text + start, size - start)) { | |
247 | goto abort; |
|
263 | goto abort; | |
|
264 | } | |||
248 | return result; |
|
265 | return result; | |
249 | abort: |
|
266 | abort: | |
250 | Py_XDECREF(result); |
|
267 | Py_XDECREF(result); | |
@@ -257,8 +274,9 b' static int hunk_consumer(int64_t a1, int' | |||||
257 | PyObject *rl = (PyObject *)priv; |
|
274 | PyObject *rl = (PyObject *)priv; | |
258 | PyObject *m = Py_BuildValue("LLLL", a1, a2, b1, b2); |
|
275 | PyObject *m = Py_BuildValue("LLLL", a1, a2, b1, b2); | |
259 | int r; |
|
276 | int r; | |
260 | if (!m) |
|
277 | if (!m) { | |
261 | return -1; |
|
278 | return -1; | |
|
279 | } | |||
262 | r = PyList_Append(rl, m); |
|
280 | r = PyList_Append(rl, m); | |
263 | Py_DECREF(m); |
|
281 | Py_DECREF(m); | |
264 | return r; |
|
282 | return r; | |
@@ -282,15 +300,17 b' static PyObject *xdiffblocks(PyObject *s' | |||||
282 | }; |
|
300 | }; | |
283 |
|
301 | |||
284 | if (!PyArg_ParseTuple(args, PY23("s#s#", "y#y#"), &a.ptr, &la, &b.ptr, |
|
302 | if (!PyArg_ParseTuple(args, PY23("s#s#", "y#y#"), &a.ptr, &la, &b.ptr, | |
285 | &lb)) |
|
303 | &lb)) { | |
286 | return NULL; |
|
304 | return NULL; | |
|
305 | } | |||
287 |
|
306 | |||
288 | a.size = la; |
|
307 | a.size = la; | |
289 | b.size = lb; |
|
308 | b.size = lb; | |
290 |
|
309 | |||
291 | rl = PyList_New(0); |
|
310 | rl = PyList_New(0); | |
292 | if (!rl) |
|
311 | if (!rl) { | |
293 | return PyErr_NoMemory(); |
|
312 | return PyErr_NoMemory(); | |
|
313 | } | |||
294 |
|
314 | |||
295 | ecb.priv = rl; |
|
315 | ecb.priv = rl; | |
296 |
|
316 |
@@ -114,8 +114,9 b' PyObject *unhexlify(const char *str, Py_' | |||||
114 |
|
114 | |||
115 | ret = PyBytes_FromStringAndSize(NULL, len / 2); |
|
115 | ret = PyBytes_FromStringAndSize(NULL, len / 2); | |
116 |
|
116 | |||
117 | if (!ret) |
|
117 | if (!ret) { | |
118 | return NULL; |
|
118 | return NULL; | |
|
119 | } | |||
119 |
|
120 | |||
120 | d = PyBytes_AsString(ret); |
|
121 | d = PyBytes_AsString(ret); | |
121 |
|
122 | |||
@@ -133,21 +134,24 b' PyObject *isasciistr(PyObject *self, PyO' | |||||
133 | const char *buf; |
|
134 | const char *buf; | |
134 | Py_ssize_t i, len; |
|
135 | Py_ssize_t i, len; | |
135 | if (!PyArg_ParseTuple(args, PY23("s#:isasciistr", "y#:isasciistr"), |
|
136 | if (!PyArg_ParseTuple(args, PY23("s#:isasciistr", "y#:isasciistr"), | |
136 | &buf, &len)) |
|
137 | &buf, &len)) { | |
137 | return NULL; |
|
138 | return NULL; | |
|
139 | } | |||
138 | i = 0; |
|
140 | i = 0; | |
139 | /* char array in PyStringObject should be at least 4-byte aligned */ |
|
141 | /* char array in PyStringObject should be at least 4-byte aligned */ | |
140 | if (((uintptr_t)buf & 3) == 0) { |
|
142 | if (((uintptr_t)buf & 3) == 0) { | |
141 | const uint32_t *p = (const uint32_t *)buf; |
|
143 | const uint32_t *p = (const uint32_t *)buf; | |
142 | for (; i < len / 4; i++) { |
|
144 | for (; i < len / 4; i++) { | |
143 | if (p[i] & 0x80808080U) |
|
145 | if (p[i] & 0x80808080U) { | |
144 | Py_RETURN_FALSE; |
|
146 | Py_RETURN_FALSE; | |
|
147 | } | |||
145 | } |
|
148 | } | |
146 | i *= 4; |
|
149 | i *= 4; | |
147 | } |
|
150 | } | |
148 | for (; i < len; i++) { |
|
151 | for (; i < len; i++) { | |
149 | if (buf[i] & 0x80) |
|
152 | if (buf[i] & 0x80) { | |
150 | Py_RETURN_FALSE; |
|
153 | Py_RETURN_FALSE; | |
|
154 | } | |||
151 | } |
|
155 | } | |
152 | Py_RETURN_TRUE; |
|
156 | Py_RETURN_TRUE; | |
153 | } |
|
157 | } | |
@@ -164,8 +168,9 b' static inline PyObject *' | |||||
164 | len = PyBytes_GET_SIZE(str_obj); |
|
168 | len = PyBytes_GET_SIZE(str_obj); | |
165 |
|
169 | |||
166 | newobj = PyBytes_FromStringAndSize(NULL, len); |
|
170 | newobj = PyBytes_FromStringAndSize(NULL, len); | |
167 | if (!newobj) |
|
171 | if (!newobj) { | |
168 | goto quit; |
|
172 | goto quit; | |
|
173 | } | |||
169 |
|
174 | |||
170 | newstr = PyBytes_AS_STRING(newobj); |
|
175 | newstr = PyBytes_AS_STRING(newobj); | |
171 |
|
176 | |||
@@ -197,16 +202,18 b' quit:' | |||||
197 | PyObject *asciilower(PyObject *self, PyObject *args) |
|
202 | PyObject *asciilower(PyObject *self, PyObject *args) | |
198 | { |
|
203 | { | |
199 | PyObject *str_obj; |
|
204 | PyObject *str_obj; | |
200 | if (!PyArg_ParseTuple(args, "O!:asciilower", &PyBytes_Type, &str_obj)) |
|
205 | if (!PyArg_ParseTuple(args, "O!:asciilower", &PyBytes_Type, &str_obj)) { | |
201 | return NULL; |
|
206 | return NULL; | |
|
207 | } | |||
202 | return _asciitransform(str_obj, lowertable, NULL); |
|
208 | return _asciitransform(str_obj, lowertable, NULL); | |
203 | } |
|
209 | } | |
204 |
|
210 | |||
205 | PyObject *asciiupper(PyObject *self, PyObject *args) |
|
211 | PyObject *asciiupper(PyObject *self, PyObject *args) | |
206 | { |
|
212 | { | |
207 | PyObject *str_obj; |
|
213 | PyObject *str_obj; | |
208 | if (!PyArg_ParseTuple(args, "O!:asciiupper", &PyBytes_Type, &str_obj)) |
|
214 | if (!PyArg_ParseTuple(args, "O!:asciiupper", &PyBytes_Type, &str_obj)) { | |
209 | return NULL; |
|
215 | return NULL; | |
|
216 | } | |||
210 | return _asciitransform(str_obj, uppertable, NULL); |
|
217 | return _asciitransform(str_obj, uppertable, NULL); | |
211 | } |
|
218 | } | |
212 |
|
219 | |||
@@ -222,8 +229,9 b' PyObject *make_file_foldmap(PyObject *se' | |||||
222 |
|
229 | |||
223 | if (!PyArg_ParseTuple(args, "O!O!O!:make_file_foldmap", &PyDict_Type, |
|
230 | if (!PyArg_ParseTuple(args, "O!O!O!:make_file_foldmap", &PyDict_Type, | |
224 | &dmap, &PyInt_Type, &spec_obj, &PyFunction_Type, |
|
231 | &dmap, &PyInt_Type, &spec_obj, &PyFunction_Type, | |
225 | &normcase_fallback)) |
|
232 | &normcase_fallback)) { | |
226 | goto quit; |
|
233 | goto quit; | |
|
234 | } | |||
227 |
|
235 | |||
228 | spec = (int)PyInt_AS_LONG(spec_obj); |
|
236 | spec = (int)PyInt_AS_LONG(spec_obj); | |
229 | switch (spec) { |
|
237 | switch (spec) { | |
@@ -244,8 +252,9 b' PyObject *make_file_foldmap(PyObject *se' | |||||
244 | /* Add some more entries to deal with additions outside this |
|
252 | /* Add some more entries to deal with additions outside this | |
245 | function. */ |
|
253 | function. */ | |
246 | file_foldmap = _dict_new_presized((PyDict_Size(dmap) / 10) * 11); |
|
254 | file_foldmap = _dict_new_presized((PyDict_Size(dmap) / 10) * 11); | |
247 | if (file_foldmap == NULL) |
|
255 | if (file_foldmap == NULL) { | |
248 | goto quit; |
|
256 | goto quit; | |
|
257 | } | |||
249 |
|
258 | |||
250 | while (PyDict_Next(dmap, &pos, &k, &v)) { |
|
259 | while (PyDict_Next(dmap, &pos, &k, &v)) { | |
251 | if (!dirstate_tuple_check(v)) { |
|
260 | if (!dirstate_tuple_check(v)) { | |
@@ -265,8 +274,9 b' PyObject *make_file_foldmap(PyObject *se' | |||||
265 | normcase_fallback, k, NULL); |
|
274 | normcase_fallback, k, NULL); | |
266 | } |
|
275 | } | |
267 |
|
276 | |||
268 | if (normed == NULL) |
|
277 | if (normed == NULL) { | |
269 | goto quit; |
|
278 | goto quit; | |
|
279 | } | |||
270 | if (PyDict_SetItem(file_foldmap, normed, k) == -1) { |
|
280 | if (PyDict_SetItem(file_foldmap, normed, k) == -1) { | |
271 | Py_DECREF(normed); |
|
281 | Py_DECREF(normed); | |
272 | goto quit; |
|
282 | goto quit; | |
@@ -377,22 +387,25 b' PyObject *jsonescapeu8fast(PyObject *sel' | |||||
377 | Py_ssize_t origlen, esclen; |
|
387 | Py_ssize_t origlen, esclen; | |
378 | int paranoid; |
|
388 | int paranoid; | |
379 | if (!PyArg_ParseTuple(args, "O!i:jsonescapeu8fast", &PyBytes_Type, |
|
389 | if (!PyArg_ParseTuple(args, "O!i:jsonescapeu8fast", &PyBytes_Type, | |
380 | &origstr, ¶noid)) |
|
390 | &origstr, ¶noid)) { | |
381 | return NULL; |
|
391 | return NULL; | |
|
392 | } | |||
382 |
|
393 | |||
383 | origbuf = PyBytes_AS_STRING(origstr); |
|
394 | origbuf = PyBytes_AS_STRING(origstr); | |
384 | origlen = PyBytes_GET_SIZE(origstr); |
|
395 | origlen = PyBytes_GET_SIZE(origstr); | |
385 | esclen = jsonescapelen(origbuf, origlen, paranoid); |
|
396 | esclen = jsonescapelen(origbuf, origlen, paranoid); | |
386 | if (esclen < 0) |
|
397 | if (esclen < 0) { | |
387 | return NULL; /* unsupported char found or overflow */ |
|
398 | return NULL; /* unsupported char found or overflow */ | |
|
399 | } | |||
388 | if (origlen == esclen) { |
|
400 | if (origlen == esclen) { | |
389 | Py_INCREF(origstr); |
|
401 | Py_INCREF(origstr); | |
390 | return origstr; |
|
402 | return origstr; | |
391 | } |
|
403 | } | |
392 |
|
404 | |||
393 | escstr = PyBytes_FromStringAndSize(NULL, esclen); |
|
405 | escstr = PyBytes_FromStringAndSize(NULL, esclen); | |
394 | if (!escstr) |
|
406 | if (!escstr) { | |
395 | return NULL; |
|
407 | return NULL; | |
|
408 | } | |||
396 | encodejsonescape(PyBytes_AS_STRING(escstr), esclen, origbuf, origlen, |
|
409 | encodejsonescape(PyBytes_AS_STRING(escstr), esclen, origbuf, origlen, | |
397 | paranoid); |
|
410 | paranoid); | |
398 |
|
411 |
@@ -55,13 +55,16 b' struct mpatch_flist *cpygetitem(void *bi' | |||||
55 | int r; |
|
55 | int r; | |
56 |
|
56 | |||
57 | PyObject *tmp = PyList_GetItem((PyObject *)bins, pos); |
|
57 | PyObject *tmp = PyList_GetItem((PyObject *)bins, pos); | |
58 | if (!tmp) |
|
58 | if (!tmp) { | |
59 | return NULL; |
|
59 | return NULL; | |
60 | if (PyObject_GetBuffer(tmp, &buffer, PyBUF_CONTIG_RO)) |
|
60 | } | |
|
61 | if (PyObject_GetBuffer(tmp, &buffer, PyBUF_CONTIG_RO)) { | |||
61 | return NULL; |
|
62 | return NULL; | |
|
63 | } | |||
62 | if ((r = mpatch_decode(buffer.buf, buffer.len, &res)) < 0) { |
|
64 | if ((r = mpatch_decode(buffer.buf, buffer.len, &res)) < 0) { | |
63 | if (!PyErr_Occurred()) |
|
65 | if (!PyErr_Occurred()) { | |
64 | setpyerr(r); |
|
66 | setpyerr(r); | |
|
67 | } | |||
65 | res = NULL; |
|
68 | res = NULL; | |
66 | } |
|
69 | } | |
67 |
|
70 | |||
@@ -78,8 +81,9 b' static PyObject *patches(PyObject *self,' | |||||
78 | char *out; |
|
81 | char *out; | |
79 | Py_ssize_t len, outlen; |
|
82 | Py_ssize_t len, outlen; | |
80 |
|
83 | |||
81 | if (!PyArg_ParseTuple(args, "OO:mpatch", &text, &bins)) |
|
84 | if (!PyArg_ParseTuple(args, "OO:mpatch", &text, &bins)) { | |
82 | return NULL; |
|
85 | return NULL; | |
|
86 | } | |||
83 |
|
87 | |||
84 | len = PyList_Size(bins); |
|
88 | len = PyList_Size(bins); | |
85 | if (!len) { |
|
89 | if (!len) { | |
@@ -94,8 +98,9 b' static PyObject *patches(PyObject *self,' | |||||
94 |
|
98 | |||
95 | patch = mpatch_fold(bins, cpygetitem, 0, len); |
|
99 | patch = mpatch_fold(bins, cpygetitem, 0, len); | |
96 | if (!patch) { /* error already set or memory error */ |
|
100 | if (!patch) { /* error already set or memory error */ | |
97 | if (!PyErr_Occurred()) |
|
101 | if (!PyErr_Occurred()) { | |
98 | PyErr_NoMemory(); |
|
102 | PyErr_NoMemory(); | |
|
103 | } | |||
99 | result = NULL; |
|
104 | result = NULL; | |
100 | goto cleanup; |
|
105 | goto cleanup; | |
101 | } |
|
106 | } | |
@@ -126,8 +131,9 b' static PyObject *patches(PyObject *self,' | |||||
126 | cleanup: |
|
131 | cleanup: | |
127 | mpatch_lfree(patch); |
|
132 | mpatch_lfree(patch); | |
128 | PyBuffer_Release(&buffer); |
|
133 | PyBuffer_Release(&buffer); | |
129 | if (!result && !PyErr_Occurred()) |
|
134 | if (!result && !PyErr_Occurred()) { | |
130 | setpyerr(r); |
|
135 | setpyerr(r); | |
|
136 | } | |||
131 | return result; |
|
137 | return result; | |
132 | } |
|
138 | } | |
133 |
|
139 | |||
@@ -138,15 +144,18 b' static PyObject *patchedsize(PyObject *s' | |||||
138 | Py_ssize_t patchlen; |
|
144 | Py_ssize_t patchlen; | |
139 | char *bin; |
|
145 | char *bin; | |
140 |
|
146 | |||
141 |
if (!PyArg_ParseTuple(args, PY23("ls#", "ly#"), &orig, &bin, |
|
147 | if (!PyArg_ParseTuple(args, PY23("ls#", "ly#"), &orig, &bin, | |
|
148 | &patchlen)) { | |||
142 | return NULL; |
|
149 | return NULL; | |
|
150 | } | |||
143 |
|
151 | |||
144 | while (pos >= 0 && pos < patchlen) { |
|
152 | while (pos >= 0 && pos < patchlen) { | |
145 | start = getbe32(bin + pos); |
|
153 | start = getbe32(bin + pos); | |
146 | end = getbe32(bin + pos + 4); |
|
154 | end = getbe32(bin + pos + 4); | |
147 | len = getbe32(bin + pos + 8); |
|
155 | len = getbe32(bin + pos + 8); | |
148 | if (start > end) |
|
156 | if (start > end) { | |
149 | break; /* sanity check */ |
|
157 | break; /* sanity check */ | |
|
158 | } | |||
150 | pos += 12 + len; |
|
159 | pos += 12 + len; | |
151 | outlen += start - last; |
|
160 | outlen += start - last; | |
152 | last = end; |
|
161 | last = end; | |
@@ -154,9 +163,10 b' static PyObject *patchedsize(PyObject *s' | |||||
154 | } |
|
163 | } | |
155 |
|
164 | |||
156 | if (pos != patchlen) { |
|
165 | if (pos != patchlen) { | |
157 | if (!PyErr_Occurred()) |
|
166 | if (!PyErr_Occurred()) { | |
158 | PyErr_SetString(mpatch_Error, |
|
167 | PyErr_SetString(mpatch_Error, | |
159 | "patch cannot be decoded"); |
|
168 | "patch cannot be decoded"); | |
|
169 | } | |||
160 | return NULL; |
|
170 | return NULL; | |
161 | } |
|
171 | } | |
162 |
|
172 |
@@ -32,8 +32,9 b' static PyObject *dict_new_presized(PyObj' | |||||
32 | { |
|
32 | { | |
33 | Py_ssize_t expected_size; |
|
33 | Py_ssize_t expected_size; | |
34 |
|
34 | |||
35 | if (!PyArg_ParseTuple(args, "n:make_presized_dict", &expected_size)) |
|
35 | if (!PyArg_ParseTuple(args, "n:make_presized_dict", &expected_size)) { | |
36 | return NULL; |
|
36 | return NULL; | |
|
37 | } | |||
37 |
|
38 | |||
38 | return _dict_new_presized(expected_size); |
|
39 | return _dict_new_presized(expected_size); | |
39 | } |
|
40 | } | |
@@ -43,8 +44,9 b' static inline dirstateTupleObject *make_' | |||||
43 | { |
|
44 | { | |
44 | dirstateTupleObject *t = |
|
45 | dirstateTupleObject *t = | |
45 | PyObject_New(dirstateTupleObject, &dirstateTupleType); |
|
46 | PyObject_New(dirstateTupleObject, &dirstateTupleType); | |
46 | if (!t) |
|
47 | if (!t) { | |
47 | return NULL; |
|
48 | return NULL; | |
|
49 | } | |||
48 | t->state = state; |
|
50 | t->state = state; | |
49 | t->mode = mode; |
|
51 | t->mode = mode; | |
50 | t->size = size; |
|
52 | t->size = size; | |
@@ -60,12 +62,14 b' static PyObject *dirstate_tuple_new(PyTy' | |||||
60 | dirstateTupleObject *t; |
|
62 | dirstateTupleObject *t; | |
61 | char state; |
|
63 | char state; | |
62 | int size, mode, mtime; |
|
64 | int size, mode, mtime; | |
63 | if (!PyArg_ParseTuple(args, "ciii", &state, &mode, &size, &mtime)) |
|
65 | if (!PyArg_ParseTuple(args, "ciii", &state, &mode, &size, &mtime)) { | |
64 | return NULL; |
|
66 | return NULL; | |
|
67 | } | |||
65 |
|
68 | |||
66 | t = (dirstateTupleObject *)subtype->tp_alloc(subtype, 1); |
|
69 | t = (dirstateTupleObject *)subtype->tp_alloc(subtype, 1); | |
67 | if (!t) |
|
70 | if (!t) { | |
68 | return NULL; |
|
71 | return NULL; | |
|
72 | } | |||
69 | t->state = state; |
|
73 | t->state = state; | |
70 | t->mode = mode; |
|
74 | t->mode = mode; | |
71 | t->size = size; |
|
75 | t->size = size; | |
@@ -165,8 +169,9 b' static PyObject *parse_dirstate(PyObject' | |||||
165 |
|
169 | |||
166 | if (!PyArg_ParseTuple( |
|
170 | if (!PyArg_ParseTuple( | |
167 | args, PY23("O!O!s#:parse_dirstate", "O!O!y#:parse_dirstate"), |
|
171 | args, PY23("O!O!s#:parse_dirstate", "O!O!y#:parse_dirstate"), | |
168 | &PyDict_Type, &dmap, &PyDict_Type, &cmap, &str, &readlen)) |
|
172 | &PyDict_Type, &dmap, &PyDict_Type, &cmap, &str, &readlen)) { | |
169 | goto quit; |
|
173 | goto quit; | |
|
174 | } | |||
170 |
|
175 | |||
171 | len = readlen; |
|
176 | len = readlen; | |
172 |
|
177 | |||
@@ -178,8 +183,9 b' static PyObject *parse_dirstate(PyObject' | |||||
178 | } |
|
183 | } | |
179 |
|
184 | |||
180 | parents = Py_BuildValue(PY23("s#s#", "y#y#"), str, 20, str + 20, 20); |
|
185 | parents = Py_BuildValue(PY23("s#s#", "y#y#"), str, 20, str + 20, 20); | |
181 | if (!parents) |
|
186 | if (!parents) { | |
182 | goto quit; |
|
187 | goto quit; | |
|
188 | } | |||
183 |
|
189 | |||
184 | /* read filenames */ |
|
190 | /* read filenames */ | |
185 | while (pos >= 40 && pos < len) { |
|
191 | while (pos >= 40 && pos < len) { | |
@@ -212,13 +218,16 b' static PyObject *parse_dirstate(PyObject' | |||||
212 | cpos + 1, flen - (cpos - cur) - 1); |
|
218 | cpos + 1, flen - (cpos - cur) - 1); | |
213 | if (!fname || !cname || |
|
219 | if (!fname || !cname || | |
214 | PyDict_SetItem(cmap, fname, cname) == -1 || |
|
220 | PyDict_SetItem(cmap, fname, cname) == -1 || | |
215 | PyDict_SetItem(dmap, fname, entry) == -1) |
|
221 | PyDict_SetItem(dmap, fname, entry) == -1) { | |
216 | goto quit; |
|
222 | goto quit; | |
|
223 | } | |||
217 | Py_DECREF(cname); |
|
224 | Py_DECREF(cname); | |
218 | } else { |
|
225 | } else { | |
219 | fname = PyBytes_FromStringAndSize(cur, flen); |
|
226 | fname = PyBytes_FromStringAndSize(cur, flen); | |
220 | if (!fname || PyDict_SetItem(dmap, fname, entry) == -1) |
|
227 | if (!fname || | |
|
228 | PyDict_SetItem(dmap, fname, entry) == -1) { | |||
221 | goto quit; |
|
229 | goto quit; | |
|
230 | } | |||
222 | } |
|
231 | } | |
223 | Py_DECREF(fname); |
|
232 | Py_DECREF(fname); | |
224 | Py_DECREF(entry); |
|
233 | Py_DECREF(entry); | |
@@ -245,16 +254,20 b' static PyObject *nonnormalotherparentent' | |||||
245 | PyObject *nonnset = NULL, *otherpset = NULL, *result = NULL; |
|
254 | PyObject *nonnset = NULL, *otherpset = NULL, *result = NULL; | |
246 | Py_ssize_t pos; |
|
255 | Py_ssize_t pos; | |
247 |
|
256 | |||
248 |
if (!PyArg_ParseTuple(args, "O!:nonnormalentries", &PyDict_Type, |
|
257 | if (!PyArg_ParseTuple(args, "O!:nonnormalentries", &PyDict_Type, | |
|
258 | &dmap)) { | |||
249 | goto bail; |
|
259 | goto bail; | |
|
260 | } | |||
250 |
|
261 | |||
251 | nonnset = PySet_New(NULL); |
|
262 | nonnset = PySet_New(NULL); | |
252 | if (nonnset == NULL) |
|
263 | if (nonnset == NULL) { | |
253 | goto bail; |
|
264 | goto bail; | |
|
265 | } | |||
254 |
|
266 | |||
255 | otherpset = PySet_New(NULL); |
|
267 | otherpset = PySet_New(NULL); | |
256 | if (otherpset == NULL) |
|
268 | if (otherpset == NULL) { | |
257 | goto bail; |
|
269 | goto bail; | |
|
270 | } | |||
258 |
|
271 | |||
259 | pos = 0; |
|
272 | pos = 0; | |
260 | while (PyDict_Next(dmap, &pos, &fname, &v)) { |
|
273 | while (PyDict_Next(dmap, &pos, &fname, &v)) { | |
@@ -272,15 +285,18 b' static PyObject *nonnormalotherparentent' | |||||
272 | } |
|
285 | } | |
273 | } |
|
286 | } | |
274 |
|
287 | |||
275 | if (t->state == 'n' && t->mtime != -1) |
|
288 | if (t->state == 'n' && t->mtime != -1) { | |
276 | continue; |
|
289 | continue; | |
277 | if (PySet_Add(nonnset, fname) == -1) |
|
290 | } | |
|
291 | if (PySet_Add(nonnset, fname) == -1) { | |||
278 | goto bail; |
|
292 | goto bail; | |
|
293 | } | |||
279 | } |
|
294 | } | |
280 |
|
295 | |||
281 | result = Py_BuildValue("(OO)", nonnset, otherpset); |
|
296 | result = Py_BuildValue("(OO)", nonnset, otherpset); | |
282 | if (result == NULL) |
|
297 | if (result == NULL) { | |
283 | goto bail; |
|
298 | goto bail; | |
|
299 | } | |||
284 | Py_DECREF(nonnset); |
|
300 | Py_DECREF(nonnset); | |
285 | Py_DECREF(otherpset); |
|
301 | Py_DECREF(otherpset); | |
286 | return result; |
|
302 | return result; | |
@@ -304,8 +320,10 b' static PyObject *pack_dirstate(PyObject ' | |||||
304 | int now; |
|
320 | int now; | |
305 |
|
321 | |||
306 | if (!PyArg_ParseTuple(args, "O!O!O!i:pack_dirstate", &PyDict_Type, &map, |
|
322 | if (!PyArg_ParseTuple(args, "O!O!O!i:pack_dirstate", &PyDict_Type, &map, | |
307 |
&PyDict_Type, ©map, &PyTuple_Type, &pl, |
|
323 | &PyDict_Type, ©map, &PyTuple_Type, &pl, | |
|
324 | &now)) { | |||
308 | return NULL; |
|
325 | return NULL; | |
|
326 | } | |||
309 |
|
327 | |||
310 | if (PyTuple_Size(pl) != 2) { |
|
328 | if (PyTuple_Size(pl) != 2) { | |
311 | PyErr_SetString(PyExc_TypeError, "expected 2-element tuple"); |
|
329 | PyErr_SetString(PyExc_TypeError, "expected 2-element tuple"); | |
@@ -332,8 +350,9 b' static PyObject *pack_dirstate(PyObject ' | |||||
332 | } |
|
350 | } | |
333 |
|
351 | |||
334 | packobj = PyBytes_FromStringAndSize(NULL, nbytes); |
|
352 | packobj = PyBytes_FromStringAndSize(NULL, nbytes); | |
335 | if (packobj == NULL) |
|
353 | if (packobj == NULL) { | |
336 | goto bail; |
|
354 | goto bail; | |
|
355 | } | |||
337 |
|
356 | |||
338 | p = PyBytes_AS_STRING(packobj); |
|
357 | p = PyBytes_AS_STRING(packobj); | |
339 |
|
358 | |||
@@ -377,10 +396,12 b' static PyObject *pack_dirstate(PyObject ' | |||||
377 | mtime = -1; |
|
396 | mtime = -1; | |
378 | mtime_unset = (PyObject *)make_dirstate_tuple( |
|
397 | mtime_unset = (PyObject *)make_dirstate_tuple( | |
379 | state, mode, size, mtime); |
|
398 | state, mode, size, mtime); | |
380 | if (!mtime_unset) |
|
399 | if (!mtime_unset) { | |
381 | goto bail; |
|
400 | goto bail; | |
382 | if (PyDict_SetItem(map, k, mtime_unset) == -1) |
|
401 | } | |
|
402 | if (PyDict_SetItem(map, k, mtime_unset) == -1) { | |||
383 | goto bail; |
|
403 | goto bail; | |
|
404 | } | |||
384 | Py_DECREF(mtime_unset); |
|
405 | Py_DECREF(mtime_unset); | |
385 | mtime_unset = NULL; |
|
406 | mtime_unset = NULL; | |
386 | } |
|
407 | } | |
@@ -664,8 +685,9 b' static void module_init(PyObject *mod)' | |||||
664 | manifest_module_init(mod); |
|
685 | manifest_module_init(mod); | |
665 | revlog_module_init(mod); |
|
686 | revlog_module_init(mod); | |
666 |
|
687 | |||
667 | if (PyType_Ready(&dirstateTupleType) < 0) |
|
688 | if (PyType_Ready(&dirstateTupleType) < 0) { | |
668 | return; |
|
689 | return; | |
|
690 | } | |||
669 | Py_INCREF(&dirstateTupleType); |
|
691 | Py_INCREF(&dirstateTupleType); | |
670 | PyModule_AddObject(mod, "dirstatetuple", |
|
692 | PyModule_AddObject(mod, "dirstatetuple", | |
671 | (PyObject *)&dirstateTupleType); |
|
693 | (PyObject *)&dirstateTupleType); | |
@@ -675,12 +697,14 b' static int check_python_version(void)' | |||||
675 | { |
|
697 | { | |
676 | PyObject *sys = PyImport_ImportModule("sys"), *ver; |
|
698 | PyObject *sys = PyImport_ImportModule("sys"), *ver; | |
677 | long hexversion; |
|
699 | long hexversion; | |
678 | if (!sys) |
|
700 | if (!sys) { | |
679 | return -1; |
|
701 | return -1; | |
|
702 | } | |||
680 | ver = PyObject_GetAttrString(sys, "hexversion"); |
|
703 | ver = PyObject_GetAttrString(sys, "hexversion"); | |
681 | Py_DECREF(sys); |
|
704 | Py_DECREF(sys); | |
682 | if (!ver) |
|
705 | if (!ver) { | |
683 | return -1; |
|
706 | return -1; | |
|
707 | } | |||
684 | hexversion = PyInt_AsLong(ver); |
|
708 | hexversion = PyInt_AsLong(ver); | |
685 | Py_DECREF(ver); |
|
709 | Py_DECREF(ver); | |
686 | /* sys.hexversion is a 32-bit number by default, so the -1 case |
|
710 | /* sys.hexversion is a 32-bit number by default, so the -1 case | |
@@ -720,8 +744,9 b' PyMODINIT_FUNC initparsers(void)' | |||||
720 | { |
|
744 | { | |
721 | PyObject *mod; |
|
745 | PyObject *mod; | |
722 |
|
746 | |||
723 | if (check_python_version() == -1) |
|
747 | if (check_python_version() == -1) { | |
724 | return; |
|
748 | return; | |
|
749 | } | |||
725 | mod = Py_InitModule3("parsers", methods, parsers_doc); |
|
750 | mod = Py_InitModule3("parsers", methods, parsers_doc); | |
726 | module_init(mod); |
|
751 | module_init(mod); | |
727 | } |
|
752 | } |
@@ -126,8 +126,9 b' static Py_ssize_t _encodedir(char *dest,' | |||||
126 | if (src[i] == 'g') { |
|
126 | if (src[i] == 'g') { | |
127 | state = DHGDI; |
|
127 | state = DHGDI; | |
128 | charcopy(dest, &destlen, destsize, src[i++]); |
|
128 | charcopy(dest, &destlen, destsize, src[i++]); | |
129 | } else |
|
129 | } else { | |
130 | state = DDEFAULT; |
|
130 | state = DDEFAULT; | |
|
131 | } | |||
131 | break; |
|
132 | break; | |
132 | case DHGDI: |
|
133 | case DHGDI: | |
133 | if (src[i] == '/') { |
|
134 | if (src[i] == '/') { | |
@@ -137,8 +138,9 b' static Py_ssize_t _encodedir(char *dest,' | |||||
137 | state = DDEFAULT; |
|
138 | state = DDEFAULT; | |
138 | break; |
|
139 | break; | |
139 | case DDEFAULT: |
|
140 | case DDEFAULT: | |
140 | if (src[i] == '.') |
|
141 | if (src[i] == '.') { | |
141 | state = DDOT; |
|
142 | state = DDOT; | |
|
143 | } | |||
142 | charcopy(dest, &destlen, destsize, src[i++]); |
|
144 | charcopy(dest, &destlen, destsize, src[i++]); | |
143 | break; |
|
145 | break; | |
144 | } |
|
146 | } | |
@@ -153,8 +155,9 b' PyObject *encodedir(PyObject *self, PyOb' | |||||
153 | PyObject *pathobj, *newobj; |
|
155 | PyObject *pathobj, *newobj; | |
154 | char *path; |
|
156 | char *path; | |
155 |
|
157 | |||
156 | if (!PyArg_ParseTuple(args, "O:encodedir", &pathobj)) |
|
158 | if (!PyArg_ParseTuple(args, "O:encodedir", &pathobj)) { | |
157 | return NULL; |
|
159 | return NULL; | |
|
160 | } | |||
158 |
|
161 | |||
159 | if (PyBytes_AsStringAndSize(pathobj, &path, &len) == -1) { |
|
162 | if (PyBytes_AsStringAndSize(pathobj, &path, &len) == -1) { | |
160 | PyErr_SetString(PyExc_TypeError, "expected a string"); |
|
163 | PyErr_SetString(PyExc_TypeError, "expected a string"); | |
@@ -235,15 +238,17 b' static Py_ssize_t _encode(const uint32_t' | |||||
235 | if (src[i] == 'u') { |
|
238 | if (src[i] == 'u') { | |
236 | state = AU; |
|
239 | state = AU; | |
237 | charcopy(dest, &destlen, destsize, src[i++]); |
|
240 | charcopy(dest, &destlen, destsize, src[i++]); | |
238 | } else |
|
241 | } else { | |
239 | state = DEFAULT; |
|
242 | state = DEFAULT; | |
|
243 | } | |||
240 | break; |
|
244 | break; | |
241 | case AU: |
|
245 | case AU: | |
242 | if (src[i] == 'x') { |
|
246 | if (src[i] == 'x') { | |
243 | state = THIRD; |
|
247 | state = THIRD; | |
244 | i++; |
|
248 | i++; | |
245 | } else |
|
249 | } else { | |
246 | state = DEFAULT; |
|
250 | state = DEFAULT; | |
|
251 | } | |||
247 | break; |
|
252 | break; | |
248 | case THIRD: |
|
253 | case THIRD: | |
249 | state = DEFAULT; |
|
254 | state = DEFAULT; | |
@@ -262,8 +267,9 b' static Py_ssize_t _encode(const uint32_t' | |||||
262 | if (src[i] == 'o') { |
|
267 | if (src[i] == 'o') { | |
263 | state = CO; |
|
268 | state = CO; | |
264 | charcopy(dest, &destlen, destsize, src[i++]); |
|
269 | charcopy(dest, &destlen, destsize, src[i++]); | |
265 | } else |
|
270 | } else { | |
266 | state = DEFAULT; |
|
271 | state = DEFAULT; | |
|
272 | } | |||
267 | break; |
|
273 | break; | |
268 | case CO: |
|
274 | case CO: | |
269 | if (src[i] == 'm') { |
|
275 | if (src[i] == 'm') { | |
@@ -272,8 +278,9 b' static Py_ssize_t _encode(const uint32_t' | |||||
272 | } else if (src[i] == 'n') { |
|
278 | } else if (src[i] == 'n') { | |
273 | state = THIRD; |
|
279 | state = THIRD; | |
274 | i++; |
|
280 | i++; | |
275 | } else |
|
281 | } else { | |
276 | state = DEFAULT; |
|
282 | state = DEFAULT; | |
|
283 | } | |||
277 | break; |
|
284 | break; | |
278 | case COMLPT: |
|
285 | case COMLPT: | |
279 | switch (src[i]) { |
|
286 | switch (src[i]) { | |
@@ -314,43 +321,49 b' static Py_ssize_t _encode(const uint32_t' | |||||
314 | if (src[i] == 'p') { |
|
321 | if (src[i] == 'p') { | |
315 | state = LP; |
|
322 | state = LP; | |
316 | charcopy(dest, &destlen, destsize, src[i++]); |
|
323 | charcopy(dest, &destlen, destsize, src[i++]); | |
317 | } else |
|
324 | } else { | |
318 | state = DEFAULT; |
|
325 | state = DEFAULT; | |
|
326 | } | |||
319 | break; |
|
327 | break; | |
320 | case LP: |
|
328 | case LP: | |
321 | if (src[i] == 't') { |
|
329 | if (src[i] == 't') { | |
322 | state = COMLPT; |
|
330 | state = COMLPT; | |
323 | i++; |
|
331 | i++; | |
324 | } else |
|
332 | } else { | |
325 | state = DEFAULT; |
|
333 | state = DEFAULT; | |
|
334 | } | |||
326 | break; |
|
335 | break; | |
327 | case N: |
|
336 | case N: | |
328 | if (src[i] == 'u') { |
|
337 | if (src[i] == 'u') { | |
329 | state = NU; |
|
338 | state = NU; | |
330 | charcopy(dest, &destlen, destsize, src[i++]); |
|
339 | charcopy(dest, &destlen, destsize, src[i++]); | |
331 | } else |
|
340 | } else { | |
332 | state = DEFAULT; |
|
341 | state = DEFAULT; | |
|
342 | } | |||
333 | break; |
|
343 | break; | |
334 | case NU: |
|
344 | case NU: | |
335 | if (src[i] == 'l') { |
|
345 | if (src[i] == 'l') { | |
336 | state = THIRD; |
|
346 | state = THIRD; | |
337 | i++; |
|
347 | i++; | |
338 | } else |
|
348 | } else { | |
339 | state = DEFAULT; |
|
349 | state = DEFAULT; | |
|
350 | } | |||
340 | break; |
|
351 | break; | |
341 | case P: |
|
352 | case P: | |
342 | if (src[i] == 'r') { |
|
353 | if (src[i] == 'r') { | |
343 | state = PR; |
|
354 | state = PR; | |
344 | charcopy(dest, &destlen, destsize, src[i++]); |
|
355 | charcopy(dest, &destlen, destsize, src[i++]); | |
345 | } else |
|
356 | } else { | |
346 | state = DEFAULT; |
|
357 | state = DEFAULT; | |
|
358 | } | |||
347 | break; |
|
359 | break; | |
348 | case PR: |
|
360 | case PR: | |
349 | if (src[i] == 'n') { |
|
361 | if (src[i] == 'n') { | |
350 | state = THIRD; |
|
362 | state = THIRD; | |
351 | i++; |
|
363 | i++; | |
352 | } else |
|
364 | } else { | |
353 | state = DEFAULT; |
|
365 | state = DEFAULT; | |
|
366 | } | |||
354 | break; |
|
367 | break; | |
355 | case LDOT: |
|
368 | case LDOT: | |
356 | switch (src[i]) { |
|
369 | switch (src[i]) { | |
@@ -397,18 +410,21 b' static Py_ssize_t _encode(const uint32_t' | |||||
397 | if (src[i] == 'g') { |
|
410 | if (src[i] == 'g') { | |
398 | state = HGDI; |
|
411 | state = HGDI; | |
399 | charcopy(dest, &destlen, destsize, src[i++]); |
|
412 | charcopy(dest, &destlen, destsize, src[i++]); | |
400 | } else |
|
413 | } else { | |
401 | state = DEFAULT; |
|
414 | state = DEFAULT; | |
|
415 | } | |||
402 | break; |
|
416 | break; | |
403 | case HGDI: |
|
417 | case HGDI: | |
404 | if (src[i] == '/') { |
|
418 | if (src[i] == '/') { | |
405 | state = START; |
|
419 | state = START; | |
406 | if (encodedir) |
|
420 | if (encodedir) { | |
407 | memcopy(dest, &destlen, destsize, ".hg", |
|
421 | memcopy(dest, &destlen, destsize, ".hg", | |
408 | 3); |
|
422 | 3); | |
|
423 | } | |||
409 | charcopy(dest, &destlen, destsize, src[i++]); |
|
424 | charcopy(dest, &destlen, destsize, src[i++]); | |
410 | } else |
|
425 | } else { | |
411 | state = DEFAULT; |
|
426 | state = DEFAULT; | |
|
427 | } | |||
412 | break; |
|
428 | break; | |
413 | case SPACE: |
|
429 | case SPACE: | |
414 | switch (src[i]) { |
|
430 | switch (src[i]) { | |
@@ -427,8 +443,9 b' static Py_ssize_t _encode(const uint32_t' | |||||
427 | case DEFAULT: |
|
443 | case DEFAULT: | |
428 | while (inset(onebyte, src[i])) { |
|
444 | while (inset(onebyte, src[i])) { | |
429 | charcopy(dest, &destlen, destsize, src[i++]); |
|
445 | charcopy(dest, &destlen, destsize, src[i++]); | |
430 | if (i == len) |
|
446 | if (i == len) { | |
431 | goto done; |
|
447 | goto done; | |
|
448 | } | |||
432 | } |
|
449 | } | |
433 | switch (src[i]) { |
|
450 | switch (src[i]) { | |
434 | case '.': |
|
451 | case '.': | |
@@ -456,9 +473,10 b' static Py_ssize_t _encode(const uint32_t' | |||||
456 | charcopy(dest, &destlen, destsize, '_'); |
|
473 | charcopy(dest, &destlen, destsize, '_'); | |
457 | charcopy(dest, &destlen, destsize, |
|
474 | charcopy(dest, &destlen, destsize, | |
458 | c == '_' ? '_' : c + 32); |
|
475 | c == '_' ? '_' : c + 32); | |
459 | } else |
|
476 | } else { | |
460 | escape3(dest, &destlen, destsize, |
|
477 | escape3(dest, &destlen, destsize, | |
461 | src[i++]); |
|
478 | src[i++]); | |
|
479 | } | |||
462 | break; |
|
480 | break; | |
463 | } |
|
481 | } | |
464 | break; |
|
482 | break; | |
@@ -498,12 +516,13 b' static Py_ssize_t _lowerencode(char *des' | |||||
498 | Py_ssize_t i, destlen = 0; |
|
516 | Py_ssize_t i, destlen = 0; | |
499 |
|
517 | |||
500 | for (i = 0; i < len; i++) { |
|
518 | for (i = 0; i < len; i++) { | |
501 | if (inset(onebyte, src[i])) |
|
519 | if (inset(onebyte, src[i])) { | |
502 | charcopy(dest, &destlen, destsize, src[i]); |
|
520 | charcopy(dest, &destlen, destsize, src[i]); | |
503 | else if (inset(lower, src[i])) |
|
521 | } else if (inset(lower, src[i])) { | |
504 | charcopy(dest, &destlen, destsize, src[i] + 32); |
|
522 | charcopy(dest, &destlen, destsize, src[i] + 32); | |
505 | else |
|
523 | } else { | |
506 | escape3(dest, &destlen, destsize, src[i]); |
|
524 | escape3(dest, &destlen, destsize, src[i]); | |
|
525 | } | |||
507 | } |
|
526 | } | |
508 |
|
527 | |||
509 | return destlen; |
|
528 | return destlen; | |
@@ -516,13 +535,15 b' PyObject *lowerencode(PyObject *self, Py' | |||||
516 | PyObject *ret; |
|
535 | PyObject *ret; | |
517 |
|
536 | |||
518 | if (!PyArg_ParseTuple(args, PY23("s#:lowerencode", "y#:lowerencode"), |
|
537 | if (!PyArg_ParseTuple(args, PY23("s#:lowerencode", "y#:lowerencode"), | |
519 | &path, &len)) |
|
538 | &path, &len)) { | |
520 | return NULL; |
|
539 | return NULL; | |
|
540 | } | |||
521 |
|
541 | |||
522 | newlen = _lowerencode(NULL, 0, path, len); |
|
542 | newlen = _lowerencode(NULL, 0, path, len); | |
523 | ret = PyBytes_FromStringAndSize(NULL, newlen); |
|
543 | ret = PyBytes_FromStringAndSize(NULL, newlen); | |
524 | if (ret) |
|
544 | if (ret) { | |
525 | _lowerencode(PyBytes_AS_STRING(ret), newlen, path, len); |
|
545 | _lowerencode(PyBytes_AS_STRING(ret), newlen, path, len); | |
|
546 | } | |||
526 |
|
547 | |||
527 | return ret; |
|
548 | return ret; | |
528 | } |
|
549 | } | |
@@ -551,8 +572,9 b' static PyObject *hashmangle(const char *' | |||||
551 | Py_ssize_t destsize, destlen = 0, slop, used; |
|
572 | Py_ssize_t destsize, destlen = 0, slop, used; | |
552 |
|
573 | |||
553 | while (lastslash >= 0 && src[lastslash] != '/') { |
|
574 | while (lastslash >= 0 && src[lastslash] != '/') { | |
554 | if (src[lastslash] == '.' && lastdot == -1) |
|
575 | if (src[lastslash] == '.' && lastdot == -1) { | |
555 | lastdot = lastslash; |
|
576 | lastdot = lastslash; | |
|
577 | } | |||
556 | lastslash--; |
|
578 | lastslash--; | |
557 | } |
|
579 | } | |
558 |
|
580 | |||
@@ -570,12 +592,14 b' static PyObject *hashmangle(const char *' | |||||
570 | /* If src contains a suffix, we will append it to the end of |
|
592 | /* If src contains a suffix, we will append it to the end of | |
571 | the new string, so make room. */ |
|
593 | the new string, so make room. */ | |
572 | destsize = 120; |
|
594 | destsize = 120; | |
573 | if (lastdot >= 0) |
|
595 | if (lastdot >= 0) { | |
574 | destsize += len - lastdot - 1; |
|
596 | destsize += len - lastdot - 1; | |
|
597 | } | |||
575 |
|
598 | |||
576 | ret = PyBytes_FromStringAndSize(NULL, destsize); |
|
599 | ret = PyBytes_FromStringAndSize(NULL, destsize); | |
577 | if (ret == NULL) |
|
600 | if (ret == NULL) { | |
578 | return NULL; |
|
601 | return NULL; | |
|
602 | } | |||
579 |
|
603 | |||
580 | dest = PyBytes_AS_STRING(ret); |
|
604 | dest = PyBytes_AS_STRING(ret); | |
581 | memcopy(dest, &destlen, destsize, "dh/", 3); |
|
605 | memcopy(dest, &destlen, destsize, "dh/", 3); | |
@@ -587,30 +611,36 b' static PyObject *hashmangle(const char *' | |||||
587 | char d = dest[destlen - 1]; |
|
611 | char d = dest[destlen - 1]; | |
588 | /* After truncation, a directory name may end |
|
612 | /* After truncation, a directory name may end | |
589 | in a space or dot, which are unportable. */ |
|
613 | in a space or dot, which are unportable. */ | |
590 | if (d == '.' || d == ' ') |
|
614 | if (d == '.' || d == ' ') { | |
591 | dest[destlen - 1] = '_'; |
|
615 | dest[destlen - 1] = '_'; | |
592 |
/* The + 3 is to account for "dh/" in the |
|
616 | /* The + 3 is to account for "dh/" in the | |
593 | if (destlen > maxshortdirslen + 3) |
|
617 | * beginning */ | |
|
618 | } | |||
|
619 | if (destlen > maxshortdirslen + 3) { | |||
594 | break; |
|
620 | break; | |
|
621 | } | |||
595 | charcopy(dest, &destlen, destsize, src[i]); |
|
622 | charcopy(dest, &destlen, destsize, src[i]); | |
596 | p = -1; |
|
623 | p = -1; | |
597 | } else if (p < dirprefixlen) |
|
624 | } else if (p < dirprefixlen) { | |
598 | charcopy(dest, &destlen, destsize, src[i]); |
|
625 | charcopy(dest, &destlen, destsize, src[i]); | |
|
626 | } | |||
599 | } |
|
627 | } | |
600 |
|
628 | |||
601 | /* Rewind to just before the last slash copied. */ |
|
629 | /* Rewind to just before the last slash copied. */ | |
602 | if (destlen > maxshortdirslen + 3) |
|
630 | if (destlen > maxshortdirslen + 3) { | |
603 | do { |
|
631 | do { | |
604 | destlen--; |
|
632 | destlen--; | |
605 | } while (destlen > 0 && dest[destlen] != '/'); |
|
633 | } while (destlen > 0 && dest[destlen] != '/'); | |
|
634 | } | |||
606 |
|
635 | |||
607 | if (destlen > 3) { |
|
636 | if (destlen > 3) { | |
608 | if (lastslash > 0) { |
|
637 | if (lastslash > 0) { | |
609 | char d = dest[destlen - 1]; |
|
638 | char d = dest[destlen - 1]; | |
610 | /* The last directory component may be |
|
639 | /* The last directory component may be | |
611 | truncated, so make it safe. */ |
|
640 | truncated, so make it safe. */ | |
612 | if (d == '.' || d == ' ') |
|
641 | if (d == '.' || d == ' ') { | |
613 | dest[destlen - 1] = '_'; |
|
642 | dest[destlen - 1] = '_'; | |
|
643 | } | |||
614 | } |
|
644 | } | |
615 |
|
645 | |||
616 | charcopy(dest, &destlen, destsize, '/'); |
|
646 | charcopy(dest, &destlen, destsize, '/'); | |
@@ -620,27 +650,32 b' static PyObject *hashmangle(const char *' | |||||
620 | depends on the number of bytes left after accounting for |
|
650 | depends on the number of bytes left after accounting for | |
621 | hash and suffix. */ |
|
651 | hash and suffix. */ | |
622 | used = destlen + 40; |
|
652 | used = destlen + 40; | |
623 | if (lastdot >= 0) |
|
653 | if (lastdot >= 0) { | |
624 | used += len - lastdot - 1; |
|
654 | used += len - lastdot - 1; | |
|
655 | } | |||
625 | slop = maxstorepathlen - used; |
|
656 | slop = maxstorepathlen - used; | |
626 | if (slop > 0) { |
|
657 | if (slop > 0) { | |
627 | Py_ssize_t basenamelen = |
|
658 | Py_ssize_t basenamelen = | |
628 | lastslash >= 0 ? len - lastslash - 2 : len - 1; |
|
659 | lastslash >= 0 ? len - lastslash - 2 : len - 1; | |
629 |
|
660 | |||
630 | if (basenamelen > slop) |
|
661 | if (basenamelen > slop) { | |
631 | basenamelen = slop; |
|
662 | basenamelen = slop; | |
632 | if (basenamelen > 0) |
|
663 | } | |
|
664 | if (basenamelen > 0) { | |||
633 | memcopy(dest, &destlen, destsize, &src[lastslash + 1], |
|
665 | memcopy(dest, &destlen, destsize, &src[lastslash + 1], | |
634 | basenamelen); |
|
666 | basenamelen); | |
|
667 | } | |||
635 | } |
|
668 | } | |
636 |
|
669 | |||
637 | /* Add hash and suffix. */ |
|
670 | /* Add hash and suffix. */ | |
638 | for (i = 0; i < 20; i++) |
|
671 | for (i = 0; i < 20; i++) { | |
639 | hexencode(dest, &destlen, destsize, sha[i]); |
|
672 | hexencode(dest, &destlen, destsize, sha[i]); | |
|
673 | } | |||
640 |
|
674 | |||
641 | if (lastdot >= 0) |
|
675 | if (lastdot >= 0) { | |
642 | memcopy(dest, &destlen, destsize, &src[lastdot], |
|
676 | memcopy(dest, &destlen, destsize, &src[lastdot], | |
643 | len - lastdot - 1); |
|
677 | len - lastdot - 1); | |
|
678 | } | |||
644 |
|
679 | |||
645 | assert(PyBytes_Check(ret)); |
|
680 | assert(PyBytes_Check(ret)); | |
646 | Py_SIZE(ret) = destlen; |
|
681 | Py_SIZE(ret) = destlen; | |
@@ -677,13 +712,15 b' static int sha1hash(char hash[20], const' | |||||
677 |
|
712 | |||
678 | shaobj = PyObject_CallFunction(shafunc, PY23("s#", "y#"), str, len); |
|
713 | shaobj = PyObject_CallFunction(shafunc, PY23("s#", "y#"), str, len); | |
679 |
|
714 | |||
680 | if (shaobj == NULL) |
|
715 | if (shaobj == NULL) { | |
681 | return -1; |
|
716 | return -1; | |
|
717 | } | |||
682 |
|
718 | |||
683 | hashobj = PyObject_CallMethod(shaobj, "digest", ""); |
|
719 | hashobj = PyObject_CallMethod(shaobj, "digest", ""); | |
684 | Py_DECREF(shaobj); |
|
720 | Py_DECREF(shaobj); | |
685 | if (hashobj == NULL) |
|
721 | if (hashobj == NULL) { | |
686 | return -1; |
|
722 | return -1; | |
|
723 | } | |||
687 |
|
724 | |||
688 | if (!PyBytes_Check(hashobj) || PyBytes_GET_SIZE(hashobj) != 20) { |
|
725 | if (!PyBytes_Check(hashobj) || PyBytes_GET_SIZE(hashobj) != 20) { | |
689 | PyErr_SetString(PyExc_TypeError, |
|
726 | PyErr_SetString(PyExc_TypeError, | |
@@ -714,8 +751,9 b' static PyObject *hashencode(const char *' | |||||
714 | } |
|
751 | } | |
715 |
|
752 | |||
716 | dirlen = _encodedir(dired, baselen, src, len); |
|
753 | dirlen = _encodedir(dired, baselen, src, len); | |
717 | if (sha1hash(sha, dired, dirlen - 1) == -1) |
|
754 | if (sha1hash(sha, dired, dirlen - 1) == -1) { | |
718 | return NULL; |
|
755 | return NULL; | |
|
756 | } | |||
719 | lowerlen = _lowerencode(lowered, baselen, dired + 5, dirlen - 5); |
|
757 | lowerlen = _lowerencode(lowered, baselen, dired + 5, dirlen - 5); | |
720 | auxlen = auxencode(auxed, baselen, lowered, lowerlen); |
|
758 | auxlen = auxencode(auxed, baselen, lowered, lowerlen); | |
721 | return hashmangle(auxed, auxlen, sha); |
|
759 | return hashmangle(auxed, auxlen, sha); | |
@@ -727,18 +765,20 b' PyObject *pathencode(PyObject *self, PyO' | |||||
727 | PyObject *pathobj, *newobj; |
|
765 | PyObject *pathobj, *newobj; | |
728 | char *path; |
|
766 | char *path; | |
729 |
|
767 | |||
730 | if (!PyArg_ParseTuple(args, "O:pathencode", &pathobj)) |
|
768 | if (!PyArg_ParseTuple(args, "O:pathencode", &pathobj)) { | |
731 | return NULL; |
|
769 | return NULL; | |
|
770 | } | |||
732 |
|
771 | |||
733 | if (PyBytes_AsStringAndSize(pathobj, &path, &len) == -1) { |
|
772 | if (PyBytes_AsStringAndSize(pathobj, &path, &len) == -1) { | |
734 | PyErr_SetString(PyExc_TypeError, "expected a string"); |
|
773 | PyErr_SetString(PyExc_TypeError, "expected a string"); | |
735 | return NULL; |
|
774 | return NULL; | |
736 | } |
|
775 | } | |
737 |
|
776 | |||
738 | if (len > maxstorepathlen) |
|
777 | if (len > maxstorepathlen) { | |
739 | newlen = maxstorepathlen + 2; |
|
778 | newlen = maxstorepathlen + 2; | |
740 | else |
|
779 | } else { | |
741 | newlen = len ? basicencode(NULL, 0, path, len + 1) : 1; |
|
780 | newlen = len ? basicencode(NULL, 0, path, len + 1) : 1; | |
|
781 | } | |||
742 |
|
782 | |||
743 | if (newlen <= maxstorepathlen + 1) { |
|
783 | if (newlen <= maxstorepathlen + 1) { | |
744 | if (newlen == len + 1) { |
|
784 | if (newlen == len + 1) { | |
@@ -754,8 +794,9 b' PyObject *pathencode(PyObject *self, PyO' | |||||
754 | basicencode(PyBytes_AS_STRING(newobj), newlen, path, |
|
794 | basicencode(PyBytes_AS_STRING(newobj), newlen, path, | |
755 | len + 1); |
|
795 | len + 1); | |
756 | } |
|
796 | } | |
757 | } else |
|
797 | } else { | |
758 | newobj = hashencode(path, len + 1); |
|
798 | newobj = hashencode(path, len + 1); | |
|
799 | } | |||
759 |
|
800 | |||
760 | return newobj; |
|
801 | return newobj; | |
761 | } |
|
802 | } |
@@ -41,8 +41,9 b' static struct mpatch_flist *lalloc(ssize' | |||||
41 | { |
|
41 | { | |
42 | struct mpatch_flist *a = NULL; |
|
42 | struct mpatch_flist *a = NULL; | |
43 |
|
43 | |||
44 | if (size < 1) |
|
44 | if (size < 1) { | |
45 | size = 1; |
|
45 | size = 1; | |
|
46 | } | |||
46 |
|
47 | |||
47 | a = (struct mpatch_flist *)malloc(sizeof(struct mpatch_flist)); |
|
48 | a = (struct mpatch_flist *)malloc(sizeof(struct mpatch_flist)); | |
48 | if (a) { |
|
49 | if (a) { | |
@@ -110,10 +111,12 b' static int gather(struct mpatch_flist *d' | |||||
110 |
|
111 | |||
111 | while (s != src->tail) { |
|
112 | while (s != src->tail) { | |
112 | int soffset = s->start; |
|
113 | int soffset = s->start; | |
113 | if (!safeadd(offset, &soffset)) |
|
114 | if (!safeadd(offset, &soffset)) { | |
114 | break; /* add would overflow, oh well */ |
|
115 | break; /* add would overflow, oh well */ | |
115 | if (soffset >= cut) |
|
116 | } | |
|
117 | if (soffset >= cut) { | |||
116 | break; /* we've gone far enough */ |
|
118 | break; /* we've gone far enough */ | |
|
119 | } | |||
117 |
|
120 | |||
118 | postend = offset; |
|
121 | postend = offset; | |
119 | if (!safeadd(s->start, &postend) || |
|
122 | if (!safeadd(s->start, &postend) || | |
@@ -139,11 +142,13 b' static int gather(struct mpatch_flist *d' | |||||
139 | if (!safesub(offset, &c)) { |
|
142 | if (!safesub(offset, &c)) { | |
140 | break; |
|
143 | break; | |
141 | } |
|
144 | } | |
142 | if (s->end < c) |
|
145 | if (s->end < c) { | |
143 | c = s->end; |
|
146 | c = s->end; | |
|
147 | } | |||
144 | l = cut - offset - s->start; |
|
148 | l = cut - offset - s->start; | |
145 | if (s->len < l) |
|
149 | if (s->len < l) { | |
146 | l = s->len; |
|
150 | l = s->len; | |
|
151 | } | |||
147 |
|
152 | |||
148 | offset += s->start + l - c; |
|
153 | offset += s->start + l - c; | |
149 |
|
154 | |||
@@ -176,8 +181,9 b' static int discard(struct mpatch_flist *' | |||||
176 | if (!safeadd(offset, &cmpcut)) { |
|
181 | if (!safeadd(offset, &cmpcut)) { | |
177 | break; |
|
182 | break; | |
178 | } |
|
183 | } | |
179 | if (cmpcut >= cut) |
|
184 | if (cmpcut >= cut) { | |
180 | break; |
|
185 | break; | |
|
186 | } | |||
181 |
|
187 | |||
182 | postend = offset; |
|
188 | postend = offset; | |
183 | if (!safeadd(s->start, &postend)) { |
|
189 | if (!safeadd(s->start, &postend)) { | |
@@ -205,11 +211,13 b' static int discard(struct mpatch_flist *' | |||||
205 | if (!safesub(offset, &c)) { |
|
211 | if (!safesub(offset, &c)) { | |
206 | break; |
|
212 | break; | |
207 | } |
|
213 | } | |
208 | if (s->end < c) |
|
214 | if (s->end < c) { | |
209 | c = s->end; |
|
215 | c = s->end; | |
|
216 | } | |||
210 | l = cut - offset - s->start; |
|
217 | l = cut - offset - s->start; | |
211 | if (s->len < l) |
|
218 | if (s->len < l) { | |
212 | l = s->len; |
|
219 | l = s->len; | |
|
220 | } | |||
213 |
|
221 | |||
214 | offset += s->start + l - c; |
|
222 | offset += s->start + l - c; | |
215 | s->start = c; |
|
223 | s->start = c; | |
@@ -233,8 +241,9 b' static struct mpatch_flist *combine(stru' | |||||
233 | struct mpatch_frag *bh, *ct; |
|
241 | struct mpatch_frag *bh, *ct; | |
234 | int offset = 0, post; |
|
242 | int offset = 0, post; | |
235 |
|
243 | |||
236 | if (a && b) |
|
244 | if (a && b) { | |
237 | c = lalloc((lsize(a) + lsize(b)) * 2); |
|
245 | c = lalloc((lsize(a) + lsize(b)) * 2); | |
|
246 | } | |||
238 |
|
247 | |||
239 | if (c) { |
|
248 | if (c) { | |
240 |
|
249 | |||
@@ -284,8 +293,9 b' int mpatch_decode(const char *bin, ssize' | |||||
284 |
|
293 | |||
285 | /* assume worst case size, we won't have many of these lists */ |
|
294 | /* assume worst case size, we won't have many of these lists */ | |
286 | l = lalloc(len / 12 + 1); |
|
295 | l = lalloc(len / 12 + 1); | |
287 | if (!l) |
|
296 | if (!l) { | |
288 | return MPATCH_ERR_NO_MEM; |
|
297 | return MPATCH_ERR_NO_MEM; | |
|
298 | } | |||
289 |
|
299 | |||
290 | lt = l->tail; |
|
300 | lt = l->tail; | |
291 |
|
301 | |||
@@ -295,8 +305,9 b' int mpatch_decode(const char *bin, ssize' | |||||
295 | lt->start = getbe32(bin + pos); |
|
305 | lt->start = getbe32(bin + pos); | |
296 | lt->end = getbe32(bin + pos + 4); |
|
306 | lt->end = getbe32(bin + pos + 4); | |
297 | lt->len = getbe32(bin + pos + 8); |
|
307 | lt->len = getbe32(bin + pos + 8); | |
298 | if (lt->start < 0 || lt->start > lt->end || lt->len < 0) |
|
308 | if (lt->start < 0 || lt->start > lt->end || lt->len < 0) { | |
299 | break; /* sanity check */ |
|
309 | break; /* sanity check */ | |
|
310 | } | |||
300 | if (!safeadd(12, &pos)) { |
|
311 | if (!safeadd(12, &pos)) { | |
301 | break; |
|
312 | break; | |
302 | } |
|
313 | } |
@@ -33,28 +33,36 b' static void handlestopsignal(int sig)' | |||||
33 | { |
|
33 | { | |
34 | sigset_t unblockset, oldset; |
|
34 | sigset_t unblockset, oldset; | |
35 | struct sigaction sa, oldsa; |
|
35 | struct sigaction sa, oldsa; | |
36 | if (sigemptyset(&unblockset) < 0) |
|
36 | if (sigemptyset(&unblockset) < 0) { | |
37 | return; |
|
37 | return; | |
38 | if (sigaddset(&unblockset, sig) < 0) |
|
38 | } | |
|
39 | if (sigaddset(&unblockset, sig) < 0) { | |||
39 | return; |
|
40 | return; | |
|
41 | } | |||
40 | memset(&sa, 0, sizeof(sa)); |
|
42 | memset(&sa, 0, sizeof(sa)); | |
41 | sa.sa_handler = SIG_DFL; |
|
43 | sa.sa_handler = SIG_DFL; | |
42 | sa.sa_flags = SA_RESTART; |
|
44 | sa.sa_flags = SA_RESTART; | |
43 | if (sigemptyset(&sa.sa_mask) < 0) |
|
45 | if (sigemptyset(&sa.sa_mask) < 0) { | |
44 | return; |
|
46 | return; | |
|
47 | } | |||
45 |
|
48 | |||
46 | forwardsignal(sig); |
|
49 | forwardsignal(sig); | |
47 | if (raise(sig) < 0) /* resend to self */ |
|
50 | if (raise(sig) < 0) { /* resend to self */ | |
48 | return; |
|
51 | return; | |
49 | if (sigaction(sig, &sa, &oldsa) < 0) |
|
52 | } | |
|
53 | if (sigaction(sig, &sa, &oldsa) < 0) { | |||
50 | return; |
|
54 | return; | |
51 | if (sigprocmask(SIG_UNBLOCK, &unblockset, &oldset) < 0) |
|
55 | } | |
|
56 | if (sigprocmask(SIG_UNBLOCK, &unblockset, &oldset) < 0) { | |||
52 | return; |
|
57 | return; | |
|
58 | } | |||
53 | /* resent signal will be handled before sigprocmask() returns */ |
|
59 | /* resent signal will be handled before sigprocmask() returns */ | |
54 | if (sigprocmask(SIG_SETMASK, &oldset, NULL) < 0) |
|
60 | if (sigprocmask(SIG_SETMASK, &oldset, NULL) < 0) { | |
55 | return; |
|
61 | return; | |
56 | if (sigaction(sig, &oldsa, NULL) < 0) |
|
62 | } | |
|
63 | if (sigaction(sig, &oldsa, NULL) < 0) { | |||
57 | return; |
|
64 | return; | |
|
65 | } | |||
58 | } |
|
66 | } | |
59 |
|
67 | |||
60 | /* |
|
68 | /* | |
@@ -81,37 +89,46 b' int setupsignalhandler(pid_t pid, pid_t ' | |||||
81 | * - SIGINT: usually generated by the terminal */ |
|
89 | * - SIGINT: usually generated by the terminal */ | |
82 | sa.sa_handler = forwardsignaltogroup; |
|
90 | sa.sa_handler = forwardsignaltogroup; | |
83 | sa.sa_flags = SA_RESTART; |
|
91 | sa.sa_flags = SA_RESTART; | |
84 | if (sigemptyset(&sa.sa_mask) < 0) |
|
92 | if (sigemptyset(&sa.sa_mask) < 0) { | |
|
93 | return -1; | |||
|
94 | } | |||
|
95 | if (sigaction(SIGHUP, &sa, NULL) < 0) { | |||
85 | return -1; |
|
96 | return -1; | |
86 | if (sigaction(SIGHUP, &sa, NULL) < 0) |
|
97 | } | |
|
98 | if (sigaction(SIGINT, &sa, NULL) < 0) { | |||
87 | return -1; |
|
99 | return -1; | |
88 | if (sigaction(SIGINT, &sa, NULL) < 0) |
|
100 | } | |
89 | return -1; |
|
|||
90 |
|
101 | |||
91 | /* terminate frontend by double SIGTERM in case of server freeze */ |
|
102 | /* terminate frontend by double SIGTERM in case of server freeze */ | |
92 | sa.sa_handler = forwardsignal; |
|
103 | sa.sa_handler = forwardsignal; | |
93 | sa.sa_flags |= SA_RESETHAND; |
|
104 | sa.sa_flags |= SA_RESETHAND; | |
94 | if (sigaction(SIGTERM, &sa, NULL) < 0) |
|
105 | if (sigaction(SIGTERM, &sa, NULL) < 0) { | |
95 | return -1; |
|
106 | return -1; | |
|
107 | } | |||
96 |
|
108 | |||
97 | /* notify the worker about window resize events */ |
|
109 | /* notify the worker about window resize events */ | |
98 | sa.sa_flags = SA_RESTART; |
|
110 | sa.sa_flags = SA_RESTART; | |
99 | if (sigaction(SIGWINCH, &sa, NULL) < 0) |
|
111 | if (sigaction(SIGWINCH, &sa, NULL) < 0) { | |
100 | return -1; |
|
112 | return -1; | |
|
113 | } | |||
101 | /* forward user-defined signals */ |
|
114 | /* forward user-defined signals */ | |
102 | if (sigaction(SIGUSR1, &sa, NULL) < 0) |
|
115 | if (sigaction(SIGUSR1, &sa, NULL) < 0) { | |
103 | return -1; |
|
116 | return -1; | |
104 | if (sigaction(SIGUSR2, &sa, NULL) < 0) |
|
117 | } | |
|
118 | if (sigaction(SIGUSR2, &sa, NULL) < 0) { | |||
105 | return -1; |
|
119 | return -1; | |
|
120 | } | |||
106 | /* propagate job control requests to worker */ |
|
121 | /* propagate job control requests to worker */ | |
107 | sa.sa_handler = forwardsignal; |
|
122 | sa.sa_handler = forwardsignal; | |
108 | sa.sa_flags = SA_RESTART; |
|
123 | sa.sa_flags = SA_RESTART; | |
109 | if (sigaction(SIGCONT, &sa, NULL) < 0) |
|
124 | if (sigaction(SIGCONT, &sa, NULL) < 0) { | |
110 | return -1; |
|
125 | return -1; | |
|
126 | } | |||
111 | sa.sa_handler = handlestopsignal; |
|
127 | sa.sa_handler = handlestopsignal; | |
112 | sa.sa_flags = SA_RESTART; |
|
128 | sa.sa_flags = SA_RESTART; | |
113 | if (sigaction(SIGTSTP, &sa, NULL) < 0) |
|
129 | if (sigaction(SIGTSTP, &sa, NULL) < 0) { | |
114 | return -1; |
|
130 | return -1; | |
|
131 | } | |||
115 |
|
132 | |||
116 | return 0; |
|
133 | return 0; | |
117 | } |
|
134 | } | |
@@ -127,24 +144,31 b' int restoresignalhandler(void)' | |||||
127 | memset(&sa, 0, sizeof(sa)); |
|
144 | memset(&sa, 0, sizeof(sa)); | |
128 | sa.sa_handler = SIG_DFL; |
|
145 | sa.sa_handler = SIG_DFL; | |
129 | sa.sa_flags = SA_RESTART; |
|
146 | sa.sa_flags = SA_RESTART; | |
130 | if (sigemptyset(&sa.sa_mask) < 0) |
|
147 | if (sigemptyset(&sa.sa_mask) < 0) { | |
131 | return -1; |
|
148 | return -1; | |
|
149 | } | |||
132 |
|
150 | |||
133 | if (sigaction(SIGHUP, &sa, NULL) < 0) |
|
151 | if (sigaction(SIGHUP, &sa, NULL) < 0) { | |
134 | return -1; |
|
152 | return -1; | |
135 | if (sigaction(SIGTERM, &sa, NULL) < 0) |
|
153 | } | |
|
154 | if (sigaction(SIGTERM, &sa, NULL) < 0) { | |||
136 | return -1; |
|
155 | return -1; | |
137 | if (sigaction(SIGWINCH, &sa, NULL) < 0) |
|
156 | } | |
|
157 | if (sigaction(SIGWINCH, &sa, NULL) < 0) { | |||
138 | return -1; |
|
158 | return -1; | |
139 | if (sigaction(SIGCONT, &sa, NULL) < 0) |
|
159 | } | |
|
160 | if (sigaction(SIGCONT, &sa, NULL) < 0) { | |||
140 | return -1; |
|
161 | return -1; | |
141 | if (sigaction(SIGTSTP, &sa, NULL) < 0) |
|
162 | } | |
|
163 | if (sigaction(SIGTSTP, &sa, NULL) < 0) { | |||
142 | return -1; |
|
164 | return -1; | |
|
165 | } | |||
143 |
|
166 | |||
144 | /* ignore Ctrl+C while shutting down to make pager exits cleanly */ |
|
167 | /* ignore Ctrl+C while shutting down to make pager exits cleanly */ | |
145 | sa.sa_handler = SIG_IGN; |
|
168 | sa.sa_handler = SIG_IGN; | |
146 | if (sigaction(SIGINT, &sa, NULL) < 0) |
|
169 | if (sigaction(SIGINT, &sa, NULL) < 0) { | |
147 | return -1; |
|
170 | return -1; | |
|
171 | } | |||
148 |
|
172 | |||
149 | peerpid = 0; |
|
173 | peerpid = 0; | |
150 | return 0; |
|
174 | return 0; |
General Comments 0
You need to be logged in to leave comments.
Login now