]> Zhao Yanbai Git Server - minix.git/commitdiff
Applied MINIX 2.0.4 pathes provides by Al Woodhull.
authorJorrit Herder <jnherder@minix3.org>
Fri, 17 Jun 2005 13:00:04 +0000 (13:00 +0000)
committerJorrit Herder <jnherder@minix3.org>
Fri, 17 Jun 2005 13:00:04 +0000 (13:00 +0000)
34 files changed:
commands/cron/crontab.c
commands/cron/tab.c
commands/ftpd200/Makefile [new file with mode: 0644]
commands/ftpd200/README [new file with mode: 0644]
commands/ftpd200/README2 [new file with mode: 0644]
commands/ftpd200/access.c [new file with mode: 0644]
commands/ftpd200/access.h [new file with mode: 0644]
commands/ftpd200/file.c [new file with mode: 0644]
commands/ftpd200/file.h [new file with mode: 0644]
commands/ftpd200/ftpd.8 [new file with mode: 0644]
commands/ftpd200/ftpd.c [new file with mode: 0644]
commands/ftpd200/ftpd.h [new file with mode: 0644]
commands/ftpd200/ftpdsh [new file with mode: 0755]
commands/ftpd200/net.c [new file with mode: 0644]
commands/ftpd200/net.h [new file with mode: 0644]
commands/ftpd200/setup.anonftp [new file with mode: 0755]
commands/ps/ps.c
drivers/libpci/pci_table.c
kernel/clock.c
kernel/proc.c
kernel/proto.h
kernel/system.c
lib/ansi/misc.c
man/man1/ash.1
man/man1/eject.1
man/man1/elvis.1
man/man1/flex.1
man/man1/flexdoc.1
man/man1/fsck.1
man/man1/join.1
man/man1/makewhatis.1
man/man1/ps.1
man/man1/tar.1
man/man1/touch.1

index 13da7d390650a00c752665f9def8e10c8e704eef..6797ae28c794e4cb3e217a59b184b274694b2435 100755 (executable)
@@ -189,6 +189,9 @@ int main(int argc, char **argv)
                pflag= 1;
        }
 
+       /* Initialize current Time */
+       time(&now);
+
        if (cflag) {
                int fd1, fd2;
 
index 858d12418eecb167f0329a66bde7afc0aeca387f..2cdce435bdc2d503bd9dd4a29b74d7805dfc9c2c 100755 (executable)
@@ -158,6 +158,7 @@ void tab_reschedule(cronjob_t *job)
                        job->rtime= NEVER;
                        return; 
                }
+               tmptm= *localtime(&job->rtime);
                if (tmptm.tm_hour != nexttm.tm_hour ||
                        tmptm.tm_min != nexttm.tm_min)
                {
@@ -182,6 +183,7 @@ void tab_reschedule(cronjob_t *job)
                                job->rtime= NEVER;
                                return; 
                        }
