/*
  Program: htpass
  Program by: lockdown (www.lockeddown.net)
  Date: April 25, 2003

This program adds users or changes the passwd of a user if they exist in
.htpasswd.  It also deletes a user from .htpasswd.  Make sure you point
HTPASSWD and HTFILE to the correct files.  My purpose for this program is to
use this in conjuction with a php interface to allow an admin to manage users
and allow users to change their passwords.  Make sure you are careful with
file permissions.

BUGS: Lines are truncated to 80 characters.
      The deleting of users isn't exact, its more like *username.  It is
      possible to delete other users by "accident".
*/

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>


#define HTPASSWD "/usr/local/apache/bin/htpasswd"
#define HTFILE "/usr/local/apache/.htpasswd"

void usage(char *);

int main(int argc, char *argv[])
{
  int j,i,len;
  char *action,*user, *pass,line[80+1],*buffer;
  FILE *file;
  struct stat statbuf;

  if(argc <3 || argc >4)
  {
    usage(argv[0]);
    return 1;
  }

  action= argv[1];
  user= argv[2];

  /*stat here so we can error out if file doesn't exist*/
  if(stat(HTFILE,&statbuf)==-1)
  {
    perror("stat");
    return 1;
  }
  /*add user*/
  if(!strcasecmp("add",action))
  {
    if(argc!=4)
    {
      usage(argv[0]);
      return 1;
    }
    pass= argv[3];
    execl(HTPASSWD,HTPASSWD,"-b",HTFILE,user,pass,NULL);
  }/*if*/
  /*delete user*/
  else if(!strcasecmp("del",action))
  {
    len=strlen(user);
    user[len]=':';
    user[++len]='\0';
    len=statbuf.st_size;
    if((buffer=(char *)malloc(len * sizeof(char)))==NULL)
    {
      perror("malloc");
      return 1;
    }
    if((file=fopen(HTFILE,"r"))==NULL)
    {
      perror("fopen");
      return 1;
    }
    fread(buffer,len,1,file);
    fclose(file);
    /*close file and reopen it truncating the file at the same time*/
    /*pray this open doesn't fail, if so file is lost*/
    if((file=fopen(HTFILE,"w"))==NULL)
    {
      perror("fopen");
      return 1;
    }
    j=0;
    while(j<len)
    {
      memset(line,0,sizeof(line));
      /*grab a line and stop at 80 characters or a newline*/
      for(i=0;i<80 && buffer[j]!='\n';i++,j++)
        line[i]=buffer[j];
      /*ensure we didn't loose the newline*/
      line[i]='\n';
      i++;
      /*null terminate our string*/
      line[i]='\0';
      /*if its not the user we are looking for keep it*/
      if(strstr(line,user)==NULL)
      {
        fwrite(line,strlen(line),sizeof(char),file);
        fflush(file);
      }
      j++;
    }/*while*/
    fclose(file);
  }/*elseif*/
  /*print usage because they didn't choose a valid option*/
  else
  {
    usage(argv[0]);
    return 1;
  }

  return 0;
}

void usage(char *name)
{
  printf("Usage: %s <action> <user> <pass>\n",name);
  printf("\taction - add or del\n");
  printf("\tuser - username\n");
  printf("\tpass - password (not needed for delete)\n");
  return;
}
