Magellan Linux

Diff of /trunk/mkinitrd-magellan/busybox/libpwdgrp/pwd_grp.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 815 by niro, Sat Sep 1 22:45:15 2007 UTC revision 816 by niro, Fri Apr 24 18:33:46 2009 UTC
# Line 53  static int bb__parsespent(void *sp, char Line 53  static int bb__parsespent(void *sp, char
53  #endif  #endif
54    
55  /**********************************************************************/  /**********************************************************************/
56    /* We avoid having big global data. */
57    
58    struct statics {
59     /* Smaller things first */
60     struct passwd getpwuid_resultbuf;
61     struct group getgrgid_resultbuf;
62     struct passwd getpwnam_resultbuf;
63     struct group getgrnam_resultbuf;
64    
65     char getpwuid_buffer[PWD_BUFFER_SIZE];
66     char getgrgid_buffer[GRP_BUFFER_SIZE];
67     char getpwnam_buffer[PWD_BUFFER_SIZE];
68     char getgrnam_buffer[GRP_BUFFER_SIZE];
69    #if 0
70     struct passwd fgetpwent_resultbuf;
71     struct group fgetgrent_resultbuf;
72     struct spwd fgetspent_resultbuf;
73     char fgetpwent_buffer[PWD_BUFFER_SIZE];
74     char fgetgrent_buffer[GRP_BUFFER_SIZE];
75     char fgetspent_buffer[PWD_BUFFER_SIZE];
76    #endif
77    #if 0 //ENABLE_USE_BB_SHADOW
78     struct spwd getspuid_resultbuf;
79     struct spwd getspnam_resultbuf;
80     char getspuid_buffer[PWD_BUFFER_SIZE];
81     char getspnam_buffer[PWD_BUFFER_SIZE];
82    #endif
83    // Not converted - too small to bother
84    //pthread_mutex_t mylock = PTHREAD_MUTEX_INITIALIZER;
85    //FILE *pwf /*= NULL*/;
86    //FILE *grf /*= NULL*/;
87    //FILE *spf /*= NULL*/;
88    #if 0
89     struct passwd getpwent_pwd;
90     struct group getgrent_gr;
91     char getpwent_line_buff[PWD_BUFFER_SIZE];
92     char getgrent_line_buff[GRP_BUFFER_SIZE];
93    #endif
94    #if 0 //ENABLE_USE_BB_SHADOW
95     struct spwd getspent_spwd;
96     struct spwd sgetspent_spwd;
97     char getspent_line_buff[PWD_BUFFER_SIZE];
98     char sgetspent_line_buff[PWD_BUFFER_SIZE];
99    #endif
100    };
101    
102    static struct statics *ptr_to_statics;
103    
104    static struct statics *get_S(void)
105    {
106     if (!ptr_to_statics)
107     ptr_to_statics = xzalloc(sizeof(*ptr_to_statics));
108     return ptr_to_statics;
109    }
110    
111    /* Always use in this order, get_S() must be called first */
112    #define RESULTBUF(name) &((S = get_S())->name##_resultbuf)
113    #define BUFFER(name)    (S->name##_buffer)
114    
115    /**********************************************************************/
116  /* For the various fget??ent_r funcs, return  /* For the various fget??ent_r funcs, return
117   *   *
118   *  0: success   *  0: success
# Line 121  int fgetspent_r(FILE *__restrict stream, Line 181  int fgetspent_r(FILE *__restrict stream,
181  /**********************************************************************/  /**********************************************************************/
182  /* For the various fget??ent funcs, return NULL on failure and a  /* For the various fget??ent funcs, return NULL on failure and a
183   * pointer to the appropriate struct (statically allocated) on success.   * pointer to the appropriate struct (statically allocated) on success.
184   */   * TODO: audit & stop using these in bbox, they pull in static buffers */
185  /**********************************************************************/  /**********************************************************************/
186    
187    #if 0
188  struct passwd *fgetpwent(FILE *stream)  struct passwd *fgetpwent(FILE *stream)
189  {  {
190   static char buffer[PWD_BUFFER_SIZE];   struct statics *S;
191   static struct passwd resultbuf;   struct passwd *resultbuf = RESULTBUF(fgetpwent);
192     char *buffer = BUFFER(fgetpwent);
193   struct passwd *result;   struct passwd *result;
194    
195   fgetpwent_r(stream, &resultbuf, buffer, sizeof(buffer), &result);   fgetpwent_r(stream, resultbuf, buffer, sizeof(BUFFER(fgetpwent)), &result);
196   return result;   return result;
197  }  }
198    
199  struct group *fgetgrent(FILE *stream)  struct group *fgetgrent(FILE *stream)
200  {  {
201   static char buffer[GRP_BUFFER_SIZE];   struct statics *S;
202   static struct group resultbuf;   struct group *resultbuf = RESULTBUF(fgetgrent);
203     char *buffer = BUFFER(fgetgrent);
204   struct group *result;   struct group *result;
205    
206   fgetgrent_r(stream, &resultbuf, buffer, sizeof(buffer), &result);   fgetgrent_r(stream, resultbuf, buffer, sizeof(BUFFER(fgetgrent)), &result);
207   return result;   return result;
208  }  }
209    #endif
210    
211  #if ENABLE_USE_BB_SHADOW  #if ENABLE_USE_BB_SHADOW
212    #if 0
213  struct spwd *fgetspent(FILE *stream)  struct spwd *fgetspent(FILE *stream)
214  {  {
215   static char buffer[PWD_BUFFER_SIZE];   struct statics *S;
216   static struct spwd resultbuf;   struct spwd *resultbuf = RESULTBUF(fgetspent);
217     char *buffer = BUFFER(fgetspent);
218   struct spwd *result;   struct spwd *result;
219    
220   fgetspent_r(stream, &resultbuf, buffer, sizeof(buffer), &result);   fgetspent_r(stream, resultbuf, buffer, sizeof(BUFFER(fgetspent)), &result);
221   return result;   return result;
222  }  }
223    #endif
224    
225  int sgetspent_r(const char *string, struct spwd *result_buf,  int sgetspent_r(const char *string, struct spwd *result_buf,
226   char *buffer, size_t buflen, struct spwd **result)   char *buffer, size_t buflen, struct spwd **result)
# Line 230  int sgetspent_r(const char *string, stru Line 297  int sgetspent_r(const char *string, stru
297  #include "pwd_grp_internal.c"  #include "pwd_grp_internal.c"
298    
299  /**********************************************************************/  /**********************************************************************/
300    /* TODO: audit & stop using these in bbox, they pull in static buffers */
301    
302    /* This one has many users */
303  struct passwd *getpwuid(uid_t uid)  struct passwd *getpwuid(uid_t uid)
304  {  {
305   static char buffer[PWD_BUFFER_SIZE];   struct statics *S;
306   static struct passwd resultbuf;   struct passwd *resultbuf = RESULTBUF(getpwuid);
307     char *buffer = BUFFER(getpwuid);
308   struct passwd *result;   struct passwd *result;
309    
310   getpwuid_r(uid, &resultbuf, buffer, sizeof(buffer), &result);   getpwuid_r(uid, resultbuf, buffer, sizeof(BUFFER(getpwuid)), &result);
311   return result;   return result;
312  }  }
313    
314    /* This one has many users */
315  struct group *getgrgid(gid_t gid)  struct group *getgrgid(gid_t gid)
316  {  {
317   static char buffer[GRP_BUFFER_SIZE];   struct statics *S;
318   static struct group resultbuf;   struct group *resultbuf = RESULTBUF(getgrgid);
319     char *buffer = BUFFER(getgrgid);
320   struct group *result;   struct group *result;
321    
322   getgrgid_r(gid, &resultbuf, buffer, sizeof(buffer), &result);   getgrgid_r(gid, resultbuf, buffer, sizeof(BUFFER(getgrgid)), &result);
323   return result;   return result;
324  }  }
325    
# Line 277  int getspuid_r(uid_t uid, struct spwd *_ Line 349  int getspuid_r(uid_t uid, struct spwd *_
349   * Why it was added, I do not know. */   * Why it was added, I do not know. */
350  struct spwd *getspuid(uid_t uid)  struct spwd *getspuid(uid_t uid)
351  {  {
352   static char buffer[PWD_BUFFER_SIZE];   struct statics *S;
353   static struct spwd resultbuf;   struct spwd *resultbuf = RESULTBUF(getspuid);
354     char *buffer = BUFFER(getspuid);
355   struct spwd *result;   struct spwd *result;
356    
357   getspuid_r(uid, &resultbuf, buffer, sizeof(buffer), &result);   getspuid_r(uid, resultbuf, buffer, sizeof(BUFFER(getspuid)), &result);
358   return result;   return result;
359  }  }
360  #endif  #endif
361    
362    /* This one has many users */
363  struct passwd *getpwnam(const char *name)  struct passwd *getpwnam(const char *name)
364  {  {
365   static char buffer[PWD_BUFFER_SIZE];   struct statics *S;
366   static struct passwd resultbuf;   struct passwd *resultbuf = RESULTBUF(getpwnam);
367     char *buffer = BUFFER(getpwnam);
368   struct passwd *result;   struct passwd *result;
369    
370   getpwnam_r(name, &resultbuf, buffer, sizeof(buffer), &result);   getpwnam_r(name, resultbuf, buffer, sizeof(BUFFER(getpwnam)), &result);
371   return result;   return result;
372  }  }
373    
374    /* This one has many users */
375  struct group *getgrnam(const char *name)  struct group *getgrnam(const char *name)
376  {  {
377   static char buffer[GRP_BUFFER_SIZE];   struct statics *S;
378   static struct group resultbuf;   struct group *resultbuf = RESULTBUF(getgrnam);
379     char *buffer = BUFFER(getgrnam);
380   struct group *result;   struct group *result;
381    
382   getgrnam_r(name, &resultbuf, buffer, sizeof(buffer), &result);   getgrnam_r(name, resultbuf, buffer, sizeof(BUFFER(getgrnam)), &result);
383   return result;   return result;
384  }  }
385    
386  #if ENABLE_USE_BB_SHADOW  #if 0 //ENABLE_USE_BB_SHADOW
387  struct spwd *getspnam(const char *name)  struct spwd *getspnam(const char *name)
388  {  {
389   static char buffer[PWD_BUFFER_SIZE];   struct statics *S;
390   static struct spwd resultbuf;   struct spwd *resultbuf = RESULTBUF(getspnam);
391     char *buffer = BUFFER(getspnam);
392   struct spwd *result;   struct spwd *result;
393    
394   getspnam_r(name, &resultbuf, buffer, sizeof(buffer), &result);   getspnam_r(name, resultbuf, buffer, sizeof(BUFFER(getspnam)), &result);
395   return result;   return result;
396  }  }
397  #endif  #endif
398    
399    #ifdef THIS_ONE_IS_UNUSED
400    /* This one doesn't use static buffers */
401  int getpw(uid_t uid, char *buf)  int getpw(uid_t uid, char *buf)
402  {  {
403   struct passwd resultbuf;   struct passwd resultbuf;
# Line 325  int getpw(uid_t uid, char *buf) Line 405  int getpw(uid_t uid, char *buf)
405   char buffer[PWD_BUFFER_SIZE];   char buffer[PWD_BUFFER_SIZE];
406    
407   if (!buf) {   if (!buf) {
408   errno=EINVAL;   errno = EINVAL;
409   } else if (!getpwuid_r(uid, &resultbuf, buffer, sizeof(buffer), &result)) {   } else if (!getpwuid_r(uid, &resultbuf, buffer, sizeof(buffer), &result)) {
410   if (sprintf(buf, "%s:%s:%lu:%lu:%s:%s:%s\n",   if (sprintf(buf, "%s:%s:%lu:%lu:%s:%s:%s\n",
411   resultbuf.pw_name, resultbuf.pw_passwd,   resultbuf.pw_name, resultbuf.pw_passwd,
# Line 340  int getpw(uid_t uid, char *buf) Line 420  int getpw(uid_t uid, char *buf)
420    
421   return -1;   return -1;
422  }  }
423    #endif
424    
425  /**********************************************************************/  /**********************************************************************/
426    
# Line 385  int getpwent_r(struct passwd *__restrict Line 466  int getpwent_r(struct passwd *__restrict
466   *result = NULL; /* In case of error... */   *result = NULL; /* In case of error... */
467    
468   if (!pwf) {   if (!pwf) {
469   pwf = fopen(_PATH_PASSWD, "r");   pwf = fopen_for_read(_PATH_PASSWD);
470   if (!pwf) {   if (!pwf) {
471   rv = errno;   rv = errno;
472   goto ERR;   goto ERR;
# Line 432  int getgrent_r(struct group *__restrict Line 513  int getgrent_r(struct group *__restrict
513   *result = NULL; /* In case of error... */   *result = NULL; /* In case of error... */
514    
515   if (!grf) {   if (!grf) {
516   grf = fopen(_PATH_GROUP, "r");   grf = fopen_for_read(_PATH_GROUP);
517   if (!grf) {   if (!grf) {
518   rv = errno;   rv = errno;
519   goto ERR;   goto ERR;
# Line 479  int getspent_r(struct spwd *resultbuf, c Line 560  int getspent_r(struct spwd *resultbuf, c
560   *result = NULL; /* In case of error... */   *result = NULL; /* In case of error... */
561    
562   if (!spf) {   if (!spf) {
563   spf = fopen(_PATH_SHADOW, "r");   spf = fopen_for_read(_PATH_SHADOW);
564   if (!spf) {   if (!spf) {
565   rv = errno;   rv = errno;
566   goto ERR;   goto ERR;
# Line 497  int getspent_r(struct spwd *resultbuf, c Line 578  int getspent_r(struct spwd *resultbuf, c
578  }  }
579  #endif  #endif
580    
581    #if 0
582  struct passwd *getpwent(void)  struct passwd *getpwent(void)
583  {  {
584   static char line_buff[PWD_BUFFER_SIZE];   static char line_buff[PWD_BUFFER_SIZE];
# Line 516  struct group *getgrent(void) Line 598  struct group *getgrent(void)
598   getgrent_r(&gr, line_buff, sizeof(line_buff), &result);   getgrent_r(&gr, line_buff, sizeof(line_buff), &result);
599   return result;   return result;
600  }  }
601    #endif
602    
603  #if ENABLE_USE_BB_SHADOW  #if 0 //ENABLE_USE_BB_SHADOW
604  struct spwd *getspent(void)  struct spwd *getspent(void)
605  {  {
606   static char line_buff[PWD_BUFFER_SIZE];   static char line_buff[PWD_BUFFER_SIZE];
# Line 539  struct spwd *sgetspent(const char *strin Line 622  struct spwd *sgetspent(const char *strin
622  }  }
623  #endif  #endif
624    
625  int initgroups(const char *user, gid_t gid)  static gid_t *getgrouplist_internal(int *ngroups_ptr, const char *user, gid_t gid)
626  {  {
627   FILE *grfile;   FILE *grfile;
628   gid_t *group_list;   gid_t *group_list;
629   int num_groups, rv;   int ngroups;
  char **m;  
630   struct group group;   struct group group;
631   char buff[PWD_BUFFER_SIZE];   char buff[PWD_BUFFER_SIZE];
632    
  rv = -1;  
   
633   /* We alloc space for 8 gids at a time. */   /* We alloc space for 8 gids at a time. */
634   group_list = (gid_t *) malloc(8*sizeof(gid_t *));   group_list = xmalloc(8 * sizeof(group_list[0]));
635   if (group_list   group_list[0] = gid;
636   && ((grfile = fopen(_PATH_GROUP, "r")) != NULL)   ngroups = 1;
  ) {  
  *group_list = gid;  
  num_groups = 1;  
637    
638     grfile = fopen_for_read(_PATH_GROUP);
639     if (grfile) {
640   while (!bb__pgsreader(bb__parsegrent, &group, buff, sizeof(buff), grfile)) {   while (!bb__pgsreader(bb__parsegrent, &group, buff, sizeof(buff), grfile)) {
641     char **m;
642   assert(group.gr_mem); /* Must have at least a NULL terminator. */   assert(group.gr_mem); /* Must have at least a NULL terminator. */
643   if (group.gr_gid != gid) {   if (group.gr_gid == gid)
644   for (m=group.gr_mem ; *m ; m++) {   continue;
645   if (!strcmp(*m, user)) {   for (m = group.gr_mem; *m; m++) {
646   if (!(num_groups & 7)) {   if (strcmp(*m, user) != 0)
647   gid_t *tmp = (gid_t *)   continue;
648   realloc(group_list,   group_list = xrealloc_vector(group_list, 3, ngroups);
649   (num_groups+8) * sizeof(gid_t *));   group_list[ngroups++] = group.gr_gid;
650   if (!tmp) {   break;
  rv = -1;  
  goto DO_CLOSE;  
  }  
  group_list = tmp;  
  }  
  group_list[num_groups++] = group.gr_gid;  
  break;  
  }  
  }  
651   }   }
652   }   }
   
  rv = setgroups(num_groups, group_list);  
  DO_CLOSE:  
653   fclose(grfile);   fclose(grfile);
654   }   }
655     *ngroups_ptr = ngroups;
656     return group_list;
657    }
658    
659   /* group_list will be NULL if initial malloc failed, which may trigger  int initgroups(const char *user, gid_t gid)
660   * warnings from various malloc debuggers. */  {
661     int ngroups;
662     gid_t *group_list = getgrouplist_internal(&ngroups, user, gid);
663    
664     ngroups = setgroups(ngroups, group_list);
665   free(group_list);   free(group_list);
666   return rv;   return ngroups;
667    }
668    
669    int getgrouplist(const char *user, gid_t gid, gid_t *groups, int *ngroups)
670    {
671     int ngroups_old = *ngroups;
672     gid_t *group_list = getgrouplist_internal(ngroups, user, gid);
673    
674     if (*ngroups <= ngroups_old) {
675     ngroups_old = *ngroups;
676     memcpy(groups, group_list, ngroups_old * sizeof(groups[0]));
677     } else {
678     ngroups_old = -1;
679     }
680     free(group_list);
681     return ngroups_old;
682  }  }
683    
684  int putpwent(const struct passwd *__restrict p, FILE *__restrict f)  int putpwent(const struct passwd *__restrict p, FILE *__restrict f)
# Line 596  int putpwent(const struct passwd *__rest Line 686  int putpwent(const struct passwd *__rest
686   int rv = -1;   int rv = -1;
687    
688   if (!p || !f) {   if (!p || !f) {
689   errno=EINVAL;   errno = EINVAL;
690   } else {   } else {
691   /* No extra thread locking is needed above what fprintf does. */   /* No extra thread locking is needed above what fprintf does. */
692   if (fprintf(f, "%s:%s:%lu:%lu:%s:%s:%s\n",   if (fprintf(f, "%s:%s:%lu:%lu:%s:%s:%s\n",
# Line 614  int putpwent(const struct passwd *__rest Line 704  int putpwent(const struct passwd *__rest
704    
705  int putgrent(const struct group *__restrict p, FILE *__restrict f)  int putgrent(const struct group *__restrict p, FILE *__restrict f)
706  {  {
707   static const char format[] = ",%s";   static const char format[] ALIGN1 = ",%s";
708    
709   char **m;   char **m;
710   const char *fmt;   const char *fmt;
711   int rv = -1;   int rv = -1;
712    
713   if (!p || !f) { /* Sigh... glibc checks. */   if (!p || !f) { /* Sigh... glibc checks. */
714   errno=EINVAL;   errno = EINVAL;
715   } else {   } else {
716   if (fprintf(f, "%s:%s:%lu:",   if (fprintf(f, "%s:%s:%lu:",
717   p->gr_name, p->gr_passwd,   p->gr_name, p->gr_passwd,
# Line 654  int putgrent(const struct group *__restr Line 745  int putgrent(const struct group *__restr
745  }  }
746    
747  #if ENABLE_USE_BB_SHADOW  #if ENABLE_USE_BB_SHADOW
748  static const unsigned char _sp_off[] = {  static const unsigned char _sp_off[] ALIGN1 = {
749   offsetof(struct spwd, sp_lstchg), /* 2 - not a char ptr */   offsetof(struct spwd, sp_lstchg),       /* 2 - not a char ptr */
750   offsetof(struct spwd, sp_min), /* 3 - not a char ptr */   offsetof(struct spwd, sp_min),          /* 3 - not a char ptr */
751   offsetof(struct spwd, sp_max), /* 4 - not a char ptr */   offsetof(struct spwd, sp_max),          /* 4 - not a char ptr */
752   offsetof(struct spwd, sp_warn), /* 5 - not a char ptr */   offsetof(struct spwd, sp_warn),         /* 5 - not a char ptr */
753   offsetof(struct spwd, sp_inact), /* 6 - not a char ptr */   offsetof(struct spwd, sp_inact),        /* 6 - not a char ptr */
754   offsetof(struct spwd, sp_expire), /* 7 - not a char ptr */   offsetof(struct spwd, sp_expire)        /* 7 - not a char ptr */
755  };  };
756    
757  int putspent(const struct spwd *p, FILE *stream)  int putspent(const struct spwd *p, FILE *stream)
758  {  {
759   static const char ld_format[] = "%ld:";   static const char ld_format[] ALIGN1 = "%ld:";
760    
761   const char *f;   const char *f;
762   long int x;   long x;
763   int i;   int i;
764   int rv = -1;   int rv = -1;
765    
# Line 678  int putspent(const struct spwd *p, FILE Line 770  int putspent(const struct spwd *p, FILE
770   goto DO_UNLOCK;   goto DO_UNLOCK;
771   }   }
772    
773   for (i=0 ; i < sizeof(_sp_off) ; i++) {   for (i = 0; i < sizeof(_sp_off); i++) {
774   f = ld_format;   f = ld_format;
775   x = *(const long int *)(((const char *) p) + _sp_off[i]);   x = *(const long *)(((const char *) p) + _sp_off[i]);
776   if (x == -1) {   if (x == -1) {
777   f += 3;   f += 3;
778   }   }
# Line 706  DO_UNLOCK: Line 798  DO_UNLOCK:
798  /* Internal uClibc functions.                                         */  /* Internal uClibc functions.                                         */
799  /**********************************************************************/  /**********************************************************************/
800    
801  static const unsigned char pw_off[] = {  static const unsigned char pw_off[] ALIGN1 = {
802   offsetof(struct passwd, pw_name), /* 0 */   offsetof(struct passwd, pw_name),       /* 0 */
803   offsetof(struct passwd, pw_passwd), /* 1 */   offsetof(struct passwd, pw_passwd),     /* 1 */
804   offsetof(struct passwd, pw_uid), /* 2 - not a char ptr */   offsetof(struct passwd, pw_uid),        /* 2 - not a char ptr */
805   offsetof(struct passwd, pw_gid), /* 3 - not a char ptr */   offsetof(struct passwd, pw_gid),        /* 3 - not a char ptr */
806   offsetof(struct passwd, pw_gecos), /* 4 */   offsetof(struct passwd, pw_gecos),      /* 4 */
807   offsetof(struct passwd, pw_dir), /* 5 */   offsetof(struct passwd, pw_dir),        /* 5 */
808   offsetof(struct passwd, pw_shell) /* 6 */   offsetof(struct passwd, pw_shell)       /* 6 */
809  };  };
810    
811  static int bb__parsepwent(void *data, char *line)  static int bb__parsepwent(void *data, char *line)
# Line 764  static int bb__parsepwent(void *data, ch Line 856  static int bb__parsepwent(void *data, ch
856    
857  /**********************************************************************/  /**********************************************************************/
858    
859  static const unsigned char gr_off[] = {  static const unsigned char gr_off[] ALIGN1 = {
860   offsetof(struct group, gr_name), /* 0 */   offsetof(struct group, gr_name),        /* 0 */
861   offsetof(struct group, gr_passwd), /* 1 */   offsetof(struct group, gr_passwd),      /* 1 */
862   offsetof(struct group, gr_gid) /* 2 - not a char ptr */   offsetof(struct group, gr_gid)          /* 2 - not a char ptr */
863  };  };
864    
865  static int bb__parsegrent(void *data, char *line)  static int bb__parsegrent(void *data, char *line)
# Line 862  static int bb__parsegrent(void *data, ch Line 954  static int bb__parsegrent(void *data, ch
954  /**********************************************************************/  /**********************************************************************/
955    
956  #if ENABLE_USE_BB_SHADOW  #if ENABLE_USE_BB_SHADOW
957  static const unsigned char sp_off[] = {  static const unsigned char sp_off[] ALIGN1 = {
958   offsetof(struct spwd, sp_namp), /* 0 */   offsetof(struct spwd, sp_namp),         /* 0 */
959   offsetof(struct spwd, sp_pwdp), /* 1 */   offsetof(struct spwd, sp_pwdp),         /* 1 */
960   offsetof(struct spwd, sp_lstchg), /* 2 - not a char ptr */   offsetof(struct spwd, sp_lstchg),       /* 2 - not a char ptr */
961   offsetof(struct spwd, sp_min), /* 3 - not a char ptr */   offsetof(struct spwd, sp_min),          /* 3 - not a char ptr */
962   offsetof(struct spwd, sp_max), /* 4 - not a char ptr */   offsetof(struct spwd, sp_max),          /* 4 - not a char ptr */
963   offsetof(struct spwd, sp_warn), /* 5 - not a char ptr */   offsetof(struct spwd, sp_warn),         /* 5 - not a char ptr */
964   offsetof(struct spwd, sp_inact), /* 6 - not a char ptr */   offsetof(struct spwd, sp_inact),        /* 6 - not a char ptr */
965   offsetof(struct spwd, sp_expire), /* 7 - not a char ptr */   offsetof(struct spwd, sp_expire),       /* 7 - not a char ptr */
966   offsetof(struct spwd, sp_flag) /* 8 - not a char ptr */   offsetof(struct spwd, sp_flag)          /* 8 - not a char ptr */
967  };  };
968    
969  static int bb__parsespent(void *data, char * line)  static int bb__parsespent(void *data, char * line)

Legend:
Removed from v.815  
changed lines
  Added in v.816