+                       tmptm= *localtime(&job->rtime);
                        if (tmptm.tm_hour != nexttm.tm_hour ||
                                tmptm.tm_min != nexttm.tm_min)
                        {
diff --git a/commands/ftpd200/Makefile b/commands/ftpd200/Makefile
new file mode 100644 (file)
index 0000000..0287658
--- /dev/null
@@ -0,0 +1,42 @@
+# Makefile for ftpd
+#
+# 01/25/96 Initial Release     Michael Temari, <Michael@TemWare.Com>
+# 2005-02-25 version 2.00
+
+CFLAGS=        -O -D_MINIX -D_POSIX_SOURCE -m
+LDFLAGS=-i
+BINDIR=        /usr/bin
+PROG=  in.ftpd
+MANDIR= /usr/man/man8
+MANPAGE=ftpd.8
+
+OBJS=  ftpd.o access.o file.o net.o
+
+all:   $(PROG)
+
+$(PROG):       $(OBJS)
+       $(CC) $(LDFLAGS) -o $@ $(OBJS)
+       install -S 8kw $@
+
+clean:
+       rm -f $(PROG) $(OBJS)
+
+install:       $(BINDIR)/$(PROG) $(BINDIR)/setup.anonftp $(BINDIR)/ftpdsh
+
+$(BINDIR)/$(PROG):     $(PROG)
+       install -cs -o bin $? $@
+
+$(BINDIR)/setup.anonftp:       setup.anonftp
+       install -c -o bin $? $@
+
+$(BINDIR)/ftpdsh:      ftpdsh
+       install -c -o bin $? $@
+
+ftpd.o:                ftpd.c   ftpd.h access.h file.h net.h
+access.o:      access.c ftpd.h access.h
+file.o:                file.c   ftpd.h access.h file.h net.h
+net.o:         net.c    ftpd.h                 net.h
+
+installman:    $(MANDIR)/$(MANPAGE)
+       cp $(MANPAGE) $(MANDIR)
+       echo "You may need to run makewhatis to update man page index"
diff --git a/commands/ftpd200/README b/commands/ftpd200/README
new file mode 100644 (file)
index 0000000..0d267c1
--- /dev/null
@@ -0,0 +1,35 @@
+ftpd200 --- FTP server program for Minix 2.0  
+written by Michael Temari <Michael@TemWare.Com> release 2.00 2005-02-25
+
+Full download: <a href="/pub/contrib/ftpd200.tar.Z">ftpd200.tar.Z</a>
+
+Ftpd is the File Transfer Protocol (FTP) server.  
+
+Important: Release 2.00 incorporates an improved mechanism to restrict
+execution of commands on the server.  This is done through use of a
+shell script, ftpdsh.  Any earlier ftpd version in use on a system
+accessible from the Internet should be upgraded at least to version 1.01,
+version 2.00 is preferable.
+
+Installation: unpack the tarball in /usr/local/src or another directory 
+of your choice:
+zcat < ftpd200.tar.Z | tar xvfp -
+
+The ftpd200 directory will be created.  Read the Makefile to see how
+the program is compiled and installed:
+
+make (or make ftpd) -- compiles the binary
+make install        -- installs /usr/bin/in.ftpd, and ftpdsh. Also installs 
+                       setup.anonftp script.  
+make installman     -- installs new ftpd.8 man page in /usr/local/man/man8
+
+The shell script setup.anonftp sets up and verifies configuration for
+anonymous ftp.  If you provide anonymous ftp you are letting anyone in
+the whole wide world execute a program on your computer.  You want to
+make sure it's set up correctly so outsiders can't mess with things
+they shouldn't.  
+
+This file is included as README in the source directory.  For more
+notes on compiling and installing, also please see the file README2.
+
+notes updated by asw 2005-02-25
diff --git a/commands/ftpd200/README2 b/commands/ftpd200/README2
new file mode 100644 (file)
index 0000000..40e035b
--- /dev/null
@@ -0,0 +1,34 @@
+README2: additional notes on compiling and installing ftpd.
+
+Note that the Makefile install options will replace files in /usr/bin
+and /usr/man that were installed with the Minix distribution.  If you
+are not sure you want to do this you can either rename the original
+in.ftpd binary, the anonftp.* scripts, and the ftpd.8 man page to
+prevent them from being replaced, or you can edit the Makefile to
+change the directory values:
+  BINDIR= /usr/local/bin
+  MANDIR= /usr/local/man/man8
+ASW's practice is to rename binaries with a suffix that indicates the
+original distribution from which they were obtained, i.e., in.ftpd.203
+for the version distributed with Minix 2.0.3, or with a date code or a
+version number.
+
+If you are sure you want to replace the original ftpd provided with your
+distribution you  may want to copy the contents of the unpacked tarball
+to the main directory tree, in this case /usr/src/commands/ftpd, so that
+a new version will be compiled if you do a general recompilation of all 
+commands using "make all" or "make compile" in /usr/src. ASW's practice
+is generally to make a directory in /usr/local/src for new versions of
+major programs. 
+Also note that if you create a new man page where one did not exist
+previously you will need to run makewhatis to rebuild the whatis
+database, i.e.:
+  makewhatis /usr/man
+or
+  makewhatis /usr/local/man
+
+Important: the scripts for setting up and maintaining an anonymous ftp
+installation haven't been checked for a long time, I would appreciate 
+comments.
+
+ASW 2005-02-06
diff --git a/commands/ftpd200/access.c b/commands/ftpd200/access.c
new file mode 100644 (file)
index 0000000..0e686bb
--- /dev/null
@@ -0,0 +1,134 @@
+/* access.c Copyright 1992-2000 by Michael Temari All Rights Reserved
+ *
+ * This file is part of ftpd.
+ *
+ * This file handles:
+ *
+ *      USER PASS QUIT
+ *
+ *
+ * 01/25/96 Initial Release    Michael Temari, <Michael@TemWare.Com>
+ */
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <net/gen/in.h>
+#include <net/gen/tcp.h>
+
+#include "ftpd.h"
+#include "access.h"
+
+_PROTOTYPE(static int AreWeIn, (char *name, struct passwd *pwd));
+
+static char *msg530 = "530 Not logged in.\r\n";
+
+/* Returns -1 = not logged in, 0 = loggedin */
+int ChkLoggedIn()
+{
+   if(!loggedin) {
+       printf(msg530);
+       return(-1);
+   } else
+       return(0);
+}
+
+/* what a USER! */
+int doUSER(buff)
+char *buff;
+{
+   loggedin = 0;
+   gotuser = 0;
+   strncpy(username, buff, sizeof(username));
+   username[sizeof(username)-1] = '\0';
+
+   if(*username == '\0') {
+       printf("501 Bad user name.\r\n");
+       return(GOOD);
+   }
+
+   gotuser = 1;
+
+   printf("331 Password required for %s.\r\n", username);
+
+   return(GOOD);
+}
+
+/* secret, secret, secret */
+int doPASS(buff)
+char *buff;
+{
+char *name;
+struct passwd *pwd;
+int bad=0;
+
+   name = username;
+
+   if(!strcmp(name, "anonymous"))
+       name = "ftp";
+
+   if(!gotuser || ((pwd = getpwnam(name)) == (struct passwd *)0))
+       bad = 1;
+   else
+       if(strcmp(name, "ftp")) {
+               if(!strcmp(pwd->pw_passwd, crypt("", pwd->pw_passwd)))
+                       bad = 1;
+               if(strcmp(pwd->pw_passwd, crypt(buff, pwd->pw_passwd)))
+                       bad = 1;
+       } else {
+               strncpy(anonpass, buff, sizeof(anonpass));
+               anonpass[sizeof(anonpass)-1] = '\0';
+       }
+
+   if(bad) {
+       logit("LOGIN", "FAIL");
+       printf(msg530);
+       return(GOOD);
+   }
+
+   return(AreWeIn(name, pwd));
+}
+
+/* bye, bye don't let the door hit you in the butt on the way out */
+int doQUIT(buff)
+char *buff;
+{
+   printf("221 Service closing, don't be a stranger.\r\n");
+
+   return(BAD);
+}
+
+/* see if this user is okay */
+static int AreWeIn(name, pwd)
+char *name;
+struct passwd *pwd;
+{
+   if(!strcmp(name, "ftp")) {
+       if(chroot(pwd->pw_dir)) {
+               logit("LOGIN", "FAIL");
+               printf("530 Not logged in, could not chroot.\r\n");
+               return(GOOD);
+       }
+       strncpy(newroot, pwd->pw_dir, sizeof(newroot));
+       newroot[sizeof(newroot)-1] = '\0';
+       anonymous = 1;
+       strcpy(pwd->pw_dir, "/");
+   }
+
+   if(setgid(pwd->pw_gid) || setuid(pwd->pw_uid) || chdir(pwd->pw_dir)) {
+       logit("LOGIN", "FAIL");
+       printf(msg530);
+       anonymous = 0;
+   } else {
+       logit("LOGIN", "PASS");
+       showmsg("230", (char *)NULL);
+       printf("230 User %s logged in, directory %s.\r\n",
+               username, pwd->pw_dir);
+       loggedin = 1;
+   }
+
+   return(GOOD);
+}
diff --git a/commands/ftpd200/access.h b/commands/ftpd200/access.h
new file mode 100644 (file)
index 0000000..f2f4462
--- /dev/null
@@ -0,0 +1,12 @@
+/* ftpd.h
+ *
+ * This file is part of ftpd.
+ *
+ *
+ * 01/25/96 Initial Release    Michael Temari, <Michael@TemWare.Com>
+ */
+
+_PROTOTYPE(int ChkLoggedIn, (void));
+_PROTOTYPE(int doUSER, (char *buff));
+_PROTOTYPE(int doPASS, (char *buff));
+_PROTOTYPE(int doQUIT, (char *buff));
diff --git a/commands/ftpd200/file.c b/commands/ftpd200/file.c
new file mode 100644 (file)
index 0000000..381cfdb
--- /dev/null
@@ -0,0 +1,1252 @@
+/* file.c Copyright 1992-2000 by Michael Temari All Rights Reserved
+ *
+ * This file is part of ftpd.
+ *
+ * This file handles:
+ *
+ *      ALLO APPE CDUP CWD  DELE LIST MDTM MODE MKD  NLST PWD REST RETR
+ *      RMD  RNFR RNTO SITE SIZE STAT STOR STOU STRU SYST TYPE
+ *
+ * 01/25/96 Initial Release    Michael Temari
+ * 03/09/00                    Michael Temari, <Michael@TemWare.Com>
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <unistd.h>
+#include <string.h>
+#include <time.h>
+#include <net/hton.h>
+#include <net/gen/in.h>
+#include <net/gen/inet.h>
+#include <net/gen/tcp.h>
+
+#include "ftpd.h"
+#include "access.h"
+#include "file.h"
+#include "net.h"
+
+_PROTOTYPE(static int fdxcmd, (int cmd, char *arg));
+_PROTOTYPE(static int endfdxcmd, (int fd));
+_PROTOTYPE(static int asciisize, (char *filename, unsigned long *filesize));
+_PROTOTYPE(static int cnvtfile, (char *name, char **name2));
+_PROTOTYPE(static int procfile, (char *name));
+_PROTOTYPE(static unsigned long fsize, (char *fname));
+_PROTOTYPE(static int sendfile, (char *name, int xmode));
+_PROTOTYPE(static int recvfile, (char *name, int xmode));
+_PROTOTYPE(static char *uniqname, (void));
+_PROTOTYPE(static int docrc, (char *buff, int xmode));
+_PROTOTYPE(static int dofdet, (char *buff));
+_PROTOTYPE(static char *path, (char *fname));
+
+#define        SEND_FILE       0
+#define        SEND_NLST       1
+#define        SEND_LIST       2
+
+#define        RECV_FILE       0
+#define        RECV_APND       1
+#define        RECV_UNIQ       2
+
+#define        CNVT_ERROR      0
+#define        CNVT_NONE       1
+#define        CNVT_TAR        2
+#define        CNVT_TAR_Z      3
+#define        CNVT_COMP       4
+#define        CNVT_TAR_GZ     5
+#define        CNVT_GZIP       6
+#define        CNVT_UNCOMP     7
+
+
+#define        PROG_FTPDSH     "ftpdsh"
+#define        CMD_NLST        1
+#define        CMD_LIST        2
+#define        CMD_CRC         3
+
+static char *msg550 = "550 %s %s.\r\n";
+
+static unsigned long file_restart = 0;
+
+static char rnfr[256];
+static char buffer[8192];
+static char bufout[8192];
+
+static cmdpid = -1;
+
+/* allocate, we don't need no stink'n allocate */
+int doALLO(buff)
+char *buff;
+{
+   printf("202 ALLO command not needed at this site.\r\n");
+
+   return(GOOD);
+}
+
+/* append to a file if it exists */
+int doAPPE(buff)
+char *buff;
+{
+   return(recvfile(buff, RECV_APND));
+}
+
+/* change to parent directory */
+int doCDUP(buff)
+char *buff;
+{
+   if(ChkLoggedIn())
+       return(GOOD);
+
+   return(doCWD(".."));
+}
+
+/* change directory */
+int doCWD(buff)
+char *buff;
+{
+   if(ChkLoggedIn())
+       return(GOOD);
+
+   if(chdir(buff))
+       printf(msg550, buff, strerror(errno));
+   else {
+       showmsg("250", ".ftpd_msg");
+       printf("250 %s command okay.\r\n", line);
+   }
+
+   return(GOOD);
+}
+
+/* remove a file */
+int doDELE(buff)
+char *buff;
+{
+   if(ChkLoggedIn())
+       return(GOOD);
+
+   if(anonymous) {
+       printf("550 Command not allowed for anonymous user\r\n");
+       return(GOOD);
+   }
+
+   if(unlink(buff))
+       printf(msg550, buff, strerror(errno));
+   else {
+       printf("250 File \"%s\" deleted.\r\n", buff);
+       logit("DELE", path(buff));
+   }
+
+   return(GOOD);
+}
+
+/* directory listing */
+int doLIST(buff)
+char *buff;
+{
+   file_restart = 0;
+
+   return(sendfile(buff, SEND_LIST));
+}
+
+/* file modification time, btw when will this be put into an RFC */
+int doMDTM(buff)
+char *buff;
+{
+struct stat st;
+struct tm *t;
+
+   if(ChkLoggedIn())
+       return(GOOD);
+
+   if(stat(buff, &st)) {
+       printf(msg550, buff, strerror(errno));
+       return(GOOD);
+   }
+
+   if((st.st_mode & S_IFMT) != S_IFREG) {
+       printf("550 Not a regular file.\r\n");
+       return(GOOD);
+   }
+
+   t = gmtime(&st.st_mtime);
+
+   printf("215 %04d%02d%02d%02d%02d%02d\r\n",
+       t->tm_year+1900, t->tm_mon+1, t->tm_mday,
+       t->tm_hour, t->tm_min, t->tm_sec);
+
+   return(GOOD);
+}
+
+/* mode */
+int doMODE(buff)
+char *buff;
+{
+   switch(*buff) {
+       case 'b':
+       case 'B':
+               printf("200 Mode set to %c.\r\n", *buff);
+               mode = MODE_B;
+               break;
+       case 's':
+       case 'S':
+               printf("200 Mode set to %c.\r\n", *buff);
+               mode = MODE_S;
+               break;
+       default:
+               printf("501 Unknown mode %c.\r\n", *buff);
+   }
+
+   return(GOOD);
+}
+
+/* make a directory */
+int doMKD(buff)
+char *buff;
+{
+   if(ChkLoggedIn())
+       return(GOOD);
+
+   if(anonymous) {
+       printf("550 Command not allowed for anonymous user\r\n");
+       return(GOOD);
+   }
+
+   if(mkdir(buff, 0777))
+       printf(msg550, buff, strerror(errno));
+   else {
+       printf("257 \"%s\" directory created.\r\n", buff);
+       logit("MKD ", path(buff));
+   }
+
+   return(GOOD);
+}
+
+/* name listing */
+int doNLST(buff)
+char *buff;
+{
+   file_restart = 0;
+
+   return(sendfile(buff, SEND_NLST));
+}
+
+/* where are we */
+int doPWD(buff)
+char *buff;
+{
+char dir[128];
+
+   if(ChkLoggedIn())
+       return(GOOD);
+
+   if(getcwd(dir, sizeof(dir)) == (char *)NULL)
+       printf(msg550, buff, strerror(errno));
+   else
+       printf("257 \"%s\" is current directory.\r\n", dir);
+
+   return(GOOD);
+}
+
+/* restart command */
+int doREST(buff)
+char *buff;
+{
+   if(ChkLoggedIn())
+       return(GOOD);
+
+   file_restart = atol(buff);
+
+   printf("350 Next file transfer will restart at %lu.\r\n", file_restart);
+
+   return(GOOD);
+}
+
+/* they want a file */
+int doRETR(buff)
+char *buff;
+{
+   return(sendfile(buff, SEND_FILE));
+}
+
+/* remove a directory */
+int doRMD(buff)
+char *buff;
+{
+   if(ChkLoggedIn())
+       return(GOOD);
+
+   if(anonymous) {
+       printf("550 Command not allowed for anonymous user\r\n");
+       return(GOOD);
+   }
+
+   if(rmdir(buff))
+       printf(msg550, buff, strerror(errno));
+   else {
+       printf("250 Directory \"%s\" deleted.\r\n", buff);
+       logit("RMD ", path(buff));
+   }
+
+   return(GOOD);
+}
+
+/* rename from */
+int doRNFR(buff)
+char *buff;
+{
+   if(ChkLoggedIn())
+       return(GOOD);
+
+   if(anonymous) {
+       printf("550 Command not allowed for anonymous user\r\n");
+       return(GOOD);
+   }
+
+   strncpy(rnfr, buff, sizeof(rnfr));
+   rnfr[sizeof(rnfr)-1] = '\0';
+
+   printf("350 Got RNFR waiting for RNTO.\r\n");
+
+   return(GOOD);
+}
+
+/* rename to */
+int doRNTO(buff)
+char *buff;
+{
+   if(ChkLoggedIn())
+       return(GOOD);
+
+   if(anonymous) {
+       printf("550 Command not allowed for anonymous user\r\n");
+       return(GOOD);
+   }
+
+   if(rnfr[0] == '\0') {
+       printf("550 Rename failed.\r\n");
+       return(GOOD);
+   }
+
+   if(rename(rnfr, buff) < 0)
+       printf("550 Rename failed. Error %s\r\n", strerror(errno));
+   else {
+       printf("250 Renamed %s to %s.\r\n", rnfr, buff);
+       logit("RNFR", path(rnfr));
+       logit("RNTO", path(buff));
+   }
+
+   rnfr[0] = '\0';
+
+   return(GOOD);
+}
+
+/* xmode = 0 for multiline crc, xmode <> 0 for single file single line crc */
+static int docrc(buff, xmode)
+char *buff;
+int xmode;
+{
+unsigned short cs;
+long fs;
+int fd;
+int s;
+char *p;
+
+   if((fd = fdxcmd(CMD_CRC, buff)) < 0) {
+       printf("501 Could not obtain CRC.\r\n");
+       return(GOOD);
+   }
+
+   if(xmode == 0)
+       printf("202-SITE CRC \"%s\"\r\n", buff);
+
+   while(1) {
+       p = buffer;
+       while(1) {
+               if((s = read(fd, p, 1)) != 1) {
+                       if(xmode == 0)
+                               printf("202 SITE CRC DONE.\r\n");
+                       else
+                               printf("501 Could not obtain CRC.\r\n");
+                       endfdxcmd(fd);
+                       return(GOOD);
+               }
+               if(*p == '\n') {
+                       *p++ = '\r';
+                       *p++ = '\n';
+                       *p = '\0';
+                       break;
+               }
+               p++;
+       }
+       if(xmode != 0)
+               break;
+       printf("    %s", buffer);
+   }
+
+   cs = atoi(buffer);
+
+   fs = atol(buffer+6);
+
+   printf("202 CRC %05u %ld.\r\n", cs, fs);
+
+   endfdxcmd(fd);
+
+   return(GOOD);
+}
+
+/* site specific */
+int doSITE(buff)
+char *buff;
+{
+char *args;
+
+   if(ChkLoggedIn())
+       return(GOOD);
+
+
+   strncpy(line, buff, sizeof(line));
+   line[sizeof(line)-1] = '\0';
+
+   cvtline(&args);
+
+   if(!strcmp(line, "CRC") || !strcmp(line, "CCRC"))
+       return(docrc(args, strcmp(line, "CRC")));
+
+   if(!strcmp(line, "FDET"))
+       return(dofdet(args));
+
+   printf("501 Unknown SITE command %s.\r\n", line);
+
+   return(GOOD);
+}
+
+static unsigned long fsize(fname)
+char *fname;
+{
+struct stat st;
+unsigned long fs = 0L;
+
+   if(stat(fname, &st))
+       return(fs);
+
+   if((st.st_mode & S_IFMT) != S_IFREG)
+       return(fs);
+
+   if(type == TYPE_A)
+       return(fs);
+
+   fs = st.st_size;
+
+   return(fs);
+}
+
+/* file size, btw when will this be put into an RFC */
+int doSIZE(buff)
+char *buff;
+{
+struct stat st;
+unsigned long filesize;
+
+   if(ChkLoggedIn())
+       return(GOOD);
+
+   if(stat(buff, &st)) {
+       printf(msg550, buff, strerror(errno));
+       return(GOOD);
+   }
+
+   if((st.st_mode & S_IFMT) != S_IFREG) {
+       printf("550 Not a regular file.\r\n");
+       return(GOOD);
+   }
+
+   filesize = st.st_size;
+
+   if(type == TYPE_A)
+       if(asciisize(buff, &filesize))
+               return(GOOD);
+
+   printf("215 %lu\r\n", filesize);
+
+   return(GOOD);
+}
+
+/* server status, or file status */
+int doSTAT(buff)
+char *buff;
+{
+time_t now;
+struct tm *tm;
+int fd;
+int s;
+
+   if(!*buff) {
+       (void) time(&now);
+       tm = localtime(&now);
+       printf("211-%s(%s:%u) FTP server status:\r\n",
+               myhostname, inet_ntoa(myipaddr), ntohs(myport));
+       printf("    Version %s  ", FtpdVersion);
+       printf("%s, %02d %s %d %02d:%02d:%02d %s\r\n", days[tm->tm_wday],
+               tm->tm_mday, months[tm->tm_mon], 1900+tm->tm_year,
+               tm->tm_hour, tm->tm_min, tm->tm_sec, tzname[tm->tm_isdst]);
+       printf("    Connected to %s:%u\r\n", inet_ntoa(rmtipaddr), ntohs(rmtport));
+       if(!loggedin)
+               printf("    Not logged in\r\n");
+       else
+               printf("    Logged in %s\r\n", username);
+       printf("    MODE: %s\r\n",(mode == MODE_B) ? "Block" : "Stream");
+       printf("    TYPE: %s\r\n",(type == TYPE_A) ? "Ascii" : "Binary");
+       printf("211 End of status\r\n");
+       return(GOOD);
+   }
+
+   if(ChkLoggedIn())
+       return(GOOD);
+
+   printf("211-Status of %s:\r\n", buff);
+
+   if((fd = fdxcmd(CMD_LIST, buff)) < 0)
+       printf("   Could not retrieve status");
+   else {
+       while((s = read(fd, buffer, 1)) == 1) {
+               if(*buffer == '\n')
+                       printf("\r\n");
+               else
+                       printf("%c", *buffer);
+       }
+       endfdxcmd(fd);
+   }
+
+   printf("211 End of status\r\n");
+
+   return(GOOD);
+}
+
+/* hey look, we're getting a file */
+int doSTOR(buff)
+char *buff;
+{
+   return(recvfile(buff, RECV_FILE));
+}
+
+/* hey, get a file unique */
+int doSTOU(buff)
+char *buff;
+{
+   return(recvfile(buff, RECV_UNIQ));
+}
+
+/* structure */
+int doSTRU(buff)
+char *buff;
+{
+   switch(*buff) {
+       case 'f':
+       case 'F':
+               printf("200 Structure set to %c.\r\n", *buff);
+               break;
+       default:
+               printf("501 Unknown structure %c.\r\n", *buff);
+   }
+
+   return(GOOD);
+}
+
+/* we're UNIX and proud of it! */
+int doSYST(buff)
+char *buff;
+{
+   printf("215 UNIX Type: L8\r\n");
+
+   return(GOOD);
+}
+
+/* change transfer type */
+int doTYPE(buff)
+char *buff;
+{
+   if(*(buff+1) != '\0') {
+       printf("501 Syntax error in parameters.\r\n");
+       return(GOOD);
+   }
+
+   switch(*buff) {
+       case 'A':
+       case 'a':
+               type = TYPE_A;
+               printf("200 Type set to A.\r\n");
+               break;
+       case 'I':
+       case 'i':
+               type = TYPE_I;
+               printf("200 Type set to I.\r\n");
+               break;
+       default:
+               printf("501 Invalid type %c.\r\n", *buff);
+   }
+
+   return(GOOD);
+}
+
+static int fdxcmd(cmd, arg)
+int   cmd;
+char *arg;
+{
+char xcmd[3];
+char *argv[5];
+int fds[2];
+char *smallenv[] = { "PATH=/bin:/usr/bin:/usr/local/bin", NULL, NULL };
+
+   if((smallenv[1] = getenv("TZ")) != NULL) smallenv[1] -= 3;  /* ouch... */
+
+   sprintf(xcmd, "%d", cmd);
+
+   argv[0] = PROG_FTPDSH;
+   argv[1] = xcmd;
+   argv[2] = arg;
+   argv[3] = (char *)NULL;
+
+   if(pipe(fds) < 0)
+       return(-1);
+
+   if((cmdpid = fork()) < 0) {
+       close(fds[0]);
+       close(fds[1]);
+       return(-1);
+   }
+
+   if(cmdpid == 0) { /* Child */
+       close(fds[0]);
+       close(0);
+       open("/dev/null", O_RDONLY);
+       dup2(fds[1], 1);
+       dup2(fds[1], 2);
+       close(fds[1]);
+       sprintf(argv[0], "/bin/%s", PROG_FTPDSH);
+       execve(argv[0], argv, smallenv);
+       sprintf(argv[0], "/usr/bin/%s", PROG_FTPDSH);
+       execve(argv[0], argv, smallenv);
+       sprintf(argv[0], "/usr/local/bin/%s", PROG_FTPDSH);
+       execve(argv[0], argv, smallenv);
+       exit(0);
+   }
+
+   close(fds[1]);
+
+   return(fds[0]);
+}
+
+/* Same as close if not cmd child started */
+static int endfdxcmd(fd)
+int fd;
+{
+int s;
+int cs;
+
+   close(fd);
+
+   if(cmdpid == -1)
+       return(0);
+
+   s = waitpid(cmdpid, &cs, 0);
+
+   cmdpid = -1;
+
+   return(0);
+}
+
+/* returns -1 = size could not be determined, */
+/*          0 = size determined and in filesize */
+static int asciisize(filename, filesize)
+char *filename;
+unsigned long *filesize;
+{
+unsigned long count;
+int fd;
+char *p, *pp;
+int cnt;
+
+   if((fd = open(filename, O_RDONLY)) < 0) {
+       printf(msg550, filename, strerror(errno));
+       return(-1);
+   }
+
+   count = 0;
+
+   while((cnt = read(fd, buffer, sizeof(buffer))) > 0) {
+       count += cnt;
+       p = buffer;
+       while(cnt > 0)
+               if((pp = memchr(p, '\n', cnt)) != (char *)NULL) {
+                       count++;
+                       cnt = cnt - 1 - (pp - p);
+                       p = pp + 1;
+               } else
+                       break;
+   }
+
+   if(cnt == 0) {
+       *filesize = count;
+       close(fd);
+       return(0);
+   }
+
+   printf(msg550, filename, strerror(errno));
+
+   close(fd);
+
+   return(-1);
+}
+
+/* see if we need to run a command to convert the file */
+static int cnvtfile(name, name2)
+char *name;
+char **name2;
+{
+struct stat st;
+static char fname[256];
+char *p;
+int cmode;
+
+   if(!stat(name, &st))                        /* file exists can't be a conversion */
+       if((st.st_mode & S_IFMT) != S_IFREG) {  /* must be regular file */
+               printf("550 Not a regular file.\r\n");
+               return(CNVT_ERROR);
+       } else
+               return(CNVT_NONE);
+
+   if(errno != ENOENT) {       /* doesn't exist is okay, others are not */
+       printf(msg550, name, strerror(errno));
+       return(CNVT_ERROR);
+   }
+
+   /* find out what kind of conversion */
+   strncpy(fname, name, sizeof(fname));
+   fname[sizeof(fname)-1] = '\0';
+
+   p = fname + strlen(fname);
+   cmode = CNVT_ERROR;
+   while(p > fname && cmode == CNVT_ERROR) {
+       if(*p == '.') {
+               if(!strcmp(p, ".tar"))
+                       cmode = CNVT_TAR;
+               else
+               if(!strcmp(p, ".tar.Z"))
+                       cmode = CNVT_TAR_Z;
+               else
+               if(!strcmp(p, ".Z"))
+                       cmode = CNVT_COMP;
+               else
+               if(!strcmp(p, ".tar.gz"))
+                       cmode = CNVT_TAR_GZ;
+               else
+               if(!strcmp(p, ".gz"))
+                       cmode = CNVT_GZIP;
+
+               if (cmode != CNVT_ERROR) {
+                       /* is there a file to convert? */
+                       *p = '\0';
+                       if (!stat(fname, &st)) break;
+                       *p = '.';
+                       cmode = CNVT_ERROR;
+               }
+       }
+       p--;
+   }
+
+   if(cmode == CNVT_ERROR) {
+       printf(msg550, fname, strerror(errno));
+       return(CNVT_ERROR);
+   }
+
+   if(cmode == CNVT_COMP || cmode == CNVT_GZIP || cmode == CNVT_UNCOMP)
+       if((st.st_mode & S_IFMT) != S_IFREG) {
+               printf("550 Not a regular file.\r\n");
+               return(CNVT_ERROR);
+       }
+
+   *name2 = fname;
+
+   return(cmode);
+}
+
+static int procfile(name)
+char *name;
+{
+int cmd;
+int fd;
+char *name2;
+
+   cmd = cnvtfile(name, &name2);
+
+   switch(cmd) {
+       case CNVT_TAR:
+               fd = fdxcmd(cmd + 10, name2);
+               break;
+       case CNVT_TAR_Z:
+               fd = fdxcmd(cmd + 10, name2);
+               break;
+       case CNVT_COMP:
+               fd = fdxcmd(cmd + 10, name2);
+               break;
+       case CNVT_TAR_GZ:
+               fd = fdxcmd(cmd + 10, name2);
+               break;
+       case CNVT_GZIP:
+               fd = fdxcmd(cmd + 10, name2);
+               break;
+       case CNVT_UNCOMP:
+               fd = fdxcmd(cmd + 10, name2);
+               break;
+       case CNVT_NONE:
+               fd = open(name, O_RDONLY);
+               break;
+       case CNVT_ERROR:
+       default:
+               return(-1);
+   }
+
+   if(fd < 0)
+       printf(msg550, name, strerror(errno));
+
+   return(fd);
+}
+
+/* oh no, they're taking a file */
+static int sendfile(name, xmode)
+char *name;
+int xmode;
+{
+char *fname;
+int fd, s;
+time_t datastart, dataend;
+unsigned long datacount;
+long kbs;
+char c;
+char *p;
+char *op, *ope;
+off_t sp;
+int doascii;
+unsigned long fs;
+char block[3];
+
+   if(ChkLoggedIn()) 
+       return(GOOD);
+
+   switch(xmode) {
+       case SEND_NLST:
+               fname = "NLST";
+               fd = fdxcmd(CMD_NLST, name);
+               if(fd < 0)
+                       printf(msg550, name, strerror(errno));
+               break;
+       case SEND_LIST:
+               fname = "LIST";
+               fd = fdxcmd(CMD_LIST, name);
+               if(fd < 0)
+                       printf(msg550, name, strerror(errno));
+               break;
+       default:
+               fname = name;
+               fd = procfile(name);
+               if(fd < 0)
+                       logit("FAIL", path(fname));
+               else
+                       logit("SEND", path(fname));
+   }
+
+   if(fd < 0)
+       return(GOOD);
+
+   /* set file position at approriate spot */
+   if(file_restart) {
+       if(type == TYPE_A) {
+               sp = 0;
+               while(sp < file_restart) {
+                       sp++;
+                       s = read(fd, buffer, 1);
+                       if(s < 0) {
+                               printf(msg550, fname, strerror(errno));
+                               endfdxcmd(fd);
+                               file_restart = 0;
+                               return(GOOD);
+                       }
+                       if(s == 0) break;
+                       if(*buffer == '\n')
+                               sp++;
+               }
+       } else {
+               sp = lseek(fd, file_restart, SEEK_SET);
+               if(sp == -1) {
+                       printf(msg550, fname, strerror(errno));
+                       endfdxcmd(fd);
+                       file_restart = 0;
+                       return(GOOD);
+               }
+       }
+       if(sp != file_restart) {
+               printf("550 File restart point error. %lu not %lu\r\n", sp, file_restart);
+               endfdxcmd(fd);
+               file_restart = 0;
+               return(GOOD);
+       }
+   }
+   file_restart = 0;
+
+   fs = fsize(fname);
+   if(fs == 0L)
+       printf("%03d File %s okay.  Opening data connection.\r\n",
+               ftpdata_fd >= 0 ? 125 : 150, fname);
+   else
+       printf("%03d Opening %s mode data connection for %s (%ld bytes).\r\n",
+               ftpdata_fd >= 0 ? 125 : 150,
+               type == TYPE_A ? "ASCII" : "BINARY",
+               fname, fs);
+   fflush(stdout);
+
+#ifdef DEBUG
+   fprintf(logfile, "After 125/150 b4 DataConnect\n");
+   fflush(logfile);
+#endif
+
+   if(DataConnect()) {
+       endfdxcmd(fd);
+       return(GOOD);
+   }
+
+#ifdef DEBUG
+   fprintf(logfile, "After DataConnect\n");
+   fflush(logfile);
+   fprintf(logfile, "ftpd: parent %d start sendfile \n", getpid());
+   fflush(logfile);
+#endif
+
+   /* start transfer */
+   doascii = (type == TYPE_A) ||
+       ((xmode == SEND_LIST) || (xmode == SEND_NLST)); /* per RFC1123 4.1.2.7 */
+   datacount = 0;
+   time(&datastart);
+   op = bufout; ope = bufout + sizeof(bufout) - 3;
+   while((s = read(fd, buffer, sizeof(buffer))) > 0) {
+#ifdef DEBUG
+       fprintf(logfile, "sendfile read %d\n", s); fflush(logfile);
+#endif
+       datacount += s;
+       if(doascii) {
+               p = buffer;
+               while(s-- > 0) {
+                       c = *p++;
+                       if(c == '\n') {
+                               *op++ = '\r';
+                               datacount++;
+                       }
+                       *op++ = c;
+                       if(op >= ope) {
+                               if(mode == MODE_B) {
+                                       block[0] = '\0';
+                                       *(u16_t *)&block[1] = htons(op - bufout);
+                                       write(ftpdata_fd, block, sizeof(block));
+                               }
+                               write(ftpdata_fd, bufout, op - bufout);
+                               op = bufout;
+                       }
+               }
+       } else {
+               if(mode == MODE_B) {
+                       block[0] = '\0';
+                       *(u16_t *)&block[1] = htons(s);
+                       write(ftpdata_fd, block, sizeof(block));
+               }
+               s = write(ftpdata_fd, buffer, s);
+       }
+   }
+   if(op > bufout) {
+       if(mode == MODE_B) {
+               block[0] = MODE_B_EOF;
+               *(u16_t *)&block[1] = htons(op - bufout);
+               write(ftpdata_fd, block, sizeof(block));
+       }
+       write(ftpdata_fd, bufout, op - bufout);
+   } else
+       if(mode == MODE_B) {
+               block[0] = MODE_B_EOF;
+               *(u16_t *)&block[1] = htons(0);
+               write(ftpdata_fd, block, sizeof(block));
+       }
+   time(&dataend);
+
+#ifdef DEBUG
+   fprintf(logfile, "ftpd: parent %d end sendfile \n", getpid());
+   fflush(logfile);
+#endif
+
+   endfdxcmd(fd);
+   if(mode != MODE_B) {
+       close(ftpdata_fd); 
+       ftpdata_fd = -1;
+   }
+
+   if(dataend == datastart) dataend++;
+   kbs = (datacount * 100 / (dataend - datastart)) / 1024;
+
+   if(s < 0)
+       printf("451 Transfer aborted.\r\n");
+   else
+       printf("%03d Transfer finished successfully. %ld.%02d KB/s\r\n",
+               mode == MODE_B ? 250 : 226,
+               (long)(kbs / 100), (int)(kbs % 100));
+
+   return(GOOD);
+}
+
+static int recvfile(name, xmode)
+char *name;
+int xmode;
+{
+char *fname;
+time_t datastart, dataend;
+unsigned long datacount;
+long kbs;
+char c;
+char *p;
+char *op, *ope;
+int fd, oflag;
+int s;
+int gotcr;
+off_t sp;
+char block[3];
+unsigned short cnt;
+
+   if(ChkLoggedIn())
+       return(GOOD);
+
+   fname = name;
+
+   switch(xmode) {
+       case RECV_APND:
+               oflag = O_WRONLY | O_APPEND;
+               break;
+       case RECV_UNIQ:
+               fname = uniqname();
+               oflag = O_WRONLY | O_CREAT;
+               break;
+       default:
+               oflag = O_WRONLY | O_CREAT | O_TRUNC;
+   }
+
+   if(file_restart)
+       oflag = O_RDWR;
+
+   fd = open(fname, oflag, (anonymous ? 0000:0600));
+
+   if(fd < 0) {
+       printf(msg550, fname, strerror(errno));
+       return(GOOD);
+   }
+
+   /* log the received file */
+   logit("RECV", path(fname));
+
+   /* set file position at approriate spot */
+   if(file_restart) {
+       if(type == TYPE_A) {
+               sp = 0;
+               while(sp < file_restart) {
+                       sp++;
+                       s = read(fd, buffer, 1);
+                       if(s < 0) {
+                               printf(msg550, fname, strerror(errno));
+                               close(fd);
+                               file_restart = 0;
+                               return(GOOD);
+                       }
+                       if(s == 0) break;
+                       if(*buffer == '\n')
+                               sp++;
+               }
+       } else {
+               sp = lseek(fd, file_restart, SEEK_SET);
+               if(sp == -1) {
+                       printf(msg550, fname, strerror(errno));
+                       close(fd);
+                       file_restart = 0;
+                       return(GOOD);
+               }
+       }
+       if(sp != file_restart) {
+               printf("550 File restart point error. %lu not %lu\r\n", sp, file_restart);
+               close(fd);
+               file_restart = 0;
+               return(GOOD);
+       }
+   }
+   file_restart = 0;
+
+   if(xmode == RECV_UNIQ)
+       printf("%03d FILE: %s\r\n",
+               ftpdata_fd >= 0 ? 125 : 150, fname);    /* per RFC1123 4.1.2.9 */
+   else
+       printf("%03d File %s okay.  Opening data connection.\r\n",
+               ftpdata_fd >= 0 ? 125 : 150, fname);
+   fflush(stdout);
+
+   if(DataConnect()) {
+       close(fd);
+       return(GOOD);
+   }
+
+#ifdef DEBUG
+   fprintf(logfile, "ftpd: parent %d start recvfile \n", getpid());
+   fflush(logfile);
+#endif
+
+   /* start receiving file */
+   datacount = 0;
+   gotcr = 0;
+   op = bufout; ope = bufout + sizeof(bufout) - 3;
+   cnt = 0;
+   time(&datastart);
+   while(1) {
+       if(mode != MODE_B)
+               cnt = sizeof(buffer);
+       else
+               if(cnt == 0) {
+                       s = read(ftpdata_fd, block, sizeof(block));
+                       cnt = ntohs(*(u16_t *)&block[1]);
+                       s = 0;
+                       if(cnt == 0 && block[0] & MODE_B_EOF)
+                               break;
+               }
+       s = read(ftpdata_fd, buffer, cnt > sizeof(buffer) ? sizeof(buffer) : cnt);
+       if(s <= 0) break;
+       cnt -= s;
+       datacount += (long)s;
+       if(type == TYPE_A) {
+               p = buffer;
+               while(s-- > 0) {
+                       c = *p++;
+                       if(gotcr) {
+                               gotcr = 0;
+                               if(c != '\n')
+                                       *op++ = '\r';
+                       }
+                       if(c == '\r')
+                               gotcr = 1;
+                       else
+                               *op++ = c;
+                       if(op >= ope) {
+                               write(fd, bufout, op - bufout);
+                               op = bufout;
+                       }
+               }
+       } else
+               write(fd, buffer, s);
+       if(cnt == 0 && mode == MODE_B && block[0] & MODE_B_EOF) {
+               s = 0;
+               break;
+       }
+   }
+   if(gotcr)
+       *op++ = '\r';
+   if(op > bufout)
+       write(fd, bufout, op - bufout);
+   time(&dataend);
+
+#ifdef DEBUG
+   fprintf(logfile, "ftpd: parent %d end recvfile \n", getpid());
+   fflush(logfile);
+#endif
+
+   close(fd);
+   if(mode != MODE_B) {
+       close(ftpdata_fd); 
+       ftpdata_fd = -1;
+   }
+
+   if(dataend == datastart) dataend++;
+   kbs = (datacount * 100 / (dataend - datastart)) / 1024;
+
+   if((mode == MODE_B && cnt != 0) || s != 0)
+       printf("451 Transfer aborted.\r\n");
+   else {
+       printf("%03d Transfer finished successfully. ",
+               mode == MODE_B ? 250 : 226);
+       if(xmode == RECV_UNIQ)
+               printf("Unique file %s. ", fname);
+       printf("%ld.%02d KB/s\r\n", (long)(kbs / 100), (int)(kbs % 100));
+   }
+
+   return(GOOD);
+}
+
+static char *uniqname()
+{
+static char uniq[32];
+int i;
+struct stat st;
+
+   for(i = 0; i < 1000; i++) {
+       sprintf(uniq, "ftpd%d%d", getpid(), i);
+       if(stat(uniq, &st) == -1)
+               return(uniq);
+   }
+   return(uniq);
+}
+
+static char *spath[256];
+static char *path(fname)
+char *fname;
+{
+char dir[128];
+
+   if(getcwd(dir, sizeof(dir)) == (char *)NULL)
+       sprintf(dir, "???");
+
+   if(fname[0] == '/')
+       sprintf((char *)spath, "%s%s", newroot, fname);
+   else
+       if(dir[1] == '\0')
+               sprintf((char *)spath, "%s%s%s", newroot, dir, fname);
+       else
+               sprintf((char *)spath, "%s%s/%s", newroot, dir, fname);
+
+   return((char *)spath);
+}
+
+/* do file detail */
+static int dofdet(buff)
+char *buff;
+{
+struct stat st;
+char ft;
+
+   if(ChkLoggedIn())
+       return(GOOD);
+
+   if(stat(buff, &st)) {
+       printf("501 Could not obtain file detail.\r\n");
+       return(GOOD);
+   }
+   switch(st.st_mode & S_IFMT) {
+       case S_IFIFO:   ft = 'p'; break;
+       case S_IFCHR:   ft = 'c'; break;
+       case S_IFDIR:   ft = 'd'; break;
+       case S_IFBLK:   ft = 'b'; break;
+       case S_IFREG:   ft = 'f'; break;
+       default:        ft = '?'; break;
+   }
+   printf("202 %c %u %u %u %u %u %lu %lu\r\n", 
+       ft,                                     /* file type */
+       st.st_rdev >> 8,                        /* Major */
+       st.st_rdev & 0xff,                      /* Minor */
+       st.st_uid,                              /* UID */
+       st.st_gid,                              /* GID */
+       st.st_mode,                             /* File Modes */
+       st.st_size,                             /* SIZE */
+       st.st_mtime);                           /* Mod Time */
+
+   return(GOOD);
+}
diff --git a/commands/ftpd200/file.h b/commands/ftpd200/file.h
new file mode 100644 (file)
index 0000000..fdce039
--- /dev/null
@@ -0,0 +1,32 @@
+/* file.h Copyright 1992-2000 by Michael Temari All Rights Reserved
+ *
+ * This file is part of ftpd.
+ *
+ *
+ * 01/25/96 Initial Release    Michael Temari, <Michael@TemWare.Com>
+ */
+
+_PROTOTYPE(int doALLO, (char *buff));
+_PROTOTYPE(int doAPPE, (char *buff));
+_PROTOTYPE(int doCDUP, (char *buff));
+_PROTOTYPE(int doCWD,  (char *buff));
+_PROTOTYPE(int doDELE, (char *buff));
+_PROTOTYPE(int doLIST, (char *buff));
+_PROTOTYPE(int doMDTM, (char *buff));
+_PROTOTYPE(int doMODE, (char *buff));
+_PROTOTYPE(int doMKD,  (char *buff));
+_PROTOTYPE(int doNLST, (char *buff));
+_PROTOTYPE(int doPWD,  (char *buff));
+_PROTOTYPE(int doREST, (char *buff));
+_PROTOTYPE(int doRETR, (char *buff));
+_PROTOTYPE(int doRMD,  (char *buff));
+_PROTOTYPE(int doRNFR, (char *buff));
+_PROTOTYPE(int doRNTO, (char *buff));
+_PROTOTYPE(int doSITE, (char *buff));
+_PROTOTYPE(int doSIZE, (char *buff));
+_PROTOTYPE(int doSTAT, (char *buff));
+_PROTOTYPE(int doSTOR, (char *buff));
+_PROTOTYPE(int doSTOU, (char *buff));
+_PROTOTYPE(int doSTRU, (char *buff));
+_PROTOTYPE(int doSYST, (char *buff));
+_PROTOTYPE(int doTYPE, (char *buff));
diff --git a/commands/ftpd200/ftpd.8 b/commands/ftpd200/ftpd.8
new file mode 100644 (file)
index 0000000..bae1757
--- /dev/null
@@ -0,0 +1,161 @@
+.\" Copyright (c) 1985 Regents of the University of California.
+.\" All rights reserved.  The Berkeley software License Agreement
+.\" specifies the terms and conditions for redistribution.
+.\"
+.\"    @(#)ftpd.8c     6.4 (Berkeley) 5/28/86
+.\"
+.TH FTPD 8
+.SH NAME
+ftpd, in.ftpd, ftpdsh, setup.anonftp \- DARPA Internet File Transfer Protocol server
+.SH SYNOPSIS
+.B "ftp stream tcp nowait root /usr/bin/in.ftpd in.ftpd"
+.br
+.B "tcpd ftp /usr/bin/in.ftpd"
+.SH DESCRIPTION
+.B Ftpd
+is the DARPA Internet File Transfer Prototocol
+server process.  The server uses the TCP protocol
+and listens at the port specified in the ``ftp''
+service specification; see
+.BR services (5).
+.PP
+The ftp server currently supports the following ftp
+requests;  case is not distinguished.
+.PP
+.nf
+.ta \w'Request        'u
+\fBRequest     Description\fP
+ABOR   abort previous command
+ACCT   specify account (ignored)
+ALLO   allocate storage (vacuously)
+APPE   append to a file
+CDUP   change to parent of current working directory
+CWD    change working directory
+DELE   delete a file
+HELP   give help information
+LIST   give list files in a directory (``ls -lA'')
+MKD    make a directory
+MODE   specify data transfer \fImode\fP
+NLST   give name list of files in directory (``ls'')
+NOOP   do nothing
+PASS   specify password
+PASV   prepare for server-to-server transfer
+PORT   specify data connection port
+PWD    print the current working directory
+QUIT   terminate session
+RETR   retrieve a file
+RMD    remove a directory
+RNFR   specify rename-from file name
+RNTO   specify rename-to file name
+STOR   store a file
+STOU   store a file with a unique name
+STRU   specify data transfer \fIstructure\fP
+TYPE   specify data transfer \fItype\fP
+USER   specify user name
+XCUP   change to parent of current working directory
+XCWD   change working directory
+XMKD   make a directory
+XPWD   print the current working directory
+XRMD   remove a directory
+.fi
+.PP
+The remaining ftp requests specified in Internet RFC 959 are
+recognized, but not implemented.
+.PP
+The ftp server will abort an active file transfer only when the
+ABOR command is preceded by a Telnet "Interrupt Process" (IP)
+signal and a Telnet "Synch" signal in the command Telnet stream,
+as described in Internet RFC 959.
+.PP
+.B Ftpd
+interprets file names according to the ``globbing''
+conventions used by
+.BR csh (1).
+This allows users to utilize the metacharacters ``*?[]{}~''.
+.PP
+.B Ftpd
+authenticates users according to two rules. 
+.IP 1)
+The user name must be in the password data base,
+.BR /etc/passwd ,
+and not have a null password.  In this case a password
+must be provided by the client before any file operations
+may be performed.
+.IP 2)
+If the user name is ``anonymous'' or ``ftp'', an
+anonymous ftp account must be present in the password
+file (user ``ftp'').  In this case the user is allowed
+to log in by specifying any password (by convention this
+is given as the client host's name).
+.PP
+In the last case, 
+.B ftpd
+takes special measures to restrict the client's access privileges.
+The server performs a 
+.BR chroot (2)
+command to the home directory of the ``ftp'' user.
+In order that system security is not breached, it is recommended
+that the ``ftp'' subtree be constructed with care;  the following
+rules are recommended.
+.IP ~ftp)
+Make the home directory owned by ``ftp'' and unwritable by anyone.
+.IP ~ftp/bin)
+Make this directory owned by the super-user and unwritable by
+anyone.  The program
+.BR ls (1)
+must be present to support the list commands.  
+Also, 
+.BR crc (1) 
+must be present to support generating crcs using the site command, 
+.BR tar (1)
+and 
+.BR compress (1)
+must be present to support on-the-fly generation of .tar and .tar.Z archives, 
+.BR gzip (1)
+must be present to support gzip compression, and 
+.BR sh (1)
+must be present to support 
+.BR ftpdsh (8)
+which also must be present. 
+.BR ftpdsh controls which binaries can be used.
+These programs should all have mode 111.
+.IP ~ftp/etc)
+Make this directory owned by the super-user and unwritable by
+anyone.  The files
+.BR passwd (5)
+and
+.BR group (5)
+must be present for the 
+.B ls
+command to work properly.  These files should be mode 444. They can (and 
+should) be stripped down versions so as not to reveal names of users who
+are not owners of files in the ~ftp/pub directory tree. 
+.IP ~ftp/pub)
+Make this directory mode 755 and owned by the super-user.  Create
+directories in it owned by users if those users want to manage an
+anonymous ftp directory.
+.IP ~ftp/pub/incoming)
+Optionally create this directory for anonymous uploads.  Make it mode
+777.  The FTP daemon will create files with mode 266, so remote users
+can write a file, but only local users can do something with it.
+.PP
+The script
+.B setup.anonftp
+can be used to create or check an anonymous FTP tree.
+.SH "SEE ALSO"
+.BR ftp (1).
+.SH BUGS
+The anonymous account is inherently dangerous and should
+avoided when possible.
+.ig \" Minix doesn't have privileged port numbers (yet?)
+.PP
+The server must run as the super-user
+to create sockets with privileged port numbers.  It maintains
+an effective user id of the logged in user, reverting to
+the super-user only when binding addresses to sockets.  The
+possible security holes have been extensively
+scrutinized, but are possibly incomplete.
+..
+.\" man page updated by Al Woodhull 2005-02-25
+
+
diff --git a/commands/ftpd200/ftpd.c b/commands/ftpd200/ftpd.c
new file mode 100644 (file)
index 0000000..5727f1b
--- /dev/null
@@ -0,0 +1,405 @@
+/* ftpd.c Copyright 1992-2000 by Michael Temari All Rights Reserved
+ *
+ * ftpd         An FTP server program for use with Minix.
+ *
+ * Usage:       Minix usage: tcpd ftp ftpd
+ *
+ * 06/14/92 Tnet Release       Michael Temari
+ * 01/15/96 0.30               Michael Temari
+ * 01/25/96 0.90               Michael Temari
+ * 03/17/96 0.91               Michael Temari
+ * 06/27/96 0.92               Michael Temari
+ * 07/02/96 0.93               Michael Temari
+ * 07/15/96 0.94               Michael Temari
+ * 08/27/96 0.95               Michael Temari
+ * 02/09/97 0.96               Michael Temari
+ * 02/10/97 0.97               Michael Temari
+ * 09/25/97 0.98               Michael Temari
+ * 03/10/00 0.99               Michael Temari, <Michael@TemWare.Com>
+ * 12/12/03 1.00               Michael Temari, <Michael@TemWare.Com>
+ * 02/06/05 1.01               Michael Temari, <Michael@TemWare.Com>
+ * 02/12/05 2.00               Michael Temari, <Michael@TemWare.Com>
+ */
+
+char *FtpdVersion = "2.00";
+
+#include <sys/types.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <net/gen/in.h>
+#include <net/gen/tcp.h>
+
+#include "ftpd.h"
+#include "access.h"
+#include "file.h"
+#include "net.h"
+
+_PROTOTYPE(static void init, (void));
+_PROTOTYPE(static int doHELP, (char *buff));
+_PROTOTYPE(static int doNOOP, (char *buff));
+_PROTOTYPE(static int doUNIMP, (char *buff));
+_PROTOTYPE(static int getline, (char *line, int len));
+
+FILE *msgfile = (FILE *)NULL;
+
+/* The following defines the inactivity timeout in seconds */
+#define        INACTIVITY_TIMEOUT      60*5
+
+char *days[] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
+char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
+                 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
+
+char line[512];
+
+int type, format, mode, structure;
+int ftpdata_fd = -1;
+int loggedin, gotuser, anonymous;
+char username[80];
+char anonpass[128];
+char newroot[128];
+
+ipaddr_t myipaddr, rmtipaddr, dataaddr;
+tcpport_t myport, rmtport, dataport;
+
+char myhostname[256], rmthostname[256];
+
+#define        FTPD_LOG        "/usr/adm/ftpd.log"
+#define        FTPD_MSG        "/etc/ftpd_msg"
+
+FILE *logfile;
+
+int timeout = 0;
+
+_PROTOTYPE(static int doHELP, (char *buff));
+_PROTOTYPE(int readline, (char **args));
+_PROTOTYPE(void Timeout, (int sig));
+_PROTOTYPE(int main, (int argc, char *argv[]));
+
+struct commands {
+       char *name;
+       _PROTOTYPE(int (*func), (char *buff));
+};
+
+struct commands commands[] = {
+       "ABOR", doUNIMP,
+       "ACCT", doUNIMP,
+       "ALLO", doALLO,
+       "APPE", doAPPE,
+       "CDUP", doCDUP,
+       "CWD",  doCWD,
+       "DELE", doDELE,
+       "HELP", doHELP,
+       "LIST", doLIST,
+       "MDTM", doMDTM,
+       "MKD",  doMKD,
+       "MODE", doMODE,
+       "NLST", doNLST,
+       "NOOP", doNOOP,
+       "PASS", doPASS,
+       "PASV", doPASV,
+       "PORT", doPORT,
+       "PWD",  doPWD,
+       "QUIT", doQUIT,
+       "REIN", doUNIMP,
+       "REST", doREST,
+       "RETR", doRETR,
+       "RMD",  doRMD,
+       "RNFR", doRNFR,
+       "RNTO", doRNTO,
+       "SITE", doSITE,
+       "SIZE", doSIZE,
+       "SMNT", doUNIMP,
+       "STAT", doSTAT,
+       "STOR", doSTOR,
+       "STOU", doSTOU,
+       "STRU", doSTRU,
+       "SYST", doSYST,
+       "TYPE", doTYPE,
+       "USER", doUSER,
+       "XCUP", doCDUP,
+       "XCWD", doCWD,
+       "XMKD", doMKD,
+       "XPWD", doPWD,
+       "XRMD", doRMD,
+       "",     (int (*)())0
+};
+
+static void init()
+{
+   loggedin = 0;
+   gotuser = 0;
+   anonymous = 0;
+   newroot[0] = '\0';
+   type = TYPE_A;
+   format = 0;
+   mode = MODE_S;
+   structure = 0;
+   ftpdata_fd = -1;
+   username[0] = '\0';
+   anonpass[0] = '\0';
+}
+
+/* nothing, nada, zilch... */
+static int doNOOP(buff)
+char *buff;
+{
+   printf("200 NOOP to you too!\r\n");
+
+   return(GOOD);
+}
+
+/* giv'em help, what a USER! */
+static int doHELP(buff)
+char *buff;
+{
+struct commands *cmd;
+char star;
+int i;
+char *space = "    ";
+
+   printf("214-Here is a list of available ftp commands\r\n");
+   printf("    Those with '*' are not yet implemented.\r\n");
+
+   i = 0;
+   for(cmd = commands; *cmd->name != '\0'; cmd++) {
+       if(cmd->func == doUNIMP)
+               star = '*';
+       else
+               star = ' ';
+       printf("     %s%c%s", cmd->name, star, space + strlen(cmd->name));
+       if(++i == 6) {
+               printf("\r\n");
+               i = 0;
+       }
+   }
+
+   if(i)
+       printf("\r\n");
+
+   printf("214 That's all the help you get.\r\n");
+
+   return(GOOD);
+}
+
+/* not implemented */
+static int doUNIMP(buff)
+char *buff;
+{
+   printf("502 Command \"%s\" not implemented!\r\n", line);
+
+   return(GOOD);
+}
+
+/* convert line for use */
+void cvtline(args)
+char **args;
+{
+char *p;
+
+   p = line + strlen(line);
+   while(--p >= line)
+       if(*p == '\r' || *p == '\n' || isspace(*p))
+               *p = '\0';
+       else
+               break;
+
+  p = line;
+
+#ifdef DEBUG
+  logit("COMMAND", line);
+#endif
+
+  while(*p && !isspace(*p)) {
+       *p = toupper(*p);
+       p++;
+  }
+
+  if(*p) {
+       *p = '\0';
+       p++;
+       while(*p && isspace(*p))
+               p++;
+   }
+
+   *args = p;
+
+   return;
+}
+
+static int getline(line, len)
+char *line;
+int len;
+{
+int s;
+int gotcr;
+
+   /* leave room for at end for null */
+   len--;
+
+   /* got to be able to put in at least 1 character */
+   if(len < 1)
+       return(-1);
+
+   gotcr = 0;
+   while(len-- > 0) {
+       s = read(0, line, 1);
+       if(s != 1)
+               return(-1);
+       if(*line == '\n')
+               break;
+       gotcr = (*line == '\r');
+       line++;
+   }
+   if(gotcr)
+       --line;
+
+   *line = '\0';
+
+   return(0);
+}
+
+int readline(args)
+char **args;
+{
+   if(getline(line, sizeof(line)))
+       return(BAD);
+
+   cvtline(args);
+
+   return(GOOD);
+}
+
+/* signal handler for inactivity timeout */
+void Timeout(sig)
+int sig;
+{
+   timeout = 1;
+
+   printf("421 Inactivity timer expired.\r\n");
+}
+
+/* logit */
+void logit(type, parm)
+char *type;
+char *parm;
+{
+time_t now;
+struct tm *tm;
+
+   if(logfile == (FILE *)NULL)
+       return;
+
+   time(&now);
+   tm = localtime(&now);
+   fprintf(logfile, "%4d%02d%02d%02d%02d%02d ",
+       1900+tm->tm_year,
+       tm->tm_mon + 1,
+       tm->tm_mday,
+       tm->tm_hour, tm->tm_min, tm->tm_sec);
+   fprintf(logfile, "%s %s %s %s %s\n",
+       rmthostname, username, anonymous ? anonpass : username, type, parm);
+   fflush(logfile);
+}
+
+void showmsg(reply, filename)
+char *reply;
+char *filename;
+{
+FILE *mfp;
+char *pe;
+static char mline[256];
+
+   if(filename == (char *)NULL)
+       mfp = msgfile;
+   else
+       mfp = fopen(filename, "r");
+
+   if(mfp == (FILE *)NULL)
+       return;
+
+   while(fgets(mline, sizeof(mline), mfp) != (char *)NULL) {
+       pe = mline + strlen(mline);
+       while(--pe >= mline)
+               if(*pe == '\r' || *pe == '\n')
+                       *pe = '\0';
+               else
+                       break;
+       printf("%s- %s\r\n", reply, mline);
+   }
+
+   if(filename != (char *)NULL)
+       fclose(mfp);
+}
+
+int main(argc, argv)
+int argc;
+char *argv[];
+{
+struct commands *cmd;
+char *args;
+int status;
+time_t now;
+struct tm *tm;
+int s;
+
+   GetNetInfo();
+
+   /* open transfer log file if it exists */
+   if((logfile = fopen(FTPD_LOG, "r")) != (FILE *)NULL) {
+       fclose(logfile);
+       logfile = fopen(FTPD_LOG, "a");
+   }
+
+   /* open login msg file */
+   msgfile = fopen(FTPD_MSG, "r");
+
+   /* Let's initialize some stuff */
+   init();
+
+   /* Log the connection */
+   logit("CONNECT", "");
+
+   /* Tell 'em we are ready */
+   time(&now);
+   tm = localtime(&now);
+   printf("220 FTP service (Ftpd %s) ready on %s at ",
+       FtpdVersion, myhostname);
+   printf("%s, %02d %s %d %02d:%02d:%02d %s\r\n", days[tm->tm_wday],
+       tm->tm_mday, months[tm->tm_mon], 1900+tm->tm_year,
+       tm->tm_hour, tm->tm_min, tm->tm_sec,
+       tzname[tm->tm_isdst]);
+   fflush(stdout);
+
+   /* Loop here getting commands */
+   while(1) {
+       signal(SIGALRM, Timeout);
+       alarm(INACTIVITY_TIMEOUT);
+       if(readline(&args) != GOOD) {
+               if(!timeout)
+                       printf("221 Control connection closing (EOF).\r\n");
+               break;
+       }
+       alarm(0);
+       for(cmd = commands; *cmd->name != '\0'; cmd++)
+               if(!strcmp(line, cmd->name))
+                       break;
+       if(*cmd->name != '\0')
+               status = (*cmd->func)(args);
+       else {
+               printf("500 Command \"%s\" not recognized.\r\n", line);
+               status = GOOD;
+       }
+       fflush(stdout);
+       if(status != GOOD)
+               break;
+   }
+
+   CleanUpPasv();
+
+   return(-1);
+}
diff --git a/commands/ftpd200/ftpd.h b/commands/ftpd200/ftpd.h
new file mode 100644 (file)
index 0000000..373709e
--- /dev/null
@@ -0,0 +1,37 @@
+/* ftpd.h Copyright 1992-2000 by Michael Temari All Rights Reserved
+ *
+ * This file is part of ftpd.
+ *
+ *
+ * 01/25/96 Initial Release    Michael Temari, <Michael@TemWare.Com>
+ */
+
+#define        GOOD    0
+#define        BAD     1
+
+#define        TYPE_A  0
+#define        TYPE_I  1
+
+#define        MODE_S  0
+#define        MODE_B  1
+
+#define        MODE_B_EOF      64
+
+extern char *FtpdVersion;
+extern int type, format, mode, structure;
+extern ipaddr_t myipaddr, rmtipaddr, dataaddr;
+extern tcpport_t myport, rmtport, dataport;
+extern int ftpdata_fd;
+extern int loggedin, gotuser, anonymous;
+extern char newroot[128];
+extern char *days[], *months[];
+extern char username[80];
+extern char anonpass[128];
+extern char myhostname[256], rmthostname[256];
+extern char line[512];
+
+extern FILE *logfile;
+
+_PROTOTYPE(void cvtline, (char **args));
+_PROTOTYPE(void logit, (char *type, char *parm));
+_PROTOTYPE(void showmsg, (char *reply, char *filename));
diff --git a/commands/ftpd200/ftpdsh b/commands/ftpd200/ftpdsh
new file mode 100755 (executable)
index 0000000..6ca54e3
--- /dev/null
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+case $1 in
+       1)      ls -A $2 ;;
+       2)      ls -la $2 ;;
+       3)      crc $2 ;;
+       12)     tar cf - $2 ;;
+       13)     tar cf - $2 | compress -q ;;
+       14)     compress -cq $2 ;;
+       15)     tar cf - $2 | gzip ;;
+       16)     tar -c $2 ;;
+       17)     compress -dcq $2 ;;
+esac
+exit
diff --git a/commands/ftpd200/net.c b/commands/ftpd200/net.c
new file mode 100644 (file)
index 0000000..0c5755d
--- /dev/null
@@ -0,0 +1,431 @@
+/* net.c Copyright 1992-2000 by Michael Temari All Rights Reserved
+ *
+ * This file is part of ftpd.
+ *
+ * This file handles:
+ *
+ *      PASV PORT
+ *
+ *
+ * 01/25/1995 Initial Release  Michael Temari, <Michael@TemWare.Com>
+ * 02/09/2005 Initial Release  Michael Temari, <Michael@TemWare.Com>
+ */
+
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/wait.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <unistd.h>
+#include <time.h>
+#include <net/netlib.h>
+#include <net/hton.h>
+#include <net/gen/in.h>
+#include <net/gen/inet.h>
+#include <net/gen/tcp.h>
+#include <net/gen/tcp_io.h>
+#include <net/gen/socket.h>
+#include <net/gen/netdb.h>
+
+#include "ftpd.h"
+#include "access.h"
+#include "net.h"
+
+_PROTOTYPE(static void timeout, (int sig));
+
+static char *msg425 = "425-Could not open data connection.\r\n";
+static char *msg501 = "501 Syntax error in parameters.\r\n";
+
+static int gottimeout = 0;
+static int lpid = -1;
+static int didpassive = 0;
+
+/* they must be behind a firewall or using a web browser */
+int doPASV(buff)
+char *buff;
+{
+nwio_tcpconf_t tcpconf;
+nwio_tcpcl_t tcplopt;
+char *tcp_device;
+ipaddr_t ipaddr;
+tcpport_t lport;
+int s;
+time_t starttime;
+int retry;
+
+   if(ChkLoggedIn())
+       return(GOOD);
+
+   CleanUpPasv();
+
+   /* here we set up a connection to listen on */
+   if((tcp_device = getenv("TCP_DEVICE")) == NULL)
+       tcp_device = TCP_DEVICE;
+
+   if(ftpdata_fd >= 0) {
+       close(ftpdata_fd);
+       ftpdata_fd = -1;
+   }
+
+   if((ftpdata_fd = open(tcp_device, O_RDWR)) < 0) {
+       printf(msg425); 
+       printf("425 Could not open tcp_device.  Error %s\r\n", strerror(errno));
+       return(GOOD);
+   }
+
+   tcpconf.nwtc_flags = NWTC_LP_SEL | NWTC_SET_RA | NWTC_UNSET_RP;
+
+   tcpconf.nwtc_remaddr = rmtipaddr;
+   tcpconf.nwtc_remport = htons(0);
+   tcpconf.nwtc_locport = htons(0);
+
+   s = ioctl(ftpdata_fd, NWIOSTCPCONF, &tcpconf);
+   if(s < 0) {
+       printf(msg425);
+       printf("425 Could not ioctl NWIOSTCPCONF. Error %s\r\n", strerror(errno));
+       close(ftpdata_fd);
+       ftpdata_fd = -1;
+       return(GOOD);
+   }
+
+   s = ioctl(ftpdata_fd, NWIOGTCPCONF, &tcpconf);
+   if(s < 0) {
+       printf(msg425);
+       printf("425 Could not NWIOGTCPCONF. Error %s\r\n", strerror(errno));
+       close(ftpdata_fd);
+       ftpdata_fd = -1;
+       return(GOOD);
+   }
+   ipaddr = tcpconf.nwtc_locaddr;
+   lport = tcpconf.nwtc_locport;
+
+   /* Now lets fork a child to do the listening :-( */
+
+   tcplopt.nwtcl_flags = 0;
+
+   lpid = fork();
+   if(lpid < 0) {
+       printf(msg425);
+       printf("425 Could not fork listener.  Error %s\r\n", strerror(errno));
+       close(ftpdata_fd);
+       ftpdata_fd = -1;
+       return(GOOD);
+   } else if(lpid == 0) {
+       retry = 0;
+       while(1) {
+#ifdef DEBUG
+               fprintf(logfile, "ftpd: child %d  parent %d  listen try %d\n", getpid(), getppid(), retry);
+               fflush(logfile);
+#endif
+               s = ioctl(ftpdata_fd, NWIOTCPLISTEN, &tcplopt);
+               if(!(s == -1 && errno == EAGAIN)) break;
+               if(retry++ > 10) break;
+               sleep(1);
+       }
+#ifdef DEBUG
+       fprintf(logfile, "ftpd: child %d  s %d  errno %d\n", getpid(), s, errno);
+       fflush(logfile);
+#endif
+       if(s < 0) 
+               exit(errno);    /* tells parent listen failed */
+       else
+               exit(0);        /* tells parent listen okay */
+   }
+
+#ifdef DEBUG
+   fprintf(logfile, "ftpd: parent %d  wait for %d\n", getpid(), lpid);
+   fflush(logfile);
+#endif
+
+   /* wait for child to be listening, no more than serveral seconds */
+   (void) time(&starttime);
+   while(1) {
+       if(time((time_t *)NULL) > (starttime + 15)) break;
+       signal(SIGALRM, timeout);
+       alarm(1);
+       s = ioctl(ftpdata_fd, NWIOGTCPCONF, &tcpconf);
+#ifdef DEBUG
+       fprintf(logfile, "ftpd: parent %d  child %d  s %d  errno %d start %ld  now %ld\n",
+               getpid(), lpid, s, errno, starttime, time((time_t *)NULL));
+       fflush(logfile);
+#endif
+       alarm(0);
+       if(s == -1) break;
+       sleep(1);
+   }
+
+#define hiword(x)       ((u16_t)((x) >> 16))
+#define loword(x)       ((u16_t)(x & 0xffff)) 
+#define hibyte(x)       (((x) >> 8) & 0xff)
+#define lobyte(x)       ((x) & 0xff)
+
+   printf("227 Entering Passive Mode (%u,%u,%u,%u,%u,%u).\r\n",
+               hibyte(hiword(htonl(ipaddr))), lobyte(hiword(htonl(ipaddr))),
+               hibyte(loword(htonl(ipaddr))), lobyte(loword(htonl(ipaddr))),
+               hibyte(htons(lport)), lobyte(htons(lport)));
+
+#ifdef DEBUG
+   fprintf(logfile, "ftpd: parent %d  child %d  send 227\n", getpid(), lpid);
+   fflush(logfile);
+#endif
+
+   didpassive = -1;
+
+   return(GOOD);
+}
+
+/* they want us to connect here */
+int doPORT(buff)
+char *buff;
+{
+u32_t ipaddr;
+u16_t port;
+int i;
+
+   if(ftpdata_fd >= 0) {
+       close(ftpdata_fd);
+       ftpdata_fd = -1;
+   }
+
+   ipaddr = (u32_t)0;
+   for(i = 0; i < 4; i++) {
+       ipaddr = (ipaddr << 8) + (u32_t)atoi(buff);
+       if((buff = strchr(buff, ',')) == (char *)0) {
+               printf(msg501);
+               return(GOOD);
+       }
+       buff++;
+   }
+   port = (u16_t)atoi(buff);
+   if((buff = strchr(buff, ',')) == (char *)0) {
+       printf(msg501);
+       return(0);
+   }
+   buff++;
+   port = (port << 8) + (u16_t)atoi(buff);
+
+   dataaddr = htonl(ipaddr);
+   dataport = htons(port);
+   if(dataaddr != rmtipaddr) {
+       printf(msg501);
+       return(GOOD);
+   }
+
+   printf("200 Port command okay.\r\n");
+
+   return(GOOD);
+}
+
+/* connect, huh? */
+int DataConnect()
+{
+nwio_tcpconf_t tcpconf;
+nwio_tcpcl_t tcpcopt;
+nwio_tcpcl_t tcplopt;
+char *tcp_device;
+int s, cs;
+int retry;
+
+   if(didpassive && ftpdata_fd >= 0) {
+       didpassive = 0;
+       gottimeout = 0;
+       signal(SIGALRM, timeout);
+       alarm(10);
+       while(!gottimeout) {
+               s = waitpid(lpid, &cs, 0);
+               if((s == lpid) || (s < 0 && errno == ECHILD)) break;
+#ifdef DEBUG
+               fprintf(logfile, "ftpd: parent %d  child %d waitpid s %d  cs %04x  errno %d\n", getpid(), lpid, s, cs, errno);
+               fflush(logfile);
+#endif
+       }
+       alarm(0);
+#ifdef DEBUG
+       fprintf(logfile, "ftpd: parent %d  child %d waitpid s %d  cs %04x  errno %d\n", getpid(), lpid, s, cs, errno);
+               fflush(logfile);
+#endif
+       if(gottimeout) {
+#ifdef DEBUG
+               fprintf(logfile, "ftpd: parent %d  child %d  got timeout\n", getpid(), lpid);
+               fflush(logfile);
+#endif
+               kill(lpid, SIGKILL);
+               s = waitpid(lpid, &cs, 0);
+       }
+#ifdef DEBUG
+       fprintf(logfile, "ftpd: parent %d  child %d continuing\n", getpid(), lpid);
+       fflush(logfile);
+#endif
+       lpid = -1;
+       if(gottimeout) {
+               printf(msg425);
+               printf("425 Child listener timeout.\r\n");
+               close(ftpdata_fd);
+               ftpdata_fd = -1;
+               return(BAD);
+       }
+       if(s < 0) {
+               printf(msg425);
+               printf("425 Child listener vanished.\r\n");
+               close(ftpdata_fd);
+               ftpdata_fd = -1;
+               return(BAD);
+       }
+       if((cs & 0x00ff)) {
+               printf(msg425);
+               printf("425 Child listener failed %04x\r\n", cs);
+               close(ftpdata_fd);
+               ftpdata_fd = -1;
+               return(BAD);
+       }
+       cs = (cs >> 8) & 0x00ff;
+       if(cs) {
+               printf(msg425);
+               printf("425 Child listener error %s\r\n", strerror(cs));
+               close(ftpdata_fd);
+               ftpdata_fd = -1;
+               return(BAD);
+       }
+#ifdef DEBUG
+       fprintf(logfile, "ftpd: parent %d  child %d pasv done\n", getpid(), lpid);
+       fflush(logfile);
+#endif
+       return(GOOD);
+   }
+
+   if(ftpdata_fd >= 0)
+       return(GOOD);
+
+   if((tcp_device = getenv("TCP_DEVICE")) == NULL)
+       tcp_device = TCP_DEVICE;
+
+   if((ftpdata_fd = open(tcp_device, O_RDWR)) < 0) {
+       printf(msg425);
+       printf("425 Could not open tcp_device. Error %s\r\n", strerror(errno));
+       return(BAD);
+   }
+
+   tcpconf.nwtc_flags = NWTC_LP_SET | NWTC_SET_RA | NWTC_SET_RP;
+   tcpconf.nwtc_remaddr = dataaddr;
+   tcpconf.nwtc_remport = dataport;
+   tcpconf.nwtc_locport = htons(20);
+
+   s = ioctl(ftpdata_fd, NWIOSTCPCONF, &tcpconf);
+   if(s < 0) {
+       printf(msg425);
+       printf("425 Could not ioctl NWIOSTCPCONF. Error %s\r\n", strerror(errno));
+       close(ftpdata_fd);
+       ftpdata_fd = -1;
+       return(BAD);
+   }
+
+   s = ioctl(ftpdata_fd, NWIOGTCPCONF, &tcpconf);
+   if(s < 0) {
+       printf(msg425);
+       printf("425 Could not ioctl NWIOGTCPCONF. Error %s\r\n", strerror(errno));
+       close(ftpdata_fd);
+       ftpdata_fd = -1;
+       return(BAD);
+   }
+
+   tcpcopt.nwtcl_flags = 0;
+
+   retry = 0;
+   do  {
+#ifdef DEBUG
+       fprintf(logfile, "try connect\n"); fflush(logfile);
+       fflush(logfile);
+#endif
+       sleep(2);
+       s = ioctl(ftpdata_fd, NWIOTCPCONN, &tcpcopt);
+#ifdef DEBUG
+       fprintf(logfile, "after connect %d %d\n", s, errno);
+       fflush(logfile);
+#endif
+       if(!(s == -1 && errno == EAGAIN)) break;
+       if(retry++ > 10) break;
+       sleep(1);
+   } while(1);
+   if(s < 0) {
+       printf(msg425);
+       printf("425 Could not ioctl NWIOTCPCONN. Error %s\r\n", strerror(errno));
+       close(ftpdata_fd);
+       ftpdata_fd = -1;
+       return(BAD);
+   }
+
+   s = ioctl(ftpdata_fd, NWIOGTCPCONF, &tcpconf);
+   if(s < 0) {
+       printf(msg425);
+       printf("425 Could not ioctl NWIOGTCPCONF. Error %s\r\n", strerror(errno));
+       close(ftpdata_fd);
+       ftpdata_fd = -1;
+       return(BAD);
+   }
+
+   return(GOOD);
+}
+
+/* Clean up stuff we did to get a Pasv connection going */
+int CleanUpPasv()
+{
+int s, cs;
+
+   if(lpid >= 0) {
+       kill(lpid, SIGKILL);
+       while(1) {
+               s = waitpid(lpid, &cs, 0);
+               if(s == lpid || (s == -1 && errno == ECHILD))
+                       break;
+       }
+   }
+
+   lpid = -1;
+
+   didpassive = 0;
+
+   return(GOOD);
+}
+
+void GetNetInfo()
+{
+nwio_tcpconf_t tcpconf;
+int s;
+struct hostent *hostent;
+
+   /* Ask the system what our hostname is. */
+   if(gethostname(myhostname, sizeof(myhostname)) < 0)
+       strcpy(myhostname, "unknown");
+
+   /* lets get our ip address and the clients ip address */
+   s = ioctl(0, NWIOGTCPCONF, &tcpconf);
+   if(s < 0) {
+       printf("421 FTP service unable to get remote ip address. Closing.\r\n");
+       fflush(stdout);
+       exit(1);
+   }
+
+   myipaddr = tcpconf.nwtc_locaddr;
+   myport = tcpconf.nwtc_locport;
+   rmtipaddr = tcpconf.nwtc_remaddr;
+   rmtport = tcpconf.nwtc_remport;
+
+   /* Look up the host name of the remote host. */
+   hostent = gethostbyaddr((char *) &rmtipaddr, sizeof(rmtipaddr), AF_INET);
+   if(!hostent)
+       strcpy(rmthostname, inet_ntoa(rmtipaddr));
+   else {
+       strncpy(rmthostname, hostent->h_name, sizeof(rmthostname)-1);
+       rmthostname[sizeof(rmthostname)-1] = '\0';
+   }
+}
+
+static void timeout(sig)
+int sig;
+{
+   gottimeout = 1;
+}
diff --git a/commands/ftpd200/net.h b/commands/ftpd200/net.h
new file mode 100644 (file)
index 0000000..2bedf9f
--- /dev/null
@@ -0,0 +1,13 @@
+/* net.h Copyright 1992-2000 by Michael Temari All Rights Reserved
+ *
+ * This file is part of ftpd.
+ *
+ *
+ * 01/25/96 Initial Release    Michael Temari, <Michael@TemWare.Com>
+ */
+
+_PROTOTYPE(int doPASV, (char *buff));
+_PROTOTYPE(int doPORT, (char *buff));
+_PROTOTYPE(int DataConnect, (void));
+_PROTOTYPE(int CleanUpPasv, (void));
+_PROTOTYPE(void GetNetInfo, (void));
diff --git a/commands/ftpd200/setup.anonftp b/commands/ftpd200/setup.anonftp
new file mode 100755 (executable)
index 0000000..8dbb0fb
--- /dev/null
@@ -0,0 +1,75 @@
+#!/bin/sh
+# setup.anonftp - Anonymous FTP setup and maintenance.
+#
+# 01/22/96 Initial Release     Al Woodhul, <asw@hampshire.edu>
+# 01/25/96                     Michael Temari, <temari@ix.netcom.com>
+#
+
+# What is needed for anon ftp
+
+# ref: Hunt TCP/IP Net Admin pp. 338++
+# ref: Nemeth et al UNIX System Admin Handbook p. 295
+# ref: mail from M. Temari 18.01.96
+
+# programs possibly used by ftpd
+PROGS="sh ls crc tar compress gzip"
+
+echo Checking /etc/passwd
+if grep '^ftp:[^:]*:[1-9][0-9]*:[1-9][0-9]*:[^:]*:/[^:]*:[^:]*$' \
+                                               /etc/passwd >/dev/null
+then
+  echo -n "OK, ftp entry found: "
+  grep '^ftp:' /etc/passwd
+else
+  echo "Found no entry for ftp in /etc/passwd, please add one with the"
+  echo "home directory pointing to the anonymous FTP directory"
+  exit 1
+fi
+
+# ftp directory
+FTPDIR="`sed '/^ftp:/!d; s/^.*:\\([^:]*\\):[^:]*/\\1/' /etc/passwd`"
+
+if [ `whoami` != root ]
+then
+  echo You must be root to do this
+  exit 1
+fi
+
+echo Setting up for anonymous ftp
+
+echo Making $FTPDIR and subdirectories
+install -d -m 755 -o root -g operator $FTPDIR
+install -d -m 751 -o root -g operator $FTPDIR/bin
+install -d -m 751 -o root -g operator $FTPDIR/dev
+install -d -m 751 -o root -g operator $FTPDIR/etc
+install -d -m 755 -o root -g operator $FTPDIR/pub
+incoming=
+if [ -d $FTPDIR/pub/incoming ]
+then
+       incoming=t
+elif [ -t 0 ]
+then
+       echo -n "Create \"incoming\" directory? [n] "; read yn
+       case "$yn" in
+       [yY]*|ok|sure)  incoming=t
+       esac
+fi
+test "$incoming" && install -d -m 777 -o root -g operator $FTPDIR/pub/incoming
+
+echo Copying files
+for PROG in $PROGS
+do
+  test -f /usr/bin/$PROG && install -lcs /usr/bin/$PROG $FTPDIR/bin
+done
+cp -rp /dev/tcp $FTPDIR/dev/tcp
+install -lcs ftpdsh $FTPDIR/bin
+
+echo Copying a minimum of the password and group files
+sed 's/^\([^:]*\):[^:]*:\([^:]*:[^:]*\):.*$/\1:*:\2:::/' \
+                                       /etc/passwd >$FTPDIR/etc/passwd
+sed 's/^\([^:]*\):[^:]*:\([^:]*\):.*$/\1:*:\2:/' \
+                                       /etc/group >$FTPDIR/etc/group
+chown root:operator $FTPDIR/etc/*
+chmod 444 $FTPDIR/etc/*
+
+echo "Anonymous ftp setup complete"
index df857d20ee01dab74974e25e55f93d76bf8cd2ff..2c97f4e29b5bfdb49fb3afd2133f82fabda93362 100644 (file)
@@ -7,9 +7,12 @@
  * If you want to compile this for non-IBM PC architectures, the header files
  * require that you have your CHIP, MACHINE etc. defined.
  * Full syntax:
- *     ps [-][alx]
+ *     ps [-][aeflx]
  * Option `a' gives all processes, `l' for detailed info, `x' includes even
  * processes without a terminal.
+ * The `f' and `e' options were added by Kees Bot for the convenience of 
+ * Solaris users accustomed to these options. The `e' option is equivalent to 
+ * `a' and `f' is equivalent to  -l. These do not appear in the usage message.
  *
  * VERY IMPORTANT NOTE:
  *     To compile ps, the kernel/, fs/ and pm/ source directories must be in
@@ -549,7 +552,7 @@ int nbytes;
 void usage(pname)
 char *pname;
 {
-  fprintf(stderr, "Usage: %s [-][alx]\n", pname);
+  fprintf(stderr, "Usage: %s [-][aeflx]\n", pname);
   exit(1);
 }
 
index 172676826dfc6a0b7584c9a45a240f4fa6f6e933..9e430c36f58d917a24d57e381bd3ff85bfcbcac7 100644 (file)
@@ -55,6 +55,7 @@ struct pci_device pci_device_table[]=
        { 0x100B, 0xD001, "Nat. Semi. 87410" },
        { 0x1013, 0x00B8, "Cirrus Logic GD 5446" },
        { 0x1013, 0x6003, "Cirrus Logic CS4614/22/24 CrystalClear" },
+       { 0x1022, 0x2000, "AMD Lance/PCI" },
        { 0x1022, 0x700C, "AMD-762 CPU to PCI Bridge (SMP chipset)" },
        { 0x1022, 0x700D, "AMD-762 CPU to PCI Bridge (AGP 4x)" },
        { 0x1022, 0x7410, "AMD-766 PCI to ISA/LPC Bridge" },
@@ -100,20 +101,27 @@ struct pci_device pci_device_table[]=
        { 0x5333, 0x88d0, "S3 Vision 964 vers 0" },
        { 0x5333, 0x8a01, "S3 Virge/DX or /GX" },
        { 0x8086, 0x1004, "Intel 82543GC Gigabit Ethernet Controller" },
-       { 0x8086, 0x1229, "Intel 82557" },
+       { 0x8086, 0x1029, "Intel EtherExpressPro100 ID1029" },
+       { 0x8086, 0x1030, "Intel Corporation 82559 InBusiness 10/100" },
+       { 0x8086, 0x1209, "Intel EtherExpressPro100 82559ER" },
+       { 0x8086, 0x1229, "Intel EtherExpressPro100 82557/8/9" },
        { 0x8086, 0x122D, "Intel 82437FX" },
        { 0x8086, 0x122E, "Intel 82371FB (PIIX)" },
        { 0x8086, 0x1230, "Intel 82371FB (IDE)" },
        { 0x8086, 0x1237, "Intel 82441FX (440FX)" },
        { 0x8086, 0x1250, "Intel 82439HX" },
+       { 0x8086, 0x2449, "Intel EtherExpressPro100 82562EM" },
        { 0x8086, 0x7000, "Intel 82371SB" },
        { 0x8086, 0x7010, "Intel 82371SB (IDE)" },
        { 0x8086, 0x7020, "Intel 82371SB (USB)" },
+       { 0x8086, 0x7030, "Intel 82437VX" },    /* asw 2005-03-02 */
+       { 0x8086, 0x7100, "Intel 82371AB" },    /* asw 2004-07-31 */
        { 0x8086, 0x7100, "Intel 82371AB" },
        { 0x8086, 0x7110, "Intel 82371AB (PIIX4)" },
        { 0x8086, 0x7111, "Intel 82371AB (IDE)" },
        { 0x8086, 0x7112, "Intel 82371AB (USB)" },
        { 0x8086, 0x7113, "Intel 82371AB (Power)" },
