LIB.TXT
上传用户:jnzhq888
上传日期:2007-01-18
资源大小:51694k
文件大小:1006k
源码类别:

操作系统开发

开发平台:

WINDOWS

  1. 32101  *
  2. 32102  *  Author: Terrence Holm          Aug. 1988
  3. 32103  *
  4. 32104  *
  5. 32105  *  Ctermid(3) returns a pointer to a string naming the controlling
  6. 32106  *  terminal. If <name_space> is NULL then local PRIVATE storage
  7. 32107  *  is used, otherwise <name_space> must point to storage of at
  8. 32108  *  least L_ctermid characters.
  9. 32109  *
  10. 32110  *  Returns a pointer to "/dev/tty".
  11. 32111  */
  12. 32112
  13. 32113 #include <lib.h>
  14. 32114 #include <string.h>
  15. 32115 #include <stdio.h>
  16. 32116
  17. 32117 _PROTOTYPE( char *ctermid, (char *name_space));
  18. 32118
  19. 32119 #ifndef L_ctermid
  20. 32120 #define L_ctermid  9
  21. 32121 #endif
  22. 32122
  23. 32123 char *ctermid(name_space)
  24. 32124 char *name_space;
  25. 32125 {
  26. 32126   PRIVATE char termid[L_ctermid];
  27. 32127
  28. 32128   if (name_space == (char *)NULL) name_space = termid;
  29. 32129   strcpy(name_space, "/dev/tty");
  30. 32130   return(name_space);
  31. 32131 }
  32. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  33. src/lib/other/cuserid.c    
  34. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  35. 32200 /*  cuserid(3)
  36. 32201  *
  37. 32202  *  Author: Terrence W. Holm          Sept. 1987
  38. 32203  */
  39. 32204
  40. 32205 #include <lib.h>
  41. 32206 #include <pwd.h>
  42. 32207 #include <string.h>
  43. 32208 #include <unistd.h>
  44. 32209 #include <stdio.h>
  45. 32210
  46. 32211 #ifndef  L_cuserid
  47. 32212 #define  L_cuserid   9
  48. 32213 #endif
  49. 32214
  50. 32215 char *cuserid(user_name)
  51. 32216 char *user_name;
  52. 32217 {
  53. 32218   PRIVATE char userid[L_cuserid];
  54. 32219   struct passwd *pw_entry;
  55. 32220
  56. 32221   if (user_name == (char *)NULL) user_name = userid;
  57. 32222
  58. 32223   pw_entry = getpwuid(geteuid());
  59. 32224
  60. 32225   if (pw_entry == (struct passwd *)NULL) {
  61. 32226         *user_name = '';
  62. 32227         return((char *)NULL);
  63. 32228   }
  64. 32229   strcpy(user_name, pw_entry->pw_name);
  65. 32230
  66. 32231   return(user_name);
  67. 32232 }
  68. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  69. src/lib/other/environ.c    
  70. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  71. 32300 /*
  72. 32301  * environ.c - define the variable environ
  73. 32302  */
  74. 32303 /* $Header: environ.c,v 1.1 90/09/27 13:39:50 eck Exp $ */
  75. 32304 /*
  76. 32305  * This file defines the variable environ and initializes it with a magic
  77. 32306  * value.  The C run-time start-off routine tests whether the variable
  78. 32307  * environ is initialized with this value.  If it is not, it is assumed
  79. 32308  * that it is defined by the user.  Only two bytes are tested, since we
  80. 32309  * don't know the endian-ness and alignment restrictions of the machine.
  81. 32310  * This means that the low-order two-bytes should be equal to the
  82. 32311  * high-order two-bytes on machines with four-byte pointers.  In fact, all
  83. 32312  * the bytes in the pointer are the same, just in case.
  84. 32313  */
  85. 32314
  86. 32315 #if _EM_PSIZE==2
  87. 32316 char **environ = (char **) 0x5353;
  88. 32317 #else
  89. 32318 char **environ = (char **) 0x53535353;
  90. 32319 #endif
  91. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  92. src/lib/other/errno.c    
  93. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  94. 32400 #include <lib.h>
  95. 32401 /* errno.c - declare variable errno             Author: F. Meulenbroeks */
  96. 32402
  97. 32403 int errno = 0;
  98. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  99. src/lib/other/execlp.c    
  100. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  101. 32500 /* execlp(3) and execvp(3)
  102. 32501  *
  103. 32502  * Author: Terrence W. Holm      July 1988
  104. 32503  */
  105. 32504
  106. 32505 /* FIXES - Dec 1989 - Jan 1990 Bruce Evans.
  107. 32506  *       - Don't use search path when file name contains a '/' *anywhere*.
  108. 32507  *       - Invoke sh(1) on command files.
  109. 32508  *       - Use PATH_MAX and check strings fit in buffer.
  110. 32509  *       - Use stdargs, with the unjustified assumption that va_start() turns
  111. 32510  *         the arg list into a char *[].  Strictly, the arg list should be
  112. 32511  *         copied, "wasting" up to ARG_MAX bytes.
  113. 32512  */
  114. 32513
  115. 32514 /*  Execlp(3) and execvp(3) are like execl(3) and execv(3),
  116. 32515  *  except that they use the environment variable $PATH as
  117. 32516  *  a search list of possible locations for the executable
  118. 32517  *  file, if <file> does not contain a '/', and they attempt
  119. 32518  *  to run non-binary executable files using sh(1).
  120. 32519  *
  121. 32520  *  The path search list is a list of directory names separated
  122. 32521  *  by ':'s. If a colon appears at the beginning or end of the
  123. 32522  *  list, or two appear together, then an empty prefix is tried.
  124. 32523  *  If $PATH is not in the environment, it defaults to "".
  125. 32524  *
  126. 32525  *  For example, if <file> is "ls", and the $PATH is
  127. 32526  *  ":/usr/local/bin:/bin:/usr/bin", then  ./ls,
  128. 32527  *  /usr/local/bin/ls, /bin/ls and /usr/bin/ls are tried until
  129. 32528  *  an exectable one is found. If the direct attempt to exec it
  130. 32529  *  fails, the arg list is modified to begin with "sh" and the
  131. 32530  *  absolute name of <file>, and an exec of /bin/sh is tried.
  132. 32531  *  If this fails, no further attempts are made.
  133. 32532  *
  134. 32533  *  This function only returns after an error.  It returns -1
  135. 32534  *  and sets errno like execv().
  136. 32535  */
  137. 32536
  138. 32537 #include <sys/types.h>
  139. 32538 #include <lib.h>
  140. 32539 #include <errno.h>
  141. 32540 #include <limits.h>
  142. 32541 #include <stdlib.h>
  143. 32542 #include <string.h>
  144. 32543 #include <unistd.h>
  145. 32544 #include <stdarg.h>
  146. 32545
  147. 32546 #undef NULL
  148. 32547 #define NULL 0                  /* kludge for ACK not understanding void * */
  149. 32548
  150. 32549 #define MAX_NUM_ARGS 512        /* maximum number of arguments to execvp */
  151. 32550
  152. 32551 extern char **environ;          /* environment pointer */
  153. 32552
  154. 32553 #ifdef _ANSI
  155. 32554 int execlp(const char *file, const char *arg, ...)
  156. 32555 #else
  157. 32556 int execlp(file)
  158. 32557 char *file;
  159. 32558 #endif
  160. 32559 {
  161. 32560   register va_list argp;
  162. 32561   register int result;
  163. 32562
  164. 32563   va_start(argp, file);
  165. 32564   result = execvp(file, (char **) argp);
  166. 32565   va_end(argp);
  167. 32566   return(result);
  168. 32567 }
  169. 32569 #ifdef _ANSI
  170. 32570 int execvp(const char *file, char *const argv[])
  171. 32571 #else
  172. 32572 int execvp(file, argv)
  173. 32573 char *file;
  174. 32574 char **argv;
  175. 32575 #endif
  176. 32576 {
  177. 32577   int i, best_errno;
  178. 32578   char **envtop;
  179. 32579   size_t flength;
  180. 32580   char *searchpath;
  181. 32581   size_t slength;
  182. 32582   char *split;
  183. 32583   char execpath[PATH_MAX + 1];
  184. 32584   char *arg2[MAX_NUM_ARGS + 3]; /* place to copy argv */
  185. 32585
  186. 32586   /* POSIX requires argv to be immutable.  Unfortunately, we have to change it
  187. 32587    * during execution.  To keep POSIX happy, a copy is made and the copy 
  188. 32588    * changed.  The question arises: how big should the copy be?  Allocating
  189. 32589    * space dynamically requires using malloc, which itself takes up a lot
  190. 32590    * of space.  The solution chosen here is to limit the number of arguments
  191. 32591    * to MAX_NUM_ARGS and set this value fairly high.  This solution is simpler
  192. 32592    * and is probably adequate.  Only programs with huge numbers of very short
  193. 32593    * arguments will get an error (if the arguments are large, ARG_MAX will
  194. 32594    * be exceeded.
  195. 32595    */
  196. 32596
  197. 32597   if (strchr(file, '/') != NULL || (searchpath = getenv("PATH")) == NULL)
  198. 32598         searchpath = "";
  199. 32599   flength = strlen(file);
  200. 32600   best_errno = ENOENT;
  201. 32601
  202. 32602   while (1) {
  203. 32603         split = strchr(searchpath, ':');
  204. 32604         if (split == NULL)
  205. 32605                 slength = strlen(searchpath);
  206. 32606         else
  207. 32607                 slength = split - searchpath;
  208. 32608         if (slength + flength >= sizeof execpath - 2) {
  209. 32609                 errno = ENAMETOOLONG;   /* too bad if premature */
  210. 32610                 return(-1);
  211. 32611         }
  212. 32612         strncpy(execpath, searchpath, slength);
  213. 32613         if (slength != 0) execpath[slength++] = '/';
  214. 32614         strcpy(execpath + slength, file);
  215. 32615
  216. 32616         /* Don't try to avoid execv() for non-existent files, since the Minix
  217. 32617          * shell doesn't, and it is not clear whether access() or stat() work
  218. 32618          * right when this code is set-uid.
  219. 32619          */
  220. 32620         execv(execpath, argv);
  221. 32621         switch (errno) {
  222. 32622             case EACCES:
  223. 32623                 best_errno = errno;     /* more useful than ENOENT */
  224. 32624             case ENOENT:
  225. 32625                 if (split == NULL) {
  226. 32626                         /* No more path components. */
  227. 32627                         errno = best_errno;
  228. 32628                         return(-1);
  229. 32629                 }
  230. 32630                 searchpath = split + 1; /* try next in path */
  231. 32631                 break;
  232. 32632             case ENOEXEC:
  233. 32633                 /* Assume a command file and invoke sh(1) on it.  Replace arg0
  234. 32634                  * (which is usually a short name for the command) by the full
  235. 32635                  * name of the command file.
  236. 32636                  */
  237. 32637
  238. 32638                 /* Copy the arg pointers from argv to arg2,  moving them up by
  239. 32639                  * 1, overlaying the assumed NULL at the end, to make room 
  240. 32640                  * for "sh" at the beginning.
  241. 32641                  */
  242. 32642                 i = 0;
  243. 32643                 if (argv != NULL)
  244. 32644                 {
  245. 32645                         while (argv[i] != 0) {
  246. 32646                                 if (i >= MAX_NUM_ARGS) {
  247. 32647                                         /* Copy failed.  Not enough room. */
  248. 32648                                         errno = ENOEXEC;
  249. 32649                                         return(-1);
  250. 32650                                 }
  251. 32651                                 arg2[i + 1] = argv[i];
  252. 32652                                 i++;
  253. 32653                         }
  254. 32654                 }
  255. 32655                 arg2[0] = "sh";         /* exec the shell */
  256. 32656                 arg2[1] = execpath;     /* full path */
  257. 32657                 arg2[i + 1] = NULL;     /* terminator */
  258. 32658
  259. 32659                 /* Count the environment pointers. */
  260. 32660                 for (envtop = environ; *envtop != NULL; ) envtop++;
  261. 32661
  262. 32662                 /* Try only /bin/sh, like the Minix shell.  Lose if the user
  263. 32663                  * has a different shell or the command has #!another/shell.
  264. 32664                  */
  265. 32665                 __execve("/bin/sh", arg2, environ, i + 1, (int)(envtop - environ));
  266. 32666
  267. 32667                 /* Oops, no shell?   Give up. */
  268. 32668                 errno = ENOEXEC;
  269. 32669                 return(-1);
  270. 32670             default:
  271. 32671                 return(-1);     /* probably  ENOMEM or E2BIG */
  272. 32672         }
  273. 32673   }
  274. 32674 }
  275. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  276. src/lib/other/fdopen.c    
  277. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  278. 32700 /*
  279. 32701  * fdopen - convert a (UNIX) file descriptor into a FILE pointer
  280. 32702  */
  281. 32703 /* $Header: fdopen.c,v 1.4 91/02/22 16:32:05 ceriel Exp $ */
  282. 32704
  283. 32705 #include        <stdlib.h>
  284. 32706 #include        "../stdio/loc_incl.h"
  285. 32707 #include        <stdio.h>
  286. 32708
  287. 32709 FILE *
  288. 32710 fdopen(fd, mode)
  289. 32711 int fd;
  290. 32712 _CONST char *mode;
  291. 32713 {
  292. 32714         register int i;
  293. 32715         FILE *stream;
  294. 32716         int flags = 0;
  295. 32717
  296. 32718         if (fd < 0) return (FILE *)NULL;
  297. 32719         for (i = 0; __iotab[i] != 0 ; i++) 
  298. 32720                 if (i >= FOPEN_MAX-1)
  299. 32721                         return (FILE *)NULL;
  300. 32722
  301. 32723         switch(*mode++) {
  302. 32724         case 'r':
  303. 32725                 flags |= _IOREAD | _IOREADING;
  304. 32726                 break;
  305. 32727         case 'a':
  306. 32728                 flags |= _IOAPPEND;
  307. 32729         case 'w':
  308. 32730                 flags |= _IOWRITE | _IOWRITING;
  309. 32731                 break;
  310. 32732         default:
  311. 32733                 return (FILE *)NULL;
  312. 32734         }
  313. 32735         while(*mode) {
  314. 32736                 switch(*mode++) {
  315. 32737                 case 'b':
  316. 32738                         continue;
  317. 32739                 case '+':
  318. 32740                         flags |= _IOREAD | _IOWRITE;
  319. 32741                         continue;
  320. 32742                 /* The sequence may be followed by aditional characters */
  321. 32743                 default:
  322. 32744                         break;
  323. 32745                 }
  324. 32746                 break;
  325. 32747         }
  326. 32748
  327. 32749         if ((stream = (FILE *) malloc(sizeof(FILE))) == NULL) {
  328. 32750                 return (FILE *)NULL;
  329. 32751         }
  330. 32752
  331. 32753         if ((flags & _IOREAD) && (flags & _IOWRITE))
  332. 32754                 flags &= ~(_IOREADING | _IOWRITING);
  333. 32755
  334. 32756         stream->_count = 0;
  335. 32757         stream->_fd = fd;
  336. 32758         stream->_flags = flags;
  337. 32759         stream->_buf = NULL;
  338. 32760         __iotab[i] = stream;
  339. 32761         return stream;
  340. 32762 }
  341. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  342. src/lib/other/ffs.c    
  343. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  344. 32800 #include <lib.h>
  345. 32801 /*  ffs(3)
  346. 32802  *
  347. 32803  *  Author: Terrence W. Holm          Sep. 1988
  348. 32804  */
  349. 32805 _PROTOTYPE( int ffs, (int word));
  350. 32806
  351. 32807 int ffs(word)
  352. 32808 int word;
  353. 32809 {
  354. 32810   int i;
  355. 32811
  356. 32812   if (word == 0) return(0);
  357. 32813
  358. 32814   for (i = 1;; ++i, word >>= 1)
  359. 32815         if (word & 1) return(i);
  360. 32816 }
  361. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  362. src/lib/other/fslib.c    
  363. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  364. 32900 /* fslib.c - routines needed by fs and fs utilities */
  365. 32901
  366. 32902 #include <minix/config.h>       /* for unused stuff in <minix/type.h> :-( */
  367. 32903 #include <ansi.h>
  368. 32904 #include <sys/types.h>
  369. 32905 #include <minix/const.h>
  370. 32906 #include <minix/type.h>         /* for unshort :-( */
  371. 32907 #include "fs/const.h"           /* depends of -I flag in Makefile */
  372. 32908 #include "fs/type.h"            /* ditto */
  373. 32909 #include "fs/inode.h"           /* ditto */
  374. 32910 #include <minix/fslib.h>
  375. 32911
  376. 32912 /* The next routine is copied from fsck.c and mkfs.c...  (Re)define some
  377. 32913  * things for consistency.  Some things should be done better.  The shifts
  378. 32914  * should be replaced by multiplications and divisions by MAP_BITS_PER_BLOCK
  379. 32915  * since log2 of this is too painful to get right.
  380. 32916  */
  381. 32917 #define BITMAPSHIFT      13     /* = log2(MAP_BITS_PER_BLOCK) */
  382. 32918
  383. 32919 /* Convert from bit count to a block count. The usual expression
  384. 32920  *
  385. 32921  *      (nr_bits + (1 << BITMAPSHIFT) - 1) >> BITMAPSHIFT
  386. 32922  *
  387. 32923  * doesn't work because of overflow.
  388. 32924  *
  389. 32925  * Other overflow bugs, such as the expression for N_ILIST overflowing when
  390. 32926  * s_inodes is just over V*_INODES_PER_BLOCK less than the maximum+1, are not
  391. 32927  * fixed yet, because that number of inodes is silly.
  392. 32928  */
  393. 32929 /* The above comment doesn't all apply now bit_t is long.  Overflow is now
  394. 32930  * unlikely, but negative bit counts are now possible (though unlikely)
  395. 32931  * and give silly results.
  396. 32932  */ 
  397. 32933 PUBLIC int bitmapsize(nr_bits)
  398. 32934 bit_t nr_bits;
  399. 32935 {
  400. 32936   int nr_blocks;
  401. 32937
  402. 32938   nr_blocks = (int) (nr_bits >> BITMAPSHIFT);
  403. 32939   if (((bit_t) nr_blocks << BITMAPSHIFT) < nr_bits) ++nr_blocks;
  404. 32940   return(nr_blocks);
  405. 32941 }
  406. 32944 /*===========================================================================*
  407. 32945  *                              conv2                                        *
  408. 32946  *===========================================================================*/
  409. 32947 PUBLIC unsigned conv2(norm, w)
  410. 32948 int norm;                       /* TRUE if no swap, FALSE for byte swap */
  411. 32949 int w;                          /* promotion of 16-bit word to be swapped */
  412. 32950 {
  413. 32951 /* Possibly swap a 16-bit word between 8086 and 68000 byte order. */
  414. 32952
  415. 32953   if (norm) return( (unsigned) w & 0xFFFF);
  416. 32954   return( ((w&BYTE) << 8) | ( (w>>8) & BYTE));
  417. 32955 }
  418. 32958 /*===========================================================================*
  419. 32959  *                              conv4                                        *
  420. 32960  *===========================================================================*/
  421. 32961 PUBLIC long conv4(norm, x)
  422. 32962 int norm;                       /* TRUE if no swap, FALSE for byte swap */
  423. 32963 long x;                         /* 32-bit long to be byte swapped */
  424. 32964 {
  425. 32965 /* Possibly swap a 32-bit long between 8086 and 68000 byte order. */
  426. 32966
  427. 32967   unsigned lo, hi;
  428. 32968   long l;
  429. 32969   
  430. 32970   if (norm) return(x);                  /* byte order was already ok */
  431. 32971   lo = conv2(FALSE, (int) x & 0xFFFF);  /* low-order half, byte swapped */
  432. 32972   hi = conv2(FALSE, (int) (x>>16) & 0xFFFF);    /* high-order half, swapped */
  433. 32973   l = ( (long) lo <<16) | hi;
  434. 32974   return(l);
  435. 32975 }
  436. 32978 /*===========================================================================*
  437. 32979  *                              conv_inode                                   *
  438. 32980  *===========================================================================*/
  439. 32981 PUBLIC void conv_inode(rip, dip, dip2, rw_flag, magic)
  440. 32982 register struct inode *rip;     /* pointer to the in-core inode struct */
  441. 32983 register d1_inode *dip;         /* pointer to the V1 on-disk inode struct */
  442. 32984 register d2_inode *dip2;        /* pointer to the V2 on-disk inode struct */
  443. 32985 int rw_flag;                    /* READING or WRITING */
  444. 32986 int magic;                      /* magic number of file system */
  445. 32987 { 
  446. 32988 /* Copy the inode from the disk block to the in-core table or vice versa.
  447. 32989  * If the fourth parameter below is FALSE, the bytes are swapped.
  448. 32990  */
  449. 32991   switch (magic) {
  450. 32992         case SUPER_MAGIC:       old_icopy(rip, dip,  rw_flag, TRUE);    break;
  451. 32993         case SUPER_REV:         old_icopy(rip, dip,  rw_flag, FALSE);   break;
  452. 32994         case SUPER_V2:          new_icopy(rip, dip2, rw_flag, TRUE);    break;
  453. 32995         case SUPER_V2_REV:      new_icopy(rip, dip2, rw_flag, FALSE);   break;
  454. 32996   } 
  455. 32997 }
  456. 33000 /*===========================================================================*
  457. 33001  *                              old_icopy                                    *
  458. 33002  *===========================================================================*/
  459. 33003 PUBLIC void old_icopy(rip, dip, direction, norm)
  460. 33004 register struct inode *rip;     /* pointer to the in-core inode struct */
  461. 33005 register d1_inode *dip;         /* pointer to the d1_inode inode struct */
  462. 33006 int direction;                  /* READING (from disk) or WRITING (to disk) */
  463. 33007 int norm;                       /* TRUE = do not swap bytes; FALSE = swap */
  464. 33008
  465. 33009 {
  466. 33010 /* 4 different on-disk inode layouts are supported, one for each combination
  467. 33011  * of V1.x/V2.x * bytes-swapped/not-swapped.  When an inode is read or written
  468. 33012  * this routine handles the conversions so that the information in the inode
  469. 33013  * table is independent of the disk structure from which the inode came.
  470. 33014  * The old_icopy routine copies to and from V1 disks.
  471. 33015  */
  472. 33016
  473. 33017   int i;
  474. 33018
  475. 33019   if (direction == READING) {
  476. 33020         /* Copy V1.x inode to the in-core table, swapping bytes if need be. */
  477. 33021         rip->i_mode    = conv2(norm, dip->d1_mode);
  478. 33022         rip->i_uid     = conv2(norm,dip->d1_uid );
  479. 33023         rip->i_size    = conv4(norm,dip->d1_size);
  480. 33024         rip->i_mtime   = conv4(norm,dip->d1_mtime);
  481. 33025         rip->i_atime   = 0;
  482. 33026         rip->i_ctime   = 0;
  483. 33027         rip->i_nlinks  = (nlink_t) dip->d1_nlinks;      /* 1 char */
  484. 33028         rip->i_gid     = (gid_t) dip->d1_gid;           /* 1 char */
  485. 33029         rip->i_ndzones = V1_NR_DZONES;
  486. 33030         rip->i_nindirs = V1_INDIRECTS;
  487. 33031         for (i = 0; i < V1_NR_TZONES; i++)
  488. 33032                 rip->i_zone[i] = conv2(norm, (int) dip->d1_zone[i]);
  489. 33033   } else {
  490. 33034         /* Copying V1.x inode to disk from the in-core table. */
  491. 33035         dip->d1_mode   = conv2(norm,rip->i_mode);
  492. 33036         dip->d1_uid    = conv2(norm,rip->i_uid );
  493. 33037         dip->d1_size   = conv4(norm,rip->i_size);
  494. 33038         dip->d1_mtime  = conv4(norm,rip->i_mtime);
  495. 33039         dip->d1_nlinks = (nlink_t) rip->i_nlinks;       /* 1 char */
  496. 33040         dip->d1_gid    = (gid_t) rip->i_gid;            /* 1 char */
  497. 33041         for (i = 0; i < V1_NR_TZONES; i++)
  498. 33042                 dip->d1_zone[i] = conv2(norm, (int) rip->i_zone[i]);
  499. 33043   }
  500. 33044 }
  501. 33047 /*===========================================================================*
  502. 33048  *                              new_icopy                                    *
  503. 33049  *===========================================================================*/
  504. 33050 PUBLIC void new_icopy(rip, dip, direction, norm)
  505. 33051 register struct inode *rip;     /* pointer to the in-core inode struct */
  506. 33052 register d2_inode *dip; /* pointer to the d2_inode struct */
  507. 33053 int direction;                  /* READING (from disk) or WRITING (to disk) */
  508. 33054 int norm;                       /* TRUE = do not swap bytes; FALSE = swap */
  509. 33055
  510. 33056 {
  511. 33057 /* Same as old_icopy, but to/from V2 disk layout. */
  512. 33058
  513. 33059   int i;
  514. 33060
  515. 33061   if (direction == READING) {
  516. 33062         /* Copy V2.x inode to the in-core table, swapping bytes if need be. */
  517. 33063         rip->i_mode    = conv2(norm,dip->d2_mode);
  518. 33064         rip->i_uid     = conv2(norm,dip->d2_uid );
  519. 33065         rip->i_nlinks  = conv2(norm,(int) dip->d2_nlinks);
  520. 33066         rip->i_gid     = conv2(norm,(int) dip->d2_gid );
  521. 33067         rip->i_size    = conv4(norm,dip->d2_size);
  522. 33068         rip->i_atime   = conv4(norm,dip->d2_atime);
  523. 33069         rip->i_ctime   = conv4(norm,dip->d2_ctime);
  524. 33070         rip->i_mtime   = conv4(norm,dip->d2_mtime);
  525. 33071         rip->i_ndzones = V2_NR_DZONES;
  526. 33072         rip->i_nindirs = V2_INDIRECTS;
  527. 33073         for (i = 0; i < V2_NR_TZONES; i++)
  528. 33074                 rip->i_zone[i] = conv4(norm, (long) dip->d2_zone[i]);
  529. 33075   } else {
  530. 33076         /* Copying V2.x inode to disk from the in-core table. */
  531. 33077         dip->d2_mode   = conv2(norm,rip->i_mode);
  532. 33078         dip->d2_uid    = conv2(norm,rip->i_uid );
  533. 33079         dip->d2_nlinks = conv2(norm,rip->i_nlinks);
  534. 33080         dip->d2_gid    = conv2(norm,rip->i_gid );
  535. 33081         dip->d2_size   = conv4(norm,rip->i_size);
  536. 33082         dip->d2_atime  = conv4(norm,rip->i_atime);
  537. 33083         dip->d2_ctime  = conv4(norm,rip->i_ctime);
  538. 33084         dip->d2_mtime  = conv4(norm,rip->i_mtime);
  539. 33085         for (i = 0; i < V2_NR_TZONES; i++)
  540. 33086                 dip->d2_zone[i] = conv4(norm, (long) rip->i_zone[i]);
  541. 33087   }
  542. 33088 }
  543. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  544. src/lib/other/fsversion.c    
  545. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  546. 33100 /* This procedure examines a file system and figures out whether it is
  547. 33101  * version 1 or version 2.  It returns the result as an int.  If the
  548. 33102  * file system is neither, it returns -1.  A typical call is:
  549. 33103  *
  550. 33104  *      n = fsversion("/dev/hd1", "df");
  551. 33105  *
  552. 33106  * The first argument is the special file for the file system. 
  553. 33107  * The second is the program name, which is used in error messages.
  554. 33108  */
  555. 33109
  556. 33110 #include <sys/types.h>
  557. 33111 #include <minix/config.h>
  558. 33112 #include <minix/const.h>
  559. 33113 #include <minix/minlib.h>
  560. 33114 #include <minix/type.h>
  561. 33115 #include <fcntl.h>
  562. 33116 #include <unistd.h>
  563. 33117 #include <stdio.h>
  564. 33118
  565. 33119 #include "../../fs/const.h"
  566. 33120 #include "../../fs/type.h"
  567. 33121 #include "../../fs/super.h"
  568. 33122
  569. 33123 static struct super_block super, *sp;
  570. 33124
  571. 33125 int fsversion(dev, prog)
  572. 33126 char *dev, *prog;
  573. 33127 {
  574. 33128   int fd;
  575. 33129
  576. 33130   if ((fd = open(dev, O_RDONLY)) < 0) {
  577. 33131         std_err(prog);
  578. 33132         std_err(" cannot open ");
  579. 33133         perror(dev);
  580. 33134         return(-1);
  581. 33135   }
  582. 33136
  583. 33137   lseek(fd, (off_t) BLOCK_SIZE, SEEK_SET);      /* skip boot block */
  584. 33138   if (read(fd, (char *) &super, (unsigned) SUPER_SIZE) != SUPER_SIZE) {
  585. 33139         std_err(prog);
  586. 33140         std_err(" cannot read super block on ");
  587. 33141         perror(dev);
  588. 33142         close(fd);
  589. 33143         return(-1);
  590. 33144   }
  591. 33145   close(fd);
  592. 33146   sp = &super;
  593. 33147   if (sp->s_magic == SUPER_MAGIC) return(1);
  594. 33148   if (sp->s_magic == SUPER_V2) return(2);
  595. 33149   return(-1);
  596. 33150 }
  597. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  598. src/lib/other/getgrent.c    
  599. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  600. 33200 /*      getgrent(), getgrgid(), getgrnam() - group file routines
  601. 33201  *
  602. 33202  *                                                      Author: Kees J. Bot
  603. 33203  *                                                              31 Jan 1994
  604. 33204  */
  605. 33205 #define nil 0
  606. 33206 #define open _open
  607. 33207 #define fcntl _fcntl
  608. 33208 #define read _read
  609. 33209 #define close _close
  610. 33210 #include <sys/types.h>
  611. 33211 #include <grp.h>
  612. 33212 #include <string.h>
  613. 33213 #include <stdlib.h>
  614. 33214 #include <unistd.h>
  615. 33215 #include <fcntl.h>
  616. 33216
  617. 33217 #define arraysize(a)    (sizeof(a) / sizeof((a)[0]))
  618. 33218 #define arraylimit(a)   ((a) + arraysize(a))
  619. 33219
  620. 33220 static char GROUP[]= "/etc/group";      /* The group file. */
  621. 33221 static const char *grfile;              /* Current group file. */
  622. 33222
  623. 33223 static char buf[1024];                  /* Read buffer. */
  624. 33224 static char grline[512];                /* One line from the group file. */
  625. 33225 static struct group entry;              /* Entry to fill and return. */
  626. 33226 static char *members[64];               /* Group members with the entry. */
  627. 33227 static int grfd= -1;                    /* Filedescriptor to the file. */
  628. 33228 static char *bufptr;                    /* Place in buf. */
  629. 33229 static ssize_t buflen= 0;               /* Remaining characters in buf. */
  630. 33230 static char *lineptr;                   /* Place in the line. */
  631. 33231
  632. 33232 void endgrent(void)
  633. 33233 /* Close the group file. */
  634. 33234 {
  635. 33235         if (grfd >= 0) {
  636. 33236                 (void) close(grfd);
  637. 33237                 grfd= -1;
  638. 33238                 buflen= 0;
  639. 33239         }
  640. 33240 }
  641. 33242 int setgrent(void)
  642. 33243 /* Open the group file. */
  643. 33244 {
  644. 33245         if (grfd >= 0) endgrent();
  645. 33246
  646. 33247         if (grfile == nil) grfile= GROUP;
  647. 33248
  648. 33249         if ((grfd= open(grfile, O_RDONLY)) < 0) return -1;
  649. 33250         (void) fcntl(grfd, F_SETFD, fcntl(grfd, F_GETFD) | FD_CLOEXEC);
  650. 33251         return 0;
  651. 33252 }
  652. 33254 void setgrfile(const char *file)
  653. 33255 /* Prepare for reading an alternate group file. */
  654. 33256 {
  655. 33257         endgrent();
  656. 33258         grfile= file;
  657. 33259 }
  658. 33261 static int getline(void)
  659. 33262 /* Get one line from the group file, return 0 if bad or EOF. */
  660. 33263 {
  661. 33264         lineptr= grline;
  662. 33265
  663. 33266         do {
  664. 33267                 if (buflen == 0) {
  665. 33268                         if ((buflen= read(grfd, buf, sizeof(buf))) <= 0)
  666. 33269                                 return 0;
  667. 33270                         bufptr= buf;
  668. 33271                 }
  669. 33272
  670. 33273                 if (lineptr == arraylimit(grline)) return 0;
  671. 33274                 buflen--;
  672. 33275         } while ((*lineptr++ = *bufptr++) != 'n');
  673. 33276
  674. 33277         lineptr= grline;
  675. 33278         return 1;
  676. 33279 }
  677. 33281 static char *scan_punct(int punct)
  678. 33282 /* Scan for a field separator in a line, return the start of the field. */
  679. 33283 {
  680. 33284         char *field= lineptr;
  681. 33285         char *last;
  682. 33286
  683. 33287         for (;;) {
  684. 33288                 last= lineptr;
  685. 33289                 if (*lineptr == 0) return nil;
  686. 33290                 if (*lineptr == 'n') break;
  687. 33291                 if (*lineptr++ == punct) break;
  688. 33292                 if (lineptr[-1] == ':') return nil;     /* :::,,,:,,,? */
  689. 33293         }
  690. 33294         *last= 0;
  691. 33295         return field;
  692. 33296 }
  693. 33298 struct group *getgrent(void)
  694. 33299 /* Read one entry from the group file. */
  695. 33300 {
  696. 33301         char *p;
  697. 33302         char **mem;
  698. 33303
  699. 33304         /* Open the file if not yet open. */
  700. 33305         if (grfd < 0 && setgrent() < 0) return nil;
  701. 33306
  702. 33307         /* Until a good line is read. */
  703. 33308         for (;;) {
  704. 33309                 if (!getline()) return nil;     /* EOF or corrupt. */
  705. 33310
  706. 33311                 if ((entry.gr_name= scan_punct(':')) == nil) continue;
  707. 33312                 if ((entry.gr_passwd= scan_punct(':')) == nil) continue;
  708. 33313                 if ((p= scan_punct(':')) == nil) continue;
  709. 33314                 entry.gr_gid= strtol(p, nil, 0);
  710. 33315
  711. 33316                 entry.gr_mem= mem= members;
  712. 33317                 if (*lineptr != 'n') {
  713. 33318                         do {
  714. 33319                                 if ((*mem= scan_punct(',')) == nil) goto again;
  715. 33320                                 if (mem < arraylimit(members) - 1) mem++;
  716. 33321                         } while (*lineptr != 0);
  717. 33322                 }
  718. 33323                 *mem= nil;
  719. 33324                 return &entry;
  720. 33325         again:;
  721. 33326         }
  722. 33327 }
  723. 33329 struct group *getgrgid(Gid_t gid)
  724. 33330 /* Return the group file entry belonging to the user-id. */
  725. 33331 {
  726. 33332         struct group *gr;
  727. 33333
  728. 33334         endgrent();
  729. 33335         while ((gr= getgrent()) != nil && gr->gr_gid != gid) {}
  730. 33336         endgrent();
  731. 33337         return gr;
  732. 33338 }
  733. 33340 struct group *getgrnam(const char *name)
  734. 33341 /* Return the group file entry belonging to the user name. */
  735. 33342 {
  736. 33343         struct group *gr;
  737. 33344
  738. 33345         endgrent();
  739. 33346         while ((gr= getgrent()) != nil && strcmp(gr->gr_name, name) != 0) {}
  740. 33347         endgrent();
  741. 33348         return gr;
  742. 33349 }
  743. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  744. src/lib/other/getlogin.c    
  745. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  746. 33400 /*  getlogin(3)
  747. 33401  *
  748. 33402  *  Author: Terrence W. Holm          Aug. 1988
  749. 33403  */
  750. 33404
  751. 33405 #include <lib.h>
  752. 33406 #include <pwd.h>
  753. 33407 #include <unistd.h>
  754. 33408 #include <string.h>
  755. 33409 #include <stdio.h>
  756. 33410
  757. 33411 #ifndef  L_cuserid
  758. 33412 #define  L_cuserid   9
  759. 33413 #endif
  760. 33414
  761. 33415 char *getlogin()
  762. 33416 {
  763. 33417   PRIVATE char userid[L_cuserid];
  764. 33418   struct passwd *pw_entry;
  765. 33419
  766. 33420   pw_entry = getpwuid(getuid());
  767. 33421
  768. 33422   if (pw_entry == (struct passwd *)NULL) return((char *)NULL);
  769. 33423
  770. 33424   strcpy(userid, pw_entry->pw_name);
  771. 33425
  772. 33426   return(userid);
  773. 33427 }
  774. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  775. src/lib/other/getopt.c    
  776. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  777. 33500 /*
  778. 33501  * getopt - parse command-line options
  779. 33502  */
  780. 33503 /* $Header: getopt.c,v 1.1 89/12/18 14:39:31 eck Exp $ */
  781. 33504
  782. 33505 #include        <stdlib.h>
  783. 33506 #include        <string.h>
  784. 33507 #include        <stdio.h>
  785. 33508
  786. 33509 #define ERR(s, c)       if(opterr){
  787. 33510         fputs(argv[0], stderr);
  788. 33511         fputs(s, stderr);
  789. 33512         fputc(c, stderr);
  790. 33513         fputc('n', stderr);}
  791. 33514
  792. 33515 int     opterr = 1;
  793. 33516 int     optind = 1;
  794. 33517 int     optopt;
  795. 33518 char    *optarg;
  796. 33519
  797. 33520 int
  798. 33521 getopt(argc, argv, opts)
  799. 33522 int argc;
  800. 33523 char **argv;
  801. 33524 char *opts;
  802. 33525 {
  803. 33526         static int sp = 1;
  804. 33527         register c;
  805. 33528         register char *cp;
  806. 33529
  807. 33530         if (sp == 1)
  808. 33531                 if (optind >= argc ||
  809. 33532                    argv[optind][0] != '-' || argv[optind][1] == '')
  810. 33533                         return EOF;
  811. 33534                 else if (!strcmp(argv[optind], "--")) {
  812. 33535                         optind++;
  813. 33536                         return EOF;
  814. 33537                 }
  815. 33538         optopt = c = argv[optind][sp];
  816. 33539         if (c == ':' || (cp=strchr(opts, c)) == NULL) {
  817. 33540                 ERR (": illegal option -- ", c);
  818. 33541                 if (argv[optind][++sp] == '') {
  819. 33542                         optind++;
  820. 33543                         sp = 1;
  821. 33544                 }
  822. 33545                 return '?';
  823. 33546         }
  824. 33547         if (*++cp == ':') {
  825. 33548                 if (argv[optind][sp+1] != '')
  826. 33549                         optarg = &argv[optind++][sp+1];
  827. 33550                 else if (++optind >= argc) {
  828. 33551                         ERR (": option requires an argument -- ", c);
  829. 33552                         sp = 1;
  830. 33553                         return '?';
  831. 33554                 } else
  832. 33555                         optarg = argv[optind++];
  833. 33556                 sp = 1;
  834. 33557         } else {
  835. 33558                 if (argv[optind][++sp] == '') {
  836. 33559                         sp = 1;
  837. 33560                         optind++;
  838. 33561                 }
  839. 33562                 optarg = NULL;
  840. 33563         }
  841. 33564         return c;
  842. 33565 }
  843. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  844. src/lib/other/getpass.c    
  845. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  846. 33600 /*      getpass() - read a password             Author: Kees J. Bot
  847. 33601  *                                                      Feb 16 1993
  848. 33602  */
  849. 33603 #define open _open
  850. 33604 #define sigaction _sigaction
  851. 33605 #define sigemptyset _sigemptyset
  852. 33606 #define tcgetattr _tcgetattr
  853. 33607 #define tcsetattr _tcsetattr
  854. 33608 #define write _write
  855. 33609 #define read _read
  856. 33610 #define close _close
  857. 33611 #include <sys/types.h>
  858. 33612 #include <fcntl.h>
  859. 33613 #include <unistd.h>
  860. 33614 #include <signal.h>
  861. 33615 #include <termios.h>
  862. 33616 #include <string.h>
  863. 33617
  864. 33618 static int intr;
  865. 33619
  866. 33620 static void catch(int sig)
  867. 33621 {
  868. 33622         intr= 1;
  869. 33623 }
  870. 33625 char *getpass(const char *prompt)
  871. 33626 {
  872. 33627         struct sigaction osa, sa;
  873. 33628         struct termios cooked, raw;
  874. 33629         static char password[32+1];
  875. 33630         int fd, n= 0;
  876. 33631
  877. 33632         /* Try to open the controlling terminal. */
  878. 33633         if ((fd= open("/dev/tty", O_RDONLY)) < 0) return NULL;
  879. 33634
  880. 33635         /* Trap interrupts unless ignored. */
  881. 33636         intr= 0;
  882. 33637         sigaction(SIGINT, NULL, &osa);
  883. 33638         if (osa.sa_handler != SIG_IGN) {
  884. 33639                 sigemptyset(&sa.sa_mask);
  885. 33640                 sa.sa_flags= 0;
  886. 33641                 sa.sa_handler= catch;
  887. 33642                 sigaction(SIGINT, &sa, &osa);
  888. 33643         }
  889. 33644
  890. 33645         /* Set the terminal to non-echo mode. */
  891. 33646         tcgetattr(fd, &cooked);
  892. 33647         raw= cooked;
  893. 33648         raw.c_iflag|= ICRNL;
  894. 33649         raw.c_lflag&= ~ECHO;
  895. 33650         raw.c_lflag|= ECHONL;
  896. 33651         raw.c_oflag|= OPOST | ONLCR;
  897. 33652         tcsetattr(fd, TCSANOW, &raw);
  898. 33653
  899. 33654         /* Print the prompt.  (After setting non-echo!) */
  900. 33655         write(2, prompt, strlen(prompt));
  901. 33656
  902. 33657         /* Read the password, 32 characters max. */
  903. 33658         while (read(fd, password+n, 1) > 0) {
  904. 33659                 if (password[n] == 'n') break;
  905. 33660                 if (n < 32) n++;
  906. 33661         }
  907. 33662         password[n]= 0;
  908. 33663
  909. 33664         /* Terminal back to cooked mode. */
  910. 33665         tcsetattr(fd, TCSANOW, &cooked);
  911. 33666
  912. 33667         close(fd);
  913. 33668
  914. 33669         /* Interrupt? */
  915. 33670         sigaction(SIGINT, &osa, NULL);
  916. 33671         if (intr) raise(SIGINT);
  917. 33672
  918. 33673         return password;
  919. 33674 }
  920. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  921. src/lib/other/getpwent.c    
  922. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  923. 33700 /*      getpwent(), getpwuid(), getpwnam() - password file routines
  924. 33701  *
  925. 33702  *                                                      Author: Kees J. Bot
  926. 33703  *                                                              31 Jan 1994
  927. 33704  */
  928. 33705 #define nil 0
  929. 33706 #define open _open
  930. 33707 #define fcntl _fcntl
  931. 33708 #define read _read
  932. 33709 #define close _close
  933. 33710 #include <sys/types.h>
  934. 33711 #include <pwd.h>
  935. 33712 #include <string.h>
  936. 33713 #include <stdlib.h>
  937. 33714 #include <unistd.h>
  938. 33715 #include <fcntl.h>
  939. 33716
  940. 33717 #define arraysize(a)    (sizeof(a) / sizeof((a)[0]))
  941. 33718 #define arraylimit(a)   ((a) + arraysize(a))
  942. 33719
  943. 33720 static char PASSWD[]= "/etc/passwd";    /* The password file. */
  944. 33721 static const char *pwfile;              /* Current password file. */
  945. 33722
  946. 33723 static char buf[1024];                  /* Read buffer. */
  947. 33724 static char pwline[256];                /* One line from the password file. */
  948. 33725 static struct passwd entry;             /* Entry to fill and return. */
  949. 33726 static int pwfd= -1;                    /* Filedescriptor to the file. */
  950. 33727 static char *bufptr;                    /* Place in buf. */
  951. 33728 static ssize_t buflen= 0;               /* Remaining characters in buf. */
  952. 33729 static char *lineptr;                   /* Place in the line. */
  953. 33730
  954. 33731 void endpwent(void)
  955. 33732 /* Close the password file. */
  956. 33733 {
  957. 33734         if (pwfd >= 0) {
  958. 33735                 (void) close(pwfd);
  959. 33736                 pwfd= -1;
  960. 33737                 buflen= 0;
  961. 33738         }
  962. 33739 }
  963. 33741 int setpwent(void)
  964. 33742 /* Open the password file. */
  965. 33743 {
  966. 33744         if (pwfd >= 0) endpwent();
  967. 33745
  968. 33746         if (pwfile == nil) pwfile= PASSWD;
  969. 33747
  970. 33748         if ((pwfd= open(pwfile, O_RDONLY)) < 0) return -1;
  971. 33749         (void) fcntl(pwfd, F_SETFD, fcntl(pwfd, F_GETFD) | FD_CLOEXEC);
  972. 33750         return 0;
  973. 33751 }
  974. 33753 void setpwfile(const char *file)
  975. 33754 /* Prepare for reading an alternate password file. */
  976. 33755 {
  977. 33756         endpwent();
  978. 33757         pwfile= file;
  979. 33758 }
  980. 33760 static int getline(void)
  981. 33761 /* Get one line from the password file, return 0 if bad or EOF. */
  982. 33762 {
  983. 33763         lineptr= pwline;
  984. 33764
  985. 33765         do {
  986. 33766                 if (buflen == 0) {
  987. 33767                         if ((buflen= read(pwfd, buf, sizeof(buf))) <= 0)
  988. 33768                                 return 0;
  989. 33769                         bufptr= buf;
  990. 33770                 }
  991. 33771
  992. 33772                 if (lineptr == arraylimit(pwline)) return 0;
  993. 33773                 buflen--;
  994. 33774         } while ((*lineptr++ = *bufptr++) != 'n');
  995. 33775
  996. 33776         lineptr= pwline;
  997. 33777         return 1;
  998. 33778 }
  999. 33780 static char *scan_colon(void)
  1000. 33781 /* Scan for a field separator in a line, return the start of the field. */
  1001. 33782 {
  1002. 33783         char *field= lineptr;
  1003. 33784         char *last;
  1004. 33785
  1005. 33786         for (;;) {
  1006. 33787                 last= lineptr;
  1007. 33788                 if (*lineptr == 0) return nil;
  1008. 33789                 if (*lineptr == 'n') break;
  1009. 33790                 if (*lineptr++ == ':') break;
  1010. 33791         }
  1011. 33792         *last= 0;
  1012. 33793         return field;
  1013. 33794 }
  1014. 33796 struct passwd *getpwent(void)
  1015. 33797 /* Read one entry from the password file. */
  1016. 33798 {
  1017. 33799         char *p;
  1018. 33800
  1019. 33801         /* Open the file if not yet open. */
  1020. 33802         if (pwfd < 0 && setpwent() < 0) return nil;
  1021. 33803
  1022. 33804         /* Until a good line is read. */
  1023. 33805         for (;;) {
  1024. 33806                 if (!getline()) return nil;     /* EOF or corrupt. */
  1025. 33807
  1026. 33808                 if ((entry.pw_name= scan_colon()) == nil) continue;
  1027. 33809                 if ((entry.pw_passwd= scan_colon()) == nil) continue;
  1028. 33810                 if ((p= scan_colon()) == nil) continue;
  1029. 33811                 entry.pw_uid= strtol(p, nil, 0);
  1030. 33812                 if ((p= scan_colon()) == nil) continue;
  1031. 33813                 entry.pw_gid= strtol(p, nil, 0);
  1032. 33814                 if ((entry.pw_gecos= scan_colon()) == nil) continue;
  1033. 33815                 if ((entry.pw_dir= scan_colon()) == nil) continue;
  1034. 33816                 if ((entry.pw_shell= scan_colon()) == nil) continue;
  1035. 33817
  1036. 33818                 if (*lineptr == 0) return &entry;
  1037. 33819         }
  1038. 33820 }
  1039. 33822 struct passwd *getpwuid(Uid_t uid)
  1040. 33823 /* Return the password file entry belonging to the user-id. */
  1041. 33824 {
  1042. 33825         struct passwd *pw;
  1043. 33826
  1044. 33827         endpwent();
  1045. 33828         while ((pw= getpwent()) != nil && pw->pw_uid != uid) {}
  1046. 33829         endpwent();
  1047. 33830         return pw;
  1048. 33831 }
  1049. 33833 struct passwd *getpwnam(const char *name)
  1050. 33834 /* Return the password file entry belonging to the user name. */
  1051. 33835 {
  1052. 33836         struct passwd *pw;
  1053. 33837
  1054. 33838         endpwent();
  1055. 33839         while ((pw= getpwent()) != nil && strcmp(pw->pw_name, name) != 0) {}
  1056. 33840         endpwent();
  1057. 33841         return pw;
  1058. 33842 }
  1059. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1060. src/lib/other/getttyent.c    
  1061. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1062. 33900 /*      getttyent(3) - get a ttytab entry               Author: Kees J. Bot
  1063. 33901  *                                                              28 Oct 1995
  1064. 33902  */
  1065. 33903 #define nil 0
  1066. 33904 #define open _open
  1067. 33905 #define close _close
  1068. 33906 #define fcntl _fcntl
  1069. 33907 #define read _read
  1070. 33908 #include <string.h>
  1071. 33909 #include <sys/types.h>
  1072. 33910 #include <ttyent.h>
  1073. 33911 #include <unistd.h>
  1074. 33912 #include <fcntl.h>
  1075. 33913
  1076. 33914 #define arraysize(a)    (sizeof(a) / sizeof((a)[0]))
  1077. 33915 #define arraylimit(a)   ((a) + arraysize(a))
  1078. 33916
  1079. 33917 static char TTYTAB[]= "/etc/ttytab";    /* The table of terminal devices. */
  1080. 33918
  1081. 33919 static char buf[512];                   /* Read buffer. */
  1082. 33920 static char ttline[256];                /* One line from the ttytab file. */
  1083. 33921 static char *ttargv[32];                /* Compound arguments. */
  1084. 33922 static struct ttyent entry;             /* Entry to fill and return. */
  1085. 33923 static int ttfd= -1;                    /* Filedescriptor to the file. */
  1086. 33924 static char *bufptr;                    /* Place in buf. */
  1087. 33925 static ssize_t buflen= 0;               /* Remaining characters in buf. */
  1088. 33926 static char *lineptr;                   /* Place in the line. */
  1089. 33927 static char **argvptr;                  /* Place in word lists. */
  1090. 33928
  1091. 33929 void endttyent(void)
  1092. 33930 /* Close the ttytab file. */
  1093. 33931 {
  1094. 33932         if (ttfd >= 0) {
  1095. 33933                 (void) close(ttfd);
  1096. 33934                 ttfd= -1;
  1097. 33935                 buflen= 0;
  1098. 33936         }
  1099. 33937 }
  1100. 33939 int setttyent(void)
  1101. 33940 /* Open the ttytab file. */
  1102. 33941 {
  1103. 33942         if (ttfd >= 0) endttyent();
  1104. 33943
  1105. 33944         if ((ttfd= open(TTYTAB, O_RDONLY)) < 0) return -1;
  1106. 33945         (void) fcntl(ttfd, F_SETFD, fcntl(ttfd, F_GETFD) | FD_CLOEXEC);
  1107. 33946         return 0;
  1108. 33947 }
  1109. 33949 static int getline(void)
  1110. 33950 /* Get one line from the ttytab file, return 0 if bad or EOF. */
  1111. 33951 {
  1112. 33952         lineptr= ttline;
  1113. 33953         argvptr= ttargv;
  1114. 33954
  1115. 33955         do {
  1116. 33956                 if (buflen == 0) {
  1117. 33957                         if ((buflen= read(ttfd, buf, sizeof(buf))) <= 0)
  1118. 33958                                 return 0;
  1119. 33959                         bufptr= buf;
  1120. 33960                 }
  1121. 33961
  1122. 33962                 if (lineptr == arraylimit(ttline)) return 0;
  1123. 33963                 buflen--;
  1124. 33964         } while ((*lineptr++ = *bufptr++) != 'n');
  1125. 33965
  1126. 33966         lineptr= ttline;
  1127. 33967         return 1;
  1128. 33968 }
  1129. 33970 static int white(int c)
  1130. 33971 /* Whitespace? */
  1131. 33972 {
  1132. 33973         return c == ' ' || c == 't';
  1133. 33974 }
  1134. 33976 static char *scan_white(int quoted)
  1135. 33977 /* Scan for a field separator in a line, return the start of the field.
  1136. 33978  * "quoted" is set if we have to watch out for double quotes.
  1137. 33979  */
  1138. 33980 {
  1139. 33981         char *field, *last;
  1140. 33982
  1141. 33983         while (white(*lineptr)) lineptr++;
  1142. 33984         if (!quoted && *lineptr == '#') return nil;
  1143. 33985
  1144. 33986         field= lineptr;
  1145. 33987         for (;;) {
  1146. 33988                 last= lineptr;
  1147. 33989                 if (*lineptr == 0) return nil;
  1148. 33990                 if (*lineptr == 'n') break;
  1149. 33991                 if (quoted && *lineptr == '"') return field;
  1150. 33992                 if (white(*lineptr++)) break;
  1151. 33993         }
  1152. 33994         *last= 0;
  1153. 33995         return *field == 0 ? nil : field;
  1154. 33996 }
  1155. 33998 static char **scan_quoted(void)
  1156. 33999 /* Read a field that may be a quoted list of words. */
  1157. 34000 {
  1158. 34001         char *p, **field= argvptr;
  1159. 34002
  1160. 34003         while (white(*lineptr)) lineptr++;
  1161. 34004
  1162. 34005         if (*lineptr == '"') {
  1163. 34006                 /* Quoted list of words. */
  1164. 34007                 lineptr++;
  1165. 34008                 while ((p= scan_white(1)) != nil && *p != '"') {
  1166. 34009                         if (argvptr == arraylimit(ttargv)) return nil;
  1167. 34010                         *argvptr++= p;
  1168. 34011                 }
  1169. 34012                 if (*lineptr == '"') *lineptr++= 0;
  1170. 34013         } else {
  1171. 34014                 /* Just one word. */
  1172. 34015                 if ((p= scan_white(0)) == nil) return nil;
  1173. 34016                 if (argvptr == arraylimit(ttargv)) return nil;
  1174. 34017                 *argvptr++= p;
  1175. 34018         }
  1176. 34019         if (argvptr == arraylimit(ttargv)) return nil;
  1177. 34020         *argvptr++= nil;
  1178. 34021         return field;
  1179. 34022 }
  1180. 34024 struct ttyent *getttyent(void)
  1181. 34025 /* Read one entry from the ttytab file. */
  1182. 34026 {
  1183. 34027         /* Open the file if not yet open. */
  1184. 34028         if (ttfd < 0 && setttyent() < 0) return nil;
  1185. 34029
  1186. 34030         /* Look for a line with something on it. */
  1187. 34031         for (;;) {
  1188. 34032                 if (!getline()) return nil;     /* EOF or corrupt. */
  1189. 34033
  1190. 34034                 if ((entry.ty_name= scan_white(0)) == nil) continue;
  1191. 34035                 entry.ty_type= scan_white(0);
  1192. 34036                 entry.ty_getty= scan_quoted();
  1193. 34037                 entry.ty_init= scan_quoted();
  1194. 34038
  1195. 34039                 return &entry;
  1196. 34040         }
  1197. 34041 }
  1198. 34043 struct ttyent *getttynam(const char *name)
  1199. 34044 /* Return the ttytab file entry for a given tty. */
  1200. 34045 {
  1201. 34046         struct ttyent *tty;
  1202. 34047
  1203. 34048         endttyent();
  1204. 34049         while ((tty= getttyent()) != nil && strcmp(tty->ty_name, name) != 0) {}
  1205. 34050         endttyent();
  1206. 34051         return tty;
  1207. 34052 }
  1208. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1209. src/lib/other/getw.c    
  1210. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1211. 34100 /*
  1212. 34101  * getw - read a word from a stream
  1213. 34102  */
  1214. 34103 /* $Header: getw.c,v 1.1 89/12/18 14:39:51 eck Exp $ */
  1215. 34104
  1216. 34105 #include        <stdio.h>
  1217. 34106
  1218. 34107 _PROTOTYPE(int getw, (FILE *stream ));
  1219. 34108
  1220. 34109 int getw(stream)
  1221. 34110 register FILE *stream;
  1222. 34111 {
  1223. 34112         register int cnt = sizeof(int);
  1224. 34113         int w;
  1225. 34114         register char *p = (char *) &w;
  1226. 34115
  1227. 34116         while (cnt--) {
  1228. 34117                 *p++ = getc(stream);
  1229. 34118         }
  1230. 34119         if (feof(stream) || ferror(stream)) return EOF;
  1231. 34120         return w;
  1232. 34121 }
  1233. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1234. src/lib/other/hypot.c    
  1235. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1236. 34200 /*
  1237. 34201  * (c) copyright 1988 by the Vrije Universiteit, Amsterdam, The Netherlands.
  1238. 34202  * See the copyright notice in the ACK home directory, in the file "Copyright".
  1239. 34203  *
  1240. 34204  * Author: Ceriel J.H. Jacobs
  1241. 34205  */
  1242. 34206
  1243. 34207 #include <math.h>
  1244. 34208
  1245. 34209 struct complex {
  1246. 34210         double r,i;
  1247. 34211 };
  1248. 34212
  1249. 34213 _PROTOTYPE(double hypot, (double x, double y ));
  1250. 34214 _PROTOTYPE(double cabs, (struct complex p_compl ));
  1251. 34215
  1252. 34216 /* $Header: hypot.c,v 1.1 91/02/26 18:08:08 ceriel Exp $ */
  1253. 34217
  1254. 34218 double
  1255. 34219 hypot(x, y)
  1256. 34220 double x, y;
  1257. 34221 {
  1258. 34222         /*      Computes sqrt(x*x+y*y), avoiding overflow */
  1259. 34223
  1260. 34224         if (x < 0) x = -x;
  1261. 34225         if (y < 0) y = -y;
  1262. 34226         if (x > y) {
  1263. 34227                 double t = y;
  1264. 34228                 y = x;
  1265. 34229                 x = t;
  1266. 34230         }
  1267. 34231         /* sqrt(x*x+y*y) = sqrt(y*y*(x*x/(y*y)+1.0)) = y*sqrt(x*x/(y*y)+1.0) */
  1268. 34232         if (y == 0.0) return 0.0;
  1269. 34233         x /= y;
  1270. 34234         return y*sqrt(x*x+1.0);
  1271. 34235 }
  1272. 34237 double
  1273. 34238 cabs(p_compl)
  1274. 34239 struct complex p_compl;
  1275. 34240 {
  1276. 34241         return hypot(p_compl.r, p_compl.i);
  1277. 34242 }
  1278. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1279. src/lib/other/index.c    
  1280. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1281. 34300 #include <lib.h>
  1282. 34301 /* index - find first occurrence of a character in a string */
  1283. 34302
  1284. 34303 #include <string.h>
  1285. 34304
  1286. 34305 char *index(s, charwanted)      /* found char, or NULL if none */
  1287. 34306 _CONST char *s;
  1288. 34307 char charwanted;
  1289. 34308 {
  1290. 34309   return(strchr(s, charwanted));
  1291. 34310 }
  1292. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1293. src/lib/other/itoa.c    
  1294. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1295. 34400 #include <lib.h>
  1296. 34401 /* Integer to ASCII for signed decimal integers. */
  1297. 34402
  1298. 34403 PRIVATE int next;
  1299. 34404 PRIVATE char qbuf[8];
  1300. 34405
  1301. 34406 _PROTOTYPE( char *itoa, (int n));
  1302. 34407
  1303. 34408 char *itoa(n)
  1304. 34409 int n;
  1305. 34410 {
  1306. 34411   register int r, k;
  1307. 34412   int flag = 0;
  1308. 34413
  1309. 34414   next = 0;
  1310. 34415   if (n < 0) {
  1311. 34416         qbuf[next++] = '-';
  1312. 34417         n = -n;
  1313. 34418   }
  1314. 34419   if (n == 0) {
  1315. 34420         qbuf[next++] = '0';
  1316. 34421   } else {
  1317. 34422         k = 10000;
  1318. 34423         while (k > 0) {
  1319. 34424                 r = n / k;
  1320. 34425                 if (flag || r > 0) {
  1321. 34426                         qbuf[next++] = '0' + r;
  1322. 34427                         flag = 1;
  1323. 34428                 }
  1324. 34429                 n -= r * k;
  1325. 34430                 k = k / 10;
  1326. 34431         }
  1327. 34432   }
  1328. 34433   qbuf[next] = 0;
  1329. 34434   return(qbuf);
  1330. 34435 }
  1331. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1332. src/lib/other/loadname.c    
  1333. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1334. 34500 #include <lib.h>
  1335. 34501 #include <string.h>
  1336. 34502
  1337. 34503 PUBLIC void _loadname(name, msgptr)
  1338. 34504 _CONST char *name;
  1339. 34505 message *msgptr;
  1340. 34506 {
  1341. 34507 /* This function is used to load a string into a type m3 message. If the
  1342. 34508  * string fits in the message, it is copied there.  If not, a pointer to
  1343. 34509  * it is passed.
  1344. 34510  */
  1345. 34511
  1346. 34512   register size_t k;
  1347. 34513
  1348. 34514   k = strlen(name) + 1;
  1349. 34515   msgptr->m3_i1 = k;
  1350. 34516   msgptr->m3_p1 = (char *) name;
  1351. 34517   if (k <= sizeof msgptr->m3_ca1) strcpy(msgptr->m3_ca1, name);
  1352. 34518 }
  1353. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1354. src/lib/other/lock.c    
  1355. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1356. 34600 #include <lib.h>
  1357. 34601 #include <errno.h>
  1358. 34602 #include <sys/types.h>
  1359. 34603 #include <unistd.h>
  1360. 34604 #include <string.h>
  1361. 34605 #include <fcntl.h>
  1362. 34606 #include <stdio.h>
  1363. 34607 #if _ANSI
  1364. 34608 #include <stdlib.h>
  1365. 34609 #endif
  1366. 34610
  1367. 34611 typedef enum {
  1368. 34612   False, True
  1369. 34613 } BOOLEAN;
  1370. 34614
  1371. 34615 #define LOCKDIR "/tmp/"         /* or /usr/tmp/ as the case may be */
  1372. 34616 #define MAXTRIES 3
  1373. 34617 #define NAPTIME (unsigned int)5
  1374. 34618
  1375. 34619 PRIVATE _PROTOTYPE( char *lockpath, (char *name));
  1376. 34620 _PROTOTYPE( void syserr, (char *errstring));
  1377. 34621 _PROTOTYPE( BOOLEAN lock, (char *name));
  1378. 34622 _PROTOTYPE( void unlock, (char *name));
  1379. 34623
  1380. 34624 void
  1381. 34625 syserr(errstring)
  1382. 34626 char *errstring;
  1383. 34627 {
  1384. 34628         fprintf(stderr,"couldn't %sn", errstring);
  1385. 34629         exit(1);
  1386. 34630 }
  1387. 34632 BOOLEAN lock(name)              /* acquire lock */
  1388. 34633 char *name;
  1389. 34634 {
  1390. 34635   char *path;
  1391. 34636   int fd, tries;
  1392. 34637
  1393. 34638   path = lockpath(name);
  1394. 34639   tries = 0;
  1395. 34640   while ((fd = creat(path, 0)) == -1 && errno == EACCES) {
  1396. 34641         if (++tries >= MAXTRIES) return(False);
  1397. 34642         sleep(NAPTIME);
  1398. 34643   }
  1399. 34644   if (fd == -1 || close(fd) == -1) syserr("lock");
  1400. 34645   return(True);
  1401. 34646 }
  1402. 34648 void unlock(name)               /* free lock */
  1403. 34649 char *name;
  1404. 34650 {
  1405. 34651   if (unlink(lockpath(name)) == -1) syserr("unlock");
  1406. 34652 }
  1407. 34654 PRIVATE char *lockpath(name)    /* generate lock file path */
  1408. 34655 char *name;
  1409. 34656 {
  1410. 34657   PRIVATE char path[20];
  1411. 34658
  1412. 34659   strcpy(path, LOCKDIR);
  1413. 34660   return(strcat(path, name));
  1414. 34661 }
  1415. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1416. src/lib/other/lrand.c    
  1417. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1418. 34700 /*  lrand(3)
  1419. 34701  *
  1420. 34702  *  Author: Terrence W. Holm          Nov. 1988
  1421. 34703  *
  1422. 34704  *
  1423. 34705  *  A prime modulus multiplicative linear congruential
  1424. 34706  *  generator (PMMLCG), or "Lehmer generator".
  1425. 34707  *  Implementation directly derived from the article:
  1426. 34708  *
  1427. 34709  *      S. K. Park and K. W. Miller
  1428. 34710  *      Random Number Generators: Good Ones are Hard to Find
  1429. 34711  *      CACM vol 31, #10. Oct. 1988. pp 1192-1201.
  1430. 34712  *
  1431. 34713  *
  1432. 34714  *  Using the following multiplier and modulus, we obtain a
  1433. 34715  *  generator which:
  1434. 34716  *
  1435. 34717  *      1)  Has a full period: 1 to 2^31 - 2.
  1436. 34718  *      2)  Is testably "random" (see the article).
  1437. 34719  *      3)  Has a known implementation by E. L. Schrage.
  1438. 34720  */
  1439. 34721
  1440. 34722 #include <lib.h>
  1441. 34723
  1442. 34724 _PROTOTYPE( long seed, (long lseed));
  1443. 34725 _PROTOTYPE( long lrand, (void));
  1444. 34726
  1445. 34727 #define  A        16807L        /* A "good" multiplier    */
  1446. 34728 #define  M   2147483647L        /* Modulus: 2^31 - 1      */
  1447. 34729 #define  Q       127773L        /* M / A                  */
  1448. 34730 #define  R         2836L        /* M % A                  */
  1449. 34731
  1450. 34732 PRIVATE long _lseed = 1L;
  1451. 34733
  1452. 34734 long seed(lseed)
  1453. 34735 long lseed;
  1454. 34736 {
  1455. 34737   long previous_seed = _lseed;
  1456. 34738
  1457. 34739   _lseed = lseed;
  1458. 34740
  1459. 34741   return(previous_seed);
  1460. 34742 }
  1461. 34745 long lrand()
  1462. 34746 {
  1463. 34747   _lseed = A * (_lseed % Q) - R * (_lseed / Q);
  1464. 34748
  1465. 34749   if (_lseed < 0) _lseed += M;
  1466. 34750
  1467. 34751   return(_lseed);
  1468. 34752 }
  1469. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1470. src/lib/other/lsearch.c    
  1471. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1472. 34800 #include <lib.h>
  1473. 34801 #include <string.h>
  1474. 34802 /*  lsearch(3)  and  lfind(3)
  1475. 34803  *
  1476. 34804  *  Author: Terrence W. Holm          Sep. 1988
  1477. 34805  */
  1478. 34806
  1479. 34807 #include <stddef.h>
  1480. 34808
  1481. 34809 _PROTOTYPE( char *lsearch, (char *key, char *base,
  1482. 34810                             unsigned *count, unsigned width,
  1483. 34811                             int (*keycmp)(const void *, const void *)));
  1484. 34812 _PROTOTYPE( char *lfind, (char *key, char *base,
  1485. 34813                             unsigned *count, unsigned width,
  1486. 34814                             int (*keycmp)(const void *, const void *)));
  1487. 34815
  1488. 34816 char *lsearch(key, base, count, width, keycmp)
  1489. 34817 char *key;
  1490. 34818 char *base;
  1491. 34819 unsigned *count;
  1492. 34820 unsigned width;
  1493. 34821 _PROTOTYPE( int (*keycmp), (const void *, const void *));
  1494. 34822 {
  1495. 34823   char *entry;
  1496. 34824   char *last = base + *count * width;
  1497. 34825
  1498. 34826   for (entry = base; entry < last; entry += width)
  1499. 34827         if (keycmp(key, entry) == 0) return(entry);
  1500. 34828
  1501. 34829   bcopy(key, last, width);
  1502. 34830   *count += 1;
  1503. 34831   return(last);
  1504. 34832 }
  1505. 34835 char *lfind(key, base, count, width, keycmp)
  1506. 34836 char *key;
  1507. 34837 char *base;
  1508. 34838 unsigned *count;
  1509. 34839 unsigned width;
  1510. 34840 _PROTOTYPE( int (*keycmp), (const void *, const void *));
  1511. 34841 {
  1512. 34842   char *entry;
  1513. 34843   char *last = base + *count * width;
  1514. 34844
  1515. 34845   for (entry = base; entry < last; entry += width)
  1516. 34846         if (keycmp(key, entry) == 0) return(entry);
  1517. 34847
  1518. 34848   return((char *)NULL);
  1519. 34849 }
  1520. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1521. src/lib/other/memccpy.c    
  1522. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1523. 34900 #include <lib.h>
  1524. 34901 /* memccpy - copy bytes up to a certain char
  1525. 34902  *
  1526. 34903  * CHARBITS should be defined only if the compiler lacks "unsigned char".
  1527. 34904  * It should be a mask, e.g. 0377 for an 8-bit machine.
  1528. 34905  */
  1529. 34906
  1530. 34907 #include <ansi.h>
  1531. 34908 #include <stddef.h>
  1532. 34909
  1533. 34910 _PROTOTYPE( void *memccpy, (void *dst, const void *src,
  1534. 34911                             int ucharstop, size_t size));
  1535. 34912 #ifndef CHARBITS
  1536. 34913 #       define  UNSCHAR(c)      ((unsigned char)(c))
  1537. 34914 #else
  1538. 34915 #       define  UNSCHAR(c)      ((c)&CHARBITS)
  1539. 34916 #endif
  1540. 34917
  1541. 34918 void *memccpy(dst, src, ucharstop, size)
  1542. 34919 void * dst;
  1543. 34920 _CONST void * src;
  1544. 34921 int ucharstop;
  1545. 34922 _SIZET size;
  1546. 34923 {
  1547. 34924   register char *d;
  1548. 34925   register _CONST char *s;
  1549. 34926   register _SIZET n;
  1550. 34927   register int uc;
  1551. 34928
  1552. 34929   if (size <= 0) return( (void *) NULL);
  1553. 34930
  1554. 34931   s = (char *) src;
  1555. 34932   d = (char *) dst;
  1556. 34933   uc = UNSCHAR(ucharstop);
  1557. 34934   for (n = size; n > 0; n--)
  1558. 34935         if (UNSCHAR(*d++ = *s++) == (char) uc) return( (void *) d);
  1559. 34936
  1560. 34937   return( (void *) NULL);
  1561. 34938 }
  1562. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1563. src/lib/other/mtab.c    
  1564. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1565. 35000 /* This package consists of 4 routines for handling the /etc/mtab file.
  1566. 35001  * The /etc/mtab file contains information about the root and mounted file
  1567. 35002  * systems as a series of lines, each one with exactly four fields separated 
  1568. 35003  * by one space as follows:
  1569. 35004  *
  1570. 35005  *      special mounted_on version rw_flag
  1571. 35006  *
  1572. 35007  * where 
  1573. 35008  *      special is the name of the block special file
  1574. 35009  *      mounted_on is the directory on which it is mounted
  1575. 35010  *      version is either 1 or 2 for MINIX V1 and V2 file systems
  1576. 35011  *      rw_flag is rw or ro for read/write or read only
  1577. 35012  *
  1578. 35013  * An example /etc/mtab:
  1579. 35014  *
  1580. 35015  *      /dev/ram / 2 rw
  1581. 35016  *      /dev/hd1 /usr 2 rw
  1582. 35017  *      /dev/fd0 /user 1 ro
  1583. 35018  *
  1584. 35019  *
  1585. 35020  * The four routines for handling /etc/mtab are as follows.  They use two
  1586. 35021  * (hidden) internal buffers, mtab_in for input and mtab_out for output.
  1587. 35022  *
  1588. 35023  *      load_mtab(&prog_name)              - read /etc/mtab into mtab_in
  1589. 35024  *      get_mtab_entry(&s1, &s2, &s3, &s4) - arrays that are filled in
  1590. 35025  *      put_mtab_entry(&s1, &s2, &s3, &s4) - append a line to mtab_out
  1591. 35026  *      rewrite_mtab(&prog_name)           - write mtab_out to /etc/mtab
  1592. 35027  *
  1593. 35028  * If load_mtab and rewrite_mtab work, they return 0.  If they fail, they
  1594. 35029  * print their own error messages on stderr and return -1.  When get_mtab_entry
  1595. 35030  * runs out of entries to return, it sets the first pointer to NULL and returns
  1596. 35031  * -1 instead of 0.  Also, rewrite_mtab returns -1 if it fails.
  1597. 35032  */
  1598. 35033  
  1599. 35034 #include <sys/types.h>
  1600. 35035 #include <minix/minlib.h>
  1601. 35036 #include <ctype.h>
  1602. 35037 #include <fcntl.h>
  1603. 35038 #include <stdlib.h>
  1604. 35039 #include <string.h>
  1605. 35040 #include <unistd.h>
  1606. 35041 #include <stdio.h>
  1607. 35042
  1608. 35043 #define BUF_SIZE   512            /* size of the /etc/mtab buffer */
  1609. 35044
  1610. 35045 char *etc_mtab = "/etc/mtab";     /* name of the /etc/mtab file */
  1611. 35046 static char mtab_in[BUF_SIZE+1];  /* holds /etc/mtab when it is read in */
  1612. 35047 static char mtab_out[BUF_SIZE+1]; /* buf to build /etc/mtab for output later */
  1613. 35048 static char *iptr = mtab_in;      /* pointer to next line to feed out. */
  1614. 35049 static char *optr = mtab_out;     /* pointer to place where next line goes */
  1615. 35050
  1616. 35051 _PROTOTYPE(int load_mtab, (char *prog_name ));
  1617. 35052 _PROTOTYPE(int rewrite_mtab, (char *prog_name ));
  1618. 35053 _PROTOTYPE(int get_mtab_entry, (char *special, char *mounted_on, 
  1619. 35054                                         char *version, char *rw_flag));
  1620. 35055 _PROTOTYPE(int put_mtab_entry, (char *special, char *mounted_on, 
  1621. 35056                                         char *version, char *rw_flag));
  1622. 35057 _PROTOTYPE(void err, (char *prog_name, char *str ));
  1623. 35058
  1624. 35059
  1625. 35060 int load_mtab(prog_name)
  1626. 35061 char *prog_name;
  1627. 35062 {
  1628. 35063 /* Read in /etc/mtab and store it in /etc/mtab. */
  1629. 35064
  1630. 35065   int fd, n;
  1631. 35066   char *ptr;
  1632. 35067
  1633. 35068   /* Open the file. */
  1634. 35069   fd = open(etc_mtab, O_RDONLY);
  1635. 35070   if (fd < 0) {
  1636. 35071         err(prog_name, ": cannot open ");
  1637. 35072         return(-1);
  1638. 35073   }
  1639. 35074
  1640. 35075   /* File opened.  Read it in. */
  1641. 35076   n = read(fd, mtab_in, BUF_SIZE);
  1642. 35077   if (n <= 0) {
  1643. 35078         /* Read failed. */
  1644. 35079         err(prog_name, ": cannot read ");
  1645. 35080         return(-1);
  1646. 35081   }
  1647. 35082   if (n == BUF_SIZE) {
  1648. 35083         /* Some nut has mounted 50 file systems or something like that. */
  1649. 35084         std_err(prog_name);
  1650. 35085         std_err(": file too large: ");
  1651. 35086         std_err(etc_mtab);
  1652. 35087         return(-1);
  1653. 35088   }
  1654. 35089
  1655. 35090   close(fd);
  1656. 35091
  1657. 35092   /* Replace all the whitespace by ''. */
  1658. 35093   ptr = mtab_in;
  1659. 35094   while (*ptr != '') {
  1660. 35095         if (isspace(*ptr)) *ptr = '';
  1661. 35096         ptr++;
  1662. 35097   }
  1663. 35098   return(0);
  1664. 35099 }
  1665. 35102 int rewrite_mtab(prog_name)
  1666. 35103 char *prog_name;
  1667. 35104 {
  1668. 35105 /* Write mtab_out to /etc/mtab. */
  1669. 35106
  1670. 35107   int fd, n;
  1671. 35108
  1672. 35109   /* Do a creat to truncate the file. */
  1673. 35110   fd = creat(etc_mtab, 0777);
  1674. 35111   if (fd < 0) {
  1675. 35112         err(prog_name, ": cannot overwrite ");
  1676. 35113         return(-1);
  1677. 35114   }
  1678. 35115
  1679. 35116   /* File created.  Write it. */
  1680. 35117   n = write(fd, mtab_out, (unsigned int)(optr - mtab_out));
  1681. 35118   if (n <= 0) {
  1682. 35119         /* Write failed. */
  1683. 35120         err(prog_name, " could not write ");
  1684. 35121         return(-1);
  1685. 35122   }
  1686. 35123
  1687. 35124   close(fd);
  1688. 35125   return(0);
  1689. 35126 }
  1690. 35129 int get_mtab_entry(special, mounted_on, version, rw_flag)
  1691. 35130 char *special;
  1692. 35131 char *mounted_on;
  1693. 35132 char *version;
  1694. 35133 char *rw_flag;
  1695. 35134 {
  1696. 35135 /* Return the next entry from mtab_in. */
  1697. 35136
  1698. 35137   if (iptr >= &mtab_in[BUF_SIZE]) {
  1699. 35138         special[0] = '';
  1700. 35139         return(-1);
  1701. 35140   }
  1702. 35141
  1703. 35142   strcpy(special, iptr);
  1704. 35143   while (isprint(*iptr)) iptr++;
  1705. 35144   while (*iptr == ''&& iptr < &mtab_in[BUF_SIZE]) iptr++;
  1706. 35145
  1707. 35146   strcpy(mounted_on, iptr);
  1708. 35147   while (isprint(*iptr)) iptr++;
  1709. 35148   while (*iptr == ''&& iptr < &mtab_in[BUF_SIZE]) iptr++;
  1710. 35149
  1711. 35150   strcpy(version, iptr);
  1712. 35151   while (isprint(*iptr)) iptr++;
  1713. 35152   while (*iptr == ''&& iptr < &mtab_in[BUF_SIZE]) iptr++;
  1714. 35153
  1715. 35154   strcpy(rw_flag, iptr);
  1716. 35155   while (isprint(*iptr)) iptr++;
  1717. 35156   while (*iptr == ''&& iptr < &mtab_in[BUF_SIZE]) iptr++;
  1718. 35157   return(0);
  1719. 35158 }
  1720. 35161 int put_mtab_entry(special, mounted_on, version, rw_flag)
  1721. 35162 char *special;
  1722. 35163 char *mounted_on;
  1723. 35164 char *version;
  1724. 35165 char *rw_flag;
  1725. 35166 {
  1726. 35167 /* Append an entry to the mtab_out buffer. */
  1727. 35168
  1728. 35169   int n1, n2, n3, n4;
  1729. 35170
  1730. 35171   n1 = strlen(special);
  1731. 35172   n2 = strlen(mounted_on);
  1732. 35173   n3 = strlen(version);
  1733. 35174   n4 = strlen(rw_flag);
  1734. 35175
  1735. 35176   if (optr + n1 + n2 + n3 + n4 + 5 >= &mtab_out[BUF_SIZE]) return(-1);
  1736. 35177   strcpy(optr, special);
  1737. 35178   optr += n1;
  1738. 35179   *optr++ = ' ';
  1739. 35180
  1740. 35181   strcpy(optr, mounted_on);
  1741. 35182   optr += n2;
  1742. 35183   *optr++ = ' ';
  1743. 35184
  1744. 35185   strcpy(optr, version);
  1745. 35186   optr += n3;
  1746. 35187   *optr++ = ' ';
  1747. 35188
  1748. 35189   strcpy(optr, rw_flag);
  1749. 35190   optr += n4;
  1750. 35191   *optr++ = 'n';
  1751. 35192   return(0);
  1752. 35193 }
  1753. 35196 void
  1754. 35197 err(prog_name, str)
  1755. 35198 char *prog_name, *str;
  1756. 35199 {
  1757. 35200   std_err(prog_name); 
  1758. 35201   std_err(str);
  1759. 35202   std_err(etc_mtab);
  1760. 35203   perror(" ");
  1761. 35204 }
  1762. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1763. src/lib/other/nlist.c    
  1764. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1765. 35300 /*
  1766. 35301  * "nlist.c", Peter Valkenburg, january 1989.
  1767. 35302  */
  1768. 35303  
  1769. 35304 #include <lib.h>
  1770. 35305 #include <string.h>
  1771. 35306 #include <a.out.h>
  1772. 35307 #include <sys/types.h>
  1773. 35308 #include <fcntl.h>
  1774. 35309 #include <unistd.h>
  1775. 35310 #include <stdio.h>
  1776. 35311
  1777. 35312 #define fail(fp)        (fclose(fp), -1)        /* ret. exp. when nlist fails */
  1778. 35313
  1779. 35314 _PROTOTYPE( int nlist, (char *file, struct nlist nl[]));
  1780. 35315
  1781. 35316 /*
  1782. 35317  * Nlist fills fields n_sclass and n_value of array nl with values found in
  1783. 35318  * non-stripped executable file.  Entries that are not found have their
  1784. 35319  * n_value/n_sclass fields set to 0.  Nl ends with a 0 or nul string n_name.
  1785. 35320  * The return value is -1 on failure, else the number of entries not found.
  1786. 35321  */
  1787. 35322 int nlist(file, nl)
  1788. 35323 char *file;
  1789. 35324 struct nlist nl[];
  1790. 35325 {
  1791. 35326         int nents, nsrch, nfound, i;
  1792. 35327         struct nlist nlent;
  1793. 35328         FILE *fp;
  1794. 35329         struct exec hd;
  1795. 35330
  1796. 35331         /* open executable with namelist */
  1797. 35332         if ((fp = fopen(file, "r")) == NULL)
  1798. 35333                 return -1;
  1799. 35334                 
  1800. 35335         /* get header and seek to start of namelist */  
  1801. 35336         if (fread((char *) &hd, sizeof(struct exec), 1, fp) != 1 ||
  1802. 35337             BADMAG(hd) || fseek(fp, A_SYMPOS(hd), SEEK_SET) != 0)
  1803. 35338                 return fail(fp);
  1804. 35339         
  1805. 35340         /* determine number of entries searched for & reset fields */
  1806. 35341         nsrch = 0;
  1807. 35342         while (nl[nsrch].n_name != NULL && *(nl[nsrch].n_name) != '') {
  1808. 35343                 nl[nsrch].n_sclass = 0;
  1809. 35344                 nl[nsrch].n_value = 0;
  1810. 35345                 nl[nsrch].n_type = 0;           /* for compatability */
  1811. 35346                 nsrch++;
  1812. 35347         }
  1813. 35348
  1814. 35349         /* loop through namelist & fill in user array */
  1815. 35350         nfound = 0;
  1816. 35351         for (nents = (hd.a_syms & 0xFFFF) / sizeof(struct nlist);
  1817. 35352              nents > 0; nents--) {
  1818. 35353                 if (nsrch == nfound)
  1819. 35354                         break;                  /* no need to look further */
  1820. 35355                 if (fread((char *) &nlent, sizeof(struct nlist), 1, fp) != 1)
  1821. 35356                         return fail(fp);          
  1822. 35357                 for (i = 0; i < nsrch; i++)
  1823. 35358                         if (nl[i].n_sclass == 0 &&
  1824. 35359                             strncmp(nl[i].n_name, nlent.n_name,
  1825. 35360                                     sizeof(nlent.n_name)) == 0) {
  1826. 35361                                 nl[i] = nlent;
  1827. 35362                                 nfound++;
  1828. 35363                                 break;
  1829. 35364                         }
  1830. 35365         }
  1831. 35366
  1832. 35367         (void) fclose(fp);
  1833. 35368         
  1834. 35369         return nsrch - nfound;
  1835. 35370 }
  1836. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1837. src/lib/other/peekpoke.c    
  1838. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1839. 35400 /* Peek and poke using /dev/mem.
  1840. 35401  *
  1841. 35402  * Callers now ought to check the return values.
  1842. 35403  *
  1843. 35404  * Calling peek() requires read permission on /dev/mem, and consumes
  1844. 35405  * a file descriptor.  Calling poke() requires write permission, and
  1845. 35406  * consumes another file descriptor.
  1846. 35407  */
  1847. 35408
  1848. 35409 #include <sys/types.h>
  1849. 35410 #include <fcntl.h>
  1850. 35411 #include <unistd.h>
  1851. 35412
  1852. 35413 _PROTOTYPE( int peek, (unsigned segment, unsigned offset));
  1853. 35414 _PROTOTYPE( int poke, (unsigned segment, unsigned offset, unsigned value));
  1854. 35415
  1855. 35416 #define SEGSIZE 0x10
  1856. 35417
  1857. 35418 int peek(segment, offset)
  1858. 35419 unsigned segment;
  1859. 35420 unsigned offset;
  1860. 35421 {
  1861. 35422   unsigned char chvalue;
  1862. 35423   static int infd = -1;
  1863. 35424
  1864. 35425   if (infd < 0) infd = open("/dev/mem", O_RDONLY);
  1865. 35426   if (infd < 0 ||
  1866. 35427       lseek(infd, (unsigned long) segment * SEGSIZE + offset, SEEK_SET) < 0 ||
  1867. 35428       read(infd, (char *) &chvalue, (unsigned) 1) != 1)
  1868. 35429         return(-1);
  1869. 35430   return(chvalue);
  1870. 35431 }
  1871. 35433 int poke(segment, offset, value)
  1872. 35434 unsigned segment;
  1873. 35435 unsigned offset;
  1874. 35436 unsigned value;
  1875. 35437 {
  1876. 35438   unsigned char chvalue;
  1877. 35439   static int outfd = -1;
  1878. 35440
  1879. 35441   chvalue = value;
  1880. 35442   if (outfd < 0) outfd = open("/dev/mem", O_WRONLY);
  1881. 35443   if (outfd < 0 ||
  1882. 35444       lseek(outfd, (unsigned long) segment * SEGSIZE + offset, SEEK_SET) < 0 ||
  1883. 35445       write(outfd, (char *) &chvalue, (unsigned) 1) != 1)
  1884. 35446         return(-1);
  1885. 35447   return(chvalue);
  1886. 35448 }
  1887. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1888. src/lib/other/popen.c    
  1889. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  1890. 35500 /*
  1891. 35501  * popen - open a pipe
  1892. 35502  */
  1893. 35503 /* $Header: popen.c,v 1.3 90/08/28 14:53:34 eck Exp $ */
  1894. 35504
  1895. 35505 #include        <sys/types.h>
  1896. 35506 #include        <limits.h>
  1897. 35507 #include        <errno.h>
  1898. 35508 #include        <signal.h>
  1899. 35509 #include        <stdio.h>
  1900. 35510
  1901. 35511 #if     defined(__BSD4_2)
  1902. 35512 union wait {
  1903. 35513         int     w_status;
  1904. 35514 };
  1905. 35515 typedef union wait wait_arg;
  1906. 35516 #else
  1907. 35517 typedef int wait_arg;
  1908. 35518 #endif  /* __BSD4_2 */
  1909. 35519
  1910. 35520 #include        "../stdio/loc_incl.h"
  1911. 35521
  1912. 35522 #ifdef _ANSI
  1913. 35523 int _close(int d);
  1914. 35524 int _dup2(int oldd, int newd);          /* not present in System 5 */
  1915. 35525 int _execl(const char *name, const char *_arg, ... );
  1916. 35526 pid_t _fork(void);
  1917. 35527 int _pipe(int fildes[2]);
  1918. 35528 pid_t _wait(wait_arg *status);
  1919. 35529 void _exit(int status);
  1920. 35530 #endif
  1921. 35531
  1922. 35532 static int pids[OPEN_MAX];
  1923. 35533
  1924. 35534 FILE *
  1925. 35535 popen(command, type)
  1926. 35536 _CONST char *command;
  1927. 35537 _CONST char *type;
  1928. 35538 {
  1929. 35539         int piped[2];
  1930. 35540         int Xtype = *type == 'r' ? 0 : *type == 'w' ? 1 : 2;
  1931. 35541         int pid;
  1932. 35542
  1933. 35543         if (Xtype == 2 ||
  1934. 35544             _pipe(piped) < 0 ||
  1935. 35545             (pid = _fork()) < 0) return 0;
  1936. 35546         
  1937. 35547         if (pid == 0) {
  1938. 35548                 /* child */
  1939. 35549                 register int *p;
  1940. 35550
  1941. 35551                 for (p = pids; p < &pids[OPEN_MAX]; p++) {
  1942. 35552                         if (*p) _close((int)(p - pids));
  1943. 35553                 }
  1944. 35554                 _close(piped[Xtype]);
  1945. 35555                 _dup2(piped[!Xtype], !Xtype);
  1946. 35556                 _close(piped[!Xtype]);
  1947. 35557                 _execl("/bin/sh", "sh", "-c", command, (char *) 0);
  1948. 35558                 _exit(127);     /* like system() ??? */
  1949. 35559         }
  1950. 35560
  1951. 35561         pids[piped[Xtype]] = pid;
  1952. 35562         _close(piped[!Xtype]);
  1953. 35563         return fdopen(piped[Xtype], type);
  1954. 35564 }
  1955. 35566 #if     defined(__BSD4_2)
  1956. 35567 #define ret_val status.w_status
  1957. 35568 #else
  1958. 35569 #define ret_val status
  1959. 35570 #endif
  1960. 35571
  1961. 35572 int
  1962. 35573 pclose(stream)
  1963. 35574 FILE *stream;
  1964. 35575 {
  1965. 35576         int fd = fileno(stream);
  1966. 35577         wait_arg status;
  1967. 35578         int wret;
  1968. 35579
  1969. 35580 #ifdef _ANSI
  1970. 35581         void (*intsave)(int) = signal(SIGINT, SIG_IGN);
  1971. 35582         void (*quitsave)(int) = signal(SIGQUIT, SIG_IGN);
  1972. 35583 #else
  1973. 35584         void (*intsave)() = signal(SIGINT, SIG_IGN);
  1974. 35585         void (*quitsave)() = signal(SIGQUIT, SIG_IGN);
  1975. 35586 #endif
  1976. 35587         fclose(stream);
  1977. 35588         while ((wret = _wait(&status)) != -1) {
  1978. 35589                 if (wret == pids[fd]) break;
  1979. 35590         }
  1980. 35591         if (wret == -1) ret_val = -1;
  1981. 35592         signal(SIGINT, intsave);
  1982. 35593         signal(SIGQUIT, quitsave);
  1983. 35594         pids[fd] = 0;
  1984. 35595         return ret_val;
  1985. 35596 }
  1986. 35598 #if     defined(__USG)
  1987. 35599 int _dup(int fildes);
  1988. 35600
  1989. 35601 static int
  1990. 35602 _dup2(oldd, newd)
  1991. 35603 int oldd, newd;
  1992. 35604 {
  1993. 35605         int i = 0, fd, tmp;
  1994. 35606         int fdbuf[_NFILES];
  1995. 35607
  1996. 35608         /* ignore the error on the close() */
  1997. 35609         tmp = errno; (void) _close(newd); errno = tmp;
  1998. 35610         while ((fd = _dup(oldd)) != newd) {
  1999. 35611                 if (fd == -1) break;
  2000. 35612                 fdbuf[i++] = fd;
  2001. 35613         }
  2002. 35614         tmp = errno;
  2003. 35615         while (--i >= 0) {
  2004. 35616                 _close(fdbuf[i]);
  2005. 35617         }
  2006. 35618         errno = tmp;
  2007. 35619         return -(fd == -1);
  2008. 35620 }
  2009. 35621 #endif  /* __USG */
  2010. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2011. src/lib/other/printk.c    
  2012. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2013. 35700 /*      printk() - kernel printf()                      Author: Kees J. Bot
  2014. 35701  *                                                              15 Jan 1994
  2015. 35702  */
  2016. 35703 #define nil 0
  2017. 35704 #include <stdarg.h>
  2018. 35705 #include <limits.h>
  2019. 35706
  2020. 35707 #define isdigit(c)      ((unsigned) ((c) - '0') <  (unsigned) 10)
  2021. 35708
  2022. 35709 #if !__STDC__
  2023. 35710 /* Classic C stuff, ignore. */
  2024. 35711 void putk();
  2025. 35712 void printk(fmt) char *fmt;
  2026. 35713 #else
  2027. 35714
  2028. 35715 /* Printk() uses putk() to print characters. */
  2029. 35716 void putk(int c);
  2030. 35717
  2031. 35718 void printk(const char *fmt, ...)
  2032. 35719 #endif
  2033. 35720 {
  2034. 35721         int c;
  2035. 35722         enum { LEFT, RIGHT } adjust;
  2036. 35723         enum { LONG, INT } intsize;
  2037. 35724         int fill;
  2038. 35725         int width, max, len, base;
  2039. 35726         static char X2C_tab[]= "0123456789ABCDEF";
  2040. 35727         static char x2c_tab[]= "0123456789abcdef";
  2041. 35728         char *x2c;
  2042. 35729         char *p;
  2043. 35730         long i;
  2044. 35731         unsigned long u;
  2045. 35732         char temp[8 * sizeof(long) / 3 + 2];
  2046. 35733
  2047. 35734         va_list argp;
  2048. 35735
  2049. 35736         va_start(argp, fmt);
  2050. 35737
  2051. 35738         while ((c= *fmt++) != 0) {
  2052. 35739                 if (c != '%') {
  2053. 35740                         /* Ordinary character. */
  2054. 35741                         putk(c);
  2055. 35742                         continue;
  2056. 35743                 }
  2057. 35744
  2058. 35745                 /* Format specifier of the form:
  2059. 35746                  *      %[adjust][fill][width][.max]keys
  2060. 35747                  */
  2061. 35748                 c= *fmt++;
  2062. 35749
  2063. 35750                 adjust= RIGHT;
  2064. 35751                 if (c == '-') {
  2065. 35752                         adjust= LEFT;
  2066. 35753                         c= *fmt++;
  2067. 35754                 }
  2068. 35755
  2069. 35756                 fill= ' ';
  2070. 35757                 if (c == '0') {
  2071. 35758                         fill= '0';
  2072. 35759                         c= *fmt++;
  2073. 35760                 }
  2074. 35761
  2075. 35762                 width= 0;
  2076. 35763                 if (c == '*') {
  2077. 35764                         /* Width is specified as an argument, e.g. %*d. */
  2078. 35765                         width= va_arg(argp, int);
  2079. 35766                         c= *fmt++;
  2080. 35767                 } else
  2081. 35768                 if (isdigit(c)) {
  2082. 35769                         /* A number tells the width, e.g. %10d. */
  2083. 35770                         do {
  2084. 35771                                 width= width * 10 + (c - '0');
  2085. 35772                         } while (isdigit(c= *fmt++));
  2086. 35773                 }
  2087. 35774
  2088. 35775                 max= INT_MAX;
  2089. 35776                 if (c == '.') {
  2090. 35777                         /* Max field length coming up. */
  2091. 35778                         if ((c= *fmt++) == '*') {
  2092. 35779                                 max= va_arg(argp, int);
  2093. 35780                                 c= *fmt++;
  2094. 35781                         } else
  2095. 35782                         if (isdigit(c)) {
  2096. 35783                                 max= 0;
  2097. 35784                                 do {
  2098. 35785                                         max= max * 10 + (c - '0');
  2099. 35786                                 } while (isdigit(c= *fmt++));
  2100. 35787                         }
  2101. 35788                 }
  2102. 35789
  2103. 35790                 /* Set a few flags to the default. */
  2104. 35791                 x2c= x2c_tab;
  2105. 35792                 i= 0;
  2106. 35793                 base= 10;
  2107. 35794                 intsize= INT;
  2108. 35795                 if (c == 'l' || c == 'L') {
  2109. 35796                         /* "Long" key, e.g. %ld. */
  2110. 35797                         intsize= LONG;
  2111. 35798                         c= *fmt++;
  2112. 35799                 }
  2113. 35800                 if (c == 0) break;
  2114. 35801
  2115. 35802                 switch (c) {
  2116. 35803                         /* Decimal.  Note that %D is treated as %ld. */
  2117. 35804                 case 'D':
  2118. 35805                         intsize= LONG;
  2119. 35806                 case 'd':
  2120. 35807                         i= intsize == LONG ? va_arg(argp, long)
  2121. 35808                                                 : va_arg(argp, int);
  2122. 35809                         u= i < 0 ? -i : i;
  2123. 35810                         goto int2ascii;
  2124. 35811
  2125. 35812                         /* Octal. */
  2126. 35813                 case 'O':
  2127. 35814                         intsize= LONG;
  2128. 35815                 case 'o':
  2129. 35816                         base= 010;
  2130. 35817                         goto getint;
  2131. 35818
  2132. 35819                         /* Hexadecimal.  %X prints upper case A-F, not %lx. */
  2133. 35820                 case 'X':
  2134. 35821                         x2c= X2C_tab;
  2135. 35822                 case 'x':
  2136. 35823                         base= 0x10;
  2137. 35824                         goto getint;
  2138. 35825
  2139. 35826                         /* Unsigned decimal. */
  2140. 35827                 case 'U':
  2141. 35828                         intsize= LONG;
  2142. 35829                 case 'u':
  2143. 35830                 getint:
  2144. 35831                         u= intsize == LONG ? va_arg(argp, unsigned long)
  2145. 35832                                                 : va_arg(argp, unsigned int);
  2146. 35833                 int2ascii:
  2147. 35834                         p= temp + sizeof(temp)-1;
  2148. 35835                         *p= 0;
  2149. 35836                         do {
  2150. 35837                                 *--p= x2c[u % base];
  2151. 35838                         } while ((u /= base) > 0);
  2152. 35839                         goto string_length;
  2153. 35840
  2154. 35841                         /* A character. */
  2155. 35842                 case 'c':
  2156. 35843                         p= temp;
  2157. 35844                         *p= va_arg(argp, int);
  2158. 35845                         len= 1;
  2159. 35846                         goto string_print;
  2160. 35847
  2161. 35848                         /* Simply a percent. */
  2162. 35849                 case '%':
  2163. 35850                         p= temp;
  2164. 35851                         *p= '%';
  2165. 35852                         len= 1;
  2166. 35853                         goto string_print;
  2167. 35854
  2168. 35855                         /* A string.  The other cases will join in here. */
  2169. 35856                 case 's':
  2170. 35857                         p= va_arg(argp, char *);
  2171. 35858
  2172. 35859                 string_length:
  2173. 35860                         for (len= 0; p[len] != 0 && len < max; len++) {}
  2174. 35861
  2175. 35862                 string_print:
  2176. 35863                         width -= len;
  2177. 35864                         if (i < 0) width--;
  2178. 35865                         if (fill == '0' && i < 0) putk('-');
  2179. 35866                         if (adjust == RIGHT) {
  2180. 35867                                 while (width > 0) { putk(fill); width--; }
  2181. 35868                         }
  2182. 35869                         if (fill == ' ' && i < 0) putk('-');
  2183. 35870                         while (len > 0) { putk((unsigned char) *p++); len--; }
  2184. 35871                         while (width > 0) { putk(fill); width--; }
  2185. 35872                         break;
  2186. 35873
  2187. 35874                         /* Unrecognized format key, echo it back. */
  2188. 35875                 default:
  2189. 35876                         putk('%');
  2190. 35877                         putk(c);
  2191. 35878                 }
  2192. 35879         }
  2193. 35880
  2194. 35881         /* Mark the end with a null (should be something else, like -1). */
  2195. 35882         putk(0);
  2196. 35883         va_end(argp);
  2197. 35884 }
  2198. 35886 /*
  2199. 35887  * $PchHeader: /mount/hd2/minix/lib/minix/other/RCS/printk.c,v 1.2 1994/09/07 18:45:05 philip Exp $
  2200. 35888  */
  2201. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2202. src/lib/other/putenv.c    
  2203. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2204. 35900 /*
  2205. 35901  * (c) copyright 1989 by the Vrije Universiteit, Amsterdam, The Netherlands.
  2206. 35902  * See the copyright notice in the ACK home directory, in the file "Copyright".
  2207. 35903  */
  2208. 35904 /* $Header: putenv.c,v 1.3 90/05/14 12:30:18 ceriel Exp $ */
  2209. 35905
  2210. 35906 #include        <stdlib.h>
  2211. 35907 #include        <string.h>
  2212. 35908
  2213. 35909 #define ENTRY_INC       10
  2214. 35910 #define rounded(x)      (((x / ENTRY_INC) + 1) * ENTRY_INC)
  2215. 35911
  2216. 35912 extern _CONST char **environ;
  2217. 35913
  2218. 35914 int
  2219. 35915 putenv(name)
  2220. 35916 _CONST char *name;
  2221. 35917 {
  2222. 35918         register _CONST char **v = environ;
  2223. 35919         register char *r;
  2224. 35920         static int size = 0;
  2225. 35921         /* When size != 0, it contains the number of entries in the
  2226. 35922          * table (including the final NULL pointer). This means that the
  2227. 35923          * last non-null entry  is environ[size - 2].
  2228. 35924          */
  2229. 35925
  2230. 35926         if (!name) return 0;
  2231. 35927         if (environ == NULL) return 1;
  2232. 35928         if (r = strchr(name, '=')) {
  2233. 35929                 register _CONST char *p, *q;
  2234. 35930
  2235. 35931                 *r = '';
  2236. 35932
  2237. 35933                 if (v != NULL) {
  2238. 35934                         while ((p = *v) != NULL) {
  2239. 35935                                 q = name;
  2240. 35936                                 while (*q && (*q++ == *p++))
  2241. 35937                                         /* EMPTY */ ;
  2242. 35938                                 if (*q || (*p != '=')) {
  2243. 35939                                         v++;
  2244. 35940                                 } else {
  2245. 35941                                         /* The name was already in the
  2246. 35942                                          * environment.
  2247. 35943                                          */
  2248. 35944                                         *r = '=';
  2249. 35945                                         *v = name;
  2250. 35946                                         return 0;
  2251. 35947                                 }
  2252. 35948                         }
  2253. 35949                 }
  2254. 35950                 *r = '=';
  2255. 35951                 v = environ;
  2256. 35952         }
  2257. 35953
  2258. 35954         if (!size) {
  2259. 35955                 register _CONST char **p;
  2260. 35956                 register int i = 0;
  2261. 35957
  2262. 35958                 if (v)
  2263. 35959                         do {
  2264. 35960                                 i++;
  2265. 35961                         } while (*v++);
  2266. 35962                 if (!(v = malloc(rounded(i) * sizeof(char **))))
  2267. 35963                         return 1;
  2268. 35964                 size = i;
  2269. 35965                 p = environ;
  2270. 35966                 environ = v;
  2271. 35967                 while (*v++ = *p++);            /* copy the environment */
  2272. 35968                 v = environ;
  2273. 35969         } else if (!(size % ENTRY_INC)) {
  2274. 35970                 if (!(v = realloc(environ, rounded(size) * sizeof(char **))))
  2275. 35971                         return 1;
  2276. 35972                 environ = v;
  2277. 35973         }
  2278. 35974         v[size - 1] = name;
  2279. 35975         v[size] = NULL;
  2280. 35976         size++;
  2281. 35977         return 0;
  2282. 35978 }
  2283. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2284. src/lib/other/putw.c    
  2285. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2286. 36000 /* 
  2287. 36001  * putw - write an word on a stream
  2288. 36002  */
  2289. 36003 /* $Header: putw.c,v 1.1 89/12/18 14:40:15 eck Exp $ */
  2290. 36004
  2291. 36005 #include        <stdio.h>
  2292. 36006
  2293. 36007 _PROTOTYPE(int putw, (int w, FILE *stream ));
  2294. 36008
  2295. 36009 int
  2296. 36010 putw(w, stream)
  2297. 36011 int w;
  2298. 36012 register FILE *stream;
  2299. 36013 {
  2300. 36014         register int cnt = sizeof(int);
  2301. 36015         register char *p = (char *) &w;
  2302. 36016
  2303. 36017         while (cnt--) {
  2304. 36018                 putc(*p++, stream);
  2305. 36019         }
  2306. 36020         if (ferror(stream)) return EOF;
  2307. 36021         return w;
  2308. 36022 }
  2309. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2310. src/lib/other/regexp.c    
  2311. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
  2312. 36100 /* regcomp and regexec -- regsub and regerror are elsewhere
  2313. 36101  *
  2314. 36102  *      Copyright (c) 1986 by University of Toronto.
  2315. 36103  *      Written by Henry Spencer.  Not derived from licensed software.
  2316. 36104  *
  2317. 36105  *      Permission is granted to anyone to use this software for any
  2318. 36106  *      purpose on any computer system, and to redistribute it freely,
  2319. 36107  *      subject to the following restrictions:
  2320. 36108  *
  2321. 36109  *      1. The author is not responsible for the consequences of use of
  2322. 36110  *              this software, no matter how awful, even if they arise
  2323. 36111  *              from defects in it.
  2324. 36112  *
  2325. 36113  *      2. The origin of this software must not be misrepresented, either
  2326. 36114  *              by explicit claim or by omission.
  2327. 36115  *
  2328. 36116  *      3. Altered versions must be plainly marked as such, and must not
  2329. 36117  *              be misrepresented as being the original software.
  2330. 36118  *
  2331. 36119  * Beware that some of this code is subtly aware of the way operator
  2332. 36120  * precedence is structured in regular expressions.  Serious changes in
  2333. 36121  * regular-expression syntax might require a total rethink.
  2334. 36122  *
  2335. 36123  *      The third parameter to regexec was added by Martin C. Atkins.
  2336. 36124  *      Andy Tanenbaum also made some changes.
  2337. 36125  */
  2338. 36126
  2339. 36127 #include <minix/config.h>
  2340. 36128 #include <minix/const.h>
  2341. 36129 #include <stdlib.h>
  2342. 36130 #include <string.h>
  2343. 36131 #include <regexp.h>
  2344. 36132 #include <stdio.h>
  2345. 36133
  2346. 36134 /* The first byte of the regexp internal "program" is actually this magic
  2347. 36135  * number; the start node begins in the second byte.
  2348. 36136  */
  2349. 36137 #define MAGIC   0234
  2350. 36138
  2351. 36139 /* The "internal use only" fields in regexp.h are present to pass info from
  2352. 36140  * compile to execute that permits the execute phase to run lots faster on
  2353. 36141  * simple cases.  They are:
  2354. 36142  *
  2355. 36143  * regstart     char that must begin a match; '' if none obvious
  2356. 36144  * reganch      is the match anchored (at beginning-of-line only)?
  2357. 36145  * regmust      string (pointer into program) that match must include, or NULL
  2358. 36146  * regmlen      length of regmust string
  2359. 36147  *
  2360. 36148  * Regstart and reganch permit very fast decisions on suitable starting points
  2361. 36149  * for a match, cutting down the work a lot.  Regmust permits fast rejection
  2362. 36150  * of lines that cannot possibly match.  The regmust tests are costly enough
  2363. 36151  * that regcomp() supplies a regmust only if the r.e. contains something
  2364. 36152  * potentially expensive (at present, the only such thing detected is * or +
  2365. 36153  * at the start of the r.e., which can involve a lot of backup).  Regmlen is
  2366. 36154  * supplied because the test in regexec() needs it and regcomp() is computing
  2367. 36155  * it anyway.
  2368. 36156  */
  2369. 36157
  2370. 36158 /* Structure for regexp "program".  This is essentially a linear encoding
  2371. 36159  * of a nondeterministic finite-state machine (aka syntax charts or
  2372. 36160  * "railroad normal form" in parsing technology).  Each node is an opcode
  2373. 36161  * plus a "next" pointer, possibly plus an operand.  "Next" pointers of
  2374. 36162  * all nodes except BRANCH implement concatenation; a "next" pointer with
  2375. 36163  * a BRANCH on both ends of it is connecting two alternatives.  (Here we
  2376. 36164  * have one of the subtle syntax dependencies:  an individual BRANCH (as
  2377. 36165  * opposed to a collection of them) is never concatenated with anything
  2378. 36166  * because of operator precedence.)  The operand of some types of node is
  2379. 36167  * a literal string; for others, it is a node leading into a sub-FSM.  In
  2380. 36168  * particular, the operand of a BRANCH node is the first node of the branch.
  2381. 36169  * (NB this is *not* a tree structure:  the tail of the branch connects
  2382. 36170  * to the thing following the set of BRANCHes.)  The opcodes are:
  2383. 36171  */
  2384. 36172
  2385. 36173 /* Definition   number  opnd?   meaning */
  2386. 36174 #define END     0               /* no   End of program. */
  2387. 36175 #define BOL     1               /* no   Match "" at beginning of line. */
  2388. 36176 #define EOL     2               /* no   Match "" at end of line. */
  2389. 36177 #define ANY     3               /* no   Match any one character. */
  2390. 36178 #define ANYOF   4               /* str  Match any character in this string. */
  2391. 36179 #define ANYBUT  5               /* str  Match any character not in this
  2392. 36180                          * string. */
  2393. 36181 #define BRANCH  6               /* node Match this alternative, or the
  2394. 36182                          * next... */
  2395. 36183 #define BACK    7               /* no   Match "", "next" ptr points backward. */
  2396. 36184 #define EXACTLY 8               /* str  Match this string. */
  2397. 36185 #define NOTHING 9               /* no   Match empty string. */
  2398. 36186 #define STAR    10              /* node Match this (simple) thing 0 or more
  2399. 36187                          * times. */
  2400. 36188 #define PLUS    11              /* node Match this (simple) thing 1 or more
  2401. 36189                          * times. */
  2402. 36190 #define OPEN    20              /* no   Mark this point in input as start of
  2403. 36191                          * #n. */
  2404. 36192  /* OPEN+1 is number 1, etc. */
  2405. 36193 #define CLOSE   30              /* no   Analogous to OPEN. */
  2406. 36194
  2407. 36195 /* Opcode notes:
  2408. 36196  *
  2409. 36197  * BRANCH       The set of branches constituting a single choice are hooked
  2410. 36198  *              together with their "next" pointers, since precedence prevents
  2411. 36199  *              anything being concatenated to any individual branch.  The
  2412. 36200  *              "next" pointer of the last BRANCH in a choice points to the
  2413. 36201  *              thing following the whole choice.  This is also where the
  2414. 36202  *              final "next" pointer of each individual branch points; each
  2415. 36203  *              branch starts with the operand node of a BRANCH node.
  2416. 36204  *
  2417. 36205  * BACK         Normal "next" pointers all implicitly point forward; BACK
  2418. 36206  *              exists to make loop structures possible.
  2419. 36207  *
  2420. 36208  * STAR,PLUS    '?', and complex '*' and '+', are implemented as circular
  2421. 36209  *              BRANCH structures using BACK.  Simple cases (one character
  2422. 36210  *              per match) are implemented with STAR and PLUS for speed
  2423. 36211  *              and to minimize recursive plunges.
  2424. 36212  *
  2425. 36213  * OPEN,CLOSE   ...are numbered at compile time.
  2426. 36214  */
  2427. 36215
  2428. 36216 /* A node is one char of opcode followed by two chars of "next" pointer.
  2429. 36217  * "Next" pointers are stored as two 8-bit pieces, high order first.  The
  2430. 36218  * value is a positive offset from the opcode of the node containing it.
  2431. 36219  * An operand, if any, simply follows the node.  (Note that much of the
  2432. 36220  * code generation knows about this implicit relationship.)
  2433. 36221  *
  2434. 36222  * Using two bytes for the "next" pointer is vast overkill for most things,
  2435. 36223  * but allows patterns to get big without disasters.
  2436. 36224  */
  2437. 36225 #define OP(p)   (*(p))
  2438. 36226 #define NEXT(p) (((*((p)+1)&0377)<<8) + (*((p)+2)&0377))
  2439. 36227 #define OPERAND(p)      ((p) + 3)
  2440. 36228
  2441. 36229 /* Utility definitions.
  2442. 36230  */
  2443. 36231 #ifndef CHARBITS
  2444. 36232 #define UCHARAT(p)      ((int)*(unsigned char *)(p))
  2445. 36233 #else
  2446. 36234 #define UCHARAT(p)      ((int)*(p)&CHARBITS)
  2447. 36235 #endif
  2448. 36236
  2449. 36237 #define CFAIL(m)        { regerror(m); return((char *)NULL); }
  2450. 36238 #define RFAIL(m)        { regerror(m); return((regexp *)NULL); }
  2451. 36239 #define ISMULT(c)       ((c) == '*' || (c) == '+' || (c) == '?')
  2452. 36240 #define META    "^$.[()|?+*\"
  2453. 36241
  2454. 36242 /* Flags to be passed up and down.
  2455. 36243  */
  2456. 36244 #define HASWIDTH        01      /* Known never to match null string. */
  2457. 36245 #define SIMPLE          02      /* Simple enough to be STAR/PLUS operand. */
  2458. 36246 #define SPSTART         04      /* Starts with * or +. */
  2459. 36247 #define WORST           0       /* Worst case. */
  2460. 36248
  2461. 36249 /* Global work variables for regcomp().
  2462. 36250  */
  2463. 36251 PRIVATE char *regparse;         /* Input-scan pointer. */
  2464. 36252 PRIVATE int regnpar;            /* () count. */
  2465. 36253 PRIVATE char regdummy;
  2466. 36254 PRIVATE char *regcode;          /* Code-emit pointer; &regdummy = don't. */
  2467. 36255 PRIVATE long regsize;           /* Code size. */
  2468. 36256
  2469. 36257 /* Forward declarations for regcomp()'s friends.
  2470. 36258  */
  2471. 36259 #ifndef STATIC
  2472. 36260 #define STATIC  PRIVATE
  2473. 36261 #endif
  2474. 36262 STATIC _PROTOTYPE( char *reg, (int paren, int *flagp)                   );
  2475. 36263 STATIC _PROTOTYPE( char *regbranch, (int *flagp)                        );
  2476. 36264 STATIC _PROTOTYPE( char *regpiece, (int *flagp)                         );
  2477. 36265 STATIC _PROTOTYPE( char *regatom, (int *flagp)                          );
  2478. 36266 STATIC _PROTOTYPE( char *regnode, (int op)                              );
  2479. 36267 STATIC _PROTOTYPE( char *regnext, (char *p)                             );
  2480. 36268 STATIC _PROTOTYPE( void regc, (int b)                                   );
  2481. 36269 STATIC _PROTOTYPE( void reginsert, (int op, char *opnd)                 );
  2482. 36270 STATIC _PROTOTYPE( void regtail, (char *p, char *val)                   );
  2483. 36271 STATIC _PROTOTYPE( void regoptail, (char *p, char *val)                 );
  2484. 36272
  2485. 36273 /*
  2486. 36274  - regcomp - compile a regular expression into internal code
  2487. 36275  *
  2488. 36276  * We can't allocate space until we know how big the compiled form will be,
  2489. 36277  * but we can't compile it (and thus know how big it is) until we've got a
  2490. 36278  * place to put the code.  So we cheat:  we compile it twice, once with code
  2491. 36279  * generation turned off and size counting turned on, and once "for real".
  2492. 36280  * This also means that we don't allocate space until we are sure that the
  2493. 36281  * thing really will compile successfully, and we never have to move the
  2494. 36282  * code and thus invalidate pointers into it.  (Note that it has to be in
  2495. 36283  * one piece because free() must be able to free it all.)
  2496. 36284  *
  2497. 36285  * Beware that the optimization-preparation code in here knows about some
  2498. 36286  * of the structure of the compiled regexp.
  2499. 36287  */
  2500. 36288 regexp *regcomp(exp)
  2501. 36289 char *exp;
  2502. 36290 {
  2503. 36291   register regexp *r;
  2504. 36292   register char *scan;
  2505. 36293   register char *longest;
  2506. 36294   register int len;
  2507. 36295   int flags;
  2508. 36296
  2509. 36297   if (exp == (char *)NULL) RFAIL("NULL argument");
  2510. 36298
  2511. 36299   /* First pass: determine size, legality. */
  2512. 36300   regparse = exp;
  2513. 36301   regnpar = 1;
  2514. 36302   regsize = 0L;
  2515. 36303   regcode = &regdummy;
  2516. 36304   regc(MAGIC);
  2517. 36305   if (reg(0, &flags) == (char *)NULL) return((regexp *)NULL);
  2518. 36306
  2519. 36307   /* Small enough for pointer-storage convention? */
  2520. 36308   if (regsize >= 32767L)        /* Probably could be 65535L. */
  2521. 36309         RFAIL("regexp too big");
  2522. 36310
  2523. 36311   /* Allocate space. */
  2524. 36312   r = (regexp *) malloc(sizeof(regexp) + (unsigned) regsize);
  2525. 36313   if (r == (regexp *)NULL) RFAIL("out of space");
  2526. 36314
  2527. 36315   /* Second pass: emit code. */
  2528. 36316   regparse = exp;
  2529. 36317   regnpar = 1;
  2530. 36318   regcode = r->program;
  2531. 36319   regc(MAGIC);
  2532. 36320   if (reg(0, &flags) == (char *)NULL) return((regexp *)NULL);
  2533. 36321
  2534. 36322   /* Dig out information for optimizations. */
  2535. 36323   r->regstart = '';           /* Worst-case defaults. */
  2536. 36324   r->reganch = 0;
  2537. 36325   r->regmust = (char *)NULL;
  2538. 36326   r->regmlen = 0;
  2539. 36327   scan = r->program + 1;        /* First BRANCH. */
  2540. 36328   if (OP(regnext(scan)) == END) {       /* Only one top-level choice. */
  2541. 36329         scan = OPERAND(scan);
  2542. 36330
  2543. 36331         /* Starting-point info. */
  2544. 36332         if (OP(scan) == EXACTLY)
  2545. 36333                 r->regstart = *OPERAND(scan);
  2546. 36334         else if (OP(scan) == BOL)
  2547. 36335                 r->reganch++;
  2548. 36336
  2549. 36337         /* If there's something expensive in the r.e., find the
  2550. 36338          * longest literal string that must appear and make it the
  2551. 36339          * regmust.  Resolve ties in favor of later strings, since
  2552. 36340          * the regstart check works with the beginning of the r.e.
  2553. 36341          * and avoiding duplication strengthens checking.  Not a
  2554. 36342          * strong reason, but sufficient in the absence of others. */
  2555. 36343         if (flags & SPSTART) {
  2556. 36344                 longest = (char *)NULL;
  2557. 36345                 len = 0;
  2558. 36346                 for (; scan != (char *)NULL; scan = regnext(scan))
  2559. 36347                         if (OP(scan) == EXACTLY && strlen(OPERAND(scan)) >= len) {
  2560. 36348                                 longest = OPERAND(scan);
  2561. 36349                                 len = strlen(OPERAND(scan));
  2562. 36350                         }
  2563. 36351                 r->regmust = longest;
  2564. 36352                 r->regmlen = len;
  2565. 36353         }
  2566. 36354   }
  2567. 36355   return(r);
  2568. 36356 }
  2569. 36358 /*
  2570. 36359  - reg - regular expression, i.e. main body or parenthesized thing
  2571. 36360  *
  2572. 36361  * Caller must absorb opening parenthesis.
  2573. 36362  *
  2574. 36363  * Combining parenthesis handling with the base level of regular expression
  2575. 36364  * is a trifle forced, but the need to tie the tails of the branches to what
  2576. 36365  * follows makes it hard to avoid.
  2577. 36366  */
  2578. 36367 PRIVATE char *reg(paren, flagp)
  2579. 36368 int paren;                      /* Parenthesized? */
  2580. 36369 int *flagp;
  2581. 36370 {
  2582. 36371   register char *ret;
  2583. 36372   register char *br;
  2584. 36373   register char *ender;
  2585. 36374   register int parno;
  2586. 36375   int flags;
  2587. 36376
  2588. 36377   *flagp = HASWIDTH;            /* Tentatively. */
  2589. 36378
  2590. 36379   /* Make an OPEN node, if parenthesized. */
  2591. 36380   if (paren) {
  2592. 36381         if (regnpar >= NSUBEXP) CFAIL("too many ()");
  2593. 36382         parno = regnpar;
  2594. 36383         regnpar++;
  2595. 36384         ret = regnode(OPEN + parno);
  2596. 36385   } else {
  2597. 36386         parno = 0;              /* not actually used, keep compiler quiet */
  2598. 36387         ret = (char *)NULL;
  2599. 36388   }
  2600. 36389
  2601. 36390   /* Pick up the branches, linking them together. */
  2602. 36391   br = regbranch(&flags);
  2603. 36392   if (br == (char *)NULL) return((char *)NULL);
  2604. 36393   if (ret != (char *)NULL)
  2605. 36394         regtail(ret, br);       /* OPEN -> first. */
  2606. 36395   else
  2607. 36396         ret = br;
  2608. 36397   if (!(flags & HASWIDTH)) *flagp &= ~HASWIDTH;
  2609. 36398   *flagp |= flags & SPSTART;
  2610. 36399   while (*regparse == '|') {
  2611. 36400         regparse++;
  2612. 36401         br = regbranch(&flags);
  2613. 36402         if (br == (char *)NULL) return((char *)NULL);
  2614. 36403         regtail(ret, br);       /* BRANCH -> BRANCH. */
  2615. 36404         if (!(flags & HASWIDTH)) *flagp &= ~HASWIDTH;
  2616. 36405         *flagp |= flags & SPSTART;
  2617. 36406   }
  2618. 36407
  2619. 36408   /* Make a closing node, and hook it on the end. */
  2620. 36409   ender = regnode((paren) ? CLOSE + parno : END);
  2621. 36410   regtail(ret, ender);
  2622. 36411
  2623. 36412   /* Hook the tails of the branches to the closing node. */
  2624. 36413   for (br = ret; br != (char *)NULL; br = regnext(br)) regoptail(br, ender);
  2625. 36414
  2626. 36415   /* Check for proper termination. */
  2627. 36416   if (paren && *regparse++ != ')') {
  2628. 36417         CFAIL("unmatched ()");
  2629. 36418   } else if (!paren && *regparse != '') {
  2630. 36419         if (*regparse == ')') {
  2631. 36420                 CFAIL("unmatched ()");
  2632. 36421         } else
  2633. 36422                 CFAIL("junk on end");   /* "Can't happen". */
  2634. 36423         /* NOTREACHED */
  2635. 36424   }
  2636. 36425   return(ret);
  2637. 36426 }
  2638. 36428 /*
  2639. 36429  - regbranch - one alternative of an | operator
  2640. 36430  *
  2641. 36431  * Implements the concatenation operator.
  2642. 36432  */
  2643. 36433 PRIVATE char *regbranch(flagp)
  2644. 36434 int *flagp;
  2645. 36435 {
  2646. 36436   register char *ret;
  2647. 36437   register char *chain;
  2648. 36438   register char *latest;
  2649. 36439   int flags;
  2650. 36440
  2651. 36441   *flagp = WORST;               /* Tentatively. */
  2652. 36442
  2653. 36443   ret = regnode(BRANCH);
  2654. 36444   chain = (char *)NULL;
  2655. 36445   while (*regparse != '' && *regparse != '|' && *regparse != ')') {
  2656. 36446         latest = regpiece(&flags);
  2657. 36447         if (latest == (char *)NULL) return((char *)NULL);
  2658. 36448         *flagp |= flags & HASWIDTH;
  2659. 36449         if (chain == (char *)NULL)      /* First piece. */
  2660. 36450                 *flagp |= flags & SPSTART;
  2661. 36451         else
  2662. 36452                 regtail(chain, latest);
  2663. 36453         chain = latest;
  2664. 36454   }
  2665. 36455   if (chain == (char *)NULL)            /* Loop ran zero times. */
  2666. 36456         regnode(NOTHING);
  2667. 36457
  2668. 36458   return(ret);
  2669. 36459 }
  2670. 36461 /*
  2671. 36462  - regpiece - something followed by possible [*+?]
  2672. 36463  *
  2673. 36464  * Note that the branching code sequences used for ? and the general cases
  2674. 36465  * of * and + are somewhat optimized:  they use the same NOTHING node as
  2675. 36466  * both the endmarker for their branch list and the body of the last branch.
  2676. 36467  * It might seem that this node could be dispensed with entirely, but the
  2677. 36468  * endmarker role is not redundant.
  2678. 36469  */
  2679. 36470 PRIVATE char *regpiece(flagp)
  2680. 36471 int *flagp;
  2681. 36472 {
  2682. 36473   register char *ret;
  2683. 36474   register char op;
  2684. 36475   register char *next;
  2685. 36476   int flags;
  2686. 36477
  2687. 36478   ret = regatom(&flags);
  2688. 36479   if (ret == (char *)NULL) return((char *)NULL);
  2689. 36480
  2690. 36481   op = *regparse;
  2691. 36482   if (!ISMULT(op)) {
  2692. 36483         *flagp = flags;
  2693. 36484         return(ret);
  2694. 36485   }
  2695. 36486   if (!(flags & HASWIDTH) && op != '?') CFAIL("*+ operand could be empty");
  2696. 36487   *flagp = (op != '+') ? (WORST | SPSTART) : (WORST | HASWIDTH);
  2697. 36488
  2698. 36489   if (op == '*' && (flags & SIMPLE))
  2699. 36490         reginsert(STAR, ret);
  2700. 36491   else if (op == '*') {
  2701. 36492         /* Emit x* as (x&|), where & means "self". */
  2702. 36493         reginsert(BRANCH, ret); /* Either x */
  2703. 36494         regoptail(ret, regnode(BACK));  /* and loop */
  2704. 36495         regoptail(ret, ret);    /* back */
  2705. 36496         regtail(ret, regnode(BRANCH));  /* or */
  2706. 36497         regtail(ret, regnode(NOTHING)); /* null. */
  2707. 36498   } else if (op == '+' && (flags & SIMPLE))
  2708. 36499         reginsert(PLUS, ret);
  2709. 36500   else if (op == '+') {
  2710. 36501         /* Emit x+ as x(&|), where & means "self". */
  2711. 36502         next = regnode(BRANCH); /* Either */
  2712. 36503         regtail(ret, next);
  2713. 36504         regtail(regnode(BACK), ret);    /* loop back */
  2714. 36505         regtail(next, regnode(BRANCH)); /* or */
  2715. 36506         regtail(ret, regnode(NOTHING)); /* null. */
  2716. 36507   } else if (op == '?') {
  2717. 36508         /* Emit x? as (x|) */
  2718. 36509         reginsert(BRANCH, ret); /* Either x */
  2719. 36510         regtail(ret, regnode(BRANCH));  /* or */
  2720. 36511         next = regnode(NOTHING);/* null. */
  2721. 36512         regtail(ret, next);
  2722. 36513         regoptail(ret, next);
  2723. 36514   }
  2724. 36515   regparse++;
  2725. 36516   if (ISMULT(*regparse)) CFAIL("nested *?+");
  2726. 36517
  2727. 36518   return(ret);
  2728. 36519 }
  2729. 36521 /*
  2730. 36522  - regatom - the lowest level
  2731. 36523  *
  2732. 36524  * Optimization:  gobbles an entire sequence of ordinary characters so that
  2733. 36525  * it can turn them into a single node, which is smaller to store and
  2734. 36526  * faster to run.  Backslashed characters are exceptions, each becoming a
  2735. 36527  * separate node; the code is simpler that way and it's not worth fixing.
  2736. 36528  */
  2737. 36529 PRIVATE char *regatom(flagp)
  2738. 36530 int *flagp;
  2739. 36531 {
  2740. 36532   register char *ret;
  2741. 36533   int flags;
  2742. 36534
  2743. 36535   *flagp = WORST;               /* Tentatively. */
  2744. 36536
  2745. 36537   switch (*regparse++) {
  2746. 36538       case '^': ret = regnode(BOL);             break;
  2747. 36539       case '$': ret = regnode(EOL);             break;
  2748. 36540       case '.':
  2749. 36541         ret = regnode(ANY);
  2750. 36542         *flagp |= HASWIDTH | SIMPLE;
  2751. 36543         break;
  2752. 36544       case '[':{
  2753. 36545                 register int class;
  2754. 36546                 register int classend;
  2755. 36547
  2756. 36548                 if (*regparse == '^') { /* Complement of range. */
  2757. 36549                         ret = regnode(ANYBUT);
  2758. 36550                         regparse++;
  2759. 36551                 } else
  2760. 36552                         ret = regnode(ANYOF);
  2761. 36553                 if (*regparse == ']' || *regparse == '-') regc(*regparse++);
  2762. 36554                 while (*regparse != '' && *regparse != ']') {
  2763. 36555                         if (*regparse == '-') {
  2764. 36556                                 regparse++;
  2765. 36557                                 if (*regparse == ']' || *regparse == '')
  2766. 36558                                         regc('-');
  2767. 36559                                 else {
  2768. 36560                                         class = UCHARAT(regparse - 2) + 1;
  2769. 36561                                         classend = UCHARAT(regparse);
  2770. 36562                                         if (class > classend + 1)
  2771. 36563                                                 CFAIL("invalid [] range");
  2772. 36564                                         for (; class <= classend; class++)
  2773. 36565                                                 regc(class);
  2774. 36566                                         regparse++;
  2775. 36567                                 }
  2776. 36568                         } else
  2777. 36569                                 regc(*regparse++);
  2778. 36570                 }
  2779. 36571                 regc('');
  2780. 36572                 if (*regparse != ']') CFAIL("unmatched []");
  2781. 36573                 regparse++;
  2782. 36574                 *flagp |= HASWIDTH | SIMPLE;
  2783. 36575         }
  2784. 36576         break;
  2785. 36577       case '(':
  2786. 36578         ret = reg(1, &flags);
  2787. 36579         if (ret == (char *)NULL) return((char *)NULL);
  2788. 36580         *flagp |= flags & (HASWIDTH | SPSTART);
  2789. 36581         break;
  2790. 36582       case '':
  2791. 36583       case '|':
  2792. 36584       case ')':
  2793. 36585         CFAIL("internal urp");  /* Supposed to be caught earlier. */
  2794. 36586         break;
  2795. 36587       case '?':
  2796. 36588       case '+':
  2797. 36589       case '*': CFAIL("?+* follows nothing");           break;
  2798. 36590       case '\':
  2799. 36591         if (*regparse == '') CFAIL("trailing \");
  2800. 36592         ret = regnode(EXACTLY);
  2801. 36593         regc(*regparse++);
  2802. 36594         regc('');
  2803. 36595         *flagp |= HASWIDTH | SIMPLE;
  2804. 36596         break;
  2805. 36597       default:{
  2806. 36598                 register int len;
  2807. 36599                 register char ender;
  2808. 36600
  2809. 36601                 regparse--;
  2810. 36602                 len = strcspn(regparse, META);
  2811. 36603                 if (len <= 0) CFAIL("internal disaster");
  2812. 36604                 ender = *(regparse + len);
  2813. 36605                 if (len > 1 && ISMULT(ender))
  2814. 36606                         len--;  /* Back off clear of ?+* operand. */
  2815. 36607                 *flagp |= HASWIDTH;
  2816. 36608                 if (len == 1) *flagp |= SIMPLE;
  2817. 36609                 ret = regnode(EXACTLY);
  2818. 36610                 while (len > 0) {
  2819. 36611                         regc(*regparse++);
  2820. 36612                         len--;
  2821. 36613                 }
  2822. 36614                 regc('');
  2823. 36615         }
  2824. 36616         break;
  2825. 36617   }
  2826. 36618
  2827. 36619   return(ret);
  2828. 36620 }
  2829. 36622 /*
  2830. 36623  - regnode - emit a node
  2831. 36624  */
  2832. 36625 PRIVATE char *regnode(op)
  2833. 36626 char op;
  2834. 36627 {
  2835. 36628   register char *ret;
  2836. 36629   register char *ptr;
  2837. 36630
  2838. 36631   ret = regcode;
  2839. 36632   if (ret == &regdummy) {
  2840. 36633         regsize += 3;
  2841. 36634         return(ret);
  2842. 36635   }
  2843. 36636   ptr = ret;
  2844. 36637   *ptr++ = op;
  2845. 36638   *ptr++ = '';                /* Null "next" pointer. */
  2846. 36639   *ptr++ = '';
  2847. 36640   regcode = ptr;
  2848. 36641
  2849. 36642   return(ret);
  2850. 36643 }
  2851. 36645 /*
  2852. 36646  - regc - emit (if appropriate) a byte of code
  2853. 36647  */
  2854. 36648 PRIVATE void regc(b)
  2855. 36649 char b;
  2856. 36650 {
  2857. 36651   if (regcode != &regdummy)
  2858. 36652         *regcode++ = b;
  2859. 36653   else
  2860. 36654         regsize++;
  2861. 36655 }
  2862. 36657 /*
  2863. 36658  - reginsert - insert an operator in front of already-emitted operand
  2864. 36659  *
  2865. 36660  * Means relocating the operand.
  2866. 36661  */
  2867. 36662 PRIVATE void reginsert(op, opnd)
  2868. 36663 char op;
  2869. 36664 char *opnd;
  2870. 36665 {
  2871. 36666   register char *src;
  2872. 36667   register char *dst;
  2873. 36668   register char *place;
  2874. 36669
  2875. 36670   if (regcode == &regdummy) {
  2876. 36671         regsize += 3;
  2877. 36672         return;
  2878. 36673   }
  2879. 36674   src = regcode;
  2880. 36675   regcode += 3;
  2881. 36676   dst = regcode;
  2882. 36677   while (src > opnd) *--dst = *--src;
  2883. 36678
  2884. 36679   place = opnd;                 /* Op node, where operand used to be. */
  2885. 36680   *place++ = op;
  2886. 36681   *place++ = '';
  2887. 36682   *place++ = '';
  2888. 36683 }
  2889. 36685 /*
  2890. 36686  - regtail - set the next-pointer at the end of a node chain
  2891. 36687  */
  2892. 36688 PRIVATE void regtail(p, val)
  2893. 36689 char *p;
  2894. 36690 char *val;
  2895. 36691 {
  2896. 36692   register char *scan;
  2897. 36693   register char *temp;
  2898. 36694   register int offset;
  2899. 36695
  2900. 36696   if (p == &regdummy) return;
  2901. 36697
  2902. 36698   /* Find last node. */
  2903. 36699   scan = p;
  2904. 36700   for (;;) {
  2905. 36701         temp = regnext(scan);
  2906. 36702         if (temp == (char *)NULL) break;
  2907. 36703         scan = temp;
  2908. 36704   }
  2909. 36705
  2910. 36706   if (OP(scan) == BACK)
  2911. 36707         offset = scan - val;
  2912. 36708   else
  2913. 36709         offset = val - scan;
  2914. 36710   *(scan + 1) = (offset >> 8) & 0377;
  2915. 36711   *(scan + 2) = offset & 0377;
  2916. 36712 }
  2917. 36714 /*
  2918. 36715  - regoptail - regtail on operand of first argument; nop if operandless
  2919. 36716  */
  2920. 36717 PRIVATE void regoptail(p, val)
  2921. 36718 char *p;
  2922. 36719 char *val;
  2923. 36720 {
  2924. 36721   /* "Operandless" and "op != BRANCH" are synonymous in practice. */
  2925. 36722   if (p == (char *)NULL || p == &regdummy || OP(p) != BRANCH) return;
  2926. 36723   regtail(OPERAND(p), val);
  2927. 36724 }
  2928. 36726 /* regexec and friends
  2929. 36727  */
  2930. 36728
  2931. 36729 /* Global work variables for regexec().
  2932. 36730  */
  2933. 36731 PRIVATE char *reginput;         /* String-input pointer. */
  2934. 36732 PRIVATE char *regbol;           /* Beginning of input, for ^ check. */
  2935. 36733 PRIVATE char **regstartp;       /* Pointer to startp array. */
  2936. 36734 PRIVATE char **regendp;         /* Ditto for endp. */
  2937. 36735
  2938. 36736 /* Forwards.
  2939. 36737  */
  2940. 36738 STATIC _PROTOTYPE( int regtry, (regexp *prog, char *string)             );
  2941. 36739 STATIC _PROTOTYPE( int regmatch, (char *prog)                           );
  2942. 36740 STATIC _PROTOTYPE( int regrepeat, (char *p)                             );
  2943. 36741
  2944. 36742 #ifdef DEBUG
  2945. 36743 int regnarrate = 0;
  2946. 36744 void regdump();
  2947. 36745 STATIC _PROTOTYPE( char *regprop, (char *op)                            );
  2948. 36746 #endif
  2949. 36747
  2950. 36748 /*
  2951. 36749  - regexec - match a regexp against a string
  2952. 36750  */
  2953. 36751 int regexec(prog, string, bolflag)
  2954. 36752 register regexp *prog;
  2955. 36753 register char *string;
  2956. 36754 int bolflag;
  2957. 36755 {
  2958. 36756   register char *s;
  2959. 36757
  2960. 36758   /* Be paranoid... */
  2961. 36759   if (prog == (regexp *)NULL || string == (char *)NULL) {
  2962. 36760         regerror("NULL parameter");
  2963. 36761         return(0);
  2964. 36762   }
  2965. 36763
  2966. 36764   /* Check validity of program. */
  2967. 36765   if (UCHARAT(prog->program) != MAGIC) {
  2968. 36766         regerror("corrupted program");
  2969. 36767         return(0);
  2970. 36768   }
  2971. 36769
  2972. 36770   /* If there is a "must appear" string, look for it. */
  2973. 36771   if (prog->regmust != (char *)NULL) {
  2974. 36772         s = string;
  2975. 36773         while ((s = strchr(s, prog->regmust[0])) != (char *)NULL) {
  2976. 36774                 if (strncmp(s, prog->regmust, prog->regmlen) == 0)
  2977. 36775                         break;  /* Found it. */
  2978. 36776                 s++;
  2979. 36777         }
  2980. 36778         if (s == (char *)NULL)          /* Not present. */
  2981. 36779                 return(0);
  2982. 36780   }
  2983. 36781
  2984. 36782   /* Mark beginning of line for ^ . */
  2985. 36783   if (bolflag)
  2986. 36784         regbol = string;
  2987. 36785   else
  2988. 36786         regbol = (char *)NULL;
  2989. 36787
  2990. 36788   /* Simplest case:  anchored match need be tried only once. */
  2991. 36789   if (prog->reganch) return(regtry(prog, string));
  2992. 36790
  2993. 36791   /* Messy cases:  unanchored match. */
  2994. 36792   s = string;
  2995. 36793   if (prog->regstart != '')   /* We know what char it must start with. */
  2996. 36794         while ((s = strchr(s, prog->regstart)) != (char *)NULL) {
  2997. 36795                 if (regtry(prog, s)) return(1);
  2998. 36796                 s++;
  2999. 36797         }
  3000. 36798   else
  3001. 36799         /* We don't -- general case. */
  3002. 36800         do {
  3003. 36801                 if (regtry(prog, s)) return(1);
  3004. 36802         } while (*s++ != '');
  3005. 36803
  3006. 36804   /* Failure. */
  3007. 36805   return(0);
  3008. 36806 }
  3009. 36808 /*
  3010. 36809  - regtry - try match at specific point
  3011. 36810  */
  3012. 36811 PRIVATE int regtry(prog, string)   /* 0 failure, 1 success */
  3013. 36812 regexp *prog;
  3014. 36813 char *string;
  3015. 36814 {
  3016. 36815   register int i;
  3017. 36816   register char **sp;
  3018. 36817   register char **ep;
  3019. 36818
  3020. 36819   reginput = string;
  3021. 36820   regstartp = prog->startp;
  3022. 36821   regendp = prog->endp;
  3023. 36822
  3024. 36823   sp = prog->startp;
  3025. 36824   ep = prog->endp;
  3026. 36825   for (i = NSUBEXP; i > 0; i--) {
  3027. 36826         *sp++ = (char *)NULL;
  3028. 36827         *ep++ = (char *)NULL;
  3029. 36828   }
  3030. 36829   if (regmatch(prog->program + 1)) {
  3031. 36830         prog->startp[0] = string;
  3032. 36831         prog->endp[0] = reginput;
  3033. 36832         return(1);
  3034. 36833   } else
  3035. 36834         return(0);
  3036. 36835 }
  3037. 36837 /*
  3038. 36838  - regmatch - main matching routine
  3039. 36839  *
  3040. 36840  * Conceptually the strategy is simple:  check to see whether the current
  3041. 36841  * node matches, call self recursively to see whether the rest matches,
  3042. 36842  * and then act accordingly.  In practice we make some effort to avoid
  3043. 36843  * recursion, in particular by going through "ordinary" nodes (that don't
  3044. 36844  * need to know whether the rest of the match failed) by a loop instead of
  3045. 36845  * by recursion.
  3046. 36846  */
  3047. 36847 PRIVATE int regmatch(prog)      /* 0 failure, 1 success */ 
  3048. 36848 char *prog;
  3049. 36849 {
  3050. 36850   register char *scan;          /* Current node. */
  3051. 36851   char *next;                   /* Next node. */
  3052. 36852
  3053. 36853   scan = prog;
  3054. 36854 #ifdef DEBUG
  3055. 36855   if (scan != (char *)NULL && regnarrate) fprintf(stderr, "%s(n", regprop(scan));
  3056. 36856 #endif
  3057. 36857   while (scan != (char *)NULL) {
  3058. 36858 #ifdef DEBUG
  3059. 36859         if (regnarrate) fprintf(stderr, "%s...n", regprop(scan));
  3060. 36860 #endif
  3061. 36861         next = regnext(scan);
  3062. 36862
  3063. 36863         switch (OP(scan)) {
  3064. 36864             case BOL:
  3065. 36865                 if (reginput != regbol) return(0);
  3066. 36866                 break;
  3067. 36867             case EOL:
  3068. 36868                 if (*reginput != '') return(0);
  3069. 36869                 break;
  3070. 36870             case ANY:
  3071. 36871                 if (*reginput == '') return(0);
  3072. 36872                 reginput++;
  3073. 36873                 break;
  3074. 36874             case EXACTLY:{
  3075. 36875                         register int len;
  3076. 36876                         register char *opnd;
  3077. 36877
  3078. 36878                         opnd = OPERAND(scan);
  3079. 36879                         /* Inline the first character, for speed. */
  3080. 36880                         if (*opnd != *reginput) return(0);
  3081. 36881                         len = strlen(opnd);
  3082. 36882                         if (len > 1 && strncmp(opnd, reginput, len) != 0)
  3083. 36883                                 return(0);
  3084. 36884                         reginput += len;
  3085. 36885                 }
  3086. 36886                 break;
  3087. 36887             case ANYOF:
  3088. 36888                 if (*reginput == '' || strchr(OPERAND(scan), *reginput) == (char *)NULL)
  3089. 36889                         return(0);
  3090. 36890                 reginput++;
  3091. 36891                 break;
  3092. 36892             case ANYBUT:
  3093. 36893                 if (*reginput == '' || strchr(OPERAND(scan), *reginput) != (char *)NULL)
  3094. 36894                         return(0);
  3095. 36895                 reginput++;
  3096. 36896                 break;
  3097. 36897             case NOTHING:
  3098. 36898                 break;
  3099. 36899             case BACK:
  3100. 36900                 break;
  3101. 36901             case OPEN + 1:
  3102. 36902             case OPEN + 2:
  3103. 36903             case OPEN + 3:
  3104. 36904             case OPEN + 4:
  3105. 36905             case OPEN + 5:
  3106. 36906             case OPEN + 6:
  3107. 36907             case OPEN + 7:
  3108. 36908             case OPEN + 8:
  3109. 36909             case OPEN + 9:{
  3110. 36910                         register int no;
  3111. 36911                         register char *save;
  3112. 36912
  3113. 36913                         no = OP(scan) - OPEN;
  3114. 36914                         save = reginput;
  3115. 36915
  3116. 36916                         if (regmatch(next)) {
  3117. 36917                                 /* Don't set startp if some later
  3118. 36918                                  * invocation of the same parentheses
  3119. 36919                                  * already has. */
  3120. 36920                                 if (regstartp[no] == (char *)NULL)
  3121. 36921                                         regstartp[no] = save;
  3122. 36922                                 return(1);
  3123. 36923                         } else
  3124. 36924                                 return(0);
  3125. 36925                 }
  3126. 36926                 break;
  3127. 36927             case CLOSE + 1:
  3128. 36928             case CLOSE + 2:
  3129. 36929             case CLOSE + 3:
  3130. 36930             case CLOSE + 4:
  3131. 36931             case CLOSE + 5:
  3132. 36932             case CLOSE + 6:
  3133. 36933             case CLOSE + 7:
  3134. 36934             case CLOSE + 8:
  3135. 36935             case CLOSE + 9:{
  3136. 36936                         register int no;
  3137. 36937                         register char *save;
  3138. 36938
  3139. 36939                         no = OP(scan) - CLOSE;
  3140. 36940                         save = reginput;
  3141. 36941
  3142. 36942                         if (regmatch(next)) {
  3143. 36943                                 /* Don't set endp if some later
  3144. 36944                                  * invocation of the same parentheses
  3145. 36945                                  * already has. */
  3146. 36946                                 if (regendp[no] == (char *)NULL) regendp[no] = save;
  3147. 36947                                 return(1);
  3148. 36948                         } else
  3149. 36949                                 return(0);
  3150. 36950                 }
  3151. 36951                 break;
  3152. 36952             case BRANCH:{
  3153. 36953                         register char *save;
  3154. 36954
  3155. 36955                         if (OP(next) != BRANCH) /* No choice. */
  3156. 36956                                 next = OPERAND(scan);   /* Avoid recursion. */
  3157. 36957                         else {
  3158. 36958                                 do {
  3159. 36959                                         save = reginput;
  3160. 36960                                         if (regmatch(OPERAND(scan)))
  3161. 36961                                                 return(1);
  3162. 36962                                         reginput = save;
  3163. 36963                                         scan = regnext(scan);
  3164. 36964                                 } while (scan != (char *)NULL && OP(scan) == BRANCH);
  3165. 36965                                 return(0);
  3166. 36966                                 /* NOTREACHED */
  3167. 36967                         }
  3168. 36968                 }
  3169. 36969                 break;
  3170. 36970             case STAR:
  3171. 36971             case PLUS:{
  3172. 36972                         register char nextch;
  3173. 36973                         register int no;
  3174. 36974                         register char *save;
  3175. 36975                         register int min;
  3176. 36976
  3177. 36977                         /* Lookahead to avoid useless match attempts
  3178. 36978                          * when we know what character comes next. */
  3179. 36979                         nextch = '';
  3180. 36980                         if (OP(next) == EXACTLY) nextch = *OPERAND(next);
  3181. 36981                         min = (OP(scan) == STAR) ? 0 : 1;
  3182. 36982                         save = reginput;
  3183. 36983                         no = regrepeat(OPERAND(scan));
  3184. 36984                         while (no >= min) {
  3185. 36985                                 /* If it could work, try it. */
  3186. 36986                                 if (nextch == '' || *reginput == nextch)
  3187. 36987                                         if (regmatch(next)) return(1);
  3188. 36988                                 /* Couldn't or didn't -- back up. */
  3189. 36989                                 no--;
  3190. 36990                                 reginput = save + no;
  3191. 36991                         }
  3192. 36992                         return(0);
  3193. 36993                 }
  3194. 36994                 break;
  3195. 36995             case END:
  3196. 36996                 return(1);      /* Success! */
  3197. 36997                 break;
  3198. 36998             default:
  3199. 36999                 regerror("memory corruption");
  3200. 37000                 return(0);
  3201. 37001                 break;
  3202. 37002         }
  3203. 37003
  3204. 37004         scan = next;
  3205. 37005   }
  3206. 37006
  3207. 37007   /* We get here only if there's trouble -- normally "case END" is the
  3208. 37008    * terminating point. */
  3209. 37009   regerror("corrupted pointers");
  3210. 37010   return(0);
  3211. 37011 }
  3212. 37013 /*
  3213. 37014  - regrepeat - repeatedly match something simple, report how many
  3214. 37015  */
  3215. 37016 PRIVATE int regrepeat(p)
  3216. 37017 char *p;
  3217. 37018 {
  3218. 37019   register int count = 0;
  3219. 37020   register char *scan;
  3220. 37021   register char *opnd;
  3221. 37022
  3222. 37023   scan = reginput;
  3223. 37024   opnd = OPERAND(p);
  3224. 37025   switch (OP(p)) {
  3225. 37026       case ANY:
  3226. 37027         count = strlen(scan);
  3227. 37028         scan += count;
  3228. 37029         break;
  3229. 37030       case EXACTLY:
  3230. 37031         while (*opnd == *scan) {
  3231. 37032                 count++;
  3232. 37033                 scan++;
  3233. 37034         }
  3234. 37035         break;
  3235. 37036       case ANYOF:
  3236. 37037         while (*scan != '' && strchr(opnd, *scan) != (char *)NULL) {
  3237. 37038                 count++;
  3238. 37039                 scan++;
  3239. 37040         }
  3240. 37041         break;
  3241. 37042       case ANYBUT:
  3242. 37043         while (*scan != '' && strchr(opnd, *scan) == (char *)NULL) {
  3243. 37044                 count++;
  3244. 37045                 scan++;
  3245. 37046         }
  3246. 37047         break;
  3247. 37048       default:                  /* Oh dear.  Called inappropriately. */
  3248. 37049         regerror("internal foulup");
  3249. 37050         count = 0;              /* Best compromise. */
  3250. 37051         break;
  3251. 37052   }
  3252. 37053   reginput = scan;
  3253. 37054
  3254. 37055   return(count);
  3255. 37056 }
  3256. 37058 /*
  3257. 37059  - regnext - dig the "next" pointer out of a node
  3258. 37060  */
  3259. 37061 PRIVATE char *regnext(p)
  3260. 37062 register char *p;
  3261. 37063 {
  3262. 37064   register int offset;
  3263. 37065
  3264. 37066   if (p == &regdummy) return((char *)NULL);
  3265. 37067
  3266. 37068   offset = NEXT(p);
  3267. 37069   if (offset == 0) return((char *)NULL);
  3268. 37070
  3269. 37071   if (OP(p) == BACK)
  3270. 37072         return(p - offset);
  3271. 37073   else
  3272. 37074         return(p + offset);
  3273. 37075 }
  3274. 37077 #ifdef DEBUG
  3275. 37078
  3276. 37079 STATIC char *regprop();
  3277. 37080
  3278. 37081 /*
  3279. 37082  - regdump - dump a regexp onto stdout in vaguely comprehensible form
  3280. 37083  */
  3281. 37084 void regdump(r)
  3282. 37085 regexp *r;
  3283. 37086 {
  3284. 37087   register char *s;
  3285. 37088   register char op = EXACTLY;   /* Arbitrary non-END op. */
  3286. 37089   register char *next;
  3287. 37090
  3288. 37091   s = r->program + 1;
  3289. 37092   while (op != END) {           /* While that wasn't END last time... */
  3290. 37093         op = OP(s);
  3291. 37094         printf("%2d%s", (int) (s - r->program), regprop(s));    /* Where, what. */
  3292. 37095         next = regnext(s);
  3293. 37096         if (next == (char *)NULL)       /* Next ptr. */
  3294. 37097                 printf("(0)");
  3295. 37098         else
  3296. 37099                 printf("(%d)", (int) (s - r->program) + (int) (next - s));
  3297. 37100         s += 3;
  3298. 37101         if (op == ANYOF || op == ANYBUT || op == EXACTLY) {
  3299. 37102                 /* Literal string, where present. */
  3300. 37103                 while (*s != '') {
  3301. 37104                         putchar(*s);
  3302. 37105                         s++;
  3303. 37106                 }
  3304. 37107                 s++;
  3305. 37108         }
  3306. 37109         putchar('n');
  3307. 37110   }
  3308. 37111
  3309. 37112   /* Header fields of interest. */
  3310. 37113   if (r->regstart != '') printf("start `%c' ", r->regstart);
  3311. 37114   if (r->reganch) printf("anchored ");
  3312. 37115   if (r->regmust != (char *)NULL) printf("must have "%s"", r->regmust);
  3313. 37116   printf("n");
  3314. 37117 }
  3315. 37119 /*
  3316. 37120  - regprop - printable representation of opcode
  3317. 37121  */
  3318. 37122 PRIVATE char *regprop(op)
  3319. 37123 char *op;
  3320. 37124 {
  3321. 37125   register char *p;
  3322. 37126   PRIVATE char buf[50];
  3323. 37127
  3324. 37128   (void) strcpy(buf, ":");
  3325. 37129
  3326. 37130   switch (OP(op)) {
  3327. 37131       case BOL: p = "BOL";              break;
  3328. 37132       case EOL: p = "EOL";              break;
  3329. 37133       case ANY: p = "ANY";              break;
  3330. 37134       case ANYOF:       p = "ANYOF";            break;
  3331. 37135       case ANYBUT:      p = "ANYBUT";           break;
  3332. 37136       case BRANCH:      p = "BRANCH";           break;
  3333. 37137       case EXACTLY:     p = "EXACTLY";          break;
  3334. 37138       case NOTHING:     p = "NOTHING";          break;
  3335. 37139       case BACK:        p = "BACK";             break;
  3336. 37140       case END: p = "END";              break;
  3337. 37141       case OPEN + 1:
  3338. 37142       case OPEN + 2:
  3339. 37143       case OPEN + 3:
  3340. 37144       case OPEN + 4:
  3341. 37145       case OPEN + 5:
  3342. 37146       case OPEN + 6:
  3343. 37147       case OPEN + 7:
  3344. 37148       case OPEN + 8:
  3345. 37149       case OPEN + 9:
  3346. 37150         sprintf(buf + strlen(buf), "OPEN%d", OP(op) - OPEN);
  3347. 37151         p = (char *)NULL;
  3348. 37152         break;
  3349. 37153       case CLOSE + 1:
  3350. 37154       case CLOSE + 2:
  3351. 37155       case CLOSE + 3:
  3352. 37156       case CLOSE + 4:
  3353. 37157       case CLOSE + 5:
  3354. 37158       case CLOSE + 6:
  3355. 37159       case CLOSE + 7:
  3356. 37160       case CLOSE + 8:
  3357. 37161       case CLOSE + 9:
  3358. 37162         sprintf(buf + strlen(buf), "CLOSE%d", OP(op) - CLOSE);
  3359. 37163         p = (char *)NULL;
  3360. 37164         break;
  3361. 37165       case STAR:        p = "STAR";             break;
  3362. 37166       case PLUS:        p = "PLUS";             break;
  3363. 37167       default:  regerror("corrupted opcode"); p = (char *) NULL; break;
  3364. 37168   }
  3365. 37169   if (p != (char *)NULL) (void) strcat(buf, p);
  3366. 37170   return(buf);
  3367. 37171 }