LIB.TXT
上传用户:jnzhq888
上传日期:2007-01-18
资源大小:51694k
文件大小:1006k
- 32101 *
- 32102 * Author: Terrence Holm Aug. 1988
- 32103 *
- 32104 *
- 32105 * Ctermid(3) returns a pointer to a string naming the controlling
- 32106 * terminal. If <name_space> is NULL then local PRIVATE storage
- 32107 * is used, otherwise <name_space> must point to storage of at
- 32108 * least L_ctermid characters.
- 32109 *
- 32110 * Returns a pointer to "/dev/tty".
- 32111 */
- 32112
- 32113 #include <lib.h>
- 32114 #include <string.h>
- 32115 #include <stdio.h>
- 32116
- 32117 _PROTOTYPE( char *ctermid, (char *name_space));
- 32118
- 32119 #ifndef L_ctermid
- 32120 #define L_ctermid 9
- 32121 #endif
- 32122
- 32123 char *ctermid(name_space)
- 32124 char *name_space;
- 32125 {
- 32126 PRIVATE char termid[L_ctermid];
- 32127
- 32128 if (name_space == (char *)NULL) name_space = termid;
- 32129 strcpy(name_space, "/dev/tty");
- 32130 return(name_space);
- 32131 }
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/lib/other/cuserid.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 32200 /* cuserid(3)
- 32201 *
- 32202 * Author: Terrence W. Holm Sept. 1987
- 32203 */
- 32204
- 32205 #include <lib.h>
- 32206 #include <pwd.h>
- 32207 #include <string.h>
- 32208 #include <unistd.h>
- 32209 #include <stdio.h>
- 32210
- 32211 #ifndef L_cuserid
- 32212 #define L_cuserid 9
- 32213 #endif
- 32214
- 32215 char *cuserid(user_name)
- 32216 char *user_name;
- 32217 {
- 32218 PRIVATE char userid[L_cuserid];
- 32219 struct passwd *pw_entry;
- 32220
- 32221 if (user_name == (char *)NULL) user_name = userid;
- 32222
- 32223 pw_entry = getpwuid(geteuid());
- 32224
- 32225 if (pw_entry == (struct passwd *)NULL) {
- 32226 *user_name = ' ';
- 32227 return((char *)NULL);
- 32228 }
- 32229 strcpy(user_name, pw_entry->pw_name);
- 32230
- 32231 return(user_name);
- 32232 }
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/lib/other/environ.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 32300 /*
- 32301 * environ.c - define the variable environ
- 32302 */
- 32303 /* $Header: environ.c,v 1.1 90/09/27 13:39:50 eck Exp $ */
- 32304 /*
- 32305 * This file defines the variable environ and initializes it with a magic
- 32306 * value. The C run-time start-off routine tests whether the variable
- 32307 * environ is initialized with this value. If it is not, it is assumed
- 32308 * that it is defined by the user. Only two bytes are tested, since we
- 32309 * don't know the endian-ness and alignment restrictions of the machine.
- 32310 * This means that the low-order two-bytes should be equal to the
- 32311 * high-order two-bytes on machines with four-byte pointers. In fact, all
- 32312 * the bytes in the pointer are the same, just in case.
- 32313 */
- 32314
- 32315 #if _EM_PSIZE==2
- 32316 char **environ = (char **) 0x5353;
- 32317 #else
- 32318 char **environ = (char **) 0x53535353;
- 32319 #endif
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/lib/other/errno.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 32400 #include <lib.h>
- 32401 /* errno.c - declare variable errno Author: F. Meulenbroeks */
- 32402
- 32403 int errno = 0;
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/lib/other/execlp.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 32500 /* execlp(3) and execvp(3)
- 32501 *
- 32502 * Author: Terrence W. Holm July 1988
- 32503 */
- 32504
- 32505 /* FIXES - Dec 1989 - Jan 1990 Bruce Evans.
- 32506 * - Don't use search path when file name contains a '/' *anywhere*.
- 32507 * - Invoke sh(1) on command files.
- 32508 * - Use PATH_MAX and check strings fit in buffer.
- 32509 * - Use stdargs, with the unjustified assumption that va_start() turns
- 32510 * the arg list into a char *[]. Strictly, the arg list should be
- 32511 * copied, "wasting" up to ARG_MAX bytes.
- 32512 */
- 32513
- 32514 /* Execlp(3) and execvp(3) are like execl(3) and execv(3),
- 32515 * except that they use the environment variable $PATH as
- 32516 * a search list of possible locations for the executable
- 32517 * file, if <file> does not contain a '/', and they attempt
- 32518 * to run non-binary executable files using sh(1).
- 32519 *
- 32520 * The path search list is a list of directory names separated
- 32521 * by ':'s. If a colon appears at the beginning or end of the
- 32522 * list, or two appear together, then an empty prefix is tried.
- 32523 * If $PATH is not in the environment, it defaults to "".
- 32524 *
- 32525 * For example, if <file> is "ls", and the $PATH is
- 32526 * ":/usr/local/bin:/bin:/usr/bin", then ./ls,
- 32527 * /usr/local/bin/ls, /bin/ls and /usr/bin/ls are tried until
- 32528 * an exectable one is found. If the direct attempt to exec it
- 32529 * fails, the arg list is modified to begin with "sh" and the
- 32530 * absolute name of <file>, and an exec of /bin/sh is tried.
- 32531 * If this fails, no further attempts are made.
- 32532 *
- 32533 * This function only returns after an error. It returns -1
- 32534 * and sets errno like execv().
- 32535 */
- 32536
- 32537 #include <sys/types.h>
- 32538 #include <lib.h>
- 32539 #include <errno.h>
- 32540 #include <limits.h>
- 32541 #include <stdlib.h>
- 32542 #include <string.h>
- 32543 #include <unistd.h>
- 32544 #include <stdarg.h>
- 32545
- 32546 #undef NULL
- 32547 #define NULL 0 /* kludge for ACK not understanding void * */
- 32548
- 32549 #define MAX_NUM_ARGS 512 /* maximum number of arguments to execvp */
- 32550
- 32551 extern char **environ; /* environment pointer */
- 32552
- 32553 #ifdef _ANSI
- 32554 int execlp(const char *file, const char *arg, ...)
- 32555 #else
- 32556 int execlp(file)
- 32557 char *file;
- 32558 #endif
- 32559 {
- 32560 register va_list argp;
- 32561 register int result;
- 32562
- 32563 va_start(argp, file);
- 32564 result = execvp(file, (char **) argp);
- 32565 va_end(argp);
- 32566 return(result);
- 32567 }
-
- 32569 #ifdef _ANSI
- 32570 int execvp(const char *file, char *const argv[])
- 32571 #else
- 32572 int execvp(file, argv)
- 32573 char *file;
- 32574 char **argv;
- 32575 #endif
- 32576 {
- 32577 int i, best_errno;
- 32578 char **envtop;
- 32579 size_t flength;
- 32580 char *searchpath;
- 32581 size_t slength;
- 32582 char *split;
- 32583 char execpath[PATH_MAX + 1];
- 32584 char *arg2[MAX_NUM_ARGS + 3]; /* place to copy argv */
- 32585
- 32586 /* POSIX requires argv to be immutable. Unfortunately, we have to change it
- 32587 * during execution. To keep POSIX happy, a copy is made and the copy
- 32588 * changed. The question arises: how big should the copy be? Allocating
- 32589 * space dynamically requires using malloc, which itself takes up a lot
- 32590 * of space. The solution chosen here is to limit the number of arguments
- 32591 * to MAX_NUM_ARGS and set this value fairly high. This solution is simpler
- 32592 * and is probably adequate. Only programs with huge numbers of very short
- 32593 * arguments will get an error (if the arguments are large, ARG_MAX will
- 32594 * be exceeded.
- 32595 */
- 32596
- 32597 if (strchr(file, '/') != NULL || (searchpath = getenv("PATH")) == NULL)
- 32598 searchpath = "";
- 32599 flength = strlen(file);
- 32600 best_errno = ENOENT;
- 32601
- 32602 while (1) {
- 32603 split = strchr(searchpath, ':');
- 32604 if (split == NULL)
- 32605 slength = strlen(searchpath);
- 32606 else
- 32607 slength = split - searchpath;
- 32608 if (slength + flength >= sizeof execpath - 2) {
- 32609 errno = ENAMETOOLONG; /* too bad if premature */
- 32610 return(-1);
- 32611 }
- 32612 strncpy(execpath, searchpath, slength);
- 32613 if (slength != 0) execpath[slength++] = '/';
- 32614 strcpy(execpath + slength, file);
- 32615
- 32616 /* Don't try to avoid execv() for non-existent files, since the Minix
- 32617 * shell doesn't, and it is not clear whether access() or stat() work
- 32618 * right when this code is set-uid.
- 32619 */
- 32620 execv(execpath, argv);
- 32621 switch (errno) {
- 32622 case EACCES:
- 32623 best_errno = errno; /* more useful than ENOENT */
- 32624 case ENOENT:
- 32625 if (split == NULL) {
- 32626 /* No more path components. */
- 32627 errno = best_errno;
- 32628 return(-1);
- 32629 }
- 32630 searchpath = split + 1; /* try next in path */
- 32631 break;
- 32632 case ENOEXEC:
- 32633 /* Assume a command file and invoke sh(1) on it. Replace arg0
- 32634 * (which is usually a short name for the command) by the full
- 32635 * name of the command file.
- 32636 */
- 32637
- 32638 /* Copy the arg pointers from argv to arg2, moving them up by
- 32639 * 1, overlaying the assumed NULL at the end, to make room
- 32640 * for "sh" at the beginning.
- 32641 */
- 32642 i = 0;
- 32643 if (argv != NULL)
- 32644 {
- 32645 while (argv[i] != 0) {
- 32646 if (i >= MAX_NUM_ARGS) {
- 32647 /* Copy failed. Not enough room. */
- 32648 errno = ENOEXEC;
- 32649 return(-1);
- 32650 }
- 32651 arg2[i + 1] = argv[i];
- 32652 i++;
- 32653 }
- 32654 }
- 32655 arg2[0] = "sh"; /* exec the shell */
- 32656 arg2[1] = execpath; /* full path */
- 32657 arg2[i + 1] = NULL; /* terminator */
- 32658
- 32659 /* Count the environment pointers. */
- 32660 for (envtop = environ; *envtop != NULL; ) envtop++;
- 32661
- 32662 /* Try only /bin/sh, like the Minix shell. Lose if the user
- 32663 * has a different shell or the command has #!another/shell.
- 32664 */
- 32665 __execve("/bin/sh", arg2, environ, i + 1, (int)(envtop - environ));
- 32666
- 32667 /* Oops, no shell? Give up. */
- 32668 errno = ENOEXEC;
- 32669 return(-1);
- 32670 default:
- 32671 return(-1); /* probably ENOMEM or E2BIG */
- 32672 }
- 32673 }
- 32674 }
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/lib/other/fdopen.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 32700 /*
- 32701 * fdopen - convert a (UNIX) file descriptor into a FILE pointer
- 32702 */
- 32703 /* $Header: fdopen.c,v 1.4 91/02/22 16:32:05 ceriel Exp $ */
- 32704
- 32705 #include <stdlib.h>
- 32706 #include "../stdio/loc_incl.h"
- 32707 #include <stdio.h>
- 32708
- 32709 FILE *
- 32710 fdopen(fd, mode)
- 32711 int fd;
- 32712 _CONST char *mode;
- 32713 {
- 32714 register int i;
- 32715 FILE *stream;
- 32716 int flags = 0;
- 32717
- 32718 if (fd < 0) return (FILE *)NULL;
- 32719 for (i = 0; __iotab[i] != 0 ; i++)
- 32720 if (i >= FOPEN_MAX-1)
- 32721 return (FILE *)NULL;
- 32722
- 32723 switch(*mode++) {
- 32724 case 'r':
- 32725 flags |= _IOREAD | _IOREADING;
- 32726 break;
- 32727 case 'a':
- 32728 flags |= _IOAPPEND;
- 32729 case 'w':
- 32730 flags |= _IOWRITE | _IOWRITING;
- 32731 break;
- 32732 default:
- 32733 return (FILE *)NULL;
- 32734 }
- 32735 while(*mode) {
- 32736 switch(*mode++) {
- 32737 case 'b':
- 32738 continue;
- 32739 case '+':
- 32740 flags |= _IOREAD | _IOWRITE;
- 32741 continue;
- 32742 /* The sequence may be followed by aditional characters */
- 32743 default:
- 32744 break;
- 32745 }
- 32746 break;
- 32747 }
- 32748
- 32749 if ((stream = (FILE *) malloc(sizeof(FILE))) == NULL) {
- 32750 return (FILE *)NULL;
- 32751 }
- 32752
- 32753 if ((flags & _IOREAD) && (flags & _IOWRITE))
- 32754 flags &= ~(_IOREADING | _IOWRITING);
- 32755
- 32756 stream->_count = 0;
- 32757 stream->_fd = fd;
- 32758 stream->_flags = flags;
- 32759 stream->_buf = NULL;
- 32760 __iotab[i] = stream;
- 32761 return stream;
- 32762 }
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/lib/other/ffs.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 32800 #include <lib.h>
- 32801 /* ffs(3)
- 32802 *
- 32803 * Author: Terrence W. Holm Sep. 1988
- 32804 */
- 32805 _PROTOTYPE( int ffs, (int word));
- 32806
- 32807 int ffs(word)
- 32808 int word;
- 32809 {
- 32810 int i;
- 32811
- 32812 if (word == 0) return(0);
- 32813
- 32814 for (i = 1;; ++i, word >>= 1)
- 32815 if (word & 1) return(i);
- 32816 }
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/lib/other/fslib.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 32900 /* fslib.c - routines needed by fs and fs utilities */
- 32901
- 32902 #include <minix/config.h> /* for unused stuff in <minix/type.h> :-( */
- 32903 #include <ansi.h>
- 32904 #include <sys/types.h>
- 32905 #include <minix/const.h>
- 32906 #include <minix/type.h> /* for unshort :-( */
- 32907 #include "fs/const.h" /* depends of -I flag in Makefile */
- 32908 #include "fs/type.h" /* ditto */
- 32909 #include "fs/inode.h" /* ditto */
- 32910 #include <minix/fslib.h>
- 32911
- 32912 /* The next routine is copied from fsck.c and mkfs.c... (Re)define some
- 32913 * things for consistency. Some things should be done better. The shifts
- 32914 * should be replaced by multiplications and divisions by MAP_BITS_PER_BLOCK
- 32915 * since log2 of this is too painful to get right.
- 32916 */
- 32917 #define BITMAPSHIFT 13 /* = log2(MAP_BITS_PER_BLOCK) */
- 32918
- 32919 /* Convert from bit count to a block count. The usual expression
- 32920 *
- 32921 * (nr_bits + (1 << BITMAPSHIFT) - 1) >> BITMAPSHIFT
- 32922 *
- 32923 * doesn't work because of overflow.
- 32924 *
- 32925 * Other overflow bugs, such as the expression for N_ILIST overflowing when
- 32926 * s_inodes is just over V*_INODES_PER_BLOCK less than the maximum+1, are not
- 32927 * fixed yet, because that number of inodes is silly.
- 32928 */
- 32929 /* The above comment doesn't all apply now bit_t is long. Overflow is now
- 32930 * unlikely, but negative bit counts are now possible (though unlikely)
- 32931 * and give silly results.
- 32932 */
- 32933 PUBLIC int bitmapsize(nr_bits)
- 32934 bit_t nr_bits;
- 32935 {
- 32936 int nr_blocks;
- 32937
- 32938 nr_blocks = (int) (nr_bits >> BITMAPSHIFT);
- 32939 if (((bit_t) nr_blocks << BITMAPSHIFT) < nr_bits) ++nr_blocks;
- 32940 return(nr_blocks);
- 32941 }
-
-
- 32944 /*===========================================================================*
- 32945 * conv2 *
- 32946 *===========================================================================*/
- 32947 PUBLIC unsigned conv2(norm, w)
- 32948 int norm; /* TRUE if no swap, FALSE for byte swap */
- 32949 int w; /* promotion of 16-bit word to be swapped */
- 32950 {
- 32951 /* Possibly swap a 16-bit word between 8086 and 68000 byte order. */
- 32952
- 32953 if (norm) return( (unsigned) w & 0xFFFF);
- 32954 return( ((w&BYTE) << 8) | ( (w>>8) & BYTE));
- 32955 }
-
-
- 32958 /*===========================================================================*
- 32959 * conv4 *
- 32960 *===========================================================================*/
- 32961 PUBLIC long conv4(norm, x)
- 32962 int norm; /* TRUE if no swap, FALSE for byte swap */
- 32963 long x; /* 32-bit long to be byte swapped */
- 32964 {
- 32965 /* Possibly swap a 32-bit long between 8086 and 68000 byte order. */
- 32966
- 32967 unsigned lo, hi;
- 32968 long l;
- 32969
- 32970 if (norm) return(x); /* byte order was already ok */
- 32971 lo = conv2(FALSE, (int) x & 0xFFFF); /* low-order half, byte swapped */
- 32972 hi = conv2(FALSE, (int) (x>>16) & 0xFFFF); /* high-order half, swapped */
- 32973 l = ( (long) lo <<16) | hi;
- 32974 return(l);
- 32975 }
-
-
- 32978 /*===========================================================================*
- 32979 * conv_inode *
- 32980 *===========================================================================*/
- 32981 PUBLIC void conv_inode(rip, dip, dip2, rw_flag, magic)
- 32982 register struct inode *rip; /* pointer to the in-core inode struct */
- 32983 register d1_inode *dip; /* pointer to the V1 on-disk inode struct */
- 32984 register d2_inode *dip2; /* pointer to the V2 on-disk inode struct */
- 32985 int rw_flag; /* READING or WRITING */
- 32986 int magic; /* magic number of file system */
- 32987 {
- 32988 /* Copy the inode from the disk block to the in-core table or vice versa.
- 32989 * If the fourth parameter below is FALSE, the bytes are swapped.
- 32990 */
- 32991 switch (magic) {
- 32992 case SUPER_MAGIC: old_icopy(rip, dip, rw_flag, TRUE); break;
- 32993 case SUPER_REV: old_icopy(rip, dip, rw_flag, FALSE); break;
- 32994 case SUPER_V2: new_icopy(rip, dip2, rw_flag, TRUE); break;
- 32995 case SUPER_V2_REV: new_icopy(rip, dip2, rw_flag, FALSE); break;
- 32996 }
- 32997 }
-
-
- 33000 /*===========================================================================*
- 33001 * old_icopy *
- 33002 *===========================================================================*/
- 33003 PUBLIC void old_icopy(rip, dip, direction, norm)
- 33004 register struct inode *rip; /* pointer to the in-core inode struct */
- 33005 register d1_inode *dip; /* pointer to the d1_inode inode struct */
- 33006 int direction; /* READING (from disk) or WRITING (to disk) */
- 33007 int norm; /* TRUE = do not swap bytes; FALSE = swap */
- 33008
- 33009 {
- 33010 /* 4 different on-disk inode layouts are supported, one for each combination
- 33011 * of V1.x/V2.x * bytes-swapped/not-swapped. When an inode is read or written
- 33012 * this routine handles the conversions so that the information in the inode
- 33013 * table is independent of the disk structure from which the inode came.
- 33014 * The old_icopy routine copies to and from V1 disks.
- 33015 */
- 33016
- 33017 int i;
- 33018
- 33019 if (direction == READING) {
- 33020 /* Copy V1.x inode to the in-core table, swapping bytes if need be. */
- 33021 rip->i_mode = conv2(norm, dip->d1_mode);
- 33022 rip->i_uid = conv2(norm,dip->d1_uid );
- 33023 rip->i_size = conv4(norm,dip->d1_size);
- 33024 rip->i_mtime = conv4(norm,dip->d1_mtime);
- 33025 rip->i_atime = 0;
- 33026 rip->i_ctime = 0;
- 33027 rip->i_nlinks = (nlink_t) dip->d1_nlinks; /* 1 char */
- 33028 rip->i_gid = (gid_t) dip->d1_gid; /* 1 char */
- 33029 rip->i_ndzones = V1_NR_DZONES;
- 33030 rip->i_nindirs = V1_INDIRECTS;
- 33031 for (i = 0; i < V1_NR_TZONES; i++)
- 33032 rip->i_zone[i] = conv2(norm, (int) dip->d1_zone[i]);
- 33033 } else {
- 33034 /* Copying V1.x inode to disk from the in-core table. */
- 33035 dip->d1_mode = conv2(norm,rip->i_mode);
- 33036 dip->d1_uid = conv2(norm,rip->i_uid );
- 33037 dip->d1_size = conv4(norm,rip->i_size);
- 33038 dip->d1_mtime = conv4(norm,rip->i_mtime);
- 33039 dip->d1_nlinks = (nlink_t) rip->i_nlinks; /* 1 char */
- 33040 dip->d1_gid = (gid_t) rip->i_gid; /* 1 char */
- 33041 for (i = 0; i < V1_NR_TZONES; i++)
- 33042 dip->d1_zone[i] = conv2(norm, (int) rip->i_zone[i]);
- 33043 }
- 33044 }
-
-
- 33047 /*===========================================================================*
- 33048 * new_icopy *
- 33049 *===========================================================================*/
- 33050 PUBLIC void new_icopy(rip, dip, direction, norm)
- 33051 register struct inode *rip; /* pointer to the in-core inode struct */
- 33052 register d2_inode *dip; /* pointer to the d2_inode struct */
- 33053 int direction; /* READING (from disk) or WRITING (to disk) */
- 33054 int norm; /* TRUE = do not swap bytes; FALSE = swap */
- 33055
- 33056 {
- 33057 /* Same as old_icopy, but to/from V2 disk layout. */
- 33058
- 33059 int i;
- 33060
- 33061 if (direction == READING) {
- 33062 /* Copy V2.x inode to the in-core table, swapping bytes if need be. */
- 33063 rip->i_mode = conv2(norm,dip->d2_mode);
- 33064 rip->i_uid = conv2(norm,dip->d2_uid );
- 33065 rip->i_nlinks = conv2(norm,(int) dip->d2_nlinks);
- 33066 rip->i_gid = conv2(norm,(int) dip->d2_gid );
- 33067 rip->i_size = conv4(norm,dip->d2_size);
- 33068 rip->i_atime = conv4(norm,dip->d2_atime);
- 33069 rip->i_ctime = conv4(norm,dip->d2_ctime);
- 33070 rip->i_mtime = conv4(norm,dip->d2_mtime);
- 33071 rip->i_ndzones = V2_NR_DZONES;
- 33072 rip->i_nindirs = V2_INDIRECTS;
- 33073 for (i = 0; i < V2_NR_TZONES; i++)
- 33074 rip->i_zone[i] = conv4(norm, (long) dip->d2_zone[i]);
- 33075 } else {
- 33076 /* Copying V2.x inode to disk from the in-core table. */
- 33077 dip->d2_mode = conv2(norm,rip->i_mode);
- 33078 dip->d2_uid = conv2(norm,rip->i_uid );
- 33079 dip->d2_nlinks = conv2(norm,rip->i_nlinks);
- 33080 dip->d2_gid = conv2(norm,rip->i_gid );
- 33081 dip->d2_size = conv4(norm,rip->i_size);
- 33082 dip->d2_atime = conv4(norm,rip->i_atime);
- 33083 dip->d2_ctime = conv4(norm,rip->i_ctime);
- 33084 dip->d2_mtime = conv4(norm,rip->i_mtime);
- 33085 for (i = 0; i < V2_NR_TZONES; i++)
- 33086 dip->d2_zone[i] = conv4(norm, (long) rip->i_zone[i]);
- 33087 }
- 33088 }
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/lib/other/fsversion.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 33100 /* This procedure examines a file system and figures out whether it is
- 33101 * version 1 or version 2. It returns the result as an int. If the
- 33102 * file system is neither, it returns -1. A typical call is:
- 33103 *
- 33104 * n = fsversion("/dev/hd1", "df");
- 33105 *
- 33106 * The first argument is the special file for the file system.
- 33107 * The second is the program name, which is used in error messages.
- 33108 */
- 33109
- 33110 #include <sys/types.h>
- 33111 #include <minix/config.h>
- 33112 #include <minix/const.h>
- 33113 #include <minix/minlib.h>
- 33114 #include <minix/type.h>
- 33115 #include <fcntl.h>
- 33116 #include <unistd.h>
- 33117 #include <stdio.h>
- 33118
- 33119 #include "../../fs/const.h"
- 33120 #include "../../fs/type.h"
- 33121 #include "../../fs/super.h"
- 33122
- 33123 static struct super_block super, *sp;
- 33124
- 33125 int fsversion(dev, prog)
- 33126 char *dev, *prog;
- 33127 {
- 33128 int fd;
- 33129
- 33130 if ((fd = open(dev, O_RDONLY)) < 0) {
- 33131 std_err(prog);
- 33132 std_err(" cannot open ");
- 33133 perror(dev);
- 33134 return(-1);
- 33135 }
- 33136
- 33137 lseek(fd, (off_t) BLOCK_SIZE, SEEK_SET); /* skip boot block */
- 33138 if (read(fd, (char *) &super, (unsigned) SUPER_SIZE) != SUPER_SIZE) {
- 33139 std_err(prog);
- 33140 std_err(" cannot read super block on ");
- 33141 perror(dev);
- 33142 close(fd);
- 33143 return(-1);
- 33144 }
- 33145 close(fd);
- 33146 sp = &super;
- 33147 if (sp->s_magic == SUPER_MAGIC) return(1);
- 33148 if (sp->s_magic == SUPER_V2) return(2);
- 33149 return(-1);
- 33150 }
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/lib/other/getgrent.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 33200 /* getgrent(), getgrgid(), getgrnam() - group file routines
- 33201 *
- 33202 * Author: Kees J. Bot
- 33203 * 31 Jan 1994
- 33204 */
- 33205 #define nil 0
- 33206 #define open _open
- 33207 #define fcntl _fcntl
- 33208 #define read _read
- 33209 #define close _close
- 33210 #include <sys/types.h>
- 33211 #include <grp.h>
- 33212 #include <string.h>
- 33213 #include <stdlib.h>
- 33214 #include <unistd.h>
- 33215 #include <fcntl.h>
- 33216
- 33217 #define arraysize(a) (sizeof(a) / sizeof((a)[0]))
- 33218 #define arraylimit(a) ((a) + arraysize(a))
- 33219
- 33220 static char GROUP[]= "/etc/group"; /* The group file. */
- 33221 static const char *grfile; /* Current group file. */
- 33222
- 33223 static char buf[1024]; /* Read buffer. */
- 33224 static char grline[512]; /* One line from the group file. */
- 33225 static struct group entry; /* Entry to fill and return. */
- 33226 static char *members[64]; /* Group members with the entry. */
- 33227 static int grfd= -1; /* Filedescriptor to the file. */
- 33228 static char *bufptr; /* Place in buf. */
- 33229 static ssize_t buflen= 0; /* Remaining characters in buf. */
- 33230 static char *lineptr; /* Place in the line. */
- 33231
- 33232 void endgrent(void)
- 33233 /* Close the group file. */
- 33234 {
- 33235 if (grfd >= 0) {
- 33236 (void) close(grfd);
- 33237 grfd= -1;
- 33238 buflen= 0;
- 33239 }
- 33240 }
-
- 33242 int setgrent(void)
- 33243 /* Open the group file. */
- 33244 {
- 33245 if (grfd >= 0) endgrent();
- 33246
- 33247 if (grfile == nil) grfile= GROUP;
- 33248
- 33249 if ((grfd= open(grfile, O_RDONLY)) < 0) return -1;
- 33250 (void) fcntl(grfd, F_SETFD, fcntl(grfd, F_GETFD) | FD_CLOEXEC);
- 33251 return 0;
- 33252 }
-
- 33254 void setgrfile(const char *file)
- 33255 /* Prepare for reading an alternate group file. */
- 33256 {
- 33257 endgrent();
- 33258 grfile= file;
- 33259 }
-
- 33261 static int getline(void)
- 33262 /* Get one line from the group file, return 0 if bad or EOF. */
- 33263 {
- 33264 lineptr= grline;
- 33265
- 33266 do {
- 33267 if (buflen == 0) {
- 33268 if ((buflen= read(grfd, buf, sizeof(buf))) <= 0)
- 33269 return 0;
- 33270 bufptr= buf;
- 33271 }
- 33272
- 33273 if (lineptr == arraylimit(grline)) return 0;
- 33274 buflen--;
- 33275 } while ((*lineptr++ = *bufptr++) != 'n');
- 33276
- 33277 lineptr= grline;
- 33278 return 1;
- 33279 }
-
- 33281 static char *scan_punct(int punct)
- 33282 /* Scan for a field separator in a line, return the start of the field. */
- 33283 {
- 33284 char *field= lineptr;
- 33285 char *last;
- 33286
- 33287 for (;;) {
- 33288 last= lineptr;
- 33289 if (*lineptr == 0) return nil;
- 33290 if (*lineptr == 'n') break;
- 33291 if (*lineptr++ == punct) break;
- 33292 if (lineptr[-1] == ':') return nil; /* :::,,,:,,,? */
- 33293 }
- 33294 *last= 0;
- 33295 return field;
- 33296 }
-
- 33298 struct group *getgrent(void)
- 33299 /* Read one entry from the group file. */
- 33300 {
- 33301 char *p;
- 33302 char **mem;
- 33303
- 33304 /* Open the file if not yet open. */
- 33305 if (grfd < 0 && setgrent() < 0) return nil;
- 33306
- 33307 /* Until a good line is read. */
- 33308 for (;;) {
- 33309 if (!getline()) return nil; /* EOF or corrupt. */
- 33310
- 33311 if ((entry.gr_name= scan_punct(':')) == nil) continue;
- 33312 if ((entry.gr_passwd= scan_punct(':')) == nil) continue;
- 33313 if ((p= scan_punct(':')) == nil) continue;
- 33314 entry.gr_gid= strtol(p, nil, 0);
- 33315
- 33316 entry.gr_mem= mem= members;
- 33317 if (*lineptr != 'n') {
- 33318 do {
- 33319 if ((*mem= scan_punct(',')) == nil) goto again;
- 33320 if (mem < arraylimit(members) - 1) mem++;
- 33321 } while (*lineptr != 0);
- 33322 }
- 33323 *mem= nil;
- 33324 return &entry;
- 33325 again:;
- 33326 }
- 33327 }
-
- 33329 struct group *getgrgid(Gid_t gid)
- 33330 /* Return the group file entry belonging to the user-id. */
- 33331 {
- 33332 struct group *gr;
- 33333
- 33334 endgrent();
- 33335 while ((gr= getgrent()) != nil && gr->gr_gid != gid) {}
- 33336 endgrent();
- 33337 return gr;
- 33338 }
-
- 33340 struct group *getgrnam(const char *name)
- 33341 /* Return the group file entry belonging to the user name. */
- 33342 {
- 33343 struct group *gr;
- 33344
- 33345 endgrent();
- 33346 while ((gr= getgrent()) != nil && strcmp(gr->gr_name, name) != 0) {}
- 33347 endgrent();
- 33348 return gr;
- 33349 }
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/lib/other/getlogin.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 33400 /* getlogin(3)
- 33401 *
- 33402 * Author: Terrence W. Holm Aug. 1988
- 33403 */
- 33404
- 33405 #include <lib.h>
- 33406 #include <pwd.h>
- 33407 #include <unistd.h>
- 33408 #include <string.h>
- 33409 #include <stdio.h>
- 33410
- 33411 #ifndef L_cuserid
- 33412 #define L_cuserid 9
- 33413 #endif
- 33414
- 33415 char *getlogin()
- 33416 {
- 33417 PRIVATE char userid[L_cuserid];
- 33418 struct passwd *pw_entry;
- 33419
- 33420 pw_entry = getpwuid(getuid());
- 33421
- 33422 if (pw_entry == (struct passwd *)NULL) return((char *)NULL);
- 33423
- 33424 strcpy(userid, pw_entry->pw_name);
- 33425
- 33426 return(userid);
- 33427 }
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/lib/other/getopt.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 33500 /*
- 33501 * getopt - parse command-line options
- 33502 */
- 33503 /* $Header: getopt.c,v 1.1 89/12/18 14:39:31 eck Exp $ */
- 33504
- 33505 #include <stdlib.h>
- 33506 #include <string.h>
- 33507 #include <stdio.h>
- 33508
- 33509 #define ERR(s, c) if(opterr){
- 33510 fputs(argv[0], stderr);
- 33511 fputs(s, stderr);
- 33512 fputc(c, stderr);
- 33513 fputc('n', stderr);}
- 33514
- 33515 int opterr = 1;
- 33516 int optind = 1;
- 33517 int optopt;
- 33518 char *optarg;
- 33519
- 33520 int
- 33521 getopt(argc, argv, opts)
- 33522 int argc;
- 33523 char **argv;
- 33524 char *opts;
- 33525 {
- 33526 static int sp = 1;
- 33527 register c;
- 33528 register char *cp;
- 33529
- 33530 if (sp == 1)
- 33531 if (optind >= argc ||
- 33532 argv[optind][0] != '-' || argv[optind][1] == ' ')
- 33533 return EOF;
- 33534 else if (!strcmp(argv[optind], "--")) {
- 33535 optind++;
- 33536 return EOF;
- 33537 }
- 33538 optopt = c = argv[optind][sp];
- 33539 if (c == ':' || (cp=strchr(opts, c)) == NULL) {
- 33540 ERR (": illegal option -- ", c);
- 33541 if (argv[optind][++sp] == ' ') {
- 33542 optind++;
- 33543 sp = 1;
- 33544 }
- 33545 return '?';
- 33546 }
- 33547 if (*++cp == ':') {
- 33548 if (argv[optind][sp+1] != ' ')
- 33549 optarg = &argv[optind++][sp+1];
- 33550 else if (++optind >= argc) {
- 33551 ERR (": option requires an argument -- ", c);
- 33552 sp = 1;
- 33553 return '?';
- 33554 } else
- 33555 optarg = argv[optind++];
- 33556 sp = 1;
- 33557 } else {
- 33558 if (argv[optind][++sp] == ' ') {
- 33559 sp = 1;
- 33560 optind++;
- 33561 }
- 33562 optarg = NULL;
- 33563 }
- 33564 return c;
- 33565 }
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/lib/other/getpass.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 33600 /* getpass() - read a password Author: Kees J. Bot
- 33601 * Feb 16 1993
- 33602 */
- 33603 #define open _open
- 33604 #define sigaction _sigaction
- 33605 #define sigemptyset _sigemptyset
- 33606 #define tcgetattr _tcgetattr
- 33607 #define tcsetattr _tcsetattr
- 33608 #define write _write
- 33609 #define read _read
- 33610 #define close _close
- 33611 #include <sys/types.h>
- 33612 #include <fcntl.h>
- 33613 #include <unistd.h>
- 33614 #include <signal.h>
- 33615 #include <termios.h>
- 33616 #include <string.h>
- 33617
- 33618 static int intr;
- 33619
- 33620 static void catch(int sig)
- 33621 {
- 33622 intr= 1;
- 33623 }
-
- 33625 char *getpass(const char *prompt)
- 33626 {
- 33627 struct sigaction osa, sa;
- 33628 struct termios cooked, raw;
- 33629 static char password[32+1];
- 33630 int fd, n= 0;
- 33631
- 33632 /* Try to open the controlling terminal. */
- 33633 if ((fd= open("/dev/tty", O_RDONLY)) < 0) return NULL;
- 33634
- 33635 /* Trap interrupts unless ignored. */
- 33636 intr= 0;
- 33637 sigaction(SIGINT, NULL, &osa);
- 33638 if (osa.sa_handler != SIG_IGN) {
- 33639 sigemptyset(&sa.sa_mask);
- 33640 sa.sa_flags= 0;
- 33641 sa.sa_handler= catch;
- 33642 sigaction(SIGINT, &sa, &osa);
- 33643 }
- 33644
- 33645 /* Set the terminal to non-echo mode. */
- 33646 tcgetattr(fd, &cooked);
- 33647 raw= cooked;
- 33648 raw.c_iflag|= ICRNL;
- 33649 raw.c_lflag&= ~ECHO;
- 33650 raw.c_lflag|= ECHONL;
- 33651 raw.c_oflag|= OPOST | ONLCR;
- 33652 tcsetattr(fd, TCSANOW, &raw);
- 33653
- 33654 /* Print the prompt. (After setting non-echo!) */
- 33655 write(2, prompt, strlen(prompt));
- 33656
- 33657 /* Read the password, 32 characters max. */
- 33658 while (read(fd, password+n, 1) > 0) {
- 33659 if (password[n] == 'n') break;
- 33660 if (n < 32) n++;
- 33661 }
- 33662 password[n]= 0;
- 33663
- 33664 /* Terminal back to cooked mode. */
- 33665 tcsetattr(fd, TCSANOW, &cooked);
- 33666
- 33667 close(fd);
- 33668
- 33669 /* Interrupt? */
- 33670 sigaction(SIGINT, &osa, NULL);
- 33671 if (intr) raise(SIGINT);
- 33672
- 33673 return password;
- 33674 }
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/lib/other/getpwent.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 33700 /* getpwent(), getpwuid(), getpwnam() - password file routines
- 33701 *
- 33702 * Author: Kees J. Bot
- 33703 * 31 Jan 1994
- 33704 */
- 33705 #define nil 0
- 33706 #define open _open
- 33707 #define fcntl _fcntl
- 33708 #define read _read
- 33709 #define close _close
- 33710 #include <sys/types.h>
- 33711 #include <pwd.h>
- 33712 #include <string.h>
- 33713 #include <stdlib.h>
- 33714 #include <unistd.h>
- 33715 #include <fcntl.h>
- 33716
- 33717 #define arraysize(a) (sizeof(a) / sizeof((a)[0]))
- 33718 #define arraylimit(a) ((a) + arraysize(a))
- 33719
- 33720 static char PASSWD[]= "/etc/passwd"; /* The password file. */
- 33721 static const char *pwfile; /* Current password file. */
- 33722
- 33723 static char buf[1024]; /* Read buffer. */
- 33724 static char pwline[256]; /* One line from the password file. */
- 33725 static struct passwd entry; /* Entry to fill and return. */
- 33726 static int pwfd= -1; /* Filedescriptor to the file. */
- 33727 static char *bufptr; /* Place in buf. */
- 33728 static ssize_t buflen= 0; /* Remaining characters in buf. */
- 33729 static char *lineptr; /* Place in the line. */
- 33730
- 33731 void endpwent(void)
- 33732 /* Close the password file. */
- 33733 {
- 33734 if (pwfd >= 0) {
- 33735 (void) close(pwfd);
- 33736 pwfd= -1;
- 33737 buflen= 0;
- 33738 }
- 33739 }
-
- 33741 int setpwent(void)
- 33742 /* Open the password file. */
- 33743 {
- 33744 if (pwfd >= 0) endpwent();
- 33745
- 33746 if (pwfile == nil) pwfile= PASSWD;
- 33747
- 33748 if ((pwfd= open(pwfile, O_RDONLY)) < 0) return -1;
- 33749 (void) fcntl(pwfd, F_SETFD, fcntl(pwfd, F_GETFD) | FD_CLOEXEC);
- 33750 return 0;
- 33751 }
-
- 33753 void setpwfile(const char *file)
- 33754 /* Prepare for reading an alternate password file. */
- 33755 {
- 33756 endpwent();
- 33757 pwfile= file;
- 33758 }
-
- 33760 static int getline(void)
- 33761 /* Get one line from the password file, return 0 if bad or EOF. */
- 33762 {
- 33763 lineptr= pwline;
- 33764
- 33765 do {
- 33766 if (buflen == 0) {
- 33767 if ((buflen= read(pwfd, buf, sizeof(buf))) <= 0)
- 33768 return 0;
- 33769 bufptr= buf;
- 33770 }
- 33771
- 33772 if (lineptr == arraylimit(pwline)) return 0;
- 33773 buflen--;
- 33774 } while ((*lineptr++ = *bufptr++) != 'n');
- 33775
- 33776 lineptr= pwline;
- 33777 return 1;
- 33778 }
-
- 33780 static char *scan_colon(void)
- 33781 /* Scan for a field separator in a line, return the start of the field. */
- 33782 {
- 33783 char *field= lineptr;
- 33784 char *last;
- 33785
- 33786 for (;;) {
- 33787 last= lineptr;
- 33788 if (*lineptr == 0) return nil;
- 33789 if (*lineptr == 'n') break;
- 33790 if (*lineptr++ == ':') break;
- 33791 }
- 33792 *last= 0;
- 33793 return field;
- 33794 }
-
- 33796 struct passwd *getpwent(void)
- 33797 /* Read one entry from the password file. */
- 33798 {
- 33799 char *p;
- 33800
- 33801 /* Open the file if not yet open. */
- 33802 if (pwfd < 0 && setpwent() < 0) return nil;
- 33803
- 33804 /* Until a good line is read. */
- 33805 for (;;) {
- 33806 if (!getline()) return nil; /* EOF or corrupt. */
- 33807
- 33808 if ((entry.pw_name= scan_colon()) == nil) continue;
- 33809 if ((entry.pw_passwd= scan_colon()) == nil) continue;
- 33810 if ((p= scan_colon()) == nil) continue;
- 33811 entry.pw_uid= strtol(p, nil, 0);
- 33812 if ((p= scan_colon()) == nil) continue;
- 33813 entry.pw_gid= strtol(p, nil, 0);
- 33814 if ((entry.pw_gecos= scan_colon()) == nil) continue;
- 33815 if ((entry.pw_dir= scan_colon()) == nil) continue;
- 33816 if ((entry.pw_shell= scan_colon()) == nil) continue;
- 33817
- 33818 if (*lineptr == 0) return &entry;
- 33819 }
- 33820 }
-
- 33822 struct passwd *getpwuid(Uid_t uid)
- 33823 /* Return the password file entry belonging to the user-id. */
- 33824 {
- 33825 struct passwd *pw;
- 33826
- 33827 endpwent();
- 33828 while ((pw= getpwent()) != nil && pw->pw_uid != uid) {}
- 33829 endpwent();
- 33830 return pw;
- 33831 }
-
- 33833 struct passwd *getpwnam(const char *name)
- 33834 /* Return the password file entry belonging to the user name. */
- 33835 {
- 33836 struct passwd *pw;
- 33837
- 33838 endpwent();
- 33839 while ((pw= getpwent()) != nil && strcmp(pw->pw_name, name) != 0) {}
- 33840 endpwent();
- 33841 return pw;
- 33842 }
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/lib/other/getttyent.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 33900 /* getttyent(3) - get a ttytab entry Author: Kees J. Bot
- 33901 * 28 Oct 1995
- 33902 */
- 33903 #define nil 0
- 33904 #define open _open
- 33905 #define close _close
- 33906 #define fcntl _fcntl
- 33907 #define read _read
- 33908 #include <string.h>
- 33909 #include <sys/types.h>
- 33910 #include <ttyent.h>
- 33911 #include <unistd.h>
- 33912 #include <fcntl.h>
- 33913
- 33914 #define arraysize(a) (sizeof(a) / sizeof((a)[0]))
- 33915 #define arraylimit(a) ((a) + arraysize(a))
- 33916
- 33917 static char TTYTAB[]= "/etc/ttytab"; /* The table of terminal devices. */
- 33918
- 33919 static char buf[512]; /* Read buffer. */
- 33920 static char ttline[256]; /* One line from the ttytab file. */
- 33921 static char *ttargv[32]; /* Compound arguments. */
- 33922 static struct ttyent entry; /* Entry to fill and return. */
- 33923 static int ttfd= -1; /* Filedescriptor to the file. */
- 33924 static char *bufptr; /* Place in buf. */
- 33925 static ssize_t buflen= 0; /* Remaining characters in buf. */
- 33926 static char *lineptr; /* Place in the line. */
- 33927 static char **argvptr; /* Place in word lists. */
- 33928
- 33929 void endttyent(void)
- 33930 /* Close the ttytab file. */
- 33931 {
- 33932 if (ttfd >= 0) {
- 33933 (void) close(ttfd);
- 33934 ttfd= -1;
- 33935 buflen= 0;
- 33936 }
- 33937 }
-
- 33939 int setttyent(void)
- 33940 /* Open the ttytab file. */
- 33941 {
- 33942 if (ttfd >= 0) endttyent();
- 33943
- 33944 if ((ttfd= open(TTYTAB, O_RDONLY)) < 0) return -1;
- 33945 (void) fcntl(ttfd, F_SETFD, fcntl(ttfd, F_GETFD) | FD_CLOEXEC);
- 33946 return 0;
- 33947 }
-
- 33949 static int getline(void)
- 33950 /* Get one line from the ttytab file, return 0 if bad or EOF. */
- 33951 {
- 33952 lineptr= ttline;
- 33953 argvptr= ttargv;
- 33954
- 33955 do {
- 33956 if (buflen == 0) {
- 33957 if ((buflen= read(ttfd, buf, sizeof(buf))) <= 0)
- 33958 return 0;
- 33959 bufptr= buf;
- 33960 }
- 33961
- 33962 if (lineptr == arraylimit(ttline)) return 0;
- 33963 buflen--;
- 33964 } while ((*lineptr++ = *bufptr++) != 'n');
- 33965
- 33966 lineptr= ttline;
- 33967 return 1;
- 33968 }
-
- 33970 static int white(int c)
- 33971 /* Whitespace? */
- 33972 {
- 33973 return c == ' ' || c == 't';
- 33974 }
-
- 33976 static char *scan_white(int quoted)
- 33977 /* Scan for a field separator in a line, return the start of the field.
- 33978 * "quoted" is set if we have to watch out for double quotes.
- 33979 */
- 33980 {
- 33981 char *field, *last;
- 33982
- 33983 while (white(*lineptr)) lineptr++;
- 33984 if (!quoted && *lineptr == '#') return nil;
- 33985
- 33986 field= lineptr;
- 33987 for (;;) {
- 33988 last= lineptr;
- 33989 if (*lineptr == 0) return nil;
- 33990 if (*lineptr == 'n') break;
- 33991 if (quoted && *lineptr == '"') return field;
- 33992 if (white(*lineptr++)) break;
- 33993 }
- 33994 *last= 0;
- 33995 return *field == 0 ? nil : field;
- 33996 }
-
- 33998 static char **scan_quoted(void)
- 33999 /* Read a field that may be a quoted list of words. */
- 34000 {
- 34001 char *p, **field= argvptr;
- 34002
- 34003 while (white(*lineptr)) lineptr++;
- 34004
- 34005 if (*lineptr == '"') {
- 34006 /* Quoted list of words. */
- 34007 lineptr++;
- 34008 while ((p= scan_white(1)) != nil && *p != '"') {
- 34009 if (argvptr == arraylimit(ttargv)) return nil;
- 34010 *argvptr++= p;
- 34011 }
- 34012 if (*lineptr == '"') *lineptr++= 0;
- 34013 } else {
- 34014 /* Just one word. */
- 34015 if ((p= scan_white(0)) == nil) return nil;
- 34016 if (argvptr == arraylimit(ttargv)) return nil;
- 34017 *argvptr++= p;
- 34018 }
- 34019 if (argvptr == arraylimit(ttargv)) return nil;
- 34020 *argvptr++= nil;
- 34021 return field;
- 34022 }
-
- 34024 struct ttyent *getttyent(void)
- 34025 /* Read one entry from the ttytab file. */
- 34026 {
- 34027 /* Open the file if not yet open. */
- 34028 if (ttfd < 0 && setttyent() < 0) return nil;
- 34029
- 34030 /* Look for a line with something on it. */
- 34031 for (;;) {
- 34032 if (!getline()) return nil; /* EOF or corrupt. */
- 34033
- 34034 if ((entry.ty_name= scan_white(0)) == nil) continue;
- 34035 entry.ty_type= scan_white(0);
- 34036 entry.ty_getty= scan_quoted();
- 34037 entry.ty_init= scan_quoted();
- 34038
- 34039 return &entry;
- 34040 }
- 34041 }
-
- 34043 struct ttyent *getttynam(const char *name)
- 34044 /* Return the ttytab file entry for a given tty. */
- 34045 {
- 34046 struct ttyent *tty;
- 34047
- 34048 endttyent();
- 34049 while ((tty= getttyent()) != nil && strcmp(tty->ty_name, name) != 0) {}
- 34050 endttyent();
- 34051 return tty;
- 34052 }
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/lib/other/getw.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 34100 /*
- 34101 * getw - read a word from a stream
- 34102 */
- 34103 /* $Header: getw.c,v 1.1 89/12/18 14:39:51 eck Exp $ */
- 34104
- 34105 #include <stdio.h>
- 34106
- 34107 _PROTOTYPE(int getw, (FILE *stream ));
- 34108
- 34109 int getw(stream)
- 34110 register FILE *stream;
- 34111 {
- 34112 register int cnt = sizeof(int);
- 34113 int w;
- 34114 register char *p = (char *) &w;
- 34115
- 34116 while (cnt--) {
- 34117 *p++ = getc(stream);
- 34118 }
- 34119 if (feof(stream) || ferror(stream)) return EOF;
- 34120 return w;
- 34121 }
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/lib/other/hypot.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 34200 /*
- 34201 * (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
- 34202 * See the copyright notice in the ACK home directory, in the file "Copyright".
- 34203 *
- 34204 * Author: Ceriel J.H. Jacobs
- 34205 */
- 34206
- 34207 #include <math.h>
- 34208
- 34209 struct complex {
- 34210 double r,i;
- 34211 };
- 34212
- 34213 _PROTOTYPE(double hypot, (double x, double y ));
- 34214 _PROTOTYPE(double cabs, (struct complex p_compl ));
- 34215
- 34216 /* $Header: hypot.c,v 1.1 91/02/26 18:08:08 ceriel Exp $ */
- 34217
- 34218 double
- 34219 hypot(x, y)
- 34220 double x, y;
- 34221 {
- 34222 /* Computes sqrt(x*x+y*y), avoiding overflow */
- 34223
- 34224 if (x < 0) x = -x;
- 34225 if (y < 0) y = -y;
- 34226 if (x > y) {
- 34227 double t = y;
- 34228 y = x;
- 34229 x = t;
- 34230 }
- 34231 /* sqrt(x*x+y*y) = sqrt(y*y*(x*x/(y*y)+1.0)) = y*sqrt(x*x/(y*y)+1.0) */
- 34232 if (y == 0.0) return 0.0;
- 34233 x /= y;
- 34234 return y*sqrt(x*x+1.0);
- 34235 }
-
- 34237 double
- 34238 cabs(p_compl)
- 34239 struct complex p_compl;
- 34240 {
- 34241 return hypot(p_compl.r, p_compl.i);
- 34242 }
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/lib/other/index.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 34300 #include <lib.h>
- 34301 /* index - find first occurrence of a character in a string */
- 34302
- 34303 #include <string.h>
- 34304
- 34305 char *index(s, charwanted) /* found char, or NULL if none */
- 34306 _CONST char *s;
- 34307 char charwanted;
- 34308 {
- 34309 return(strchr(s, charwanted));
- 34310 }
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/lib/other/itoa.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 34400 #include <lib.h>
- 34401 /* Integer to ASCII for signed decimal integers. */
- 34402
- 34403 PRIVATE int next;
- 34404 PRIVATE char qbuf[8];
- 34405
- 34406 _PROTOTYPE( char *itoa, (int n));
- 34407
- 34408 char *itoa(n)
- 34409 int n;
- 34410 {
- 34411 register int r, k;
- 34412 int flag = 0;
- 34413
- 34414 next = 0;
- 34415 if (n < 0) {
- 34416 qbuf[next++] = '-';
- 34417 n = -n;
- 34418 }
- 34419 if (n == 0) {
- 34420 qbuf[next++] = '0';
- 34421 } else {
- 34422 k = 10000;
- 34423 while (k > 0) {
- 34424 r = n / k;
- 34425 if (flag || r > 0) {
- 34426 qbuf[next++] = '0' + r;
- 34427 flag = 1;
- 34428 }
- 34429 n -= r * k;
- 34430 k = k / 10;
- 34431 }
- 34432 }
- 34433 qbuf[next] = 0;
- 34434 return(qbuf);
- 34435 }
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/lib/other/loadname.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 34500 #include <lib.h>
- 34501 #include <string.h>
- 34502
- 34503 PUBLIC void _loadname(name, msgptr)
- 34504 _CONST char *name;
- 34505 message *msgptr;
- 34506 {
- 34507 /* This function is used to load a string into a type m3 message. If the
- 34508 * string fits in the message, it is copied there. If not, a pointer to
- 34509 * it is passed.
- 34510 */
- 34511
- 34512 register size_t k;
- 34513
- 34514 k = strlen(name) + 1;
- 34515 msgptr->m3_i1 = k;
- 34516 msgptr->m3_p1 = (char *) name;
- 34517 if (k <= sizeof msgptr->m3_ca1) strcpy(msgptr->m3_ca1, name);
- 34518 }
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/lib/other/lock.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 34600 #include <lib.h>
- 34601 #include <errno.h>
- 34602 #include <sys/types.h>
- 34603 #include <unistd.h>
- 34604 #include <string.h>
- 34605 #include <fcntl.h>
- 34606 #include <stdio.h>
- 34607 #if _ANSI
- 34608 #include <stdlib.h>
- 34609 #endif
- 34610
- 34611 typedef enum {
- 34612 False, True
- 34613 } BOOLEAN;
- 34614
- 34615 #define LOCKDIR "/tmp/" /* or /usr/tmp/ as the case may be */
- 34616 #define MAXTRIES 3
- 34617 #define NAPTIME (unsigned int)5
- 34618
- 34619 PRIVATE _PROTOTYPE( char *lockpath, (char *name));
- 34620 _PROTOTYPE( void syserr, (char *errstring));
- 34621 _PROTOTYPE( BOOLEAN lock, (char *name));
- 34622 _PROTOTYPE( void unlock, (char *name));
- 34623
- 34624 void
- 34625 syserr(errstring)
- 34626 char *errstring;
- 34627 {
- 34628 fprintf(stderr,"couldn't %sn", errstring);
- 34629 exit(1);
- 34630 }
-
- 34632 BOOLEAN lock(name) /* acquire lock */
- 34633 char *name;
- 34634 {
- 34635 char *path;
- 34636 int fd, tries;
- 34637
- 34638 path = lockpath(name);
- 34639 tries = 0;
- 34640 while ((fd = creat(path, 0)) == -1 && errno == EACCES) {
- 34641 if (++tries >= MAXTRIES) return(False);
- 34642 sleep(NAPTIME);
- 34643 }
- 34644 if (fd == -1 || close(fd) == -1) syserr("lock");
- 34645 return(True);
- 34646 }
-
- 34648 void unlock(name) /* free lock */
- 34649 char *name;
- 34650 {
- 34651 if (unlink(lockpath(name)) == -1) syserr("unlock");
- 34652 }
-
- 34654 PRIVATE char *lockpath(name) /* generate lock file path */
- 34655 char *name;
- 34656 {
- 34657 PRIVATE char path[20];
- 34658
- 34659 strcpy(path, LOCKDIR);
- 34660 return(strcat(path, name));
- 34661 }
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/lib/other/lrand.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 34700 /* lrand(3)
- 34701 *
- 34702 * Author: Terrence W. Holm Nov. 1988
- 34703 *
- 34704 *
- 34705 * A prime modulus multiplicative linear congruential
- 34706 * generator (PMMLCG), or "Lehmer generator".
- 34707 * Implementation directly derived from the article:
- 34708 *
- 34709 * S. K. Park and K. W. Miller
- 34710 * Random Number Generators: Good Ones are Hard to Find
- 34711 * CACM vol 31, #10. Oct. 1988. pp 1192-1201.
- 34712 *
- 34713 *
- 34714 * Using the following multiplier and modulus, we obtain a
- 34715 * generator which:
- 34716 *
- 34717 * 1) Has a full period: 1 to 2^31 - 2.
- 34718 * 2) Is testably "random" (see the article).
- 34719 * 3) Has a known implementation by E. L. Schrage.
- 34720 */
- 34721
- 34722 #include <lib.h>
- 34723
- 34724 _PROTOTYPE( long seed, (long lseed));
- 34725 _PROTOTYPE( long lrand, (void));
- 34726
- 34727 #define A 16807L /* A "good" multiplier */
- 34728 #define M 2147483647L /* Modulus: 2^31 - 1 */
- 34729 #define Q 127773L /* M / A */
- 34730 #define R 2836L /* M % A */
- 34731
- 34732 PRIVATE long _lseed = 1L;
- 34733
- 34734 long seed(lseed)
- 34735 long lseed;
- 34736 {
- 34737 long previous_seed = _lseed;
- 34738
- 34739 _lseed = lseed;
- 34740
- 34741 return(previous_seed);
- 34742 }
-
-
- 34745 long lrand()
- 34746 {
- 34747 _lseed = A * (_lseed % Q) - R * (_lseed / Q);
- 34748
- 34749 if (_lseed < 0) _lseed += M;
- 34750
- 34751 return(_lseed);
- 34752 }
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/lib/other/lsearch.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 34800 #include <lib.h>
- 34801 #include <string.h>
- 34802 /* lsearch(3) and lfind(3)
- 34803 *
- 34804 * Author: Terrence W. Holm Sep. 1988
- 34805 */
- 34806
- 34807 #include <stddef.h>
- 34808
- 34809 _PROTOTYPE( char *lsearch, (char *key, char *base,
- 34810 unsigned *count, unsigned width,
- 34811 int (*keycmp)(const void *, const void *)));
- 34812 _PROTOTYPE( char *lfind, (char *key, char *base,
- 34813 unsigned *count, unsigned width,
- 34814 int (*keycmp)(const void *, const void *)));
- 34815
- 34816 char *lsearch(key, base, count, width, keycmp)
- 34817 char *key;
- 34818 char *base;
- 34819 unsigned *count;
- 34820 unsigned width;
- 34821 _PROTOTYPE( int (*keycmp), (const void *, const void *));
- 34822 {
- 34823 char *entry;
- 34824 char *last = base + *count * width;
- 34825
- 34826 for (entry = base; entry < last; entry += width)
- 34827 if (keycmp(key, entry) == 0) return(entry);
- 34828
- 34829 bcopy(key, last, width);
- 34830 *count += 1;
- 34831 return(last);
- 34832 }
-
-
- 34835 char *lfind(key, base, count, width, keycmp)
- 34836 char *key;
- 34837 char *base;
- 34838 unsigned *count;
- 34839 unsigned width;
- 34840 _PROTOTYPE( int (*keycmp), (const void *, const void *));
- 34841 {
- 34842 char *entry;
- 34843 char *last = base + *count * width;
- 34844
- 34845 for (entry = base; entry < last; entry += width)
- 34846 if (keycmp(key, entry) == 0) return(entry);
- 34847
- 34848 return((char *)NULL);
- 34849 }
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/lib/other/memccpy.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 34900 #include <lib.h>
- 34901 /* memccpy - copy bytes up to a certain char
- 34902 *
- 34903 * CHARBITS should be defined only if the compiler lacks "unsigned char".
- 34904 * It should be a mask, e.g. 0377 for an 8-bit machine.
- 34905 */
- 34906
- 34907 #include <ansi.h>
- 34908 #include <stddef.h>
- 34909
- 34910 _PROTOTYPE( void *memccpy, (void *dst, const void *src,
- 34911 int ucharstop, size_t size));
- 34912 #ifndef CHARBITS
- 34913 # define UNSCHAR(c) ((unsigned char)(c))
- 34914 #else
- 34915 # define UNSCHAR(c) ((c)&CHARBITS)
- 34916 #endif
- 34917
- 34918 void *memccpy(dst, src, ucharstop, size)
- 34919 void * dst;
- 34920 _CONST void * src;
- 34921 int ucharstop;
- 34922 _SIZET size;
- 34923 {
- 34924 register char *d;
- 34925 register _CONST char *s;
- 34926 register _SIZET n;
- 34927 register int uc;
- 34928
- 34929 if (size <= 0) return( (void *) NULL);
- 34930
- 34931 s = (char *) src;
- 34932 d = (char *) dst;
- 34933 uc = UNSCHAR(ucharstop);
- 34934 for (n = size; n > 0; n--)
- 34935 if (UNSCHAR(*d++ = *s++) == (char) uc) return( (void *) d);
- 34936
- 34937 return( (void *) NULL);
- 34938 }
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/lib/other/mtab.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 35000 /* This package consists of 4 routines for handling the /etc/mtab file.
- 35001 * The /etc/mtab file contains information about the root and mounted file
- 35002 * systems as a series of lines, each one with exactly four fields separated
- 35003 * by one space as follows:
- 35004 *
- 35005 * special mounted_on version rw_flag
- 35006 *
- 35007 * where
- 35008 * special is the name of the block special file
- 35009 * mounted_on is the directory on which it is mounted
- 35010 * version is either 1 or 2 for MINIX V1 and V2 file systems
- 35011 * rw_flag is rw or ro for read/write or read only
- 35012 *
- 35013 * An example /etc/mtab:
- 35014 *
- 35015 * /dev/ram / 2 rw
- 35016 * /dev/hd1 /usr 2 rw
- 35017 * /dev/fd0 /user 1 ro
- 35018 *
- 35019 *
- 35020 * The four routines for handling /etc/mtab are as follows. They use two
- 35021 * (hidden) internal buffers, mtab_in for input and mtab_out for output.
- 35022 *
- 35023 * load_mtab(&prog_name) - read /etc/mtab into mtab_in
- 35024 * get_mtab_entry(&s1, &s2, &s3, &s4) - arrays that are filled in
- 35025 * put_mtab_entry(&s1, &s2, &s3, &s4) - append a line to mtab_out
- 35026 * rewrite_mtab(&prog_name) - write mtab_out to /etc/mtab
- 35027 *
- 35028 * If load_mtab and rewrite_mtab work, they return 0. If they fail, they
- 35029 * print their own error messages on stderr and return -1. When get_mtab_entry
- 35030 * runs out of entries to return, it sets the first pointer to NULL and returns
- 35031 * -1 instead of 0. Also, rewrite_mtab returns -1 if it fails.
- 35032 */
- 35033
- 35034 #include <sys/types.h>
- 35035 #include <minix/minlib.h>
- 35036 #include <ctype.h>
- 35037 #include <fcntl.h>
- 35038 #include <stdlib.h>
- 35039 #include <string.h>
- 35040 #include <unistd.h>
- 35041 #include <stdio.h>
- 35042
- 35043 #define BUF_SIZE 512 /* size of the /etc/mtab buffer */
- 35044
- 35045 char *etc_mtab = "/etc/mtab"; /* name of the /etc/mtab file */
- 35046 static char mtab_in[BUF_SIZE+1]; /* holds /etc/mtab when it is read in */
- 35047 static char mtab_out[BUF_SIZE+1]; /* buf to build /etc/mtab for output later */
- 35048 static char *iptr = mtab_in; /* pointer to next line to feed out. */
- 35049 static char *optr = mtab_out; /* pointer to place where next line goes */
- 35050
- 35051 _PROTOTYPE(int load_mtab, (char *prog_name ));
- 35052 _PROTOTYPE(int rewrite_mtab, (char *prog_name ));
- 35053 _PROTOTYPE(int get_mtab_entry, (char *special, char *mounted_on,
- 35054 char *version, char *rw_flag));
- 35055 _PROTOTYPE(int put_mtab_entry, (char *special, char *mounted_on,
- 35056 char *version, char *rw_flag));
- 35057 _PROTOTYPE(void err, (char *prog_name, char *str ));
- 35058
- 35059
- 35060 int load_mtab(prog_name)
- 35061 char *prog_name;
- 35062 {
- 35063 /* Read in /etc/mtab and store it in /etc/mtab. */
- 35064
- 35065 int fd, n;
- 35066 char *ptr;
- 35067
- 35068 /* Open the file. */
- 35069 fd = open(etc_mtab, O_RDONLY);
- 35070 if (fd < 0) {
- 35071 err(prog_name, ": cannot open ");
- 35072 return(-1);
- 35073 }
- 35074
- 35075 /* File opened. Read it in. */
- 35076 n = read(fd, mtab_in, BUF_SIZE);
- 35077 if (n <= 0) {
- 35078 /* Read failed. */
- 35079 err(prog_name, ": cannot read ");
- 35080 return(-1);
- 35081 }
- 35082 if (n == BUF_SIZE) {
- 35083 /* Some nut has mounted 50 file systems or something like that. */
- 35084 std_err(prog_name);
- 35085 std_err(": file too large: ");
- 35086 std_err(etc_mtab);
- 35087 return(-1);
- 35088 }
- 35089
- 35090 close(fd);
- 35091
- 35092 /* Replace all the whitespace by ' '. */
- 35093 ptr = mtab_in;
- 35094 while (*ptr != ' ') {
- 35095 if (isspace(*ptr)) *ptr = ' ';
- 35096 ptr++;
- 35097 }
- 35098 return(0);
- 35099 }
-
-
- 35102 int rewrite_mtab(prog_name)
- 35103 char *prog_name;
- 35104 {
- 35105 /* Write mtab_out to /etc/mtab. */
- 35106
- 35107 int fd, n;
- 35108
- 35109 /* Do a creat to truncate the file. */
- 35110 fd = creat(etc_mtab, 0777);
- 35111 if (fd < 0) {
- 35112 err(prog_name, ": cannot overwrite ");
- 35113 return(-1);
- 35114 }
- 35115
- 35116 /* File created. Write it. */
- 35117 n = write(fd, mtab_out, (unsigned int)(optr - mtab_out));
- 35118 if (n <= 0) {
- 35119 /* Write failed. */
- 35120 err(prog_name, " could not write ");
- 35121 return(-1);
- 35122 }
- 35123
- 35124 close(fd);
- 35125 return(0);
- 35126 }
-
-
- 35129 int get_mtab_entry(special, mounted_on, version, rw_flag)
- 35130 char *special;
- 35131 char *mounted_on;
- 35132 char *version;
- 35133 char *rw_flag;
- 35134 {
- 35135 /* Return the next entry from mtab_in. */
- 35136
- 35137 if (iptr >= &mtab_in[BUF_SIZE]) {
- 35138 special[0] = ' ';
- 35139 return(-1);
- 35140 }
- 35141
- 35142 strcpy(special, iptr);
- 35143 while (isprint(*iptr)) iptr++;
- 35144 while (*iptr == ' '&& iptr < &mtab_in[BUF_SIZE]) iptr++;
- 35145
- 35146 strcpy(mounted_on, iptr);
- 35147 while (isprint(*iptr)) iptr++;
- 35148 while (*iptr == ' '&& iptr < &mtab_in[BUF_SIZE]) iptr++;
- 35149
- 35150 strcpy(version, iptr);
- 35151 while (isprint(*iptr)) iptr++;
- 35152 while (*iptr == ' '&& iptr < &mtab_in[BUF_SIZE]) iptr++;
- 35153
- 35154 strcpy(rw_flag, iptr);
- 35155 while (isprint(*iptr)) iptr++;
- 35156 while (*iptr == ' '&& iptr < &mtab_in[BUF_SIZE]) iptr++;
- 35157 return(0);
- 35158 }
-
-
- 35161 int put_mtab_entry(special, mounted_on, version, rw_flag)
- 35162 char *special;
- 35163 char *mounted_on;
- 35164 char *version;
- 35165 char *rw_flag;
- 35166 {
- 35167 /* Append an entry to the mtab_out buffer. */
- 35168
- 35169 int n1, n2, n3, n4;
- 35170
- 35171 n1 = strlen(special);
- 35172 n2 = strlen(mounted_on);
- 35173 n3 = strlen(version);
- 35174 n4 = strlen(rw_flag);
- 35175
- 35176 if (optr + n1 + n2 + n3 + n4 + 5 >= &mtab_out[BUF_SIZE]) return(-1);
- 35177 strcpy(optr, special);
- 35178 optr += n1;
- 35179 *optr++ = ' ';
- 35180
- 35181 strcpy(optr, mounted_on);
- 35182 optr += n2;
- 35183 *optr++ = ' ';
- 35184
- 35185 strcpy(optr, version);
- 35186 optr += n3;
- 35187 *optr++ = ' ';
- 35188
- 35189 strcpy(optr, rw_flag);
- 35190 optr += n4;
- 35191 *optr++ = 'n';
- 35192 return(0);
- 35193 }
-
-
- 35196 void
- 35197 err(prog_name, str)
- 35198 char *prog_name, *str;
- 35199 {
- 35200 std_err(prog_name);
- 35201 std_err(str);
- 35202 std_err(etc_mtab);
- 35203 perror(" ");
- 35204 }
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/lib/other/nlist.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 35300 /*
- 35301 * "nlist.c", Peter Valkenburg, january 1989.
- 35302 */
- 35303
- 35304 #include <lib.h>
- 35305 #include <string.h>
- 35306 #include <a.out.h>
- 35307 #include <sys/types.h>
- 35308 #include <fcntl.h>
- 35309 #include <unistd.h>
- 35310 #include <stdio.h>
- 35311
- 35312 #define fail(fp) (fclose(fp), -1) /* ret. exp. when nlist fails */
- 35313
- 35314 _PROTOTYPE( int nlist, (char *file, struct nlist nl[]));
- 35315
- 35316 /*
- 35317 * Nlist fills fields n_sclass and n_value of array nl with values found in
- 35318 * non-stripped executable file. Entries that are not found have their
- 35319 * n_value/n_sclass fields set to 0. Nl ends with a 0 or nul string n_name.
- 35320 * The return value is -1 on failure, else the number of entries not found.
- 35321 */
- 35322 int nlist(file, nl)
- 35323 char *file;
- 35324 struct nlist nl[];
- 35325 {
- 35326 int nents, nsrch, nfound, i;
- 35327 struct nlist nlent;
- 35328 FILE *fp;
- 35329 struct exec hd;
- 35330
- 35331 /* open executable with namelist */
- 35332 if ((fp = fopen(file, "r")) == NULL)
- 35333 return -1;
- 35334
- 35335 /* get header and seek to start of namelist */
- 35336 if (fread((char *) &hd, sizeof(struct exec), 1, fp) != 1 ||
- 35337 BADMAG(hd) || fseek(fp, A_SYMPOS(hd), SEEK_SET) != 0)
- 35338 return fail(fp);
- 35339
- 35340 /* determine number of entries searched for & reset fields */
- 35341 nsrch = 0;
- 35342 while (nl[nsrch].n_name != NULL && *(nl[nsrch].n_name) != ' ') {
- 35343 nl[nsrch].n_sclass = 0;
- 35344 nl[nsrch].n_value = 0;
- 35345 nl[nsrch].n_type = 0; /* for compatability */
- 35346 nsrch++;
- 35347 }
- 35348
- 35349 /* loop through namelist & fill in user array */
- 35350 nfound = 0;
- 35351 for (nents = (hd.a_syms & 0xFFFF) / sizeof(struct nlist);
- 35352 nents > 0; nents--) {
- 35353 if (nsrch == nfound)
- 35354 break; /* no need to look further */
- 35355 if (fread((char *) &nlent, sizeof(struct nlist), 1, fp) != 1)
- 35356 return fail(fp);
- 35357 for (i = 0; i < nsrch; i++)
- 35358 if (nl[i].n_sclass == 0 &&
- 35359 strncmp(nl[i].n_name, nlent.n_name,
- 35360 sizeof(nlent.n_name)) == 0) {
- 35361 nl[i] = nlent;
- 35362 nfound++;
- 35363 break;
- 35364 }
- 35365 }
- 35366
- 35367 (void) fclose(fp);
- 35368
- 35369 return nsrch - nfound;
- 35370 }
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/lib/other/peekpoke.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 35400 /* Peek and poke using /dev/mem.
- 35401 *
- 35402 * Callers now ought to check the return values.
- 35403 *
- 35404 * Calling peek() requires read permission on /dev/mem, and consumes
- 35405 * a file descriptor. Calling poke() requires write permission, and
- 35406 * consumes another file descriptor.
- 35407 */
- 35408
- 35409 #include <sys/types.h>
- 35410 #include <fcntl.h>
- 35411 #include <unistd.h>
- 35412
- 35413 _PROTOTYPE( int peek, (unsigned segment, unsigned offset));
- 35414 _PROTOTYPE( int poke, (unsigned segment, unsigned offset, unsigned value));
- 35415
- 35416 #define SEGSIZE 0x10
- 35417
- 35418 int peek(segment, offset)
- 35419 unsigned segment;
- 35420 unsigned offset;
- 35421 {
- 35422 unsigned char chvalue;
- 35423 static int infd = -1;
- 35424
- 35425 if (infd < 0) infd = open("/dev/mem", O_RDONLY);
- 35426 if (infd < 0 ||
- 35427 lseek(infd, (unsigned long) segment * SEGSIZE + offset, SEEK_SET) < 0 ||
- 35428 read(infd, (char *) &chvalue, (unsigned) 1) != 1)
- 35429 return(-1);
- 35430 return(chvalue);
- 35431 }
-
- 35433 int poke(segment, offset, value)
- 35434 unsigned segment;
- 35435 unsigned offset;
- 35436 unsigned value;
- 35437 {
- 35438 unsigned char chvalue;
- 35439 static int outfd = -1;
- 35440
- 35441 chvalue = value;
- 35442 if (outfd < 0) outfd = open("/dev/mem", O_WRONLY);
- 35443 if (outfd < 0 ||
- 35444 lseek(outfd, (unsigned long) segment * SEGSIZE + offset, SEEK_SET) < 0 ||
- 35445 write(outfd, (char *) &chvalue, (unsigned) 1) != 1)
- 35446 return(-1);
- 35447 return(chvalue);
- 35448 }
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/lib/other/popen.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 35500 /*
- 35501 * popen - open a pipe
- 35502 */
- 35503 /* $Header: popen.c,v 1.3 90/08/28 14:53:34 eck Exp $ */
- 35504
- 35505 #include <sys/types.h>
- 35506 #include <limits.h>
- 35507 #include <errno.h>
- 35508 #include <signal.h>
- 35509 #include <stdio.h>
- 35510
- 35511 #if defined(__BSD4_2)
- 35512 union wait {
- 35513 int w_status;
- 35514 };
- 35515 typedef union wait wait_arg;
- 35516 #else
- 35517 typedef int wait_arg;
- 35518 #endif /* __BSD4_2 */
- 35519
- 35520 #include "../stdio/loc_incl.h"
- 35521
- 35522 #ifdef _ANSI
- 35523 int _close(int d);
- 35524 int _dup2(int oldd, int newd); /* not present in System 5 */
- 35525 int _execl(const char *name, const char *_arg, ... );
- 35526 pid_t _fork(void);
- 35527 int _pipe(int fildes[2]);
- 35528 pid_t _wait(wait_arg *status);
- 35529 void _exit(int status);
- 35530 #endif
- 35531
- 35532 static int pids[OPEN_MAX];
- 35533
- 35534 FILE *
- 35535 popen(command, type)
- 35536 _CONST char *command;
- 35537 _CONST char *type;
- 35538 {
- 35539 int piped[2];
- 35540 int Xtype = *type == 'r' ? 0 : *type == 'w' ? 1 : 2;
- 35541 int pid;
- 35542
- 35543 if (Xtype == 2 ||
- 35544 _pipe(piped) < 0 ||
- 35545 (pid = _fork()) < 0) return 0;
- 35546
- 35547 if (pid == 0) {
- 35548 /* child */
- 35549 register int *p;
- 35550
- 35551 for (p = pids; p < &pids[OPEN_MAX]; p++) {
- 35552 if (*p) _close((int)(p - pids));
- 35553 }
- 35554 _close(piped[Xtype]);
- 35555 _dup2(piped[!Xtype], !Xtype);
- 35556 _close(piped[!Xtype]);
- 35557 _execl("/bin/sh", "sh", "-c", command, (char *) 0);
- 35558 _exit(127); /* like system() ??? */
- 35559 }
- 35560
- 35561 pids[piped[Xtype]] = pid;
- 35562 _close(piped[!Xtype]);
- 35563 return fdopen(piped[Xtype], type);
- 35564 }
-
- 35566 #if defined(__BSD4_2)
- 35567 #define ret_val status.w_status
- 35568 #else
- 35569 #define ret_val status
- 35570 #endif
- 35571
- 35572 int
- 35573 pclose(stream)
- 35574 FILE *stream;
- 35575 {
- 35576 int fd = fileno(stream);
- 35577 wait_arg status;
- 35578 int wret;
- 35579
- 35580 #ifdef _ANSI
- 35581 void (*intsave)(int) = signal(SIGINT, SIG_IGN);
- 35582 void (*quitsave)(int) = signal(SIGQUIT, SIG_IGN);
- 35583 #else
- 35584 void (*intsave)() = signal(SIGINT, SIG_IGN);
- 35585 void (*quitsave)() = signal(SIGQUIT, SIG_IGN);
- 35586 #endif
- 35587 fclose(stream);
- 35588 while ((wret = _wait(&status)) != -1) {
- 35589 if (wret == pids[fd]) break;
- 35590 }
- 35591 if (wret == -1) ret_val = -1;
- 35592 signal(SIGINT, intsave);
- 35593 signal(SIGQUIT, quitsave);
- 35594 pids[fd] = 0;
- 35595 return ret_val;
- 35596 }
-
- 35598 #if defined(__USG)
- 35599 int _dup(int fildes);
- 35600
- 35601 static int
- 35602 _dup2(oldd, newd)
- 35603 int oldd, newd;
- 35604 {
- 35605 int i = 0, fd, tmp;
- 35606 int fdbuf[_NFILES];
- 35607
- 35608 /* ignore the error on the close() */
- 35609 tmp = errno; (void) _close(newd); errno = tmp;
- 35610 while ((fd = _dup(oldd)) != newd) {
- 35611 if (fd == -1) break;
- 35612 fdbuf[i++] = fd;
- 35613 }
- 35614 tmp = errno;
- 35615 while (--i >= 0) {
- 35616 _close(fdbuf[i]);
- 35617 }
- 35618 errno = tmp;
- 35619 return -(fd == -1);
- 35620 }
- 35621 #endif /* __USG */
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/lib/other/printk.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 35700 /* printk() - kernel printf() Author: Kees J. Bot
- 35701 * 15 Jan 1994
- 35702 */
- 35703 #define nil 0
- 35704 #include <stdarg.h>
- 35705 #include <limits.h>
- 35706
- 35707 #define isdigit(c) ((unsigned) ((c) - '0') < (unsigned) 10)
- 35708
- 35709 #if !__STDC__
- 35710 /* Classic C stuff, ignore. */
- 35711 void putk();
- 35712 void printk(fmt) char *fmt;
- 35713 #else
- 35714
- 35715 /* Printk() uses putk() to print characters. */
- 35716 void putk(int c);
- 35717
- 35718 void printk(const char *fmt, ...)
- 35719 #endif
- 35720 {
- 35721 int c;
- 35722 enum { LEFT, RIGHT } adjust;
- 35723 enum { LONG, INT } intsize;
- 35724 int fill;
- 35725 int width, max, len, base;
- 35726 static char X2C_tab[]= "0123456789ABCDEF";
- 35727 static char x2c_tab[]= "0123456789abcdef";
- 35728 char *x2c;
- 35729 char *p;
- 35730 long i;
- 35731 unsigned long u;
- 35732 char temp[8 * sizeof(long) / 3 + 2];
- 35733
- 35734 va_list argp;
- 35735
- 35736 va_start(argp, fmt);
- 35737
- 35738 while ((c= *fmt++) != 0) {
- 35739 if (c != '%') {
- 35740 /* Ordinary character. */
- 35741 putk(c);
- 35742 continue;
- 35743 }
- 35744
- 35745 /* Format specifier of the form:
- 35746 * %[adjust][fill][width][.max]keys
- 35747 */
- 35748 c= *fmt++;
- 35749
- 35750 adjust= RIGHT;
- 35751 if (c == '-') {
- 35752 adjust= LEFT;
- 35753 c= *fmt++;
- 35754 }
- 35755
- 35756 fill= ' ';
- 35757 if (c == '0') {
- 35758 fill= '0';
- 35759 c= *fmt++;
- 35760 }
- 35761
- 35762 width= 0;
- 35763 if (c == '*') {
- 35764 /* Width is specified as an argument, e.g. %*d. */
- 35765 width= va_arg(argp, int);
- 35766 c= *fmt++;
- 35767 } else
- 35768 if (isdigit(c)) {
- 35769 /* A number tells the width, e.g. %10d. */
- 35770 do {
- 35771 width= width * 10 + (c - '0');
- 35772 } while (isdigit(c= *fmt++));
- 35773 }
- 35774
- 35775 max= INT_MAX;
- 35776 if (c == '.') {
- 35777 /* Max field length coming up. */
- 35778 if ((c= *fmt++) == '*') {
- 35779 max= va_arg(argp, int);
- 35780 c= *fmt++;
- 35781 } else
- 35782 if (isdigit(c)) {
- 35783 max= 0;
- 35784 do {
- 35785 max= max * 10 + (c - '0');
- 35786 } while (isdigit(c= *fmt++));
- 35787 }
- 35788 }
- 35789
- 35790 /* Set a few flags to the default. */
- 35791 x2c= x2c_tab;
- 35792 i= 0;
- 35793 base= 10;
- 35794 intsize= INT;
- 35795 if (c == 'l' || c == 'L') {
- 35796 /* "Long" key, e.g. %ld. */
- 35797 intsize= LONG;
- 35798 c= *fmt++;
- 35799 }
- 35800 if (c == 0) break;
- 35801
- 35802 switch (c) {
- 35803 /* Decimal. Note that %D is treated as %ld. */
- 35804 case 'D':
- 35805 intsize= LONG;
- 35806 case 'd':
- 35807 i= intsize == LONG ? va_arg(argp, long)
- 35808 : va_arg(argp, int);
- 35809 u= i < 0 ? -i : i;
- 35810 goto int2ascii;
- 35811
- 35812 /* Octal. */
- 35813 case 'O':
- 35814 intsize= LONG;
- 35815 case 'o':
- 35816 base= 010;
- 35817 goto getint;
- 35818
- 35819 /* Hexadecimal. %X prints upper case A-F, not %lx. */
- 35820 case 'X':
- 35821 x2c= X2C_tab;
- 35822 case 'x':
- 35823 base= 0x10;
- 35824 goto getint;
- 35825
- 35826 /* Unsigned decimal. */
- 35827 case 'U':
- 35828 intsize= LONG;
- 35829 case 'u':
- 35830 getint:
- 35831 u= intsize == LONG ? va_arg(argp, unsigned long)
- 35832 : va_arg(argp, unsigned int);
- 35833 int2ascii:
- 35834 p= temp + sizeof(temp)-1;
- 35835 *p= 0;
- 35836 do {
- 35837 *--p= x2c[u % base];
- 35838 } while ((u /= base) > 0);
- 35839 goto string_length;
- 35840
- 35841 /* A character. */
- 35842 case 'c':
- 35843 p= temp;
- 35844 *p= va_arg(argp, int);
- 35845 len= 1;
- 35846 goto string_print;
- 35847
- 35848 /* Simply a percent. */
- 35849 case '%':
- 35850 p= temp;
- 35851 *p= '%';
- 35852 len= 1;
- 35853 goto string_print;
- 35854
- 35855 /* A string. The other cases will join in here. */
- 35856 case 's':
- 35857 p= va_arg(argp, char *);
- 35858
- 35859 string_length:
- 35860 for (len= 0; p[len] != 0 && len < max; len++) {}
- 35861
- 35862 string_print:
- 35863 width -= len;
- 35864 if (i < 0) width--;
- 35865 if (fill == '0' && i < 0) putk('-');
- 35866 if (adjust == RIGHT) {
- 35867 while (width > 0) { putk(fill); width--; }
- 35868 }
- 35869 if (fill == ' ' && i < 0) putk('-');
- 35870 while (len > 0) { putk((unsigned char) *p++); len--; }
- 35871 while (width > 0) { putk(fill); width--; }
- 35872 break;
- 35873
- 35874 /* Unrecognized format key, echo it back. */
- 35875 default:
- 35876 putk('%');
- 35877 putk(c);
- 35878 }
- 35879 }
- 35880
- 35881 /* Mark the end with a null (should be something else, like -1). */
- 35882 putk(0);
- 35883 va_end(argp);
- 35884 }
-
- 35886 /*
- 35887 * $PchHeader: /mount/hd2/minix/lib/minix/other/RCS/printk.c,v 1.2 1994/09/07 18:45:05 philip Exp $
- 35888 */
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/lib/other/putenv.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 35900 /*
- 35901 * (c) copyright 1989 by the Vrije Universiteit, Amsterdam, The Netherlands.
- 35902 * See the copyright notice in the ACK home directory, in the file "Copyright".
- 35903 */
- 35904 /* $Header: putenv.c,v 1.3 90/05/14 12:30:18 ceriel Exp $ */
- 35905
- 35906 #include <stdlib.h>
- 35907 #include <string.h>
- 35908
- 35909 #define ENTRY_INC 10
- 35910 #define rounded(x) (((x / ENTRY_INC) + 1) * ENTRY_INC)
- 35911
- 35912 extern _CONST char **environ;
- 35913
- 35914 int
- 35915 putenv(name)
- 35916 _CONST char *name;
- 35917 {
- 35918 register _CONST char **v = environ;
- 35919 register char *r;
- 35920 static int size = 0;
- 35921 /* When size != 0, it contains the number of entries in the
- 35922 * table (including the final NULL pointer). This means that the
- 35923 * last non-null entry is environ[size - 2].
- 35924 */
- 35925
- 35926 if (!name) return 0;
- 35927 if (environ == NULL) return 1;
- 35928 if (r = strchr(name, '=')) {
- 35929 register _CONST char *p, *q;
- 35930
- 35931 *r = ' ';
- 35932
- 35933 if (v != NULL) {
- 35934 while ((p = *v) != NULL) {
- 35935 q = name;
- 35936 while (*q && (*q++ == *p++))
- 35937 /* EMPTY */ ;
- 35938 if (*q || (*p != '=')) {
- 35939 v++;
- 35940 } else {
- 35941 /* The name was already in the
- 35942 * environment.
- 35943 */
- 35944 *r = '=';
- 35945 *v = name;
- 35946 return 0;
- 35947 }
- 35948 }
- 35949 }
- 35950 *r = '=';
- 35951 v = environ;
- 35952 }
- 35953
- 35954 if (!size) {
- 35955 register _CONST char **p;
- 35956 register int i = 0;
- 35957
- 35958 if (v)
- 35959 do {
- 35960 i++;
- 35961 } while (*v++);
- 35962 if (!(v = malloc(rounded(i) * sizeof(char **))))
- 35963 return 1;
- 35964 size = i;
- 35965 p = environ;
- 35966 environ = v;
- 35967 while (*v++ = *p++); /* copy the environment */
- 35968 v = environ;
- 35969 } else if (!(size % ENTRY_INC)) {
- 35970 if (!(v = realloc(environ, rounded(size) * sizeof(char **))))
- 35971 return 1;
- 35972 environ = v;
- 35973 }
- 35974 v[size - 1] = name;
- 35975 v[size] = NULL;
- 35976 size++;
- 35977 return 0;
- 35978 }
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/lib/other/putw.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 36000 /*
- 36001 * putw - write an word on a stream
- 36002 */
- 36003 /* $Header: putw.c,v 1.1 89/12/18 14:40:15 eck Exp $ */
- 36004
- 36005 #include <stdio.h>
- 36006
- 36007 _PROTOTYPE(int putw, (int w, FILE *stream ));
- 36008
- 36009 int
- 36010 putw(w, stream)
- 36011 int w;
- 36012 register FILE *stream;
- 36013 {
- 36014 register int cnt = sizeof(int);
- 36015 register char *p = (char *) &w;
- 36016
- 36017 while (cnt--) {
- 36018 putc(*p++, stream);
- 36019 }
- 36020 if (ferror(stream)) return EOF;
- 36021 return w;
- 36022 }
-
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
- src/lib/other/regexp.c
- ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-
- 36100 /* regcomp and regexec -- regsub and regerror are elsewhere
- 36101 *
- 36102 * Copyright (c) 1986 by University of Toronto.
- 36103 * Written by Henry Spencer. Not derived from licensed software.
- 36104 *
- 36105 * Permission is granted to anyone to use this software for any
- 36106 * purpose on any computer system, and to redistribute it freely,
- 36107 * subject to the following restrictions:
- 36108 *
- 36109 * 1. The author is not responsible for the consequences of use of
- 36110 * this software, no matter how awful, even if they arise
- 36111 * from defects in it.
- 36112 *
- 36113 * 2. The origin of this software must not be misrepresented, either
- 36114 * by explicit claim or by omission.
- 36115 *
- 36116 * 3. Altered versions must be plainly marked as such, and must not
- 36117 * be misrepresented as being the original software.
- 36118 *
- 36119 * Beware that some of this code is subtly aware of the way operator
- 36120 * precedence is structured in regular expressions. Serious changes in
- 36121 * regular-expression syntax might require a total rethink.
- 36122 *
- 36123 * The third parameter to regexec was added by Martin C. Atkins.
- 36124 * Andy Tanenbaum also made some changes.
- 36125 */
- 36126
- 36127 #include <minix/config.h>
- 36128 #include <minix/const.h>
- 36129 #include <stdlib.h>
- 36130 #include <string.h>
- 36131 #include <regexp.h>
- 36132 #include <stdio.h>
- 36133
- 36134 /* The first byte of the regexp internal "program" is actually this magic
- 36135 * number; the start node begins in the second byte.
- 36136 */
- 36137 #define MAGIC 0234
- 36138
- 36139 /* The "internal use only" fields in regexp.h are present to pass info from
- 36140 * compile to execute that permits the execute phase to run lots faster on
- 36141 * simple cases. They are:
- 36142 *
- 36143 * regstart char that must begin a match; ' ' if none obvious
- 36144 * reganch is the match anchored (at beginning-of-line only)?
- 36145 * regmust string (pointer into program) that match must include, or NULL
- 36146 * regmlen length of regmust string
- 36147 *
- 36148 * Regstart and reganch permit very fast decisions on suitable starting points
- 36149 * for a match, cutting down the work a lot. Regmust permits fast rejection
- 36150 * of lines that cannot possibly match. The regmust tests are costly enough
- 36151 * that regcomp() supplies a regmust only if the r.e. contains something
- 36152 * potentially expensive (at present, the only such thing detected is * or +
- 36153 * at the start of the r.e., which can involve a lot of backup). Regmlen is
- 36154 * supplied because the test in regexec() needs it and regcomp() is computing
- 36155 * it anyway.
- 36156 */
- 36157
- 36158 /* Structure for regexp "program". This is essentially a linear encoding
- 36159 * of a nondeterministic finite-state machine (aka syntax charts or
- 36160 * "railroad normal form" in parsing technology). Each node is an opcode
- 36161 * plus a "next" pointer, possibly plus an operand. "Next" pointers of
- 36162 * all nodes except BRANCH implement concatenation; a "next" pointer with
- 36163 * a BRANCH on both ends of it is connecting two alternatives. (Here we
- 36164 * have one of the subtle syntax dependencies: an individual BRANCH (as
- 36165 * opposed to a collection of them) is never concatenated with anything
- 36166 * because of operator precedence.) The operand of some types of node is
- 36167 * a literal string; for others, it is a node leading into a sub-FSM. In
- 36168 * particular, the operand of a BRANCH node is the first node of the branch.
- 36169 * (NB this is *not* a tree structure: the tail of the branch connects
- 36170 * to the thing following the set of BRANCHes.) The opcodes are:
- 36171 */
- 36172
- 36173 /* Definition number opnd? meaning */
- 36174 #define END 0 /* no End of program. */
- 36175 #define BOL 1 /* no Match "" at beginning of line. */
- 36176 #define EOL 2 /* no Match "" at end of line. */
- 36177 #define ANY 3 /* no Match any one character. */
- 36178 #define ANYOF 4 /* str Match any character in this string. */
- 36179 #define ANYBUT 5 /* str Match any character not in this
- 36180 * string. */
- 36181 #define BRANCH 6 /* node Match this alternative, or the
- 36182 * next... */
- 36183 #define BACK 7 /* no Match "", "next" ptr points backward. */
- 36184 #define EXACTLY 8 /* str Match this string. */
- 36185 #define NOTHING 9 /* no Match empty string. */
- 36186 #define STAR 10 /* node Match this (simple) thing 0 or more
- 36187 * times. */
- 36188 #define PLUS 11 /* node Match this (simple) thing 1 or more
- 36189 * times. */
- 36190 #define OPEN 20 /* no Mark this point in input as start of
- 36191 * #n. */
- 36192 /* OPEN+1 is number 1, etc. */
- 36193 #define CLOSE 30 /* no Analogous to OPEN. */
- 36194
- 36195 /* Opcode notes:
- 36196 *
- 36197 * BRANCH The set of branches constituting a single choice are hooked
- 36198 * together with their "next" pointers, since precedence prevents
- 36199 * anything being concatenated to any individual branch. The
- 36200 * "next" pointer of the last BRANCH in a choice points to the
- 36201 * thing following the whole choice. This is also where the
- 36202 * final "next" pointer of each individual branch points; each
- 36203 * branch starts with the operand node of a BRANCH node.
- 36204 *
- 36205 * BACK Normal "next" pointers all implicitly point forward; BACK
- 36206 * exists to make loop structures possible.
- 36207 *
- 36208 * STAR,PLUS '?', and complex '*' and '+', are implemented as circular
- 36209 * BRANCH structures using BACK. Simple cases (one character
- 36210 * per match) are implemented with STAR and PLUS for speed
- 36211 * and to minimize recursive plunges.
- 36212 *
- 36213 * OPEN,CLOSE ...are numbered at compile time.
- 36214 */
- 36215
- 36216 /* A node is one char of opcode followed by two chars of "next" pointer.
- 36217 * "Next" pointers are stored as two 8-bit pieces, high order first. The
- 36218 * value is a positive offset from the opcode of the node containing it.
- 36219 * An operand, if any, simply follows the node. (Note that much of the
- 36220 * code generation knows about this implicit relationship.)
- 36221 *
- 36222 * Using two bytes for the "next" pointer is vast overkill for most things,
- 36223 * but allows patterns to get big without disasters.
- 36224 */
- 36225 #define OP(p) (*(p))
- 36226 #define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377))
- 36227 #define OPERAND(p) ((p) + 3)
- 36228
- 36229 /* Utility definitions.
- 36230 */
- 36231 #ifndef CHARBITS
- 36232 #define UCHARAT(p) ((int)*(unsigned char *)(p))
- 36233 #else
- 36234 #define UCHARAT(p) ((int)*(p)&CHARBITS)
- 36235 #endif
- 36236
- 36237 #define CFAIL(m) { regerror(m); return((char *)NULL); }
- 36238 #define RFAIL(m) { regerror(m); return((regexp *)NULL); }
- 36239 #define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?')
- 36240 #define META "^$.[()|?+*\"
- 36241
- 36242 /* Flags to be passed up and down.
- 36243 */
- 36244 #define HASWIDTH 01 /* Known never to match null string. */
- 36245 #define SIMPLE 02 /* Simple enough to be STAR/PLUS operand. */
- 36246 #define SPSTART 04 /* Starts with * or +. */
- 36247 #define WORST 0 /* Worst case. */
- 36248
- 36249 /* Global work variables for regcomp().
- 36250 */
- 36251 PRIVATE char *regparse; /* Input-scan pointer. */
- 36252 PRIVATE int regnpar; /* () count. */
- 36253 PRIVATE char regdummy;
- 36254 PRIVATE char *regcode; /* Code-emit pointer; ®dummy = don't. */
- 36255 PRIVATE long regsize; /* Code size. */
- 36256
- 36257 /* Forward declarations for regcomp()'s friends.
- 36258 */
- 36259 #ifndef STATIC
- 36260 #define STATIC PRIVATE
- 36261 #endif
- 36262 STATIC _PROTOTYPE( char *reg, (int paren, int *flagp) );
- 36263 STATIC _PROTOTYPE( char *regbranch, (int *flagp) );
- 36264 STATIC _PROTOTYPE( char *regpiece, (int *flagp) );
- 36265 STATIC _PROTOTYPE( char *regatom, (int *flagp) );
- 36266 STATIC _PROTOTYPE( char *regnode, (int op) );
- 36267 STATIC _PROTOTYPE( char *regnext, (char *p) );
- 36268 STATIC _PROTOTYPE( void regc, (int b) );
- 36269 STATIC _PROTOTYPE( void reginsert, (int op, char *opnd) );
- 36270 STATIC _PROTOTYPE( void regtail, (char *p, char *val) );
- 36271 STATIC _PROTOTYPE( void regoptail, (char *p, char *val) );
- 36272
- 36273 /*
- 36274 - regcomp - compile a regular expression into internal code
- 36275 *
- 36276 * We can't allocate space until we know how big the compiled form will be,
- 36277 * but we can't compile it (and thus know how big it is) until we've got a
- 36278 * place to put the code. So we cheat: we compile it twice, once with code
- 36279 * generation turned off and size counting turned on, and once "for real".
- 36280 * This also means that we don't allocate space until we are sure that the
- 36281 * thing really will compile successfully, and we never have to move the
- 36282 * code and thus invalidate pointers into it. (Note that it has to be in
- 36283 * one piece because free() must be able to free it all.)
- 36284 *
- 36285 * Beware that the optimization-preparation code in here knows about some
- 36286 * of the structure of the compiled regexp.
- 36287 */
- 36288 regexp *regcomp(exp)
- 36289 char *exp;
- 36290 {
- 36291 register regexp *r;
- 36292 register char *scan;
- 36293 register char *longest;
- 36294 register int len;
- 36295 int flags;
- 36296
- 36297 if (exp == (char *)NULL) RFAIL("NULL argument");
- 36298
- 36299 /* First pass: determine size, legality. */
- 36300 regparse = exp;
- 36301 regnpar = 1;
- 36302 regsize = 0L;
- 36303 regcode = ®dummy;
- 36304 regc(MAGIC);
- 36305 if (reg(0, &flags) == (char *)NULL) return((regexp *)NULL);
- 36306
- 36307 /* Small enough for pointer-storage convention? */
- 36308 if (regsize >= 32767L) /* Probably could be 65535L. */
- 36309 RFAIL("regexp too big");
- 36310
- 36311 /* Allocate space. */
- 36312 r = (regexp *) malloc(sizeof(regexp) + (unsigned) regsize);
- 36313 if (r == (regexp *)NULL) RFAIL("out of space");
- 36314
- 36315 /* Second pass: emit code. */
- 36316 regparse = exp;
- 36317 regnpar = 1;
- 36318 regcode = r->program;
- 36319 regc(MAGIC);
- 36320 if (reg(0, &flags) == (char *)NULL) return((regexp *)NULL);
- 36321
- 36322 /* Dig out information for optimizations. */
- 36323 r->regstart = ' '; /* Worst-case defaults. */
- 36324 r->reganch = 0;
- 36325 r->regmust = (char *)NULL;
- 36326 r->regmlen = 0;
- 36327 scan = r->program + 1; /* First BRANCH. */
- 36328 if (OP(regnext(scan)) == END) { /* Only one top-level choice. */
- 36329 scan = OPERAND(scan);
- 36330
- 36331 /* Starting-point info. */
- 36332 if (OP(scan) == EXACTLY)
- 36333 r->regstart = *OPERAND(scan);
- 36334 else if (OP(scan) == BOL)
- 36335 r->reganch++;
- 36336
- 36337 /* If there's something expensive in the r.e., find the
- 36338 * longest literal string that must appear and make it the
- 36339 * regmust. Resolve ties in favor of later strings, since
- 36340 * the regstart check works with the beginning of the r.e.
- 36341 * and avoiding duplication strengthens checking. Not a
- 36342 * strong reason, but sufficient in the absence of others. */
- 36343 if (flags & SPSTART) {
- 36344 longest = (char *)NULL;
- 36345 len = 0;
- 36346 for (; scan != (char *)NULL; scan = regnext(scan))
- 36347 if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) {
- 36348 longest = OPERAND(scan);
- 36349 len = strlen(OPERAND(scan));
- 36350 }
- 36351 r->regmust = longest;
- 36352 r->regmlen = len;
- 36353 }
- 36354 }
- 36355 return(r);
- 36356 }
-
- 36358 /*
- 36359 - reg - regular expression, i.e. main body or parenthesized thing
- 36360 *
- 36361 * Caller must absorb opening parenthesis.
- 36362 *
- 36363 * Combining parenthesis handling with the base level of regular expression
- 36364 * is a trifle forced, but the need to tie the tails of the branches to what
- 36365 * follows makes it hard to avoid.
- 36366 */
- 36367 PRIVATE char *reg(paren, flagp)
- 36368 int paren; /* Parenthesized? */
- 36369 int *flagp;
- 36370 {
- 36371 register char *ret;
- 36372 register char *br;
- 36373 register char *ender;
- 36374 register int parno;
- 36375 int flags;
- 36376
- 36377 *flagp = HASWIDTH; /* Tentatively. */
- 36378
- 36379 /* Make an OPEN node, if parenthesized. */
- 36380 if (paren) {
- 36381 if (regnpar >= NSUBEXP) CFAIL("too many ()");
- 36382 parno = regnpar;
- 36383 regnpar++;
- 36384 ret = regnode(OPEN + parno);
- 36385 } else {
- 36386 parno = 0; /* not actually used, keep compiler quiet */
- 36387 ret = (char *)NULL;
- 36388 }
- 36389
- 36390 /* Pick up the branches, linking them together. */
- 36391 br = regbranch(&flags);
- 36392 if (br == (char *)NULL) return((char *)NULL);
- 36393 if (ret != (char *)NULL)
- 36394 regtail(ret, br); /* OPEN -> first. */
- 36395 else
- 36396 ret = br;
- 36397 if (!(flags & HASWIDTH)) *flagp &= ~HASWIDTH;
- 36398 *flagp |= flags & SPSTART;
- 36399 while (*regparse == '|') {
- 36400 regparse++;
- 36401 br = regbranch(&flags);
- 36402 if (br == (char *)NULL) return((char *)NULL);
- 36403 regtail(ret, br); /* BRANCH -> BRANCH. */
- 36404 if (!(flags & HASWIDTH)) *flagp &= ~HASWIDTH;
- 36405 *flagp |= flags & SPSTART;
- 36406 }
- 36407
- 36408 /* Make a closing node, and hook it on the end. */
- 36409 ender = regnode((paren) ? CLOSE + parno : END);
- 36410 regtail(ret, ender);
- 36411
- 36412 /* Hook the tails of the branches to the closing node. */
- 36413 for (br = ret; br != (char *)NULL; br = regnext(br)) regoptail(br, ender);
- 36414
- 36415 /* Check for proper termination. */
- 36416 if (paren && *regparse++ != ')') {
- 36417 CFAIL("unmatched ()");
- 36418 } else if (!paren && *regparse != ' ') {
- 36419 if (*regparse == ')') {
- 36420 CFAIL("unmatched ()");
- 36421 } else
- 36422 CFAIL("junk on end"); /* "Can't happen". */
- 36423 /* NOTREACHED */
- 36424 }
- 36425 return(ret);
- 36426 }
-
- 36428 /*
- 36429 - regbranch - one alternative of an | operator
- 36430 *
- 36431 * Implements the concatenation operator.
- 36432 */
- 36433 PRIVATE char *regbranch(flagp)
- 36434 int *flagp;
- 36435 {
- 36436 register char *ret;
- 36437 register char *chain;
- 36438 register char *latest;
- 36439 int flags;
- 36440
- 36441 *flagp = WORST; /* Tentatively. */
- 36442
- 36443 ret = regnode(BRANCH);
- 36444 chain = (char *)NULL;
- 36445 while (*regparse != ' ' && *regparse != '|' && *regparse != ')') {
- 36446 latest = regpiece(&flags);
- 36447 if (latest == (char *)NULL) return((char *)NULL);
- 36448 *flagp |= flags & HASWIDTH;
- 36449 if (chain == (char *)NULL) /* First piece. */
- 36450 *flagp |= flags & SPSTART;
- 36451 else
- 36452 regtail(chain, latest);
- 36453 chain = latest;
- 36454 }
- 36455 if (chain == (char *)NULL) /* Loop ran zero times. */
- 36456 regnode(NOTHING);
- 36457
- 36458 return(ret);
- 36459 }
-
- 36461 /*
- 36462 - regpiece - something followed by possible [*+?]
- 36463 *
- 36464 * Note that the branching code sequences used for ? and the general cases
- 36465 * of * and + are somewhat optimized: they use the same NOTHING node as
- 36466 * both the endmarker for their branch list and the body of the last branch.
- 36467 * It might seem that this node could be dispensed with entirely, but the
- 36468 * endmarker role is not redundant.
- 36469 */
- 36470 PRIVATE char *regpiece(flagp)
- 36471 int *flagp;
- 36472 {
- 36473 register char *ret;
- 36474 register char op;
- 36475 register char *next;
- 36476 int flags;
- 36477
- 36478 ret = regatom(&flags);
- 36479 if (ret == (char *)NULL) return((char *)NULL);
- 36480
- 36481 op = *regparse;
- 36482 if (!ISMULT(op)) {
- 36483 *flagp = flags;
- 36484 return(ret);
- 36485 }
- 36486 if (!(flags & HASWIDTH) && op != '?') CFAIL("*+ operand could be empty");
- 36487 *flagp = (op != '+') ? (WORST | SPSTART) : (WORST | HASWIDTH);
- 36488
- 36489 if (op == '*' && (flags & SIMPLE))
- 36490 reginsert(STAR, ret);
- 36491 else if (op == '*') {
- 36492 /* Emit x* as (x&|), where & means "self". */
- 36493 reginsert(BRANCH, ret); /* Either x */
- 36494 regoptail(ret, regnode(BACK)); /* and loop */
- 36495 regoptail(ret, ret); /* back */
- 36496 regtail(ret, regnode(BRANCH)); /* or */
- 36497 regtail(ret, regnode(NOTHING)); /* null. */
- 36498 } else if (op == '+' && (flags & SIMPLE))
- 36499 reginsert(PLUS, ret);
- 36500 else if (op == '+') {
- 36501 /* Emit x+ as x(&|), where & means "self". */
- 36502 next = regnode(BRANCH); /* Either */
- 36503 regtail(ret, next);
- 36504 regtail(regnode(BACK), ret); /* loop back */
- 36505 regtail(next, regnode(BRANCH)); /* or */
- 36506 regtail(ret, regnode(NOTHING)); /* null. */
- 36507 } else if (op == '?') {
- 36508 /* Emit x? as (x|) */
- 36509 reginsert(BRANCH, ret); /* Either x */
- 36510 regtail(ret, regnode(BRANCH)); /* or */
- 36511 next = regnode(NOTHING);/* null. */
- 36512 regtail(ret, next);
- 36513 regoptail(ret, next);
- 36514 }
- 36515 regparse++;
- 36516 if (ISMULT(*regparse)) CFAIL("nested *?+");
- 36517
- 36518 return(ret);
- 36519 }
-
- 36521 /*
- 36522 - regatom - the lowest level
- 36523 *
- 36524 * Optimization: gobbles an entire sequence of ordinary characters so that
- 36525 * it can turn them into a single node, which is smaller to store and
- 36526 * faster to run. Backslashed characters are exceptions, each becoming a
- 36527 * separate node; the code is simpler that way and it's not worth fixing.
- 36528 */
- 36529 PRIVATE char *regatom(flagp)
- 36530 int *flagp;
- 36531 {
- 36532 register char *ret;
- 36533 int flags;
- 36534
- 36535 *flagp = WORST; /* Tentatively. */
- 36536
- 36537 switch (*regparse++) {
- 36538 case '^': ret = regnode(BOL); break;
- 36539 case '$': ret = regnode(EOL); break;
- 36540 case '.':
- 36541 ret = regnode(ANY);
- 36542 *flagp |= HASWIDTH | SIMPLE;
- 36543 break;
- 36544 case '[':{
- 36545 register int class;
- 36546 register int classend;
- 36547
- 36548 if (*regparse == '^') { /* Complement of range. */
- 36549 ret = regnode(ANYBUT);
- 36550 regparse++;
- 36551 } else
- 36552 ret = regnode(ANYOF);
- 36553 if (*regparse == ']' || *regparse == '-') regc(*regparse++);
- 36554 while (*regparse != ' ' && *regparse != ']') {
- 36555 if (*regparse == '-') {
- 36556 regparse++;
- 36557 if (*regparse == ']' || *regparse == ' ')
- 36558 regc('-');
- 36559 else {
- 36560 class = UCHARAT(regparse - 2) + 1;
- 36561 classend = UCHARAT(regparse);
- 36562 if (class > classend + 1)
- 36563 CFAIL("invalid [] range");
- 36564 for (; class <= classend; class++)
- 36565 regc(class);
- 36566 regparse++;
- 36567 }
- 36568 } else
- 36569 regc(*regparse++);
- 36570 }
- 36571 regc(' ');
- 36572 if (*regparse != ']') CFAIL("unmatched []");
- 36573 regparse++;
- 36574 *flagp |= HASWIDTH | SIMPLE;
- 36575 }
- 36576 break;
- 36577 case '(':
- 36578 ret = reg(1, &flags);
- 36579 if (ret == (char *)NULL) return((char *)NULL);
- 36580 *flagp |= flags & (HASWIDTH | SPSTART);
- 36581 break;
- 36582 case ' ':
- 36583 case '|':
- 36584 case ')':
- 36585 CFAIL("internal urp"); /* Supposed to be caught earlier. */
- 36586 break;
- 36587 case '?':
- 36588 case '+':
- 36589 case '*': CFAIL("?+* follows nothing"); break;
- 36590 case '\':
- 36591 if (*regparse == ' ') CFAIL("trailing \");
- 36592 ret = regnode(EXACTLY);
- 36593 regc(*regparse++);
- 36594 regc(' ');
- 36595 *flagp |= HASWIDTH | SIMPLE;
- 36596 break;
- 36597 default:{
- 36598 register int len;
- 36599 register char ender;
- 36600
- 36601 regparse--;
- 36602 len = strcspn(regparse, META);
- 36603 if (len <= 0) CFAIL("internal disaster");
- 36604 ender = *(regparse + len);
- 36605 if (len > 1 && ISMULT(ender))
- 36606 len--; /* Back off clear of ?+* operand. */
- 36607 *flagp |= HASWIDTH;
- 36608 if (len == 1) *flagp |= SIMPLE;
- 36609 ret = regnode(EXACTLY);
- 36610 while (len > 0) {
- 36611 regc(*regparse++);
- 36612 len--;
- 36613 }
- 36614 regc(' ');
- 36615 }
- 36616 break;
- 36617 }
- 36618
- 36619 return(ret);
- 36620 }
-
- 36622 /*
- 36623 - regnode - emit a node
- 36624 */
- 36625 PRIVATE char *regnode(op)
- 36626 char op;
- 36627 {
- 36628 register char *ret;
- 36629 register char *ptr;
- 36630
- 36631 ret = regcode;
- 36632 if (ret == ®dummy) {
- 36633 regsize += 3;
- 36634 return(ret);
- 36635 }
- 36636 ptr = ret;
- 36637 *ptr++ = op;
- 36638 *ptr++ = ' '; /* Null "next" pointer. */
- 36639 *ptr++ = ' ';
- 36640 regcode = ptr;
- 36641
- 36642 return(ret);
- 36643 }
-
- 36645 /*
- 36646 - regc - emit (if appropriate) a byte of code
- 36647 */
- 36648 PRIVATE void regc(b)
- 36649 char b;
- 36650 {
- 36651 if (regcode != ®dummy)
- 36652 *regcode++ = b;
- 36653 else
- 36654 regsize++;
- 36655 }
-
- 36657 /*
- 36658 - reginsert - insert an operator in front of already-emitted operand
- 36659 *
- 36660 * Means relocating the operand.
- 36661 */
- 36662 PRIVATE void reginsert(op, opnd)
- 36663 char op;
- 36664 char *opnd;
- 36665 {
- 36666 register char *src;
- 36667 register char *dst;
- 36668 register char *place;
- 36669
- 36670 if (regcode == ®dummy) {
- 36671 regsize += 3;
- 36672 return;
- 36673 }
- 36674 src = regcode;
- 36675 regcode += 3;
- 36676 dst = regcode;
- 36677 while (src > opnd) *--dst = *--src;
- 36678
- 36679 place = opnd; /* Op node, where operand used to be. */
- 36680 *place++ = op;
- 36681 *place++ = ' ';
- 36682 *place++ = ' ';
- 36683 }
-
- 36685 /*
- 36686 - regtail - set the next-pointer at the end of a node chain
- 36687 */
- 36688 PRIVATE void regtail(p, val)
- 36689 char *p;
- 36690 char *val;
- 36691 {
- 36692 register char *scan;
- 36693 register char *temp;
- 36694 register int offset;
- 36695
- 36696 if (p == ®dummy) return;
- 36697
- 36698 /* Find last node. */
- 36699 scan = p;
- 36700 for (;;) {
- 36701 temp = regnext(scan);
- 36702 if (temp == (char *)NULL) break;
- 36703 scan = temp;
- 36704 }
- 36705
- 36706 if (OP(scan) == BACK)
- 36707 offset = scan - val;
- 36708 else
- 36709 offset = val - scan;
- 36710 *(scan + 1) = (offset >> 8) & 0377;
- 36711 *(scan + 2) = offset & 0377;
- 36712 }
-
- 36714 /*
- 36715 - regoptail - regtail on operand of first argument; nop if operandless
- 36716 */
- 36717 PRIVATE void regoptail(p, val)
- 36718 char *p;
- 36719 char *val;
- 36720 {
- 36721 /* "Operandless" and "op != BRANCH" are synonymous in practice. */
- 36722 if (p == (char *)NULL || p == ®dummy || OP(p) != BRANCH) return;
- 36723 regtail(OPERAND(p), val);
- 36724 }
-
- 36726 /* regexec and friends
- 36727 */
- 36728
- 36729 /* Global work variables for regexec().
- 36730 */
- 36731 PRIVATE char *reginput; /* String-input pointer. */
- 36732 PRIVATE char *regbol; /* Beginning of input, for ^ check. */
- 36733 PRIVATE char **regstartp; /* Pointer to startp array. */
- 36734 PRIVATE char **regendp; /* Ditto for endp. */
- 36735
- 36736 /* Forwards.
- 36737 */
- 36738 STATIC _PROTOTYPE( int regtry, (regexp *prog, char *string) );
- 36739 STATIC _PROTOTYPE( int regmatch, (char *prog) );
- 36740 STATIC _PROTOTYPE( int regrepeat, (char *p) );
- 36741
- 36742 #ifdef DEBUG
- 36743 int regnarrate = 0;
- 36744 void regdump();
- 36745 STATIC _PROTOTYPE( char *regprop, (char *op) );
- 36746 #endif
- 36747
- 36748 /*
- 36749 - regexec - match a regexp against a string
- 36750 */
- 36751 int regexec(prog, string, bolflag)
- 36752 register regexp *prog;
- 36753 register char *string;
- 36754 int bolflag;
- 36755 {
- 36756 register char *s;
- 36757
- 36758 /* Be paranoid... */
- 36759 if (prog == (regexp *)NULL || string == (char *)NULL) {
- 36760 regerror("NULL parameter");
- 36761 return(0);
- 36762 }
- 36763
- 36764 /* Check validity of program. */
- 36765 if (UCHARAT(prog->program) != MAGIC) {
- 36766 regerror("corrupted program");
- 36767 return(0);
- 36768 }
- 36769
- 36770 /* If there is a "must appear" string, look for it. */
- 36771 if (prog->regmust != (char *)NULL) {
- 36772 s = string;
- 36773 while ((s = strchr(s, prog->regmust[0])) != (char *)NULL) {
- 36774 if (strncmp(s, prog->regmust, prog->regmlen) == 0)
- 36775 break; /* Found it. */
- 36776 s++;
- 36777 }
- 36778 if (s == (char *)NULL) /* Not present. */
- 36779 return(0);
- 36780 }
- 36781
- 36782 /* Mark beginning of line for ^ . */
- 36783 if (bolflag)
- 36784 regbol = string;
- 36785 else
- 36786 regbol = (char *)NULL;
- 36787
- 36788 /* Simplest case: anchored match need be tried only once. */
- 36789 if (prog->reganch) return(regtry(prog, string));
- 36790
- 36791 /* Messy cases: unanchored match. */
- 36792 s = string;
- 36793 if (prog->regstart != ' ') /* We know what char it must start with. */
- 36794 while ((s = strchr(s, prog->regstart)) != (char *)NULL) {
- 36795 if (regtry(prog, s)) return(1);
- 36796 s++;
- 36797 }
- 36798 else
- 36799 /* We don't -- general case. */
- 36800 do {
- 36801 if (regtry(prog, s)) return(1);
- 36802 } while (*s++ != ' ');
- 36803
- 36804 /* Failure. */
- 36805 return(0);
- 36806 }
-
- 36808 /*
- 36809 - regtry - try match at specific point
- 36810 */
- 36811 PRIVATE int regtry(prog, string) /* 0 failure, 1 success */
- 36812 regexp *prog;
- 36813 char *string;
- 36814 {
- 36815 register int i;
- 36816 register char **sp;
- 36817 register char **ep;
- 36818
- 36819 reginput = string;
- 36820 regstartp = prog->startp;
- 36821 regendp = prog->endp;
- 36822
- 36823 sp = prog->startp;
- 36824 ep = prog->endp;
- 36825 for (i = NSUBEXP; i > 0; i--) {
- 36826 *sp++ = (char *)NULL;
- 36827 *ep++ = (char *)NULL;
- 36828 }
- 36829 if (regmatch(prog->program + 1)) {
- 36830 prog->startp[0] = string;
- 36831 prog->endp[0] = reginput;
- 36832 return(1);
- 36833 } else
- 36834 return(0);
- 36835 }
-
- 36837 /*
- 36838 - regmatch - main matching routine
- 36839 *
- 36840 * Conceptually the strategy is simple: check to see whether the current
- 36841 * node matches, call self recursively to see whether the rest matches,
- 36842 * and then act accordingly. In practice we make some effort to avoid
- 36843 * recursion, in particular by going through "ordinary" nodes (that don't
- 36844 * need to know whether the rest of the match failed) by a loop instead of
- 36845 * by recursion.
- 36846 */
- 36847 PRIVATE int regmatch(prog) /* 0 failure, 1 success */
- 36848 char *prog;
- 36849 {
- 36850 register char *scan; /* Current node. */
- 36851 char *next; /* Next node. */
- 36852
- 36853 scan = prog;
- 36854 #ifdef DEBUG
- 36855 if (scan != (char *)NULL && regnarrate) fprintf(stderr, "%s(n", regprop(scan));
- 36856 #endif
- 36857 while (scan != (char *)NULL) {
- 36858 #ifdef DEBUG
- 36859 if (regnarrate) fprintf(stderr, "%s...n", regprop(scan));
- 36860 #endif
- 36861 next = regnext(scan);
- 36862
- 36863 switch (OP(scan)) {
- 36864 case BOL:
- 36865 if (reginput != regbol) return(0);
- 36866 break;
- 36867 case EOL:
- 36868 if (*reginput != ' ') return(0);
- 36869 break;
- 36870 case ANY:
- 36871 if (*reginput == ' ') return(0);
- 36872 reginput++;
- 36873 break;
- 36874 case EXACTLY:{
- 36875 register int len;
- 36876 register char *opnd;
- 36877
- 36878 opnd = OPERAND(scan);
- 36879 /* Inline the first character, for speed. */
- 36880 if (*opnd != *reginput) return(0);
- 36881 len = strlen(opnd);
- 36882 if (len > 1 && strncmp(opnd, reginput, len) != 0)
- 36883 return(0);
- 36884 reginput += len;
- 36885 }
- 36886 break;
- 36887 case ANYOF:
- 36888 if (*reginput == ' ' || strchr(OPERAND(scan), *reginput) == (char *)NULL)
- 36889 return(0);
- 36890 reginput++;
- 36891 break;
- 36892 case ANYBUT:
- 36893 if (*reginput == ' ' || strchr(OPERAND(scan), *reginput) != (char *)NULL)
- 36894 return(0);
- 36895 reginput++;
- 36896 break;
- 36897 case NOTHING:
- 36898 break;
- 36899 case BACK:
- 36900 break;
- 36901 case OPEN + 1:
- 36902 case OPEN + 2:
- 36903 case OPEN + 3:
- 36904 case OPEN + 4:
- 36905 case OPEN + 5:
- 36906 case OPEN + 6:
- 36907 case OPEN + 7:
- 36908 case OPEN + 8:
- 36909 case OPEN + 9:{
- 36910 register int no;
- 36911 register char *save;
- 36912
- 36913 no = OP(scan) - OPEN;
- 36914 save = reginput;
- 36915
- 36916 if (regmatch(next)) {
- 36917 /* Don't set startp if some later
- 36918 * invocation of the same parentheses
- 36919 * already has. */
- 36920 if (regstartp[no] == (char *)NULL)
- 36921 regstartp[no] = save;
- 36922 return(1);
- 36923 } else
- 36924 return(0);
- 36925 }
- 36926 break;
- 36927 case CLOSE + 1:
- 36928 case CLOSE + 2:
- 36929 case CLOSE + 3:
- 36930 case CLOSE + 4:
- 36931 case CLOSE + 5:
- 36932 case CLOSE + 6:
- 36933 case CLOSE + 7:
- 36934 case CLOSE + 8:
- 36935 case CLOSE + 9:{
- 36936 register int no;
- 36937 register char *save;
- 36938
- 36939 no = OP(scan) - CLOSE;
- 36940 save = reginput;
- 36941
- 36942 if (regmatch(next)) {
- 36943 /* Don't set endp if some later
- 36944 * invocation of the same parentheses
- 36945 * already has. */
- 36946 if (regendp[no] == (char *)NULL) regendp[no] = save;
- 36947 return(1);
- 36948 } else
- 36949 return(0);
- 36950 }
- 36951 break;
- 36952 case BRANCH:{
- 36953 register char *save;
- 36954
- 36955 if (OP(next) != BRANCH) /* No choice. */
- 36956 next = OPERAND(scan); /* Avoid recursion. */
- 36957 else {
- 36958 do {
- 36959 save = reginput;
- 36960 if (regmatch(OPERAND(scan)))
- 36961 return(1);
- 36962 reginput = save;
- 36963 scan = regnext(scan);
- 36964 } while (scan != (char *)NULL && OP(scan) == BRANCH);
- 36965 return(0);
- 36966 /* NOTREACHED */
- 36967 }
- 36968 }
- 36969 break;
- 36970 case STAR:
- 36971 case PLUS:{
- 36972 register char nextch;
- 36973 register int no;
- 36974 register char *save;
- 36975 register int min;
- 36976
- 36977 /* Lookahead to avoid useless match attempts
- 36978 * when we know what character comes next. */
- 36979 nextch = ' ';
- 36980 if (OP(next) == EXACTLY) nextch = *OPERAND(next);
- 36981 min = (OP(scan) == STAR) ? 0 : 1;
- 36982 save = reginput;
- 36983 no = regrepeat(OPERAND(scan));
- 36984 while (no >= min) {
- 36985 /* If it could work, try it. */
- 36986 if (nextch == ' ' || *reginput == nextch)
- 36987 if (regmatch(next)) return(1);
- 36988 /* Couldn't or didn't -- back up. */
- 36989 no--;
- 36990 reginput = save + no;
- 36991 }
- 36992 return(0);
- 36993 }
- 36994 break;
- 36995 case END:
- 36996 return(1); /* Success! */
- 36997 break;
- 36998 default:
- 36999 regerror("memory corruption");
- 37000 return(0);
- 37001 break;
- 37002 }
- 37003
- 37004 scan = next;
- 37005 }
- 37006
- 37007 /* We get here only if there's trouble -- normally "case END" is the
- 37008 * terminating point. */
- 37009 regerror("corrupted pointers");
- 37010 return(0);
- 37011 }
-
- 37013 /*
- 37014 - regrepeat - repeatedly match something simple, report how many
- 37015 */
- 37016 PRIVATE int regrepeat(p)
- 37017 char *p;
- 37018 {
- 37019 register int count = 0;
- 37020 register char *scan;
- 37021 register char *opnd;
- 37022
- 37023 scan = reginput;
- 37024 opnd = OPERAND(p);
- 37025 switch (OP(p)) {
- 37026 case ANY:
- 37027 count = strlen(scan);
- 37028 scan += count;
- 37029 break;
- 37030 case EXACTLY:
- 37031 while (*opnd == *scan) {
- 37032 count++;
- 37033 scan++;
- 37034 }
- 37035 break;
- 37036 case ANYOF:
- 37037 while (*scan != ' ' && strchr(opnd, *scan) != (char *)NULL) {
- 37038 count++;
- 37039 scan++;
- 37040 }
- 37041 break;
- 37042 case ANYBUT:
- 37043 while (*scan != ' ' && strchr(opnd, *scan) == (char *)NULL) {
- 37044 count++;
- 37045 scan++;
- 37046 }
- 37047 break;
- 37048 default: /* Oh dear. Called inappropriately. */
- 37049 regerror("internal foulup");
- 37050 count = 0; /* Best compromise. */
- 37051 break;
- 37052 }
- 37053 reginput = scan;
- 37054
- 37055 return(count);
- 37056 }
-
- 37058 /*
- 37059 - regnext - dig the "next" pointer out of a node
- 37060 */
- 37061 PRIVATE char *regnext(p)
- 37062 register char *p;
- 37063 {
- 37064 register int offset;
- 37065
- 37066 if (p == ®dummy) return((char *)NULL);
- 37067
- 37068 offset = NEXT(p);
- 37069 if (offset == 0) return((char *)NULL);
- 37070
- 37071 if (OP(p) == BACK)
- 37072 return(p - offset);
- 37073 else
- 37074 return(p + offset);
- 37075 }
-
- 37077 #ifdef DEBUG
- 37078
- 37079 STATIC char *regprop();
- 37080
- 37081 /*
- 37082 - regdump - dump a regexp onto stdout in vaguely comprehensible form
- 37083 */
- 37084 void regdump(r)
- 37085 regexp *r;
- 37086 {
- 37087 register char *s;
- 37088 register char op = EXACTLY; /* Arbitrary non-END op. */
- 37089 register char *next;
- 37090
- 37091 s = r->program + 1;
- 37092 while (op != END) { /* While that wasn't END last time... */
- 37093 op = OP(s);
- 37094 printf("%2d%s", (int) (s - r->program), regprop(s)); /* Where, what. */
- 37095 next = regnext(s);
- 37096 if (next == (char *)NULL) /* Next ptr. */
- 37097 printf("(0)");
- 37098 else
- 37099 printf("(%d)", (int) (s - r->program) + (int) (next - s));
- 37100 s += 3;
- 37101 if (op == ANYOF || op == ANYBUT || op == EXACTLY) {
- 37102 /* Literal string, where present. */
- 37103 while (*s != ' ') {
- 37104 putchar(*s);
- 37105 s++;
- 37106 }
- 37107 s++;
- 37108 }
- 37109 putchar('n');
- 37110 }
- 37111
- 37112 /* Header fields of interest. */
- 37113 if (r->regstart != ' ') printf("start `%c' ", r->regstart);
- 37114 if (r->reganch) printf("anchored ");
- 37115 if (r->regmust != (char *)NULL) printf("must have "%s"", r->regmust);
- 37116 printf("n");
- 37117 }
-
- 37119 /*
- 37120 - regprop - printable representation of opcode
- 37121 */
- 37122 PRIVATE char *regprop(op)
- 37123 char *op;
- 37124 {
- 37125 register char *p;
- 37126 PRIVATE char buf[50];
- 37127
- 37128 (void) strcpy(buf, ":");
- 37129
- 37130 switch (OP(op)) {
- 37131 case BOL: p = "BOL"; break;
- 37132 case EOL: p = "EOL"; break;
- 37133 case ANY: p = "ANY"; break;
- 37134 case ANYOF: p = "ANYOF"; break;
- 37135 case ANYBUT: p = "ANYBUT"; break;
- 37136 case BRANCH: p = "BRANCH"; break;
- 37137 case EXACTLY: p = "EXACTLY"; break;
- 37138 case NOTHING: p = "NOTHING"; break;
- 37139 case BACK: p = "BACK"; break;
- 37140 case END: p = "END"; break;
- 37141 case OPEN + 1:
- 37142 case OPEN + 2:
- 37143 case OPEN + 3:
- 37144 case OPEN + 4:
- 37145 case OPEN + 5:
- 37146 case OPEN + 6:
- 37147 case OPEN + 7:
- 37148 case OPEN + 8:
- 37149 case OPEN + 9:
- 37150 sprintf(buf + strlen(buf), "OPEN%d", OP(op) - OPEN);
- 37151 p = (char *)NULL;
- 37152 break;
- 37153 case CLOSE + 1:
- 37154 case CLOSE + 2:
- 37155 case CLOSE + 3:
- 37156 case CLOSE + 4:
- 37157 case CLOSE + 5:
- 37158 case CLOSE + 6:
- 37159 case CLOSE + 7:
- 37160 case CLOSE + 8:
- 37161 case CLOSE + 9:
- 37162 sprintf(buf + strlen(buf), "CLOSE%d", OP(op) - CLOSE);
- 37163 p = (char *)NULL;
- 37164 break;
- 37165 case STAR: p = "STAR"; break;
- 37166 case PLUS: p = "PLUS"; break;
- 37167 default: regerror("corrupted opcode"); p = (char *) NULL; break;
- 37168 }
- 37169 if (p != (char *)NULL) (void) strcat(buf, p);
- 37170 return(buf);
- 37171 }
-