+       { 0x8086, 0x7124, "Intel 82801AA" },    /* asw 2004-11-09 */
        { 0x8086, 0x7190, "Intel 82443BX" },
        { 0x8086, 0x7191, "Intel 82443BX (AGP bridge)" },
        { 0x9004, 0x8178, "Adaptec AHA-2940U/2940UW Ultra/Ultra-Wide SCSI Ctrlr" },
@@ -216,7 +224,9 @@ struct pci_intel_ctrl pci_intel_ctrl[]=
        { 0x8086, 0x122D, },    /* Intel 82437FX */
        { 0x8086, 0x1237, },    /* Intel 82441FX */
        { 0x8086, 0x1250, },    /* Intel 82439HX */
-       { 0x8086, 0x7100, },    /* Intel 82371AB */
+       { 0x8086, 0x7030, },    /* Intel 82437VX (asw 2005-03-02) */ 
+       { 0x8086, 0x7100, },    /* Intel 82371AB (asw 2004-07-31) */
+       { 0x8086, 0x7124, },    /* Intel 82801AA (asw 2004-11-09) */
        { 0x8086, 0x7190, },    /* Intel 82443BX */
        { 0x0000, 0x0000, },
 };
@@ -231,8 +241,10 @@ struct pci_isabridge pci_isabridge[]=
        { 0x1106, 0x3227, 1, PCI_IB_VIA,        },      /* VIA */
        { 0x8086, 0x122E, 1, PCI_IB_PIIX,       },      /* Intel 82371FB */
        { 0x8086, 0x7000, 1, PCI_IB_PIIX,       },      /* Intel 82371SB */
