/* LShell 2.01 */
/* Copyright (C) 1995 -- Joel Katz -- Stimpson@Panix.com */
/* Freely Redistributable */

#include <stdio.h>
#include <stdlib.h>
#include <pwd.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <unistd.h>

#ifndef CONFIG_FILE
#define CONFIG_FILE "/etc/lshell.conf"
#endif

#ifndef SHELL_DIR
#define SHELL_DIR "/bin/shells/"
#endif

/* #define EXEMPT_ROOT */

char *strip(char *ptr)
{ /* return ptr if ptr contains no '/' otherwise return pointer */
  /* to first character after ptr */
  char *ptr2;
  char buf[256];
  buf[0]='/';
  strcpy(buf+1,ptr);
  ptr2=buf+strlen(buf)-1;
  while(*ptr2!='/') ptr2--;
  return ptr+(ptr2-buf);
}

void process(char *buf)
{
 char *pp;
 /* We are passed a string of the form [Fw][Px][Cy][Dz] where */
 /* X is the max number of processes, Y is the max number of */
 /* cpu minutes and Z is the max number of megabytes of virtual memory */
 /* W is the max number of open files */
 int i;
 struct rlimit rlim;
 pp=buf;
 while(*pp!=0)
 {
  int i;
  
  switch(*pp++)
  {
   case 'f':
   case 'F': i=atoi(pp);
   	     if(!i) break;
             rlim.rlim_cur=i;
             rlim.rlim_max=i;
             setrlimit(RLIMIT_NOFILE,&rlim);
             break;
   case 'p':
   case 'P': i=atoi(pp);
   	     if(!i) break;
             rlim.rlim_cur=i;
             rlim.rlim_max=i;
             setrlimit(RLIMIT_NPROC,&rlim);
   	     break;
   case 'c':
   case 'C': i=atoi(pp);
             if(!i) break;
             i*=60;
             rlim.rlim_cur=i;
             rlim.rlim_max=i;
             setrlimit(RLIMIT_CPU,&rlim);
             break;
   case 'd':
   case 'D': i=atoi(pp);
   	     if(!i) break;
   	     i*=1024*1024;
   	     rlim.rlim_cur=i;
   	     rlim.rlim_max=i;
   	     setrlimit(RLIMIT_DATA,&rlim);
             break;
  }
 }
}

void set_em(char *unm)
{
 FILE *fil;
 int i;
 char buf[1024],name[1024],limits[1024];
 fil=fopen(CONFIG_FILE,"r");
 if(fil==NULL)
 {
  return;
 }
 while(fgets(buf,1024,fil)!=NULL)
 {
  i=sscanf(buf,"%s %s",name,limits);
  if(!strcmp(name,unm))
  {
   if(i==2) process(limits);
   fclose(fil);
   return;
  }
 }
 fclose(fil);
 process(limits); /* Last line is default */
}

void main(int argc, char *argv[])
{
 int i;
 char *ptr, **nargv;
 char full[64];
 struct passwd *j;
 if (argv[0][0]=='-')
 { /* We are a login shell */
  j=getpwuid(getuid());
  ptr=j->pw_name;

#ifdef EXEMPT_ROOT
  if(strcmp(ptr,"root"))
#endif
  if(ptr!=NULL)
   set_em(ptr);
  strcpy(full,SHELL_DIR);
  strcat(full,strip(argv[0]+1));
 }
 else
 {
  /* We aren't a login shell
  /* We need to assemble our new name and pass our parameters */
  strcpy(full,SHELL_DIR);
  strcat(full,strip(argv[0]));
 }
 nargv=malloc((argc+1)*sizeof(char *));
 for(i=1; i<argc; i++) nargv[i]=argv[i];
 nargv[argc]=NULL; /* argv is not null terminated :-( */
 nargv[0]=strip(argv[0]);
 execv(full,(char **) nargv);
}
