home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume13 / rolodex / part04 < prev    next >
Text File  |  1988-01-30  |  24KB  |  1,084 lines

  1. Subject:  v13i052:  Screen-oriented rolodex program, Part04/04
  2. Newsgroups: comp.sources.unix
  3. Sender: sources
  4. Approved: rsalz@uunet.UU.NET
  5.  
  6. Submitted-by: Dave Ihnat <ihnp4!homebru!ignatz>
  7. Posting-number: Volume 13, Issue 52
  8. Archive-name: rolodex/part04
  9.  
  10. #! /bin/sh
  11. # This is a shell archive.  Remove anything before this line, then unpack
  12. # it by saving it into a file and typing "sh file".  To overwrite existing
  13. # files, type "sh file -c".  You can also feed this as standard input via
  14. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  15. # will see the following message at the end:
  16. #        "End of archive 4 (of 4)."
  17. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  18. if test -f './toolsdir/ctools.c' -a "${1}" != "-c" ; then 
  19.   echo shar: Will not clobber existing file \"'./toolsdir/ctools.c'\"
  20. else
  21. echo shar: Extracting \"'./toolsdir/ctools.c'\" \(21027 characters\)
  22. sed "s/^X//" >'./toolsdir/ctools.c' <<'END_OF_FILE'
  23. X/* -*- Mode: C; Package: (CTOOLS C) -*- */
  24. X
  25. X#include <ctype.h>
  26. X#include <stdio.h>
  27. X
  28. X#ifdef BSD42
  29. X#include <strings.h>
  30. X#endif
  31. X
  32. X#include "sys5.h"
  33. X
  34. X#include "ctools.h"
  35. X
  36. X#include "basics.h"
  37. Xchar maxintstr[30] = { '\0' };
  38. X
  39. X#ifdef MSDOS
  40. X#define rindex strrchr 
  41. X#define index strchr
  42. X#include <string.h>
  43. X#endif
  44. X
  45. X/* miscellaneous fairly primitive routines that deal with characters, */
  46. X/* strings, memory, simple input and pathnames. */
  47. X
  48. X/* Author:  JP Massar */
  49. X/* Thinking Machines Corporation */
  50. X
  51. X/* Included routines:
  52. X
  53. X   emalloc
  54. X   anewstr
  55. X   
  56. X   copy
  57. X   fill
  58. X   
  59. X   to_upper_if_lower
  60. X   to_lower_if_upper
  61. X   
  62. X   buffconcat
  63. X   nbuffconcat
  64. X   
  65. X   slcompare
  66. X   slge_compare
  67. X   nocase_compare
  68. X   
  69. X   strfind
  70. X   strncfind
  71. X   strsearch
  72. X   strncsearch
  73. X   
  74. X   yes_or_no_check
  75. X   
  76. X   remove_excess_blanks
  77. X   ip_string_trim
  78. X   string_trim
  79. X   string_upcase
  80. X   string_downcase
  81. X   
  82. X   all_digits
  83. X   all_whitespace
  84. X   all_uppercase
  85. X   all_lowercase
  86. X   all_alphabetic
  87. X   all_alphanumeric
  88. X   all_ascii
  89. X   
  90. X   str_to_pos_int
  91. X   
  92. X   sreverse
  93. X   ip_sreverse
  94. X        
  95. X   temp_path
  96. X   perm_path
  97. X   make_path_numeric_extension
  98. X   make_path
  99. X   just_filename
  100. X   
  101. X   read_yes_or_no
  102. X   getline
  103. X   getlines
  104. X   ngetlines
  105. X   getfile
  106. X   ngetfile
  107. X   read_file_into_buffer
  108. X   efopen
  109. X
  110. X   check_int
  111. X   check_string
  112. X   
  113. X*/
  114. X   
  115. X
  116. Xextern char *malloc();
  117. X
  118. X
  119. Xchar *emalloc (space) int space;
  120. X
  121. X/* allocate 'space' bytes, die if we have run out of memory. */
  122. X
  123. X{
  124. X  char *rval;        
  125. X  if (space < 0) {
  126. X     fprintf(stderr,"Fatal error: argument to emalloc < 0\n");
  127. X     exit(-1);
  128. X  }
  129. X  if (0 == (rval = malloc((unsigned) space))) {
  130. X     fprintf(stderr,"Fatal error:  No more memory\n");
  131. X     exit(-1);
  132. X  }
  133. X  return(rval);
  134. X}  
  135. X
  136. X
  137. Xchar *anewstr (astring) char *astring;
  138. X
  139. X/* allocate space for and then copy a string.  Returns pointer to */
  140. X/* new string. */
  141. X
  142. X{        
  143. X  char *newstr;
  144. X  newstr = emalloc(strlen(astring)+1);
  145. X  strcpy(newstr,astring);
  146. X  return(newstr);
  147. X}
  148. X
  149. X
  150. Xcopy (dest,src,n)
  151. X
  152. X  /* copy n bytes */
  153. X
  154. X  register char *dest,*src;
  155. X  register int n;
  156. X
  157. X  { register int j = 0;
  158. X    while (j++ < n) *dest++ = *src++; 
  159. X  }
  160. X
  161. Xfill (addr,ch,n)
  162. X
  163. X  /* fill n sequential bytes with 'ch' */
  164. X
  165. X  register char *addr;
  166. X  register char ch;
  167. X  register int n;
  168. X  
  169. X  { register int j = 0;
  170. X    while (j++ < n) *addr++ = ch;
  171. X  }
  172. X
  173. X
  174. Xto_upper_if_lower (ch)
  175. X
  176. X  char ch;
  177. X
  178. X  { return(islower(ch) ? toupper(ch) : ch); }
  179. X
  180. X
  181. Xto_lower_if_upper (ch)
  182. X
  183. X  char ch;
  184. X
  185. X  { return(isupper(ch) ? tolower(ch) : ch); }
  186. X
  187. X
  188. Xbuffconcat (buffer,s1,s2) 
  189. X
  190. X  /* concatenate two null terminated strings into a buffer. */
  191. X
  192. X  char *buffer, *s1, *s2;
  193. X  
  194. X  { while (*s1 != '\0') *buffer++ = *s1++;
  195. X    while (*s2 != '\0') *buffer++ = *s2++;
  196. X    *buffer = '\0';
  197. X  }
  198. X
  199. X
  200. Xnbuffconcat (buffer,n,s1,s2,s3,s4,s5,s6)
  201. X
  202. X  /* concatenates up to 6 strings into a buffer.  Returns -1 if n */
  203. X  /* is not reasonable, otherwise returns 0. */
  204. X
  205. X  char *buffer;
  206. X  int n;
  207. X  char *s1,*s2,*s3,*s4,*s5,*s6;
  208. X
  209. X{
  210. X  register char *b;
  211. X  register char *s;
  212. X  int i;
  213. X  b = buffer;
  214. X  if (n < 1 || n > 6) return(-1);
  215. X  for (i = 1; i <= 6; i++) {
  216. X      if (i > n) break;
  217. X      switch (i) {
  218. X        case 1 : s = s1; break;
  219. X        case 2 : s = s2; break;
  220. X        case 3 : s = s3; break;
  221. X        case 4 : s = s4; break;
  222. X        case 5 : s = s5; break;
  223. X        case 6 : s = s6; break;
  224. X      }
  225. X      while (*s != '\0') *b++ = *s++;
  226. X  }
  227. X  *b = '\0';
  228. X  return(0);
  229. X}
  230. X
  231. X
  232. Xslcompare (s1,l1,s2,l2)
  233. X
  234. X  /* compare strings with possible nulls in them given their lengths */
  235. X  /* only returns EQUAL (0) or NOT EQUAL (-1) */
  236. X
  237. X  char *s1;
  238. X  int l1;
  239. X  char *s2;
  240. X  int l2;
  241. X
  242. X  { int j;
  243. X    if (l1 != l2) return(-1);
  244. X    j = 0;
  245. X    while (j++ < l1) 
  246. X      if (*s1++ != *s2++) return(-1);
  247. X    return(0);
  248. X  }
  249. X
  250. X  
  251. Xslge_compare (s1,l1,s2,l2)
  252. X
  253. X  /* returns -1 if s1 < s2; 1 if s2 < s1; 0 if s1 = s2 */
  254. X  /* ignores nulls in the strings */
  255. X
  256. X  char *s1;
  257. X  int l1;
  258. X  char *s2;
  259. X  int l2;
  260. X
  261. X  { int j,len;
  262. X    j = 0;
  263. X    len = l2 > l1 ? l1 : l2;
  264. X    while (j++ < len) {
  265. X      if (*s1 != *s2) 
  266. X         return((*s1 < *s2) ? -1 : 1);
  267. X      s1++;   
  268. X      s2++;
  269. X    }  
  270. X    return((l2 == l1) ? 0 : ((l1 < l2) ? -1 : 1));
  271. X  }
  272. X
  273. Xnocase_compare (s1,l1,s2,l2)
  274. X
  275. X  /* treats nulls as normal characters.  Returns same as slge_compare */
  276. X
  277. X  char *s1;
  278. X  int l1;
  279. X  char *s2;
  280. X  int l2;
  281. X
  282. X  { int j,len,ch1,ch2;
  283. X    j = 0;
  284. X    len = l2 > l1 ? l1 : l2;
  285. X    while (j++ < len) {
  286. X      ch1 = to_upper_if_lower(*s1++);
  287. X      ch2 = to_upper_if_lower(*s2++);
  288. X      if (ch1 != ch2) {
  289. X         return((ch1 < ch2) ? -1 : 1);
  290. X      }
  291. X    }  
  292. X    return((l2 == l1) ? 0 : ((l1 < l2) ? -1 : 1));
  293. X  }
  294. X
  295. X
  296. Xchar *strfind(s1,s2,fast)  
  297. X  
  298. X  register char *s1;
  299. X  char *s2;
  300. X  Bool fast;
  301. X  
  302. X{  
  303. X  register int len1,len2;
  304. X  len2 = strlen(s2);
  305. X  if (fast) {
  306. X     while (*s1 != '\0')
  307. X       if (0 == strncmp(s1++,s2,len2)) return(s1-1);
  308. X  }  
  309. X  else {
  310. X     len1 = strlen(s1);
  311. X     while (len1 >= len2) {
  312. X       if (0 == strncmp(s1++,s2,len2)) return(s1-1);
  313. X       len1--;
  314. X     }
  315. X  }
  316. X  return(0);
  317. X}     
  318. X
  319. X
  320. Xchar *strncfind(s1,s2,fast)
  321. X
  322. X  register char *s1;
  323. X  char *s2;
  324. X  Bool fast;
  325. X  
  326. X{  
  327. X  register int len1,len2;
  328. X  len2 = strlen(s2);
  329. X  if (fast) {
  330. X     while (*s1 != '\0')
  331. X       if (0 == nocase_compare(s1++,len2,s2,len2)) return(s1-1);
  332. X  }
  333. X  else {
  334. X     len1 = strlen(s1);
  335. X     while (len1 >= len2) {
  336. X       if (0 == nocase_compare(s1++,len2,s2,len2)) return(s1-1);
  337. X       len1--;
  338. X     }
  339. X  }
  340. X  return(0);
  341. X}  
  342. X
  343. X  
  344. Xchar *strsearch(s1,s1len,s2,s2len)
  345. X
  346. X  /* do a substring search without noticing nulls */
  347. X  /* finds s2 in s1, returns pointer into s1 or 0 */
  348. X
  349. X  register char *s1, *s2;
  350. X  register int s1len,s2len;
  351. X  
  352. X  {  register char *pc;
  353. X     register char *bound;
  354. X     register char *pctemp;
  355. X     register char *s2temp;
  356. X     register int j;
  357. X
  358. X     bound = s1 + s1len - s2len;
  359. X     for (pc = s1; pc <= bound; pc++) {
  360. X         pctemp = pc;
  361. X         s2temp = s2;
  362. X         for (j = 0; j < s2len; j++)
  363. X             if (*pctemp++ != *s2temp++) goto not_here;
  364. X         return(pc);       
  365. X         not_here :
  366. X         continue;
  367. X     }    
  368. X     return(0);
  369. X}
  370. X
  371. X
  372. Xchar *strncsearch(s1,s1len,s2,s2len)
  373. X
  374. X  /* do a substring search without noticing nulls */
  375. X  /* finds s2 in s1, returns pointer into s1 or 0 */
  376. X  /* case independent */
  377. X
  378. X  register char *s1, *s2;
  379. X  register int s1len,s2len;
  380. X  
  381. X  {  register char *pc;
  382. X     register char *bound;
  383. X     register char *pctemp;
  384. X     register char *s2temp;
  385. X     register int j;
  386. X     char ch1, ch2;
  387. X
  388. X     bound = s1 + s1len - s2len;
  389. X     for (pc = s1; pc <= bound; pc++) {
  390. X         pctemp = pc;
  391. X         s2temp = s2;
  392. X         for (j = 0; j < s2len; j++) {
  393. X             ch1 = *pctemp++;
  394. X             ch2 = *s2temp++;
  395. X             if (to_upper_if_lower(ch1) != to_upper_if_lower(ch2))
  396. X                goto not_here;
  397. X         }
  398. X         return(pc);       
  399. X         not_here :
  400. X         continue;
  401. X     }    
  402. X     return(0);
  403. X}
  404. X
  405. X
  406. Xint remove_excess_blanks (newstring,oldstring) 
  407. X
  408. X  /* it is assumed that newstring is as long as oldstring if necessary */
  409. X
  410. X  char *newstring,*oldstring;
  411. X
  412. X{
  413. X  int count = 0;
  414. X  int space_found = 0;
  415. X
  416. X  /* skip over all blanks at beginning */
  417. X  
  418. X  if (*oldstring == ' ') {
  419. X     while (*oldstring == ' ') oldstring++;
  420. X  }
  421. X
  422. X  while (*oldstring != '\0') {
  423. X        if (space_found && *oldstring == ' ') {
  424. X           oldstring++;
  425. X           continue;
  426. X        }
  427. X        space_found = (*oldstring == ' ');
  428. X        *newstring++ = *oldstring++;
  429. X        count++;
  430. X  }
  431. X
  432. X  *newstring = '\0';
  433. X  if (count > 0 && *(newstring - 1) == ' ') {
  434. X     count--;
  435. X     *(newstring - 1) = '\0';
  436. X  }
  437. X
  438. X  return(count);
  439. X
  440. X}
  441. X
  442. Xint ip_string_trim (oldstring,trimchars,pretrim,posttrim)
  443. X
  444. X  char *oldstring, *trimchars;
  445. X  Bool pretrim,posttrim;
  446. X
  447. X{
  448. X  Bool trim = T;
  449. X  char *np = oldstring, ch;
  450. X  int len;
  451. X  
  452. X  if (pretrim) {
  453. X     while (trim && ('\0' != (ch = *np))) {
  454. X       trim = (0 != index(trimchars,ch));
  455. X       if (trim) np++;
  456. X     }
  457. X     strcpy(oldstring,np);
  458. X  }
  459. X  if (1 >= (len = strlen(oldstring)) && pretrim) return(len);
  460. X  if (posttrim) {
  461. X     np = oldstring + len - 1;
  462. X     while (T) {
  463. X       ch = *np;
  464. X       trim = (0 != index(trimchars,ch));
  465. X       if (trim) *np = '\0';
  466. X       if (!trim || np == oldstring) break;
  467. X       np--;
  468. X     }
  469. X  }
  470. X  return(strlen(oldstring));
  471. X}
  472. X  
  473. Xint string_trim (newstring,oldstring,trimchars,pretrim,posttrim)
  474. X
  475. X  char *newstring, *oldstring, *trimchars;
  476. X  Bool pretrim, posttrim;
  477. X  
  478. X{  
  479. X  strcpy(newstring,oldstring);
  480. X  return(ip_string_trim(newstring,trimchars,pretrim,posttrim));
  481. X}
  482. X
  483. Xstring_upcase (astring) char *astring;
  484. X{
  485. X  while (*astring) {
  486. X    *astring = to_upper_if_lower(*astring);
  487. X    astring++;
  488. X  }
  489. X}
  490. X
  491. Xstring_downcase (astring) char *astring;
  492. X{
  493. X  while (*astring) {
  494. X    *astring = to_lower_if_upper(*astring);
  495. X    astring++;
  496. X  }
  497. X}
  498. X
  499. X
  500. Xyes_or_no_check (astring) char *astring;
  501. X
  502. X/* returns 1 if yes, 0 if no, -1 if neither */
  503. X/* works for 'Y' 'YES' 'NO' 'N' in any capitalization */
  504. X
  505. X{  
  506. X  int len;
  507. X  len = strlen(astring);
  508. X  if (len == 0 || len > 3) return(-1);
  509. X  if (0 == nocase_compare(astring,len,"YES",3) || 
  510. X      0 == nocase_compare(astring,len,"Y",1))
  511. X     return(1);
  512. X  if (0 == nocase_compare(astring,len,"NO",2) || 
  513. X      0 == nocase_compare(astring,len,"N",1))
  514. X     return(0);
  515. X  return(-1);
  516. X}
  517. X
  518. X
  519. XBool all_digits (astring) char *astring;
  520. X
  521. X/* test whether every character is a digit (0-9) */
  522. X
  523. X{
  524. X  while (*astring != '\0') 
  525. X    if (!isdigit(*astring++)) return(F);
  526. X  return(T);
  527. X}
  528. X
  529. X
  530. XBool all_whitespace (astring) char *astring;
  531. X
  532. X/* test whether every character is a blank or a tab */
  533. X
  534. X{
  535. X  register char ch;
  536. X  while ((ch = *astring++) != '\0') {
  537. X    if (ch == ' ' || ch == '\t') continue;
  538. X    return(F);
  539. X  }
  540. X  return(T);
  541. X}
  542. X
  543. XBool all_uppercase(astring) char *astring;
  544. X{
  545. X  register char ch;
  546. X  while ((ch = *astring++) != '\0') {
  547. X    if (!isupper(ch)) return(F);
  548. X  }
  549. X  return(T);
  550. X}
  551. X
  552. XBool all_lowercase(astring) char *astring;
  553. X{
  554. X  register char ch;
  555. X  while ((ch = *astring++) != '\0') {
  556. X    if (!islower(ch)) return(F);
  557. X  }
  558. X  return(T);
  559. X}
  560. X
  561. XBool all_alphabetic(astring) char *astring;
  562. X{
  563. X  register char ch;
  564. X  while ((ch = *astring++) != '\0') {
  565. X    if (!isalpha(ch)) return(F);
  566. X  }
  567. X  return(T);
  568. X}
  569. X
  570. XBool all_ascii(astring) char *astring;
  571. X{
  572. X  register char ch;
  573. X  while ((ch = *astring++) != '\0') {
  574. X    if (!isascii(ch)) return(F);
  575. X  }
  576. X  return(T);
  577. X}
  578. X
  579. XBool all_alphanumeric(astring) char *astring;
  580. X{
  581. X  register char ch;
  582. X  while ((ch = *astring++) != '\0') {
  583. X    if (!isalnum(ch)) return(F);
  584. X  }
  585. X  return(T);
  586. X}
  587. X
  588. Xint str_to_pos_int (astring,low,high) char *astring; int low,high;
  589. X
  590. X  /* returns -1 if *astring is not composed of digits. */
  591. X  /* returns -2 if the integer is out of range. */
  592. X  /* treats all digit strings as decimal. */
  593. X
  594. X{
  595. X  int value,len,maxlen,j;
  596. X  maxlen = strlen(MAXINTSTR);
  597. X  len = strlen(astring);
  598. X  if (!all_digits(astring)) return(-1);
  599. X  if (len > maxlen) return(-2);
  600. X  if (len == maxlen) {
  601. X     if (1 == strcmp(astring,MAXINTSTR)) return(-2);
  602. X  }
  603. X  for (j = 0; j < len-1; j++) {
  604. X      if (*astring != '0') break;
  605. X      astring++;
  606. X  }
  607. X  sscanf(astring,"%d",&value);
  608. X  if (value < low || value > high) return(-2);
  609. X  return(value);
  610. X}
  611. X
  612. X
  613. Xint sreverse (buffer,astring) char *buffer, *astring;
  614. X{
  615. X  register int last = strlen(astring);
  616. X  buffer[last--] = '\0';
  617. X  while (last >= 0) buffer[last--] = *astring++;
  618. X}
  619. X
  620. Xchar * ip_sreverse (astring) char *astring;
  621. X{
  622. X  register int last = strlen(astring) - 1;
  623. X  register int first = 0;
  624. X  register char ch;
  625. X  while (first < last) {
  626. X    ch = astring[first];
  627. X    astring[first++] = astring[last];
  628. X    astring[last--] = ch;
  629. X  }
  630. X  return(astring);
  631. X}
  632. X
  633. X
  634. X
  635. Xstatic char pathbuffer[PATH_MAXPATHLEN];
  636. X
  637. X
  638. Xchar *temp_path (dir,filename) char *dir; char *filename;
  639. X
  640. X{
  641. X  return(make_path(dir,filename,"",F));
  642. X}
  643. X
  644. X
  645. Xchar *perm_path (dir,filename) char *dir; char *filename;
  646. X
  647. X{
  648. X  return(make_path(dir,filename,"",T));
  649. X}
  650. X
  651. X
  652. Xchar *make_path_numeric_extension (dir,filename,extension,perm)
  653. X
  654. X  char *dir, *filename;
  655. X  int extension;
  656. X  Bool perm;
  657. X
  658. X{
  659. X#ifdef UNIX
  660. X  char *sprintf();
  661. X#else
  662. X  int sprintf();
  663. X#endif
  664. X  char buffer[20];
  665. X  sprintf(buffer,"%d",extension);
  666. X  return(make_path(dir,filename,buffer,perm));
  667. X}
  668. X
  669. X
  670. Xchar *make_path (dir,filename,extension,perm)
  671. X
  672. X  char *dir, *filename, *extension;
  673. X  Bool perm;
  674. X
  675. X{
  676. X  char *rval;
  677. X  if (!perm && (strlen(dir) + 1 + strlen(filename) + strlen(extension) + 1 >=
  678. X                PATH_MAXPATHLEN)) {
  679. X     return((char *) 0);
  680. X  }
  681. X#ifdef UNIX
  682. X  nbuffconcat(pathbuffer,4,dir,"/",filename,extension);
  683. X#endif
  684. X
  685. X#ifdef VMS
  686. X  nbuffconcat(pathbuffer,4,dir,filename,extension);
  687. X#endif
  688. X
  689. X#ifdef MSDOS
  690. X  nbuffconcat(pathbuffer,4,dir,"/",filename,extension);
  691. X#endif
  692. X
  693. X  if (!perm) return(pathbuffer);
  694. X  rval = emalloc(strlen(pathbuffer) + 1);  
  695. X  strcpy(rval,pathbuffer);
  696. X  return(rval);
  697. X}
  698. X
  699. X
  700. Xchar *just_filename (path,new,perm) char *path; Bool new,perm;
  701. X
  702. X{
  703. X  char *fnp,*rval;
  704. X#ifdef UNIX
  705. X  fnp = ((char *)NULL == (fnp = rindex(path,'/'))) ? path : fnp + 1;
  706. X#endif
  707. X
  708. X#ifdef VMS
  709. X  fnp = ((char *)NULL == (fnp = rindex(path,']'))) ? path : fnp + 1;
  710. X#endif
  711. X
  712. X#ifdef MSDOS
  713. X  if((fnp = rindex(path,'/')) != (char *)NULL)
  714. X    fnp += 1;
  715. X
  716. X  if(fnp == (char *)NULL)
  717. X    if((fnp = rindex(path,'\\')) == (char *)NULL)
  718. X        fnp = path;
  719. X    else
  720. X        fnp += 1;
  721. X#endif
  722. X
  723. X  if (!new) return(fnp);
  724. X  if (!perm) {
  725. X     strcpy(pathbuffer,fnp);
  726. X     return(pathbuffer);
  727. X  }
  728. X  else {
  729. X     rval = emalloc(strlen(fnp) + 1);
  730. X     strcpy(rval,fnp);
  731. X     return(rval);
  732. X  }
  733. X}
  734. X
  735. X
  736. X
  737. Xread_yes_or_no (iport,oport,prompt,helpstring,quitstring)
  738. X
  739. X  /* prints prompt, then reads from port until it gets 'Y', 'N', 'YES' or */
  740. X  /* 'NO' (case independently).  If helpstring and/or quitstring are not */
  741. X  /* "" or (char *) 0 then if the user types in one of those ANSWER_HELP */
  742. X  /* or ANSWER_QUIT are returned, otherwise ANSWER_NO or ANSWER_YES are */
  743. X  /* eventually returned. */
  744. X
  745. X  FILE *iport, *oport;
  746. X  char *prompt, *helpstring, *quitstring;
  747. X
  748. X{
  749. X  char buffer[20],buffer2[20];
  750. X  int bl,hl,ql;
  751. X  
  752. X  buffer[19] = '\0';
  753. X  
  754. X  while (T) {
  755. X        
  756. X    fprintf(oport,"%s",prompt);
  757. X    switch ((char)getline(iport,buffer,20)) {
  758. X      case (AT_EOF) :
  759. X        return(ANSWER_EOF);
  760. X        /* break; */
  761. X      case (TOO_MANY_CHARS) :
  762. X        break;
  763. X      default :
  764. X        if (0 == (bl = remove_excess_blanks(buffer2,buffer))) break;
  765. X        switch (yes_or_no_check(buffer2)) {
  766. X          case (0) :
  767. X            return(ANSWER_NO);
  768. X          case (1) :
  769. X            return(ANSWER_YES);
  770. X          case (-1) :
  771. X            if (helpstring != (char *) 0 && (hl = strlen(helpstring)) > 0) {
  772. X               if (0 == nocase_compare(buffer2,bl,helpstring,hl)) {
  773. X                  return(ANSWER_HELP);
  774. X               }
  775. X            }
  776. X            if (quitstring != (char *) 0 && (ql = strlen(quitstring)) > 0) {
  777. X               if (0 == nocase_compare(buffer2,bl,quitstring,ql)) {
  778. X                  return(ANSWER_QUIT);
  779. X               }
  780. X            }
  781. X            break;
  782. X        }   
  783. X        break;
  784. X    }
  785. X   
  786. X    fprintf(oport,"Please answer 'YES' or 'NO'\n");
  787. X    continue;
  788. X   
  789. X  }
  790. X    
  791. X}
  792. X
  793. X
  794. Xint getline (iport,buffer,buflen) FILE *iport; char *buffer; int buflen;
  795. X
  796. X  /* reads a line into buffer.  Does not put the '\n' into buffer. */
  797. X  /* Returns AT_EOF if at end of file when called.  If it encounters */
  798. X  /* end of file after reading at least one character, the eof is treated */
  799. X  /* as if it were a newline.   Returns TOO_MANY_CHARS if more than */
  800. X  /* buflen - 1 characters are read before encountering a newline. */        
  801. X  /* In this case exactly buflen - 1 characters are read. */
  802. X  /* The last character read is always follwed by a '\0'. */
  803. X  /* if successful getline returns the number of characters read exclusive */
  804. X  /* of a terminating newline or eof. */
  805. X
  806. X{
  807. X  int ch;
  808. X  char *bptr = buffer;
  809. X  int nchars = 0;
  810. X  
  811. X  if (buflen <= 0) return(TOO_MANY_CHARS);
  812. X  
  813. X  while (T) {
  814. X    switch (ch = getc(iport)) {
  815. X      case (EOF) :
  816. X      case ('\n') :
  817. X        if (ch == EOF && nchars == 0) return(AT_EOF);
  818. X        *bptr = '\0';
  819. X        return(nchars);
  820. X      default :
  821. X        if (++nchars == buflen) { 
  822. X           *bptr = '\0';
  823. X           ungetc(ch,iport);
  824. X           return(TOO_MANY_CHARS);
  825. X        }
  826. X        *bptr++ = ch;
  827. X    }
  828. X    
  829. X  }
  830. X    
  831. X}
  832. X
  833. X
  834. Xint getlines (fp,n,ptr_lines,linebuf,maxlinelen)
  835. X
  836. X  /* See documentation for getfile below */
  837. X
  838. X  FILE *fp;
  839. X  int n;
  840. X  char ***ptr_lines;
  841. X  char *linebuf;
  842. X  int maxlinelen;
  843. X
  844. X{
  845. X  int len;
  846. X  char *line;
  847. X  if (0 > (len = getline(fp,linebuf,maxlinelen))) {
  848. X     if (len == AT_EOF) {
  849. X        *ptr_lines = (char **) emalloc(n * sizeof(char **));
  850. X        return(n);
  851. X     }
  852. X     else {
  853. X        return(TOO_MANY_CHARS);
  854. X     }
  855. X  }
  856. X  else {
  857. X     line = emalloc(len+1);
  858. X     strcpy(line,linebuf);
  859. X     len = getlines(fp,n+1,ptr_lines,linebuf,maxlinelen);
  860. X     if (len == TOO_MANY_CHARS) return(TOO_MANY_CHARS);
  861. X     (*ptr_lines)[n] = line;
  862. X     return(len);
  863. X  }
  864. X}
  865. X
  866. X
  867. Xint getfile (filename,ptr_lines,linebuf,maxlinelen)
  868. X
  869. X  /* read in a file as an array of character strings */
  870. X  /* 'maxlinelen+1' is the maximum length a line of the file is allowed */
  871. X  /* to be.  'linebuf' must be at least 'maxlinelen+1' characters long. */
  872. X  /* Returns the number of lines in the file (and therefore the number */
  873. X  /* of entries in *ptr_lines) if successful.  Returns IOERROR if it */
  874. X  /* could not open the file to read from. Returns TOO_MANY_CHARS if */
  875. X  /* it encounters a line longer than 'maxlinelen' characters. */
  876. X
  877. X  /* Space for each line is malloc'ed as it is read in and the text for */
  878. X  /* the jth line is stored in (*ptr_lines)[j] */
  879. X
  880. X  char *filename;
  881. X  char ***ptr_lines;
  882. X  char *linebuf;
  883. X  int maxlinelen;
  884. X
  885. X{
  886. X  FILE *fp;
  887. X  int nlines;
  888. X  if (NULL == (fp = fopen(filename,"r"))) return(IOERROR);
  889. X  nlines = getlines(fp,0,ptr_lines,linebuf,maxlinelen);
  890. X  fclose(fp);
  891. X  return(nlines);
  892. X}
  893. X
  894. X
  895. Xint ngetlines (fp,n,ptr_lines,linebuf,maxlinelen)
  896. X
  897. X  /* See documentation for ngetfile below */
  898. X
  899. X  FILE *fp;
  900. X  int n;
  901. X  char ***ptr_lines;
  902. X  char *linebuf;
  903. X  int maxlinelen;
  904. X
  905. X{
  906. X  int len;
  907. X  int nlines = 0;
  908. X  *ptr_lines = (char **) emalloc(n * sizeof(char **));
  909. X  while (T) {
  910. X    if (0 > (len = getline(fp,linebuf,maxlinelen))) {
  911. X       if (len == AT_EOF) {
  912. X          return(nlines);
  913. X       }
  914. X       else {
  915. X          return(TOO_MANY_CHARS);
  916. X       }
  917. X    }
  918. X    else {
  919. X       if (++nlines > n) {
  920. X          return(TOO_MANY_LINES);
  921. X       }
  922. X       (*ptr_lines)[nlines-1] = anewstr(linebuf);
  923. X    }
  924. X  }
  925. X}
  926. X
  927. X
  928. X
  929. Xint ngetfile (n,filename,ptr_lines,linebuf,maxlinelen)
  930. X
  931. X  /* Same as getfile except that at most n lines will be read. */
  932. X  /* If it attempts to read more than n lines, TOO_MANY_LINES will */
  933. X  /* be returned. */
  934. X
  935. X  int n;
  936. X  char *filename;
  937. X  char ***ptr_lines;
  938. X  char *linebuf;
  939. X  int maxlinelen;
  940. X
  941. X{
  942. X  FILE *fp;
  943. X  int nlines;
  944. X  if (NULL == (fp = fopen(filename,"r"))) return(IOERROR);
  945. X  nlines = ngetlines(fp,n,ptr_lines,linebuf,maxlinelen);
  946. X  fclose(fp);
  947. X  return(nlines);
  948. X}
  949. X
  950. X
  951. Xint read_file_into_buffer (
  952. X
  953. X       filename,ptr_lines,maxlines,buffer,buflen,linebuffer,linebuflen
  954. X
  955. X    )
  956. X       
  957. X  char *filename; 
  958. X  char ***ptr_lines;
  959. X  int maxlines;
  960. X  char *buffer;
  961. X  int buflen;
  962. X  char *linebuffer;
  963. X  int linebuflen;
  964. X
  965. X  /* *ptr_lines should be an array of character string pointers maxlines */
  966. X  /* big.  buffer should be an array of characters buflen long.  The routine */
  967. X  /* reads lines using getline and stores them into buffer, terminating each */
  968. X  /* with a null.  A pointer to the nth line read is stored in *ptr_lines[n] */
  969. X  /* Returns IOERROR if it cannot open the file for reading, TOO_MANY_LINES */
  970. X  /* if more than maxlines were read in, TOO_MANY_CHARS if buffer is */
  971. X  /* filled before end of file is reached, and LINE_TOO_LONG is any line is */
  972. X  /* longer than linebuflen.  Returns number of lines read in if successful. */
  973. X  
  974. X{  
  975. X  FILE *fp;
  976. X  int linecount,charcount,len;
  977. X  char *bp;
  978. X  char **lines;
  979. X  
  980. X  if (NULL == (fp = fopen(filename,"r"))) return(IOERROR);
  981. X  linecount = 0;
  982. X  charcount = 0;
  983. X  bp = buffer;
  984. X  lines = *ptr_lines;
  985. X  
  986. X  while (T) {
  987. X        
  988. X    if (0 > (len = getline(fp,linebuffer,linebuflen))) {
  989. X       fclose(fp);
  990. X       if (len == AT_EOF) {
  991. X          return(linecount);
  992. X       }
  993. X       else {
  994. X          return(LINE_TOO_LONG);
  995. X       }
  996. X    }
  997. X    
  998. X    if (linecount >= maxlines) {
  999. X       fclose(fp);
  1000. X       return(TOO_MANY_LINES);
  1001. X    }
  1002. X    
  1003. X    charcount += len;
  1004. X    if (charcount >= buflen) {
  1005. X       fclose(fp);
  1006. X       return(TOO_MANY_CHARS);
  1007. X    }
  1008. X    
  1009. X    strcpy(bp,linebuffer);
  1010. X    lines[linecount++] = bp;
  1011. X    bp += (len + 1);
  1012. X  
  1013. X  }
  1014. X  
  1015. X}
  1016. X  
  1017. Xchar *efopen (filename,mode) char *filename; char *mode;
  1018. X
  1019. X  /* The routine simply calls fopen with the same arguments, but prints a */
  1020. X  /* reasonable error message and calls exit if the call to fopen fails. */
  1021. X
  1022. X{
  1023. X  FILE *fp;
  1024. X  if (NULL == (fp = fopen(filename,mode))) {
  1025. X     fprintf(stderr,"Could not open %s, mode: %s\n",filename,mode);
  1026. X     perror("Reason: ");
  1027. X     exit(1);
  1028. X  }
  1029. X  return((char *) fp);
  1030. X}
  1031. X
  1032. X
  1033. X
  1034. Xint record_fseek (fp,rnum,fromwhere,rsize,hdrsize)
  1035. X
  1036. X  FILE *fp;
  1037. X  long rnum;
  1038. X  int fromwhere;
  1039. X  int rsize;
  1040. X  int hdrsize; 
  1041. X
  1042. X{
  1043. X  if (fromwhere == 0) {
  1044. X     return(fseek(fp,(long) ((rnum - 1)*rsize + hdrsize),0));
  1045. X  }
  1046. X  else {
  1047. X     return(fseek(fp,(long) (rnum*rsize),fromwhere));
  1048. X  }
  1049. X}
  1050. X
  1051. X
  1052. XBool check_string (s,minlen,maxlen) char *s; long minlen,maxlen;
  1053. X{
  1054. X  long len;
  1055. X  if (s == 0) return(F);
  1056. X  len = strlen(s);
  1057. X  return (len >= minlen && len <= maxlen);
  1058. X}
  1059. END_OF_FILE
  1060. if test 21027 -ne `wc -c <'./toolsdir/ctools.c'`; then
  1061.     echo shar: \"'./toolsdir/ctools.c'\" unpacked with wrong size!
  1062. fi
  1063. # end of './toolsdir/ctools.c'
  1064. fi
  1065. echo shar: End of archive 4 \(of 4\).
  1066. cp /dev/null ark4isdone
  1067. MISSING=""
  1068. for I in 1 2 3 4 ; do
  1069.     if test ! -f ark${I}isdone ; then
  1070.     MISSING="${MISSING} ${I}"
  1071.     fi
  1072. done
  1073. if test "${MISSING}" = "" ; then
  1074.     echo You have unpacked all 4 archives.
  1075.     rm -f ark[1-9]isdone
  1076. else
  1077.     echo You still need to unpack the following archives:
  1078.     echo "        " ${MISSING}
  1079. fi
  1080. ##  End of shell archive.
  1081. exit 0
  1082.