-       { 0x8086, 0x7100, 1, PCI_IB_PIIX,       },      /* Intel 82371AB */
-       { 0x8086, 0x7110, 1, PCI_IB_PIIX,       },      /* Intel PIIX4 */
+       { 0x8086, 0x7030, 1, PCI_IB_PIIX,       },      /* Intel 82437VX (asw 2005-03-02) */
+       { 0x8086, 0x7100, 1, PCI_IB_PIIX,       },      /* Intel 82371AB (asw 2004-07-31) */
+       { 0x8086, 0x7110, 1, PCI_IB_PIIX,       },      /* Intel PIIX4 */
+       { 0x8086, 0x7124, 1, PCI_IB_PIIX,       },      /* Intel 82801AA (asw 2004-11-09) */
        { 0x0000, 0x0000, 0, 0,                 },
 };
 
index 6615de3a037788c937f6c96f2f7b29aab07abd23..1f1c8e62394e67861c7410dff55636302d613b0a 100755 (executable)
@@ -267,7 +267,7 @@ irq_hook_t *hook;
           && rdy_head[PPRI_USER] != NIL_PROC))
   {  
       m.NOTIFY_TYPE = HARD_INT;
-      int_notify(CLOCK, &m);
+      lock_notify(CLOCK, &m);
   } 
   else if (--sched_ticks <= 0) {
       sched_ticks = SCHED_RATE;                /* reset the quantum */
index 54cb8ed09203f0fff81bcab668042b2e2c78abca..ece2bb7a614017cc85dd7413156f4ab10fcea3be 100755 (executable)
  *
  * As well as several entry points used from the interrupt and task level:
  *
- *   lock_notify:     send a notification to inform a process of a system event
- *   int_notify:      same as above, but from an interrupt handler (no locking)
+ *   lock_notify:     notify a process of a system event
  *   lock_send:              send a message to a process
- *   lock_ready:      put a process on one of the ready queues so it can be run
+ *   lock_ready:      put a process on one of the ready queues 
  *   lock_unready:    remove a process from the ready queues
  *   lock_sched:      a process has run too long; schedule another one
  *
@@ -438,37 +437,29 @@ PUBLIC int lock_notify(dst, m_ptr)
 int dst;                       /* to whom is message being sent? */
 message *m_ptr;                        /* pointer to message buffer */
 {
-/* Safe gateway to mini_notify() for tasks. Don't use this function from the
- * interrupt level, as it will reenable interrupts (because of the unlock() 
- * call). For interrupt handlers, int_notify() is available. 
+/* Safe gateway to mini_notify() for tasks and interrupt handlers. MINIX 
+ * kernel is not reentrant, which means to interrupts are disabled after 
+ * the first kernel entry (hardware interrupt, trap, or exception). Locking
+ * work is done by temporarily disabling interrupts. 
  */
   int result;
-  register struct proc *caller_ptr;
-  lock(0, "notify");
-  caller_ptr = (k_reenter >= 0) ? proc_addr(HARDWARE) : proc_ptr;
-  result = mini_notify(caller_ptr, dst, m_ptr); 
-  unlock(0);
-  return(result);
-}
 
+  /* Exception or interrupt occurred, thus already locked. */
+  if (k_reenter >= 0) {
+      result = mini_notify(proc_addr(HARDWARE), dst, m_ptr); 
+  }
 
-/*==========================================================================*
- *                             int_notify                                  *
- *==========================================================================*/
-PUBLIC int int_notify(dst, m_ptr)
-int dst;                       /* to whom is message being sent? */
-message *m_ptr;                        /* pointer to message buffer */
-{
-/* Gateway to mini_notify() for interrupt handlers. This function doesn't
- * use lock() and unlock() because interrupts are already disabled.
- */ 
-  int result;
-  register struct proc *caller_ptr = proc_addr(HARDWARE);
-  result = mini_notify(caller_ptr, dst, m_ptr); 
+  /* Call from task level, locking is required. */
+  else {
+      lock(0, "notify");
+      result = mini_notify(proc_ptr, dst, m_ptr); 
+      unlock(0);
+  }
   return(result);
 }
 
 
+
 /*===========================================================================*
  *                             pick_proc                                    * 
  *===========================================================================*/
index 32e6e1e1d3231045a5292f98617fef35b2ce9a05..52f5c361ec9f990be0d67f736ae87de5bd03da88 100755 (executable)
@@ -41,7 +41,6 @@ _PROTOTYPE( void free_bit, (bit_t nr, bitchunk_t *map, bit_t nr_bits)         );
 /* proc.c */
 _PROTOTYPE( int sys_call, (int function, int src_dest, message *m_ptr) );
 _PROTOTYPE( int lock_notify, (int dst, message *m_ptr)                 );
-_PROTOTYPE( int int_notify, (int dst, message *m_ptr)                  );
 _PROTOTYPE( int lock_send, (int dst, message *m_ptr)                   );
 _PROTOTYPE( void lock_ready, (struct proc *rp)                         );
 _PROTOTYPE( void lock_sched, (int queue)                               );
index a040d802a330b110f91cc79bfdb4e36e821a88cc..1a9f7db30859f106c6155eb3f272dbada05d8b6f 100755 (executable)
@@ -296,7 +296,7 @@ irq_hook_t *hook;
   /* Build notification message and return. */
   m.NOTIFY_TYPE = HARD_INT;
   m.NOTIFY_ARG = hook->irq;
-  int_notify(hook->proc_nr, &m);
+  lock_notify(hook->proc_nr, &m);
   return(hook->policy & IRQ_REENABLE);
 }
 
