389 lines
11 KiB
C
389 lines
11 KiB
C
|
/*****************************************************************************
|
||
|
*
|
||
|
* $Id: door.c,v 1.26 2007/02/25 20:28:09 mbse Exp $
|
||
|
* Purpose ...............: Run external door
|
||
|
*
|
||
|
*****************************************************************************
|
||
|
* Copyright (C) 1997-2007
|
||
|
*
|
||
|
* Michiel Broek FIDO: 2:280/2802
|
||
|
* Beekmansbos 10
|
||
|
* 1971 BV IJmuiden
|
||
|
* the Netherlands
|
||
|
*
|
||
|
* This file is part of MBSE BBS.
|
||
|
*
|
||
|
* This BBS is free software; you can redistribute it and/or modify it
|
||
|
* under the terms of the GNU General Public License as published by the
|
||
|
* Free Software Foundation; either version 2, or (at your option) any
|
||
|
* later version.
|
||
|
*
|
||
|
* MBSE BBS is distributed in the hope that it will be useful, but
|
||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||
|
* General Public License for more details.
|
||
|
*
|
||
|
* You should have received a copy of the GNU General Public License
|
||
|
* along with MBSE BBS; see the file COPYING. If not, write to the Free
|
||
|
* Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
||
|
*****************************************************************************/
|
||
|
|
||
|
#include "../config.h"
|
||
|
#include "../lib/mbselib.h"
|
||
|
#include "../lib/mbse.h"
|
||
|
#include "../lib/users.h"
|
||
|
#include "language.h"
|
||
|
#include "input.h"
|
||
|
#include "timeout.h"
|
||
|
#include "exitinfo.h"
|
||
|
#include "whoson.h"
|
||
|
#include "door.h"
|
||
|
#include "term.h"
|
||
|
#include "ttyio.h"
|
||
|
#include "openport.h"
|
||
|
|
||
|
|
||
|
extern time_t t_start;
|
||
|
extern int e_pid;
|
||
|
extern char **environ;
|
||
|
extern int cols;
|
||
|
extern int rows;
|
||
|
|
||
|
|
||
|
char *Gdate(time_t, int);
|
||
|
char *Gdate(time_t tt, int Y2K)
|
||
|
{
|
||
|
static char GLC[15];
|
||
|
struct tm *tm;
|
||
|
|
||
|
tm = localtime(&tt);
|
||
|
if (Y2K)
|
||
|
snprintf(GLC, 15, "%02d-%02d-%04d", tm->tm_mon +1, tm->tm_mday, tm->tm_year + 1900);
|
||
|
else
|
||
|
snprintf(GLC, 15, "%02d-%02d-%02d", tm->tm_mon +1, tm->tm_mday, tm->tm_year % 100);
|
||
|
|
||
|
return (GLC);
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
char *Rdate(char *, int);
|
||
|
char *Rdate(char *ind, int Y2K)
|
||
|
{
|
||
|
static char GLC[15];
|
||
|
|
||
|
memset(&GLC, 0, sizeof(GLC));
|
||
|
GLC[0] = ind[3];
|
||
|
GLC[1] = ind[4];
|
||
|
GLC[2] = '-';
|
||
|
GLC[3] = ind[0];
|
||
|
GLC[4] = ind[1];
|
||
|
GLC[5] = '-';
|
||
|
if (Y2K) {
|
||
|
GLC[6] = ind[6];
|
||
|
GLC[7] = ind[7];
|
||
|
GLC[8] = ind[8];
|
||
|
GLC[9] = ind[9];
|
||
|
} else {
|
||
|
GLC[6] = ind[8];
|
||
|
GLC[7] = ind[9];
|
||
|
}
|
||
|
|
||
|
return GLC;
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Function will run a external program or door
|
||
|
*/
|
||
|
void ExtDoor(char *Program, int NoDoorsys, int Y2Kdoorsys, int Comport, int NoSuid, int NoPrompt, int SingleUser, char *What)
|
||
|
{
|
||
|
char *String, *String1;
|
||
|
int i, rc, Start;
|
||
|
char *temp1, buf[128];
|
||
|
FILE *fp;
|
||
|
|
||
|
temp1 = calloc(PATH_MAX, sizeof(char));
|
||
|
String = calloc(81, sizeof(char));
|
||
|
|
||
|
Start = TRUE;
|
||
|
if (SingleUser && What) {
|
||
|
/*
|
||
|
* Check if the door is in use
|
||
|
*/
|
||
|
while (TRUE) {
|
||
|
if (Start)
|
||
|
snprintf(buf, 128, "GMON:1,1;");
|
||
|
else
|
||
|
snprintf(buf, 128, "GMON:1,0;");
|
||
|
Start = FALSE;
|
||
|
if (socket_send(buf) == 0) {
|
||
|
strcpy(buf, socket_receive());
|
||
|
if (strncmp(buf, "100:0;", 6) == 0)
|
||
|
break; /* No more data */
|
||
|
if (strstr(buf, "mbsebbs")) {
|
||
|
strtok(buf, ","); /* Nr of parameters */
|
||
|
strtok(NULL, ","); /* Pid */
|
||
|
strtok(NULL, ","); /* tty */
|
||
|
strtok(NULL, ","); /* username */
|
||
|
strtok(NULL, ","); /* program name */
|
||
|
strtok(NULL, ","); /* location */
|
||
|
if (strcmp(strtok(NULL, ","), menus.DoorName) == 0) {
|
||
|
Syslog('+', "User tried single user door %s, but door is in use", menus.DoorName);
|
||
|
Enter(1);
|
||
|
/* The door is in use by another user, try again later */
|
||
|
pout(LIGHTRED, BLACK, (char *) Language(20));
|
||
|
Enter(2);
|
||
|
Pause();
|
||
|
free(temp1);
|
||
|
free(String);
|
||
|
return;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
WhosDoingWhat(DOOR, What);
|
||
|
|
||
|
if ((strstr(Program, "/N")) != NULL) {
|
||
|
snprintf(temp1, 81, "%d", iNode);
|
||
|
strreplace(Program, (char *)"/N", temp1);
|
||
|
}
|
||
|
|
||
|
if ((strstr(Program, "/A")) != NULL) {
|
||
|
Enter(1);
|
||
|
colour(CYAN, BLACK);
|
||
|
if ((String = strstr(Program, "/T=")) != NULL) {
|
||
|
String1 = String + 3;
|
||
|
PUTSTR(String1);
|
||
|
} else
|
||
|
PUTSTR((char *)"Please enter filename: ");
|
||
|
|
||
|
colour(CFG.InputColourF, CFG.InputColourB);
|
||
|
GetstrC(temp1, 80);
|
||
|
|
||
|
strreplace(Program, (char *)"/A", temp1);
|
||
|
|
||
|
for (i = 0; i < strlen(Program); i++) {
|
||
|
if (*(Program + i) == '\0')
|
||
|
break;
|
||
|
if (*(Program + i) == '/')
|
||
|
*(Program + i) = '\0';
|
||
|
}
|
||
|
}
|
||
|
|
||
|
free(String);
|
||
|
Syslog('+', "Door: %s", Program);
|
||
|
ReadExitinfo();
|
||
|
alarm_set((exitinfo.iTimeLeft * 60) - 10);
|
||
|
Altime((exitinfo.iTimeLeft * 60));
|
||
|
|
||
|
/*
|
||
|
* Always remove the old door.sys first.
|
||
|
*/
|
||
|
snprintf(temp1, PATH_MAX, "%s/%s/door.sys", CFG.bbs_usersdir, exitinfo.Name);
|
||
|
unlink(temp1);
|
||
|
|
||
|
/*
|
||
|
* Write door.sys in users homedirectory
|
||
|
*/
|
||
|
if (!NoDoorsys) {
|
||
|
if ((fp = fopen(temp1, "w+")) == NULL) {
|
||
|
WriteError("$Can't create %s", temp1);
|
||
|
} else {
|
||
|
if (Comport) {
|
||
|
fprintf(fp, "COM1:\r\n"); /* COM port */
|
||
|
fprintf(fp, "19200\r\n");/* Effective baudrate */
|
||
|
} else {
|
||
|
fprintf(fp, "COM0:\r\n");/* COM port */
|
||
|
fprintf(fp, "0\r\n"); /* Effective baudrate */
|
||
|
}
|
||
|
fprintf(fp, "8\r\n"); /* Databits */
|
||
|
fprintf(fp, "%d\r\n", iNode); /* Node number */
|
||
|
if (Comport)
|
||
|
fprintf(fp, "19200\r\n");/* Locked baudrate */
|
||
|
else
|
||
|
fprintf(fp, "%d\r\n", ttyinfo.portspeed); /* Locked baudrate */
|
||
|
fprintf(fp, "Y\r\n"); /* Screen snoop */
|
||
|
fprintf(fp, "N\r\n"); /* Printer on */
|
||
|
fprintf(fp, "Y\r\n"); /* Page bell */
|
||
|
fprintf(fp, "Y\r\n"); /* Caller alarm */
|
||
|
fprintf(fp, "%s\r\n", exitinfo.sUserName);
|
||
|
fprintf(fp, "%s\r\n", exitinfo.sLocation);
|
||
|
fprintf(fp, "%s\r\n", exitinfo.sVoicePhone);
|
||
|
fprintf(fp, "%s\r\n", exitinfo.sDataPhone);
|
||
|
fprintf(fp, "%s\r\n", exitinfo.Password);
|
||
|
fprintf(fp, "%d\r\n", exitinfo.Security.level);
|
||
|
fprintf(fp, "%d\r\n", exitinfo.iTotalCalls);
|
||
|
fprintf(fp, "%s\r\n", Gdate(exitinfo.tLastLoginDate, Y2Kdoorsys));
|
||
|
fprintf(fp, "%d\r\n", exitinfo.iTimeLeft * 60); /* Seconds */
|
||
|
fprintf(fp, "%d\r\n", exitinfo.iTimeLeft); /* Minutes */
|
||
|
fprintf(fp, "GR\r\n"); /* Graphics GR,RIP,NG */
|
||
|
fprintf(fp, "%d\r\n", rows);
|
||
|
fprintf(fp, "N\r\n"); /* User mode, always N */
|
||
|
fprintf(fp, "\r\n"); /* Always blank */
|
||
|
fprintf(fp, "\r\n"); /* Always blank */
|
||
|
fprintf(fp, "%s\r\n", Rdate(exitinfo.sExpiryDate, Y2Kdoorsys));
|
||
|
fprintf(fp, "%d\r\n", grecno); /* Users recordnumber */
|
||
|
fprintf(fp, "%s\r\n", exitinfo.sProtocol);
|
||
|
fprintf(fp, "%d\r\n", exitinfo.Uploads);
|
||
|
fprintf(fp, "%d\r\n", exitinfo.Downloads);
|
||
|
fprintf(fp, "%d\r\n", LIMIT.DownK); /* FIXME: Download Kb today */
|
||
|
fprintf(fp, "%d\r\n", LIMIT.DownK);
|
||
|
fprintf(fp, "%s\r\n", Rdate(exitinfo.sDateOfBirth, Y2Kdoorsys));
|
||
|
fprintf(fp, "\r\n"); /* Path to userbase */
|
||
|
fprintf(fp, "\r\n"); /* Path to messagebase */
|
||
|
fprintf(fp, "%s\r\n", CFG.sysop_name);
|
||
|
fprintf(fp, "%s\r\n", exitinfo.sHandle);
|
||
|
fprintf(fp, "none\r\n"); /* Next event time */
|
||
|
fprintf(fp, "Y\r\n"); /* Error free connect. */
|
||
|
fprintf(fp, "N\r\n"); /* Always N */
|
||
|
fprintf(fp, "Y\r\n"); /* Always Y */
|
||
|
fprintf(fp, "7\r\n"); /* Default textcolor */
|
||
|
fprintf(fp, "0\r\n"); /* Always 0 */
|
||
|
fprintf(fp, "%s\r\n", Gdate(exitinfo.tLastLoginDate, Y2Kdoorsys)); /* Last newfiles scan date */
|
||
|
fprintf(fp, "%s\r\n", StrTimeHM(t_start)); /* Time of this call */
|
||
|
fprintf(fp, "%s\r\n", LastLoginTime); /* Time of last call */
|
||
|
fprintf(fp, "32768\r\n"); /* Always 32768 */
|
||
|
fprintf(fp, "%d\r\n", exitinfo.DownloadsToday);
|
||
|
fprintf(fp, "%d\r\n", exitinfo.UploadK);
|
||
|
fprintf(fp, "%d\r\n", exitinfo.DownloadK);
|
||
|
fprintf(fp, "%s\r\n", exitinfo.sComment);
|
||
|
fprintf(fp, "0\r\n"); /* Always 0 */
|
||
|
fprintf(fp, "%d\r\n\032", exitinfo.iPosted);
|
||
|
fclose(fp);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/*
|
||
|
* Always remove the old door32.sys first.
|
||
|
*/
|
||
|
snprintf(temp1, PATH_MAX, "%s/%s/door32.sys", CFG.bbs_usersdir, exitinfo.Name);
|
||
|
unlink(temp1);
|
||
|
|
||
|
/*
|
||
|
* Write door32.sys in users homedirectory
|
||
|
*/
|
||
|
if (!NoDoorsys) {
|
||
|
if ((fp = fopen(temp1, "w+")) == NULL) {
|
||
|
WriteError("$Can't create %s", temp1);
|
||
|
} else {
|
||
|
if (Comport) {
|
||
|
fprintf(fp, "1\r\n"); /* COM type, 1=serial, 2=telnet */
|
||
|
fprintf(fp, "1\r\n"); /* COM port number */
|
||
|
fprintf(fp, "19200\r\n"); /* Effective baudrate */
|
||
|
} else {
|
||
|
fprintf(fp, "0\r\n"); /* COM type, 0=local */
|
||
|
fprintf(fp, "0\r\n"); /* COM port */
|
||
|
fprintf(fp, "0\r\n"); /* Effective baudrate */
|
||
|
}
|
||
|
fprintf(fp, "%s\r\n", CFG.bbs_name); /* BBS name */
|
||
|
fprintf(fp, "%d\r\n", grecno); /* User record */
|
||
|
fprintf(fp, "%s\r\n", exitinfo.sUserName); /* User's real name */
|
||
|
fprintf(fp, "%s\r\n", exitinfo.sHandle); /* User's handle */
|
||
|
fprintf(fp, "%d\r\n", exitinfo.Security.level); /* User's security level */
|
||
|
fprintf(fp, "%d\r\n", exitinfo.iTimeLeft); /* User's time left in minutes */
|
||
|
fprintf(fp, "1\r\n"); /* User's graphic mode */
|
||
|
fprintf(fp, "%d\r\n\032", iNode); /* Node number */
|
||
|
fclose(fp);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
clear();
|
||
|
PUTSTR((char *)"Loading, please wait ...");
|
||
|
Enter(2);
|
||
|
|
||
|
/*
|
||
|
* Put terminal back in cooked mode, prefered by some doors.
|
||
|
*/
|
||
|
cookedport();
|
||
|
|
||
|
if (NoSuid)
|
||
|
rc = exec_nosuid(Program);
|
||
|
else
|
||
|
rc = execute_str((char *)"/bin/sh", (char *)"-c", Program, NULL, NULL, NULL);
|
||
|
|
||
|
/*
|
||
|
* First set cookedport again, this will load our original saved
|
||
|
* termios values. This way it doesn't matter what the door might
|
||
|
* have done with the original termios.
|
||
|
*/
|
||
|
cookedport();
|
||
|
rawport();
|
||
|
|
||
|
Altime(0);
|
||
|
alarm_off();
|
||
|
alarm_on();
|
||
|
Syslog('+', "Door end, rc=%d", rc);
|
||
|
|
||
|
free(temp1);
|
||
|
Enter(2);
|
||
|
|
||
|
if (!NoPrompt)
|
||
|
Pause();
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
/*
|
||
|
* Execute a door as real user, not suid.
|
||
|
*/
|
||
|
int exec_nosuid(char *mandato)
|
||
|
{
|
||
|
int rc, status;
|
||
|
pid_t pid;
|
||
|
char *argv[4];
|
||
|
|
||
|
if (mandato == NULL)
|
||
|
return 1; /* Prevent running a shell */
|
||
|
|
||
|
Syslog('+', "Execve: /bin/sh -c %s", mandato);
|
||
|
pid = fork();
|
||
|
if (pid == -1)
|
||
|
return 1;
|
||
|
if (pid == 0) {
|
||
|
msleep(150);
|
||
|
argv[0] = (char *)"sh";
|
||
|
argv[1] = (char *)"-c";
|
||
|
argv[2] = mandato;
|
||
|
argv[3] = 0;
|
||
|
execve("/bin/sh", argv, environ);
|
||
|
exit(MBERR_EXEC_FAILED);
|
||
|
}
|
||
|
e_pid = pid;
|
||
|
|
||
|
do {
|
||
|
rc = waitpid(pid, &status, 0);
|
||
|
e_pid = 0;
|
||
|
} while (((rc > 0) && (rc != pid)) || ((rc == -1) && (errno == EINTR)));
|
||
|
|
||
|
switch(rc) {
|
||
|
case -1:
|
||
|
WriteError("$Waitpid returned %d, status %d,%d", rc,status>>8,status&0xff);
|
||
|
return -1;
|
||
|
case 0:
|
||
|
return 0;
|
||
|
default:
|
||
|
if (WIFEXITED(status)) {
|
||
|
rc = WEXITSTATUS(status);
|
||
|
if (rc) {
|
||
|
WriteError("Exec_nosuid: returned error %d", rc);
|
||
|
return rc;
|
||
|
}
|
||
|
}
|
||
|
if (WIFSIGNALED(status)) {
|
||
|
rc = WTERMSIG(status);
|
||
|
WriteError("Wait stopped on signal %d", rc);
|
||
|
return rc;
|
||
|
}
|
||
|
if (rc)
|
||
|
WriteError("Wait stopped unknown, rc=%d", rc);
|
||
|
return rc;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
|