This is extensions.c in view mode; [Download] [Up]
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <time.h>
#include <pwd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/file.h>
#include <sys/param.h>
#include <arpa/ftp.h>
#include "pathnames.h"
#include "extensions.h"
#include "support/ftw.h"
extern int fnmatch(),
type,
transflag,
autospout_free,
data;
extern char **glob(),
*globerr,
remotehost[],
hostname[],
*autospout,
shutdown[];
char shuttime[30],
denytime[30],
disctime[30];
extern FILE *dataconn();
FILE *dout;
time_t newer_time;
int show_fullinfo;
/*************************************************************************/
/* FUNCTION : msg_massage */
/* PURPOSE : Scan a message line for magic cookies, replacing them as */
/* needed. */
/* ARGUMENTS : pointer input and output buffers */
/*************************************************************************/
int
msg_massage(inbuf, outbuf)
char *inbuf, *outbuf;
{
char *inptr = inbuf;
char *outptr = outbuf;
char buffer[MAXPATHLEN];
time_t curtime;
int limit;
extern struct passwd *pw;
(void) time(&curtime);
(void) acl_getclass(buffer);
limit = acl_getlimit(buffer, NULL);
while (*inptr) {
if (*inptr != '%')
*outptr++ = *inptr;
else {
switch (*++inptr) {
/* broken
case 'N':
sprintf(outptr, "%d", acl_countusers(buffer));
break;
*/
case 'M':
sprintf(outptr, "%d", limit);
break;
case 'T':
strncpy(outptr, ctime(&curtime), 24);
*(outptr + 24) = NULL;
break;
case 'F':
break;
case 'C':
(void) getwd(outptr);
break;
case 'R':
strcpy(outptr, remotehost);
break;
case 'L':
strcpy(outptr, hostname);
break;
case 'U':
strcpy(outptr, pw->pw_name);
break;
case 's':
strncpy(outptr, shuttime, 24);
*(outptr + 24) = NULL;
break;
case 'd':
strncpy(outptr, disctime, 24);
*(outptr + 24) = NULL;
break;
case 'r':
strncpy(outptr, denytime, 24);
*(outptr + 24) = NULL;
break;
case '%':
*outptr++ = '%';
*outptr = '\0';
break;
default:
*outptr++ = '%';
*outptr++ = '?';
*outptr = '\0';
break;
}
while (*outptr) outptr++;
}
inptr++;
}
*outptr = NULL;
}
/*************************************************************************/
/* FUNCTION : cwd_beenhere */
/* PURPOSE : Return 1 if the user has already visited this directory */
/* via CWD. */
/* ARGUMENTS : a power-of-two directory function code (README, MESSAGE) */
/*************************************************************************/
int
cwd_beenhere(dircode)
int dircode;
{
struct dirlist {
struct dirlist *next;
int dircode;
char dirname[1];
};
static struct dirlist *head = NULL;
struct dirlist *curptr;
char cwd[MAXPATHLEN];
(void) getwd(cwd);
for (curptr = head; curptr != NULL; curptr = curptr->next)
if (strcmp(curptr->dirname, cwd) == NULL) {
if (!(curptr->dircode & dircode)) {
curptr->dircode |= dircode;
return(0);
}
return(1);
}
curptr = (struct dirlist *) malloc(strlen(cwd)+1+sizeof(struct dirlist));
if (curptr != NULL) {
curptr->next = head;
head = curptr;
curptr->dircode = dircode;
strcpy(curptr->dirname, cwd);
}
return(0);
}
/*************************************************************************/
/* FUNCTION : show_banner */
/* PURPOSE : Display a banner on the user's terminal before login */
/* ARGUMENTS : reply code to use */
/*************************************************************************/
void
show_banner(msgcode)
int msgcode;
{
char *crptr,
**filelist,
linebuf[1024],
outbuf[1024],
cwd[MAXPATHLEN];
int show,
clock;
struct stat buf;
struct aclmember *entry = NULL;
FILE *infile;
/* banner <path> */
while (getaclentry("banner", &entry)) {
if (ARG0 && strlen(ARG0) > 0) {
infile = fopen(ARG0, "r");
if (infile) {
while (fgets(linebuf, 255, infile) != NULL) {
if ((crptr = strchr(linebuf, '\n')) != NULL) *crptr = '\0';
msg_massage(linebuf, outbuf);
lreply(msgcode, "%s", outbuf);
}
fclose(infile);
lreply(msgcode, "");
}
}
}
}
/*************************************************************************/
/* FUNCTION : show_message */
/* PURPOSE : Display a message on the user's terminal if the current */
/* conditions are right */
/* ARGUMENTS : reply code to use, LOGIN|CMD */
/*************************************************************************/
void
show_message(msgcode, mode)
int msgcode, mode;
{
char *crptr,
linebuf[1024],
outbuf[1024],
cwd[MAXPATHLEN];
int show;
struct aclmember *entry = NULL;
FILE *infile;
if (cwd_beenhere(1) != 0) return;
(void) getwd(cwd);
/* message <path> [<when>] */
while (getaclentry("message", &entry)) {
if (!ARG0) continue;
show = 0;
if (mode == LOGIN && (!ARG1 || !strcasecmp(ARG1, "login")))
show++;
if (mode == CWD && ARG1 && !strncasecmp(ARG1,"cwd=",4) &&
!strcmp((ARG1)+4, cwd) || *(ARG1+4) == '*' ||
fnmatch((ARG1)+4, cwd, FNM_PATHNAME)) show++;
if (show && strlen(ARG0) > 0) {
infile = fopen(ARG0, "r");
if (infile) {
while (fgets(linebuf, 255, infile) != NULL) {
if ((crptr = strchr(linebuf, '\n')) != NULL) *crptr = '\0';
msg_massage(linebuf, outbuf);
lreply(msgcode, "%s", outbuf);
}
fclose(infile);
lreply(msgcode, "");
}
}
}
}
/*************************************************************************/
/* FUNCTION : show_readme */
/* PURPOSE : Display a message about a README file to the user if the */
/* current conditions are right */
/* ARGUMENTS : pointer to ACL buffer, reply code, LOGIN|CWD */
/*************************************************************************/
void
show_readme(code, mode)
int code, mode;
{
char **filelist,
cwd[MAXPATHLEN];
int show,
clock,
days;
struct stat buf;
struct tm *tp;
struct aclmember *entry = NULL;
if (cwd_beenhere(2) != 0) return;
(void) getwd(cwd);
/* readme <path> {<when>} */
while (getaclentry("readme", &entry)) {
if (!ARG0) continue;
show = 0;
if (mode == LOGIN && (!ARG1 || !strcasecmp(ARG1, "login")))
show++;
if (mode == CWD && ARG1 && !strncasecmp(ARG1, "cwd=", 4)
&& (!strcmp((ARG1)+4, cwd) || *(ARG1+4) == '*' ||
fnmatch((ARG1)+4, cwd, FNM_PATHNAME))) show++;
if (show) {
globerr = NULL;
filelist = glob(ARG0);
if (!globerr) {
while (filelist && *filelist) {
errno = 0;
if (!stat(*filelist, &buf)) {
lreply(code, "Please read the file %s", *filelist);
(void) time(&clock);
tp = localtime(&clock);
days = 365 * tp->tm_year + tp->tm_yday;
tp = localtime(&buf.st_mtime);
days -= 365 * tp->tm_year + tp->tm_yday;
lreply(code, " it was last modified on %.24s - %d days ago",
ctime(&buf.st_mtime), days);
}
filelist++;
}
}
}
}
}
/*************************************************************************/
/* FUNCTION : deny_badxfertype */
/* PURPOSE : If user is in ASCII transfer mode and tries to retrieve a */
/* binary file, abort transfer and display appropriate error */
/* ARGUMENTS : message code to use for denial, path of file to check for */
/* binary contents or NULL to assume binary file */
/*************************************************************************/
int
deny_badasciixfer(msgcode, filepath)
int msgcode;
char *filepath;
{
if (type == TYPE_A && !*filepath) {
reply(msgcode, "This is a BINARY file, using ASCII mode to transfer will corrupt it.");
return(1);
}
/* The hooks are here to prevent transfers of actual binary files, not
* just TAR or COMPRESS mode files...
*/
return(0);
}
/*************************************************************************/
/* FUNCTION : is_shutdown */
/* PURPOSE : */
/* ARGUMENTS : */
/*************************************************************************/
int
is_shutdown(quiet)
int quiet;
{
static struct tm tmbuf;
static struct stat s_last;
static time_t last = 0,
shut,
deny,
disc;
static char text[2048];
struct stat s_cur;
FILE *fp;
int deny_off, disc_off;
time_t curtime = time(NULL);
char buf[1024], linebuf[1024];
if (shutdown[0] == '\0' || stat(shutdown, &s_cur)) return(0);
if (s_last.st_mtime != s_cur.st_mtime) {
s_last = s_cur;
fp = fopen(shutdown, "r");
if (fp == NULL) return(0);
fgets(buf, sizeof(buf), fp);
if (sscanf(buf, "%d %d %d %d %d %d %d", &tmbuf.tm_year, &tmbuf.tm_mon,
&tmbuf.tm_mday, &tmbuf.tm_hour, &tmbuf.tm_min, &deny, &disc) != 7) {
return(0);
}
deny_off = 3600 * (deny / 100) + 60 * (deny % 100);
disc_off = 3600 * (disc / 100) + 60 * (disc % 100);
tmbuf.tm_year -= 1900;
tmbuf.tm_isdst = -1;
shut = mktime(&tmbuf);
strcpy(shuttime, ctime(&shut));
disc = shut - disc_off;
strcpy(disctime, ctime(&disc));
deny = shut - deny_off;
strcpy(denytime, ctime(&deny));
text[0] = '\0';
while (fgets(buf, sizeof(buf), fp) != NULL) {
msg_massage(buf, linebuf);
if ((strlen(text) + strlen(linebuf)) < sizeof(text))
strcat(text, linebuf);
}
(void) fclose(fp);
}
/* if last == 0, then is_shutdown() only called with quiet == 1 so far */
if (last == 0 && !quiet) {
autospout = text; /* warn them for the first time */
autospout_free = 0;
last = curtime;
}
/* if past disconnect time, tell caller to drop 'em */
if (curtime > disc) return(1);
/* if less than 60 seconds to disconnection, warn 'em continuously */
if (curtime > (disc - 60) && !quiet) {
autospout = text;
autospout_free = 0;
last = curtime;
}
/* if less than 15 minutes to disconnection, warn 'em every 5 mins */
if (curtime > (disc - 60*15)) {
if ((curtime - last) > (60*5) && !quiet) {
autospout = text;
autospout_free = 0;
last = curtime;
}
}
/* if less than 24 hours to disconnection, warn 'em every 30 mins */
if (curtime < (disc - 24*60*60) && !quiet) {
if ((curtime - last) > (60*30)) {
autospout = text;
autospout_free = 0;
last = curtime;
}
}
/* if more than 24 hours to disconnection, warn 'em every 60 mins */
if (curtime > (disc - 24*60*60) && !quiet) {
if ((curtime - last) >= (24*60*60)) {
autospout = text;
autospout_free = 0;
last = curtime;
}
}
return(0);
}
newer(date, path, showlots)
char *date, *path;
int showlots;
{
struct tm tm;
if (sscanf(date, "%04d%02d%02d%02d%02d%02d",
&tm.tm_year, &tm.tm_mon, &tm.tm_mday,
&tm.tm_hour, &tm.tm_min, &tm.tm_sec) == 6) {
tm.tm_year -= 1900;
tm.tm_mon--;
tm.tm_isdst = -1;
newer_time = mktime(&tm);
dout = dataconn("file list", (off_t)-1, "w", 0);
transflag++;
if (dout != NULL) {
int check_newer();
show_fullinfo = showlots;
treewalk(path, check_newer, -1, NULL);
if (ferror(dout) != 0)
perror_reply(550, "Data connection");
else
reply(226, "Transfer complete.");
(void) fclose(dout);
data = -1;
}
} else
reply(501, "Bad DATE format");
transflag = 0;
}
check_newer(path, st, flag)
char *path;
struct stat *st;
int flag;
{
if (st->st_mtime > newer_time) {
if (show_fullinfo != 0) {
if (flag == FTW_F || flag == FTW_D) {
fprintf(dout, "%s %d %d %s", flag == FTW_F ? "F" : "D",
st->st_size, st->st_mtime, path);
}
} else if (flag == FTW_F) fprintf(dout, "%s", path);
}
return 0;
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.