index bce1d8f1bf216805a577ceb2885b9be732633bce..d687c8395d07afabf5476a5e8ee9b18d025cde8b 100755 (executable)
@@ -352,7 +352,7 @@ date_of(register struct dsttype *dst, struct tm *timep)
        tmpday = day;
        day += (dst->ds_date[2] - firstday + 7) % 7
                + 7 * (dst->ds_date[1] - 1);
-       if (day >= tmpday + _ytab[leap][month]) day -= 7;
+       if (day >= tmpday + _ytab[leap][month-1]) day -= 7;
        return day;
 }
 
index 7c5009f14a146d191f59460a9519f84df17395a7..2fd48527a23285326bec2d5c66c0da45fe15baa4 100644 (file)
@@ -323,7 +323,7 @@ declared inside
 not to the global variable named
 .BR x .
 .PP
-The only special parameter than can be made local is ``\fB-\fR''.
+The only special parameter that can be made local is ``\fB-\fR''.
 Making ``\fB-\fR'' local any shell options that are changed via the
 .I set
 command inside the function to be restored to their original values
@@ -1103,7 +1103,7 @@ echo(1), expr(1), line(1), pwd(1), true(1).
 .SH BUGS
 When command substitution occurs inside a here document, the commands inside
 the here document are run with their standard input closed.  For example,
