LIB.T
上传用户:datang2001
上传日期:2007-02-01
资源大小:53269k
文件大小:969k
源码类别:

操作系统开发

开发平台:

C/C++

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