/msu.c
C | 960 lines | 735 code | 37 blank | 188 comment | 197 complexity | 67f81231e1f5bab79700940dddfdb80d MD5 | raw file
Possible License(s): GPL-2.0
- /*********************************************************************
- **
- ** Copyright 1999-2004 Oliver Schroeder
- **
- ** Permission to use, copy, modify, and distribute this
- ** software and its documentation for any purpose and
- ** without any fee is hereby granted, provided that the
- ** above copyright notice and this permission notice
- ** appear in all copies of the software and derivative
- ** works or modified versions thereof, and that both the
- ** copyright notice and this permission and disclaimer
- ** notice appear in supporting documentation.
- **
- ** This software is provided "as is" WITHOUT ANY WARRANTY.
- **
- ** Oliver Schroeder <progs@o-schroeder.de>
- **
- *********************************************************************/
- #define _GNU_SOURCE
- /*********************************************************************
- *
- * FIXME: check on *BSD Solaris etc.
- *
- ********************************************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #if HAVE_CONFIG_H
- # include <config.h>
- #endif
- #if HAVE_PWD_H
- # include <pwd.h>
- #endif
- #if HAVE_SYS_TYPES_H
- # include <sys/types.h>
- #endif
- #if HAVE_SYS_STAT_H
- # include <sys/stat.h>
- #endif
- #if HAVE_UNISTD_H
- # include <unistd.h>
- #endif
- #if HAVE_TERMIOS_H
- # include <termios.h>
- #endif
- #if HAVE_STRING_H
- # include <string.h>
- #endif
- #if HAVE_CTYPE_H
- # include <ctype.h>
- #endif
- #if HAVE_SYSLOG_H
- # include <syslog.h>
- #endif
- #if HAVE_LIBGEN_H
- # include <libgen.h>
- #endif
- #if HAVE_LIBGEN_H
- # include <crypt.h>
- #endif
- #include <grp.h>
- /*********************************************************************
- **
- ** global constants
- **
- **********************************************************************/
- enum
- {
- UNSPEC = -1,
- OK = 0,
- FAILED = 1,
- NO = 0,
- NIL = 0,
- YES = 1,
- MAX_BUFFER = 512
- };
- /*********************************************************************
- **
- ** return values
- **
- **********************************************************************/
- enum EXIT_VALUES
- {
- WANTED_NOT_FOUND,
- PERMISSION_DENIED,
- SETGID_FAILED,
- SETUID_FAILED,
- SHELL_FAILED,
- NO_MSUUSER,
- MSUUSER_WRONG_USER,
- MSUUSER_WRONG_MODE,
- MSUUSER_READ_FAILED,
- SYNTAX_ERROR,
- SWITCH_ERROR,
- SHADOW_READ_FAILED,
- COMMAND_LINE_ERROR,
- GROUP_NOT_FOUND,
- NO_MEMORY
- };
- /*********************************************************************
- **
- ** global variables
- **
- **********************************************************************/
- char* DEF_SHELL = "/bin/sh"; /* default shell */
- char SUSER[MAX_BUFFER];
- /*
- * modified by config file
- */
- int NEED_PASSWD = YES; /* user needs to give password */
- int WITH_ASTERISK = YES;
- /*
- * modified by command line
- */
- int LOGIN_SHELL = NO; /* -l --login */
- int CHANGE_GROUP = NO; /* -g --group */
- char* EXEC_SHELL = ""; /* -s --shell */
- char* WANTED_USER = "";
- char* EXEC_COMMAND = (char*) NIL;
- char** ADDITIONAL_ARGS = (char**) NIL;
- /*********************************************************************
- **
- ** typedef's
- **
- **********************************************************************/
- typedef struct termios TERMIOS;
- typedef struct passwd PWENTRY;
- /*
- * we use this structure, since getpwnam() and getpwuid() use
- * static buffers and the *_r()'s are just plain ill
- */
- typedef struct
- {
- char Name[MAX_BUFFER];
- char Passwd[MAX_BUFFER];
- char PW_DIR[MAX_BUFFER];
- uid_t UID;
- gid_t GID;
- }
- USER_ENTRY;
- /*********************************************************************
- **
- ** prototypes
- **
- **********************************************************************/
- int UserOK ( USER_ENTRY* Wanted, USER_ENTRY* User );
- int GetPWEntry ( char* Name, int Uid, /*@out@*/ USER_ENTRY* UserEntry );
- int GetGrpEntry ( char* Name, USER_ENTRY* UserEntry );
- int AuthUser ( USER_ENTRY* User );
- void GetShadowPW ( const char *UserName, char *UserPass );
- void SetSwitch ( const char *Switch, unsigned int LineNo );
- void ParseParams ( int argc, char *argv[] );
- static void run_shell ( /*@null@*/ char *shell, const char *command,
- char **additional_args, int login );
- /*********************************************************************
- **
- ** main
- **
- **********************************************************************/
- int
- main ( int argc, char *argv[] )
- {
- USER_ENTRY User;
- USER_ENTRY Wanted;
- (void) snprintf (SUSER, MAX_BUFFER, "%s/msuuser", SYSCONFDIR);
- openlog ("msu", LOG_ERR, LOG_AUTH);
- ParseParams (argc, argv);
- (void) GetPWEntry ("", (int) getuid(), &User);
- if (WANTED_USER == "") /* wanna be root */
- {
- (void) GetPWEntry ("root", UNSPEC, &Wanted);
- }
- else
- {
- if ((CHANGE_GROUP == NO)
- && (GetPWEntry (WANTED_USER, UNSPEC, &Wanted) != OK))
- {
- syslog (LOG_CRIT, "'%s' -> '%s' not found.\n",
- User.Name, WANTED_USER);
- fprintf (stderr, "'%s' -> '%s' not found.\n",
- User.Name, WANTED_USER);
- exit (WANTED_NOT_FOUND);
- }
- }
- if (CHANGE_GROUP == YES)
- {
- /* user wants to change his group, so get group id */
- if (GetGrpEntry (WANTED_USER , &Wanted) != OK)
- {
- syslog (LOG_CRIT, "'%s' -> '%s' not found.\n",
- User.Name, WANTED_USER);
- fprintf (stderr, "'%s' -> '%s' not found.\n",
- User.Name, WANTED_USER);
- exit (GROUP_NOT_FOUND);
- }
- }
- if (UserOK (&Wanted, &User) != OK)
- {
- syslog (LOG_CRIT, "%s -> %s permission denied.\n",
- User.Name, Wanted.Name);
- fprintf (stderr, "%s -> %s permission denied.\n",
- User.Name, Wanted.Name);
- closelog ();
- exit (PERMISSION_DENIED);
- }
- if (setgid ((gid_t) Wanted.GID) != OK)
- {
- syslog (LOG_CRIT, "can not set group id.\n");
- fprintf (stderr, "can not set group id.\n");
- closelog ();
- exit (SETGID_FAILED);
- }
- if (CHANGE_GROUP == NO)
- {
- if (setuid ((uid_t) Wanted.UID) != OK)
- {
- syslog (LOG_CRIT, "can not set user id.\n");
- fprintf (stderr, "can not set user id.\n");
- closelog ();
- exit (SETUID_FAILED);
- }
- }
- if (EXEC_SHELL == "")
- {
- EXEC_SHELL = getenv ("SHELL");
- if (EXEC_SHELL == (char*) NIL)
- {
- EXEC_SHELL = DEF_SHELL;
- }
- }
- if (CHANGE_GROUP == YES)
- {
- syslog (LOG_CRIT, "%s -> %s\n", User.Name, WANTED_USER);
- fprintf (stderr, "%s -> %s\n", User.Name, WANTED_USER);
- }
- else
- {
- syslog (LOG_CRIT, "%s -> %s\n", User.Name, Wanted.Name);
- fprintf (stderr, "%s -> %s\n", User.Name, Wanted.Name);
- }
- closelog ();
- if (LOGIN_SHELL == YES)
- {
- /* set some environment variables */
- setenv ("HOME", Wanted.PW_DIR, YES);
- }
- setenv ("USER", Wanted.Name, YES);
- run_shell (EXEC_SHELL, EXEC_COMMAND, ADDITIONAL_ARGS, LOGIN_SHELL);
- fprintf (stderr, "can not execute shell (%s).\n", EXEC_SHELL);
- return (SHELL_FAILED);
- }
- /*********************************************************************
- **
- ** get user info from passwd
- **
- **********************************************************************/
- int
- GetPWEntry ( char* Name, int Uid, USER_ENTRY* UserEntry )
- {
- PWENTRY* PW;
- UserEntry->Name[0] = '\0';
- UserEntry->Passwd[0] = '\0';
- UserEntry->PW_DIR[0] = '\0';
- UserEntry->UID = UNSPEC;
- UserEntry->GID = UNSPEC;
- if (Uid != UNSPEC)
- {
- PW = getpwuid (getuid ());
- }
- else
- {
- PW = getpwnam (Name);
- }
- if (PW == (PWENTRY*) NIL)
- {
- return (FAILED);
- }
- strncpy (UserEntry->Name, PW->pw_name, MAX_BUFFER);
- strncpy (UserEntry->Passwd, PW->pw_passwd, MAX_BUFFER);
- strncpy (UserEntry->PW_DIR, PW->pw_dir, MAX_BUFFER);
- UserEntry->UID = PW->pw_uid;
- UserEntry->GID = PW->pw_gid;
- return (OK);
- }
- /*********************************************************************
- **
- ** get group info from /etc/group
- ** return: 1 - failed
- ** 0 - ok
- **
- **********************************************************************/
- int
- GetGrpEntry ( char* Name, USER_ENTRY* UserEntry )
- {
- struct group* GroupInfo;
- GroupInfo = getgrnam(Name);
- if (GroupInfo == (struct group *) NIL)
- {
- return (FAILED);
- }
- UserEntry->GID = GroupInfo->gr_gid;
- return (OK);
- }
- /*********************************************************************
- **
- ** check if user is allowed to use msu
- **
- **********************************************************************/
- int
- UserOK ( USER_ENTRY* Wanted, USER_ENTRY* User )
- {
- char* Index;
- char* UserList;
- char Dummy[MAX_BUFFER];
- char Sep;
- char* CurSep;
- char* Seperators = ": \t";
- size_t Len;
- unsigned int LineNo;
- size_t Dummylen;
- int Found = NO;
- FILE* MSU_File;
- struct stat stats;
- /*************************************************
- **
- ** root may always use msu
- **
- **************************************************/
- if (User->UID == 0)
- {
- return (OK);
- }
- /*************************************************
- **
- ** check permissions off the msu-database
- **
- **************************************************/
- Found = stat (SUSER, & stats);
- if (Found != OK)
- {
- fprintf (stderr, "can not stat msu-database (%s).\n", SUSER);
- exit (NO_MSUUSER);
- }
- if (stats.st_uid != 0)
- {
- fprintf (stderr, "%s should be owned by root.\n", SUSER);
- exit (MSUUSER_WRONG_USER);
- }
- if (stats.st_mode != 33152) /* 0100600 = regular file, owner rw */
- {
- fprintf (stderr, "%s should have 600 (only) permissions.\n", SUSER);
- exit (MSUUSER_WRONG_MODE);
- }
- /*************************************************
- **
- ** open the msu-database
- **
- **************************************************/
- MSU_File = fopen (SUSER, "r");
- if (MSU_File == NIL)
- {
- fprintf (stderr, "can not open msu-database (%s).\n", SUSER);
- exit (MSUUSER_READ_FAILED);
- }
- /*************************************************
- **
- ** now lookup the calling user in the
- ** suser-databse.
- **
- *************************************************/
- Len = strlen (User->Name);
- LineNo = 0;
- while ((Found == NO) && (feof (MSU_File) == NO))
- {
- if (fgets (Dummy, MAX_BUFFER, MSU_File) == (char*) NIL)
- break; // exit on error
- LineNo++;
- /*************************************************
- **
- ** a comment
- **
- **************************************************/
- if (Dummy[0] == '#')
- {
- continue;
- }
- /*************************************************
- **
- ** a config switch?
- **
- **************************************************/
- if (Dummy[0] == '-')
- {
- SetSwitch (Dummy, LineNo);
- continue;
- }
- CurSep = Seperators;
- Index = 0;
- while ((*CurSep != 0) && (*CurSep != '\0') && (Index == 0))
- {
- Index = strchr (Dummy, *CurSep);
- if (Index == 0)
- {
- CurSep++;
- }
- }
- if (Index == 0)
- {
- /* no 'Sep'-erator, but perhaps username only? */
- Dummylen = strlen (Dummy);
- if (Dummy[Dummylen - 1] == '\n')
- {
- Dummy[Dummylen - 1] = '\0';
- }
- if (strcmp (User->Name, Dummy) == 0)
- { /* exakt match */
- return (AuthUser (User));
- }
- else
- {
- continue;
- }
- }
- if (Index - Dummy != Len)
- {
- continue;
- }
- if (strncmp (Dummy, User->Name, Len) == OK)
- {
- Found = YES;
- }
- }
- if (Found == NO) /* user is not in the database */
- {
- /* make sure, user has to provide a password */
- NEED_PASSWD = 1;
- (void) AuthUser (User);
- /* but don't let him get what he wants */
- return (FAILED);
- }
- /*************************************************
- **
- ** ok, the user is allowed to use msu. now look
- ** for any restrictions. '\n' and ':' are part of
- ** Dummy, so strlen(dummy)-Len is ==2 if no
- ** restriction apply!
- **
- *************************************************/
- if (strlen (Dummy) - Len == 2) /* User has no restrictions */
- {
- return (AuthUser (User));
- }
- Sep = ',';
- UserList = Index + 1;
- Len = strlen (Wanted->Name);
- while (strlen (UserList) > 0)
- {
- /*
- * FIXME: "user: [space]" does not work
- */
- while ((isspace (*UserList)) && (*UserList != '\0'))
- {
- UserList++;
- }
- if ((Index = strchr (UserList, Sep)) == (char*) OK)
- {
- break;
- }
- if ((Index - UserList) != Len)
- {
- UserList = Index + 1;
- continue;
- }
- if (strncmp (UserList, Wanted->Name, Len) == OK)
- {
- return (AuthUser (User));
- }
- UserList = Index + 1;
- }
- if (strlen (UserList) < Len)
- {
- return (FAILED);
- }
- if (strncmp (UserList, Wanted->Name, Len) == OK)
- {
- return (AuthUser (User));
- }
- return (FAILED);
- }
- /*********************************************************************
- **
- ** set a global switch from config file
- **
- **********************************************************************/
- void
- SetSwitch ( const char *Switch, unsigned int LineNo )
- {
- char* Index;
- int SwitchOn;
- Index = strchr (Switch, ':');
- if (Index == NULL)
- {
- syslog (LOG_CRIT, "error in msu-database in line %u.\n", LineNo);
- fprintf (stderr, "error in msu-database in line %u.\n", LineNo);
- exit (SYNTAX_ERROR);
- }
- Index++;
- while ((isspace (*Index)) && (*Index != '\0'))
- {
- Index++;
- }
- if (strncasecmp (Index, "ON", 2) == 0)
- {
- SwitchOn = 1;
- }
- else if (strncasecmp (Index, "OFF", 3) == 0)
- {
- SwitchOn = 0;
- }
- else
- {
- syslog (LOG_CRIT,
- "please set ON or OFF in msu-database in line %u.\n",
- LineNo);
- fprintf (stderr,
- "please set ON or OFF in msu-database in line %u.\n",
- LineNo);
- exit (SWITCH_ERROR);
- }
- if (strncmp (Switch, "-echo-asterisk:", 15) == 0)
- {
- WITH_ASTERISK = SwitchOn;
- }
- if (strncmp (Switch, "-user-auth:", 11) == 0)
- {
- NEED_PASSWD = SwitchOn;
- }
- }
- /*********************************************************************
- **
- ** authenticate user with his password
- **
- **********************************************************************/
- int
- AuthUser ( USER_ENTRY* User )
- {
- int C;
- int NumChars;
- char Buffer[MAX_BUFFER];
- char CRYPT_SALT[MAX_BUFFER];
- char UserPass[MAX_BUFFER];
- char* Index;
- TERMIOS OldModes;
- TERMIOS NewModes;
- if (NEED_PASSWD == NO)
- {
- return (OK); /* User is allowed */
- }
- /*************************************************
- * set up terminal
- **************************************************/
- setbuf (stdin, (char *) 0);
- (void) tcgetattr (fileno (stdin), &OldModes);
- NewModes = OldModes;
- NewModes.c_lflag &= ~(ICANON);
- NewModes.c_lflag &= ~(ECHO | ECHOE | ECHOK);
- NewModes.c_lflag |= ECHONL;
- (void) tcsetattr (fileno (stdin), TCSANOW, &NewModes);
- /*************************************************
- * read password
- **************************************************/
- NumChars = 0;
- C = 0;
- (void) fputs ("enter your password: ", stdout);
- (void) fflush (stdout);
- while (read (fileno (stdin), &C, 1) > 0)
- {
- switch (C)
- {
- case '\n': /* ENTER */
- case '\r':
- Buffer[NumChars] = '\0';
- goto endwhile;
- case 127: /* BACKSPACE */
- case '\b':
- if (NumChars > 0)
- {
- Buffer[NumChars] = '\0';
- NumChars--;
- if (WITH_ASTERISK == YES)
- {
- (void) fputs ("\b \b", stdout);
- }
- }
- else
- {
- (void) putc ('\a', stdout); /* BEL */
- }
- break;
- case '\025': /* CTRL-U */
- if (NumChars <= 0)
- {
- (void) putc ('\a', stdout); /* BEL */
- }
- for (C = NumChars; C > 0; C--)
- {
- Buffer[C] = '\0';
- if (WITH_ASTERISK == YES)
- {
- (void) fputs ("\b \b", stdout);
- }
- }
- NumChars = 0;
- break;
- default:
- Buffer[NumChars] = (char) C;
- NumChars++;
- if (WITH_ASTERISK == YES)
- {
- (void) putc ('*', stdout);
- }
- break;
- } // switch()
- (void) fflush (stdout);
- if (NumChars > MAX_BUFFER)
- {
- NumChars--;
- (void) putc ('\a', stdout); /* BEL */
- break;
- }
- }
- endwhile:
- Buffer[NumChars] = '\0';
- (void) putc ('\n', stdout);
- /*************************************************
- **
- ** restore terminal
- **
- **************************************************/
- (void) tcsetattr (fileno (stdin), TCSANOW, &OldModes);
- /*************************************************
- **
- ** check password
- **
- **************************************************/
- if (strlen (User->Passwd) > 1)
- { /* password from PWENTRY */
- strncpy (UserPass, User->Passwd, MAX_BUFFER);
- }
- else
- { /* read password from /etc/shadow (eg linux) */
- GetShadowPW (User->Name, UserPass);
- }
- /* at least a salt must be present */
- if (strlen (UserPass) < 5)
- {
- return (FAILED);
- }
- /*************************************************
- **
- ** get SALT
- **
- **************************************************/
- if ((strncmp (UserPass, "$1$", 3) == 0)
- || (strncmp (UserPass, "$6$", 3) == 0))
- {
- Index = strchr (&UserPass[3], '$');
- Index++;
- strncpy (CRYPT_SALT, UserPass, Index - UserPass);
- CRYPT_SALT[Index - UserPass] = '\0';
- }
- else
- {
- CRYPT_SALT[0] = UserPass[0];
- CRYPT_SALT[1] = UserPass[1];
- CRYPT_SALT[2] = '\0';
- }
- if (strcmp (UserPass, crypt (Buffer, CRYPT_SALT)) == 0)
- return (OK);
- return (FAILED);
- }
- /*********************************************************************
- **
- ** read /etc/shadow and get password for 'UserName'
- **
- **********************************************************************/
- void
- GetShadowPW (const char *UserName, char *UserPass)
- {
- FILE *Shadow_File;
- char Dummy[MAX_BUFFER];
- int Found = 0;
- size_t UserLen;
- char *Index = 0;
- char *Index2 = 0;
- Shadow_File = fopen ("/etc/shadow", "r");
- if (Shadow_File == 0)
- {
- fprintf (stderr, "can not open /etc/shadow!\n");
- exit (SHADOW_READ_FAILED);
- }
- UserLen = strlen (UserName);
- while ((Found == NO) && (feof (Shadow_File) == NO))
- {
- (void) fgets (Dummy, MAX_BUFFER, Shadow_File);
- Index = strchr (Dummy, ':');
- if (UserLen != Index-Dummy)
- {
- continue;
- }
- if (strncmp (UserName, Dummy, Index-Dummy) == 0)
- {
- Found = YES;
- }
- }
- if (Found == NO)
- {
- return;
- }
- Index++;
- Index2 = strchr (Index, ':');
- if (Index2 == (char*) NIL)
- {
- return;
- }
- strncpy (UserPass, Index, (size_t) (Index2 - Index));
- UserPass[Index2 - Index] = '\0';
- (void) fclose (Shadow_File);
- }
- /*********************************************************************
- **
- ** print version information
- **
- **********************************************************************/
- void
- PrintVersion ()
- {
- printf ("\n%s v%s (c) 1999-2005 Oliver Schroeder\n\n",
- PACKAGE, VERSION);
- }
- /*********************************************************************
- **
- ** print a help screen
- **
- **********************************************************************/
- void
- PrintHelp (char *ProgName)
- {
- PrintVersion ();
- printf ("\
- syntax: %s [options] user [exec-cmd args] \n\
- \n\
- options: \n\
- - | -l | --login use no login shell \n\
- -v | --version print version information and exit \n\
- -h | --help print this help screen \n\
- -s | --shell SHELL use SHELL as shell \n\
- -c | --command CMD pass CMD to the shell via -c option \n\
- -g | --group change group id instead of userid \n\
- \n\
- all additional arguments gets passed to the shell as is\n\
- \n", basename (ProgName));
- }
- /*********************************************************************
- **
- ** parse command line and set global flags/variables
- **
- **********************************************************************/
- void
- ParseParams (int argc, char *argv[])
- {
- int i;
- if (argc < 1)
- {
- return;
- }
- i = 1;
- while ((i < argc) && (WANTED_USER == ""))
- {
- if ((strcmp (argv[i], "-") == OK)
- || (strcmp (argv[i], "-l") == OK)
- || (strcmp (argv[i], "--login") == OK))
- {
- LOGIN_SHELL = 1;
- }
- else if ((strcmp (argv[i], "-v") == 0)
- || (strcmp (argv[i], "--version") == 0))
- {
- PrintVersion ();
- exit (OK);
- }
- else if ((strcmp (argv[i], "-h") == 0)
- || (strcmp (argv[i], "--help") == 0))
- {
- PrintHelp (argv[0]);
- exit (OK);
- }
- else if ((strcmp (argv[i], "-g") == 0)
- || (strcmp (argv[i], "--group") == 0))
- {
- CHANGE_GROUP = YES;
- }
- else if ((strcmp (argv[i], "-s") == 0)
- || (strcmp (argv[i], "--shell") == 0))
- {
- i++;
- if (i < argc)
- {
- EXEC_SHELL = argv[i];
- }
- }
- else if ((strcmp (argv[i], "-c") == 0)
- || (strcmp (argv[i], "--command") == 0))
- {
- i++;
- if (i < argc)
- {
- EXEC_COMMAND = argv[i];
- }
- }
- else
- {
- WANTED_USER = argv[i];
- }
- i++;
- }
- if (i < argc)
- {
- ADDITIONAL_ARGS = argv + i;
- }
- }
- /*********************************************************************
- **
- ** shamelessly stolen from GNU's shadow suite
- **
- **********************************************************************/
- /* we don't use gettext, maybe we do a FIXME: here */
- #define _(TEXT) TEXT
- char *
- xmalloc (size_t size)
- {
- char *ptr;
- ptr = malloc (size);
- if ((ptr == 0) && (size > 0))
- {
- fprintf (stderr, _("malloc(%d) failed\n"), (int) size);
- exit (NO_MEMORY);
- }
- return ptr;
- }
- /* borrowed from GNU sh-utils' "su.c" */
- static int
- elements (char **arr)
- {
- int n = 0;
- for (n = 0; *arr; ++arr)
- ++n;
- return n;
- }
- /* borrowed from GNU sh-utils' "su.c" */
- static void
- run_shell (char *shell, const char *command, char **additional_args,
- int login)
- {
- const char **args;
- int argno = 1;
- char cmd[BUFSIZ];
- size_t cmd_len_left = sizeof (cmd) - 1;
- if (shell == (char*) NIL)
- return;
- cmd[0] = '\0';
- if (additional_args)
- args = (const char **)
- xmalloc (sizeof (char *) * (10 + elements (additional_args)));
- else
- args = (const char **) xmalloc (sizeof (char *) * 10);
- if (login == YES)
- {
- char *arg0;
- char *shell_basename;
- shell_basename = basename (shell);
- arg0 = xmalloc (strlen (shell_basename) + 2);
- arg0[0] = '-';
- strcpy (arg0 + 1, shell_basename);
- args[0] = arg0;
- }
- else
- args[0] = basename (shell);
- if ((command != (char*) NIL) || (additional_args) != (char**) NIL)
- args[argno++] = "-c";
- if (command != (char*) NIL)
- {
- if (strlen (command) > cmd_len_left)
- {
- fprintf (stderr, _("Command line args too long\n"));
- exit (COMMAND_LINE_ERROR);
- }
- strcat (cmd, command);
- cmd_len_left -= strlen (command);
- }
- if (additional_args)
- for (; *additional_args; ++additional_args)
- {
- if ((strlen (*additional_args) + 1) > cmd_len_left)
- {
- fprintf (stderr, _("Command line args too long\n"));
- exit (COMMAND_LINE_ERROR);
- }
- if (cmd[0] != NIL)
- {
- strcat (cmd, " ");
- cmd_len_left--;
- }
- strcat (cmd, *additional_args);
- cmd_len_left -= strlen (*additional_args);
- }
- if (cmd[0])
- args[argno++] = cmd;
- args[argno] = NULL;
- (void) execv (shell, (char **) args);
- fprintf (stderr, _("No shell\n"));
- syslog (LOG_CRIT, "Cannot execute %s\n", shell);
- }
- /* vim:set ai et sts=0 sw=8 ts=8 tw=80: */