-the following will not word because the standard input of the
+the following will not work because the standard input of the
 .I line
 command will be closed when the command is run:
 .d
@@ -1121,3 +1121,4 @@ as well as by a line containing the terminator word which follows the ``<<''.
 What this means is that if you mistype the terminator line, the shell
 will silently swallow up the rest of your shell script and stick it
 in the here document.
+.\" several minor typos corrected -- ASW 2005-01-15
index 5c3f15001df98114063333873508b9073b297382..fa83cae1f78533f53006d0beca903b8b754ea29c 100644 (file)
@@ -18,7 +18,13 @@ Tapes can't be unloaded with this command, use
 instead.
 .SH "SEE ALSO"
 .BR mt (1),
-.BR hd (4),
-.BR sd (4).
+.BR disk (4),
+.BR tape (4).
 .SH AUTHOR
 Kees J. Bot (kjb@cs.vu.nl)
+
+.\" hd, sd changed to disk, tape -- ASW 2004-12-13
+
+
+
+
index 80a75b828ccbacdf8a8abb6fbf59f80b3ac47b76..7a3a6ec91b3b9f3c719577aeb20f706122fca949 100644 (file)
@@ -75,7 +75,7 @@ there, the initialization file is called "elvis.rc" instead.
 .SH "SEE ALSO"
 .BR ctags (1),
 .BR ref (1),
