* Copy password file from one descriptor to another, replacing, deleting * or adding a single record on the way. */
| 426 | * or adding a single record on the way. |
| 427 | */ |
| 428 | int |
| 429 | pw_copy(int ffd, int tfd, const struct passwd *pw, struct passwd *old_pw) |
| 430 | { |
| 431 | char *buf, *end, *line, *p, *q, *r, *tmp; |
| 432 | struct passwd *fpw; |
| 433 | const struct passwd *spw; |
| 434 | size_t len, size; |
| 435 | int eof, readlen; |
| 436 | char t; |
| 437 | |
| 438 | if (old_pw == NULL && pw == NULL) |
| 439 | return (-1); |
| 440 | |
| 441 | spw = old_pw; |
| 442 | /* deleting a user */ |
| 443 | if (pw == NULL) { |
| 444 | line = NULL; |
| 445 | } else { |
| 446 | if ((line = pw_make(pw)) == NULL) |
| 447 | return (-1); |
| 448 | } |
| 449 | |
| 450 | /* adding a user */ |
| 451 | if (spw == NULL) |
| 452 | spw = pw; |
| 453 | |
| 454 | /* initialize the buffer */ |
| 455 | if ((buf = malloc(size = 1024)) == NULL) |
| 456 | goto err; |
| 457 | |
| 458 | eof = 0; |
| 459 | len = 0; |
| 460 | p = q = end = buf; |
| 461 | for (;;) { |
| 462 | /* find the end of the current line */ |
| 463 | for (p = q; q < end && *q != '\0'; ++q) |
| 464 | if (*q == '\n') |
| 465 | break; |
| 466 | |
| 467 | /* if we don't have a complete line, fill up the buffer */ |
| 468 | if (q >= end) { |
| 469 | if (eof) |
| 470 | break; |
| 471 | while ((size_t)(q - p) >= size) { |
| 472 | if ((tmp = reallocarray(buf, 2, size)) == NULL) { |
| 473 | warnx("passwd line too long"); |
| 474 | goto err; |
| 475 | } |
| 476 | p = tmp + (p - buf); |
| 477 | q = tmp + (q - buf); |
| 478 | end = tmp + (end - buf); |
| 479 | buf = tmp; |
| 480 | size = size * 2; |
| 481 | } |
| 482 | if (p < end) { |
| 483 | q = memmove(buf, p, end - p); |
| 484 | end -= p - buf; |
| 485 | } else { |