-.BR virec (1),
+.BR elvrec (1),
 .BR elvis (9).
 .PP
 \fIElvis - A Clone of Vi/Ex\fP, the complete \fBelvis\fP documentation.
@@ -98,3 +98,4 @@ kirkenda@cs.pdx.edu
 Many other people have worked to port \fBelvis\fP to various operating systems.
 To see who deserves credit, run the \fB:version\fP command from within \fBelvis\fP,
 or look in the system-specific section of the complete documentation.
+.\" ref to virec chnaged to elvrec -- ASW 2004-12-13
index b89f90c1fb480f528f21b8dbda15a1b43af32dc7..a37fb19dfa1ccbf565c6d2b40de10408606ae996 100644 (file)
@@ -631,7 +631,7 @@ on some systems).
 library with which to link the scanners.
 .SH "SEE ALSO"
 .LP
-flexdoc(1), lex(1), yacc(1), sed(1), awk(1).
+flexdoc(1), lex(1), yacc(1), sed(1), awk(9).
 .LP
 M. E. Lesk and E. Schmidt,
 .I LEX - Lexical Analyzer Generator
@@ -777,3 +777,4 @@ required for POSIX-compliance.
 The
 .I flex
 internal algorithms need documentation.
+.\" ref. to awk(9) man page corrected -- ASW 2005-01-15
index a38a14c369d80d525fba9cc339d51baa37adf563..ca93b4f0fca4d6bc2ea2dfd3dcad33a34a8be7e7 100644 (file)
@@ -2380,7 +2380,7 @@ requires that at least one of the classes share characters.
 See flex(1).
 .SH "SEE ALSO"
 .LP
-flex(1), lex(1), yacc(1), sed(1), awk(1).
+flex(1), lex(1), yacc(1), sed(1), awk(9).
 .LP
 M. E. Lesk and E. Schmidt,
 .I LEX - Lexical Analyzer Generator
@@ -2439,3 +2439,4 @@ Send comments to:
      decvax!cornell!vern
 
 .fi
+.\" ref. to awk(9) man page corrected -- ASW 2005-01-15
index 11bca34888a4cacc5f66b08a30b2915b9e1d927f..31ce4c1f27d9fe33858cd97939f70384d13eb358 100644 (file)
@@ -21,10 +21,10 @@ fsck, fsck1 \- perform file system consistency check
 .FL "\-r" "Prompt user for repairs if inconsistencies are found
 .FL "\-s" "List the superblock of the file system"
 .SH EXAMPLES
-.EX "fsck /dev/hd4" "Check file system on \fI/dev/hd4\fR"
+.EX "fsck /dev/c0d0p3" "Check file system on \fI/dev/c0d0p3\fR"
 .EX "fsck \-a /dev/at0" "Automatically fix errors on \fI/dev/at0\fR"
 .EX "fsck \-l /dev/fd0" "List the contents of \fI/dev/fd0\fR"
-.EX "fsck \-c 2 3 /dev/hd3" "Check and list \fI/dev/hd3\fR i-nodes 2 & 3"
+.EX "fsck \-c 2 3 /dev/c0d0p2" "Check and list \fI/dev/c0d0p2\fR i-nodes 2 & 3"
 .SH DESCRIPTION
 .PP
 \fIFsck\fR performs consistency checks on the file systems which reside 
@@ -49,3 +49,4 @@ simply be unmounted before it is checked.
 .SH "SEE ALSO"
 .BR mkfs (1),
 .BR mount (1).
+.\" disk name refs corrected, i.e., old hd1 now c0d0p0 -- ASW 2005-01-15
index afa9c99a7f2cb5e774e57ae26a47bf828741f4ba..fb3ffdfc606ab13fd991c0ac51ac85b38c814940 100644 (file)
@@ -98,7 +98,7 @@ in a line is significant.
 .SH "SEE ALSO"
 .BR sort (1),
 .BR comm (1),
-.BR awk (1).
+.BR awk (9).
 .SH BUGS
 With default field separation,
 the collating sequence is that of
@@ -114,5 +114,6 @@ The conventions of
 .BR uniq ,
 .BR look
 and
-.BR awk (1)
+.BR awk (9)
 are wildly incongruous.
+.\" ref. to awk(9) man page corrected -- ASW 2005-01-15
index dce01769bbe0316195c29d77679fd55ae9569b90..a56962d36bd64a383d7be0b6a95a6218c89eb7a2 100644 (file)
@@ -14,7 +14,7 @@ to map titles to manual page names and by
 .BR whatis (1)
 to give one line descriptions.  See
 .BR whatis (5)
-for a desciption of what a whatis database should look like and the
+for a description of what a whatis database should look like and the
 restrictions that are placed on the NAME sections so that
 .B makewhatis
 can make whatis lines out of the manual pages.
@@ -25,3 +25,4 @@ Removing only font and size changes from the NAME section is often not
 enough.
 .SH AUTHOR
 Kees J. Bot (kjb@cs.vu.nl)
+.\" minor correction -- ASW 2005-01-15
index 7971c4df805b2bd6d476533f94f1ab35dce31b01..839d20a789374e6f48f9a57ae86c44ea6881e30f 100644 (file)
@@ -2,7 +2,7 @@
 .SH NAME
 ps \- process status
 .SH SYNOPSIS
-\fBps \fR[\fB\-alxU\fR] [\fBkernel mm fs\fR]\fR
+\fBps \fR[\fR[\fB\-\fR]\fBalx\fR] 
 .br
 .de FL
 .TP
@@ -19,7 +19,9 @@ ps \- process status
 .FL "\-l" "Give long listing"
 .FL "\-x" "Include processes without a terminal"
 .SH EXAMPLES
+.EX "ps " "Show user's own processes in short format"
 .EX "ps \-axl" "Print all processes and tasks in long format"
+.EX "ps \axl" "Same -- the '\-' is optional"
 .SH DESCRIPTION
 .PP
 \fIPs\fR prints the status of active processes.  Normally only the caller's own
@@ -66,3 +68,16 @@ The files \fI/dev/{mem,kmem}\fR are used to read the system tables and command
 line arguments from.  Terminal names in \fI/dev\fR are used to generate the 
 mnemonic names in the TTY column, so \fIps\fR is independent of terminal naming
 conventions.
+.SH NOTES
+The '\-' option prefix is not required.
+For marginal compatibility with System V usage, the hidden option
+.B \-e
+means the same as
+.BR \-ax ,
+and
+.B \-f
+is the same as
+.BR \-l .
+
+.\" edited by ASW 2004-12-14
+
index 1a58c9a4b1ac240bae92fd8e6a4ec4f272e1379a..fbe55d254a39bde97f5bd747f14009eca8ba2082 100644 (file)
@@ -27,7 +27,7 @@ tar \- tape archiver
 .SH EXAMPLES
 .EX "tar c /dev/fd1 ." "Back up current directory to \fI/dev/fd1\fR"
 .EX "tar xv /dev/fd1 file1 file2" "Extract two files from the archive"
-.EX "tar cf \- | (cd dest; tar xf \-)" "Copy current directory to \fIdest\fR"
+.EX "tar cf \- | (cd dest; tar xf \-)" "Copy current directory to \fIdest\fR"
 .SH DESCRIPTION
 .PP
 \fITar\fR is a POSIX-compatible archiver, except that it does not use tape.
@@ -47,3 +47,4 @@ try
 .SH "SEE ALSO"
 .BR compress (1),
 .BR vol (1).
+.\" minor correction ASW 2005-01-15
index 36d40905f55a0d16a24b1a107ddb19df395e55b3..284fda08914524222e25d411e94085a56c6089db 100644 (file)
@@ -1,8 +1,8 @@
 .TH TOUCH 1
 .SH NAME
-touch \- update a file's time of last modification
+touch \- change file access and modification times
 .SH SYNOPSIS
-\fBtouch\fR [\fB\-c\fR] \fIfile\fR ...\fR
+\fBtouch\fR [\fB\-c\fR] [\fB\-a\fR] [\fB\-m\fR] [\fB\-r\fR file] [\fB\-t\fR [CC[YY]]MMDDhhmm[.ss]] [MMDDhhmm[YY]] \fIfile\fR ...\fR
 .br
 .de FL
 .TP
@@ -15,17 +15,35 @@ touch \- update a file's time of last modification
 # \\$2
 ..
 .SH OPTIONS
-.FL "\-c" "Do not create the file"
+.FL "\-c" "Do not create the file if it doesn't already exist"
+.FL "\-a" "Change access time"
+.FL "\-m" "Change modification time"
+.FL "\-r file" "Apply time of specified file"
+.FL "\-t [CC[YY]]MMDDhhmm[.ss]]" "Apply time specified"
+.FL "\-t [MMDDhhmm[YY]]" "Apply time specified (alternate form)"
 .SH EXAMPLES
 .EX "touch *.h" "Make the \fI.h\fP files look recent"
+.EX "touch -t 199610010000 *" "Change date and time of all files in current directory to midnight Oct 1, 1996"
 .SH DESCRIPTION
-############ NEXT ENTRY HAS NOT BEEN CHECKED #############
 .PP
-The time of last modification is set to the current time.
+With no options specified, the times of last modification and last access 
+are set to the current time.
 This command is mostly used to trick
 .I make
 into thinking that a file is more recent than it really is.
 If the file being touched does not exist, it is created, unless the \fB\-c\fR
 flag is present.
+.PP
+The \fB\-a\fR or \fB\-m\fR flag may be used to change only the access or 
+modification time. The \fB\-r\fR or \fB\-t\fR flag may be used to change 
+the times to match the times of another file or to a specified time.
 .SH "SEE ALSO"
 .BR utime (2).
+.SH "AUTHOR"
+.PP
+Original author unknown.  Rewritten for POSIX by Peter Holzer
+(hp@vmars.tuwien.ac.at).
+.\" man page updated by A. S. Woodhull 2005-01-15
+
+
+